diff --git a/docs/18-self-hosted-redesign-plani.md b/docs/18-self-hosted-redesign-plani.md deleted file mode 100644 index 8c8c2ca..0000000 --- a/docs/18-self-hosted-redesign-plani.md +++ /dev/null @@ -1,1296 +0,0 @@ ---- -title: Self-Hosted Redesign ve Supabase'den Ayrılma Planı -description: Neta'yı Supabase ve Poyraz UI bağımlılıklarından çıkarıp tek konteynerde çalışan, SQLite tabanlı, hızlı ve bakım maliyeti düşük bir freelancer uygulamasına dönüştürme planı. -order: 18 -status: proposed -last_updated: 2026-07-10 ---- - -# Neta Self-Hosted Redesign Planı - -## 1. Dokümanın amacı - -Bu doküman, mevcut Neta uygulamasını çalışan ürünü bozmadan aşağıdaki hedef mimariye taşımak için uygulanabilir ana plandır: - -- Supabase Auth, Postgres, Storage, RLS ve RPC bağımlılıklarını tamamen kaldırmak. -- Tüm backend davranışını Next.js'in server tarafında toplamak. -- Tek kullanıcı veya küçük ekip ölçeğindeki freelancer iş yükü için gömülü SQLite kullanmak. -- Poyraz UI bağımlılığını kaldırıp Neta'nın sahip olduğu bir arayüz sistemi oluşturmak. -- Dokploy, Coolify veya standart Docker çalıştırıcısında tek uygulama ve tek kalıcı volume ile deploy edebilmek. -- Mevcut performans, tutarlılık, güvenlik ve kullanıcı deneyimi problemlerini yeni mimariye taşımamak. -- Supabase üzerindeki mevcut veriyi doğrulanabilir ve geri alınabilir bir süreçle yeni sisteme aktarabilmek. - -Bu çalışma bir paket değiştirme operasyonu değildir. Supabase bugün aynı anda kimlik doğrulama, yetkilendirme, veritabanı, dosya depolama, trigger, aggregate RPC ve kullanıcı oluşturma işlerini yürütmektedir. Başarılı geçiş, bu sorumlulukların her biri için açık bir yeni sahip tanımlamayı gerektirir. - -Faz sonu kontrolleri [19-self-hosted-redesign-checklist.md](./19-self-hosted-redesign-checklist.md) dosyasında tutulacaktır. - -## 2. Yönetici özeti ve önerilen karar - -Önerilen üretim topolojisi tek bir Node.js 22 konteyneridir. Uygulama Next.js 16 App Router ile çalışır; Drizzle ORM üzerinden `better-sqlite3` kullanır; veritabanı ile yüklenen dosyalar aynı kalıcı volume altında saklanır. Kimlik doğrulama Better Auth tarafından aynı SQLite veritabanında yönetilir. Arayüz, Neta'ya ait `components/ui` bileşenleri ve semantik tasarım token'ları üzerinden kodlanır. - -Önerilen temel kararlar: - -| Alan | Karar | Gerekçe | -| --- | --- | --- | -| Veritabanı | SQLite + `better-sqlite3` | Tek instance freelancer iş yükünde düşük gecikme, ayrı DB servisi gerektirmeme ve kolay yedekleme | -| ORM/migration | Drizzle ORM + Drizzle Kit | Type-safe sorgu, kaynak kontrollü SQL migration ve düşük çalışma zamanı yükü | -| Auth | Better Auth, e-posta/parola, DB session | Harici auth servisi olmadan güvenli session yönetimi; auth protokolünü sıfırdan yazmama | -| Yetkilendirme | Server-side policy/helper + sahiplik filtreli repository | SQLite'ta RLS yok; güvenlik her sorgunun server bağlamında uygulanmalı | -| Dosyalar | Yerel disk + metadata tablosu + yetkili Route Handler | S3/Supabase Storage olmadan tek volume ile çalışma | -| UI | Neta'nın kendi bileşen API'si ve stilleri | Marka ve UX kontrolü; Poyraz UI kaldırılabilirliği | -| Erişilebilir davranış | Gerekli karmaşık widget'larda tek bir headless primitive katmanı | Dialog/select/menu gibi bileşenlerde klavye, focus ve ARIA davranışını güvenli tutma | -| Deploy | Multi-stage Docker, Next.js `output: standalone`, tek volume | Coolify/Dokploy için tek servis ve tekrarlanabilir image | -| Ölçek modeli | Tek çalışan instance | SQLite aynı dosyayı kullanan yatay replica modeli için uygun değildir | -| Eski üretim | Redesign tamamlanana kadar Supabase sürümü çalışmaya devam eder | Dual-write ve yarım taşınmış üretim riskini önleme | - -Bu kararın önemli sınırı şudur: hedef sürüm aynı anda yalnızca bir Neta uygulama instance'ı çalıştırır. Yatay çoğaltma, paylaşımlı ağ dosya sistemi veya yoğun eşzamanlı yazma ihtiyacı doğarsa veritabanı adaptörü PostgreSQL'e geçirilmelidir. Bu sınır gizlenmemeli; deploy dokümanında açıkça yazılmalıdır. - -## 3. Mevcut durum analizi - -### 3.1 Teknik yüzey - -Mevcut repo incelemesinde: - -- 44 uygulama dosyası Supabase paketlerine veya `lib/supabase` yardımcılarına bağlıdır. -- 36 uygulama/CSS dosyası doğrudan `poyraz-ui` kullanmaktadır. -- Browser Supabase client özellikle sohbet ve ayarlar ekranında doğrudan auth/veri işlemi yapmaktadır. -- Server Components sayfa verisini, Server Actions mutation'ları, Route Handlers ise AI ve kullanıcı oluşturma işlemlerini yürütmektedir. -- Ayrı bir backend uygulaması yoktur; bu, hedef Next.js server-side mimarisi için iyi bir başlangıçtır. -- `lib/db.ts` içindeki Dexie/IndexedDB katmanı aktif akışlarda kullanılmamaktadır ve eski bir prototip kalıntısıdır. -- Dockerfile, Compose, otomatik migration runner, backup/restore komutu ve test altyapısı bulunmamaktadır. -- Production build başarılıdır; lint tabanı temiz değildir ve mevcut incelemede 34 hata ile 25 uyarı üretmiştir. - -### 3.2 Supabase'in bugün üstlendiği sorumluluklar - -Supabase kaldırıldığında aşağıdaki işlerin her biri yeniden uygulanmalıdır: - -1. Kullanıcı kaydı, parola doğrulama, session cookie ve çıkış. -2. İlk freelancer/admin hesabı oluşturulduktan sonra herkese açık kaydı kilitleme. -3. Freelancer tarafından müşteri portal hesabı oluşturma. -4. `freelancer` ve `client` rol ayrımı. -5. Her kaydı `user_id` ile izole eden RLS politikaları. -6. Müşterinin yalnızca kendi projelerini, public görevleri ve revizyonlarını görmesi. -7. PostgreSQL tabloları, foreign key'ler, check constraint'ler ve trigger'lar. -8. Dashboard ve analytics aggregate RPC'leri. -9. Avatar ve proje görseli depolama, dosya limiti ve signed URL üretimi. -10. `pgvector` tabanlı embedding saklama ve benzerlik araması. -11. Service-role ile ayrıcalıklı kullanıcı/dosya operasyonları. - -Yeni sistemde service-role anahtarı veya browser DB client olmayacaktır. Ayrıcalık, yalnızca server tarafında çalışan ve session/rol kontrolü yapan servis fonksiyonlarıyla temsil edilecektir. - -### 3.3 Mevcut veri alanları - -Aktif veya tarihsel şemada şu iş alanları bulunur: - -- Kimlik/profil: `profiles` ve Supabase `auth.users`. -- İş yönetimi: `clients`, `projects`, `tasks`, `calendar_events`. -- Proje çalışma alanı: `project_planning_sections`, `project_revisions`, proje kapak görselleri. -- Finans: `finance_transactions`, `invoices`, `proposals`, `contracts`, `subscriptions`. -- CRM: `client_activities`, pipeline ve takip alanları. -- Günlük: aktif ekranda `daily_logs`, eski şemada `journals`. -- AI: `chat_sessions`, `chat_messages`, `app_settings`, `document_embeddings`. - -`journals` ile `daily_logs`, `completed` ile `done`, planlama alanındaki `category` ile bazı UI kodundaki `type` gibi tarihsel tutarsızlıklar vardır. Yeni şema mevcut SQL'i körlemesine kopyalamamalı; önce kanonik sözlük belirlenmelidir. - -### 3.4 Kopyalanmaması gereken mevcut problemler - -Geçiş sırasında aşağıdaki problemler davranış paritesi olarak kabul edilmeyecektir: - -- Portal proje detayında `sort_order` yerine var olmayan `order_index` ile sıralama. -- Proje risk analizinde bitmiş görev için `done` yerine `completed` kontrolü. -- Portal planlama UI'ında `category` yerine `type` alanı okuma. -- Revizyon kotasının yalnızca UI'da kontrol edilip server action içinde zorunlu tutulmaması. -- Mevcut portal revizyon insert politikasında proje ile müşteri ilişkisinin tam doğrulanmaması. -- Liste ekranlarında sınırsız kayıt çekme, gereksiz `select("*")` ve istemciye fazla veri gönderme. -- Bazı mutation'larda pending, optimistic update, rollback veya hata mesajı olmaması. -- Browser component'lerinin doğrudan veritabanı/auth SDK'sına erişmesi. -- AI provider anahtarının veritabanında düz metin tutulması ve istemciye geri okunması. - -## 4. Hedefler, başarı ölçütleri ve kapsam dışı işler - -### 4.1 Ürün hedefleri - -- Bir freelancer, repo URL'si, birkaç secret ve tek persistent volume ile Neta'yı ayağa kaldırabilmelidir. -- Kurulum ekranı ilk freelancer hesabını oluşturmalı ve ardından public registration kapanmalıdır. -- Müşteri portalı davet bağlantısıyla kurulabilmeli; adminin parola üretip paylaşmasına gerek kalmamalıdır. -- En sık işler olan görev tamamlama, proje açma, müşteri bulma, gelir/gider ekleme ve takvim kontrolü az tıklama ve anlık geri bildirimle yürümelidir. -- UI; dashboard kartlarının toplamından ziyade günlük iş akışını, yaklaşan işleri ve nakit durumunu önceliklendirmelidir. - -### 4.2 Teknik başarı ölçütleri - -- Üretim için Supabase URL'si, anon key'i veya service-role key'i gerekmemesi. -- Üretim için ayrı PostgreSQL, Redis, S3 veya auth servisi gerekmemesi. -- Tek image ve tek volume ile temiz kurulumun otomatik tamamlanması. -- Tüm migration'ların kaynak kontrolünde bulunması ve boş veritabanına deterministik uygulanması. -- `lint`, typecheck, unit/integration test, production build ve Docker smoke testlerinin temiz geçmesi. -- Yetkisiz kullanıcı/portal erişimini kapsayan negatif entegrasyon testlerinin bulunması. -- Dashboard sıcak DB sorgu süresinin referans veri setinde hedef olarak 50 ms altında; mutation DB bölümünün 100 ms altında olması. -- Kullanıcı tıklamasından pending feedback'e kadar geçen sürenin 100 ms altında olması. -- Liste sorgularının pagination veya sınırlı tarih aralığı kullanması; veri arttıkça payload'ın doğrusal büyümemesi. -- Yedek alma ve boş bir kurulumda geri yükleme tatbikatının belgelenmiş ve başarılı olması. - -Performans hedefleri referans donanım ve veri setiyle ölçülmelidir. Ağ TTFB'si ile saf DB süresi birbirinden ayrı raporlanacaktır. - -### 4.3 Kapsam dışı işler - -İlk self-hosted sürümde aşağıdakiler hedeflenmez: - -- Birden fazla Next.js replica veya Kubernetes horizontal scaling. -- Birden fazla freelancerın aynı workspace içinde ekip olarak çalışması. -- Gerçek zamanlı collaborative editing veya websocket tabanlı presence. -- Harici object storage zorunluluğu. -- Tam offline-first veri senkronizasyonu. -- Supabase password hash veya aktif session taşıma. -- Gelişmiş vector database/RAG altyapısı. -- Native mobil uygulama. - -Bu sınırlar veri modelinin gelecekte genişlemesini engellememeli, ancak bugünkü tasarımı gereksiz soyutlamalarla ağırlaştırmamalıdır. - -## 5. Hedef mimari - -### 5.1 Çalışma zamanı topolojisi - -```mermaid -flowchart LR - B[Browser] -->|HTTPS| N[Next.js 16 Node.js container] - N --> A[Server Components / Actions / Route Handlers] - A --> AU[Better Auth] - A --> S[Domain services and repositories] - AU --> D[(SQLite: /app/data/neta.db)] - S --> D - S --> F[/Uploads: /app/data/uploads/] - N --> L[stdout logs] - J[Coolify/Dokploy scheduled job] --> BK[/Backups: /app/data/backups/] - D --> BK - F --> BK -``` - -Tek kalıcı volume içeriği: - -```text -/app/data/ - neta.db - neta.db-wal - neta.db-shm - uploads/ - avatars/ - project-assets/ - backups/ - tmp/ -``` - -`-wal` ve `-shm` dosyaları normal çalışma zamanı dosyalarıdır. Elle kopyalanarak tutarlı yedek alınmamalıdır; SQLite backup API veya kontrollü checkpoint kullanılmalıdır. - -### 5.2 Uygulama katmanları - -```mermaid -flowchart TD - UI[Server and Client UI] --> ACT[Server Actions] - UI --> RH[Route Handlers] - UI --> Q[Server Component queries] - ACT --> AUTH[Auth and authorization helpers] - RH --> AUTH - Q --> AUTH - AUTH --> SV[Domain services] - SV --> RP[Repositories] - SV --> ST[Storage service] - RP --> DB[Drizzle / SQLite] -``` - -Kurallar: - -- Client Component hiçbir zaman DB, auth secret veya filesystem modülü import etmez. -- Server Components yalnızca query/service fonksiyonlarına erişir; tablo detaylarını sayfa içine yaymaz. -- Server Actions form mutation'ları ve küçük etkileşimler için kullanılır. -- Route Handlers auth endpoint'i, AI streaming, dosya upload/download, export ve health check için kullanılır. -- Repository yalnızca veri erişiminden; service ise iş kuralları, transaction sınırı ve yetkilendirmeden sorumludur. -- Aynı iş kuralı hem Server Action hem Route Handler tarafından çağrılıyorsa service içinde tek kez tanımlanır. - -### 5.3 Önerilen klasör yapısı - -```text -app/ - (auth)/ - (dashboard)/ - portal/ - api/ -components/ - ui/ # Neta'nın sahip olduğu primitive bileşenler - layout/ -features/ - clients/ - projects/ - tasks/ - calendar/ - finance/ - business/ - journal/ - analytics/ - chat/ - portal/ -server/ - auth/ - auth.ts - session.ts - authorization.ts - db/ - client.ts - schema/ - migrations/ - queries/ - repositories/ - services/ - storage/ - security/ - observability/ -shared/ - contracts/ - validation/ - formatting/ -scripts/ - migrate.mjs - seed.mjs - backup.mjs - restore.mjs - import-supabase.mjs -``` - -Bu yapı bir kerede taşınmamalıdır. Bir feature yeni katmana geçtiğinde o feature'ın eski Supabase sorgusu silinir; yarım feature iki veri yolunu aynı anda kullanmaz. - -## 6. Temel teknik kararlar - -### 6.1 SQLite ve `better-sqlite3` - -SQLite seçimi şu kullanım profiline uygundur: - -- Tek kurulumda bir freelancer ve sınırlı sayıda portal kullanıcısı. -- Okuma ağırlıklı dashboard/liste ekranları. -- Kısa transaction'larla yapılan düşük eşzamanlı yazma. -- Operasyon kolaylığının yatay ölçekten önemli olması. - -Uygulama başlangıcında bağlantı şu PRAGMA'ları kontrollü biçimde ayarlamalıdır: - -```sql -PRAGMA foreign_keys = ON; -PRAGMA journal_mode = WAL; -PRAGMA synchronous = NORMAL; -PRAGMA busy_timeout = 5000; -``` - -Ek kurallar: - -- Uygulama process'i başına tek DB bağlantı nesnesi oluşturulur; development hot reload için global singleton korunur. -- Migration HTTP isteği içinde çalıştırılmaz; container server başlamadan önce uygulanır. -- Transaction içinde AI API çağrısı, dosya upload'ı veya başka uzun I/O yapılmaz. -- Yazma transaction'ları kısa tutulur. -- SQLite dosyası NFS/SMB gibi paylaşımlı ağ volume'unda çalıştırılmaz; yerel persistent block storage kullanılır. -- Coolify/Dokploy replica sayısı daima `1` olur; rolling deployment yerine stop/start veya recreate stratejisi kullanılır. -- `SQLITE_BUSY` hataları loglanır ve kontrollü kısa retry yalnızca idempotent operasyonlarda uygulanır. - -### 6.2 Drizzle schema ve migration modeli - -- TypeScript schema kaynak gerçeğidir; migration SQL dosyaları commit edilir. -- Şema değişikliği `generate` ile üretilir, SQL insan tarafından gözden geçirilir ve ardından uygulanır. -- Production'da `push` kullanılmaz. -- Migration'lar forward-only kabul edilir. Geri dönüş, migration öncesi yedekten restore ile yapılır. -- Container başlangıcında migration lock ve tek-instance koşulu doğrulanır. -- Migration dosyaları standalone image içine açıkça kopyalanır. -- CI her migration setini sıfır SQLite dosyasına ve bir önceki release fixture'ına uygular. - -Planlanan komutlar: - -```text -npm run db:generate -npm run db:migrate -npm run db:check -npm run db:seed -npm run db:studio # yalnızca local development -``` - -### 6.3 Kimlik doğrulama ve session - -Better Auth, email/password ve veritabanı session modeliyle kullanılacaktır. Better Auth'ın ürettiği auth tabloları manuel tahmin edilmek yerine CLI/schema çıktısıyla migration setine dahil edilir. - -Auth akışları: - -1. Boş kurulumda `/setup` açılır. -2. Server, freelancer rolünde kullanıcı bulunmadığını transaction içinde doğrular. -3. İlk kullanıcı oluşturulur ve public setup kalıcı olarak kapanır. -4. Sonraki kullanıcılar yalnızca freelancerın ürettiği süreli portal davetiyle kayıt olabilir. -5. Davet token'ının yalnızca hash'i DB'de saklanır; ham token URL'de bir kez kullanılır. -6. Parola değiştirme mevcut session ve eski session'ları iptal etme seçeneğiyle yapılır. -7. Session cookie `HttpOnly`, production'da `Secure` ve uygun `SameSite` değeriyle tutulur. - -Gerekli environment secret'ları: - -- `BETTER_AUTH_SECRET`: en az 32 karakter, yüksek entropili. -- `APP_URL`: canonical origin. -- `TRUSTED_ORIGINS`: gerekiyorsa açık origin listesi; wildcard yok. -- `APP_ENCRYPTION_KEY`: saklanan AI API anahtarlarını şifrelemek için ayrı anahtar. - -Proxy/middleware yalnızca kullanıcı deneyimi amaçlı hızlı yönlendirme yapabilir. Asıl session ve rol kontrolü her korumalı layout, Server Action, Route Handler ve service girişinde yeniden yapılır. Cookie varlığı hiçbir zaman yetkilendirme kanıtı sayılmaz. - -### 6.4 Yetkilendirme: RLS yerine uygulama politikası - -SQLite RLS sağlamadığı için güvenlik modeli açıkça kodlanmalıdır: - -```text -requireSession() -requireFreelancer() -requireClientUser() -requireOwnedClient(clientId) -requireOwnedProject(projectId) -requirePortalProjectAccess(projectId) -``` - -Repository sorgularında temel kural: - -```text -Kötü: WHERE id = :resourceId -Doğru: WHERE id = :resourceId AND owner_id = :sessionUserId -``` - -Portal sorgusu ise hem portal kullanıcı-client bağını hem de kaynak-client bağını aynı sorguda doğrular. Kaynağı önce ID ile çekip sonra UI tarafında kontrol etmek kabul edilmez. - -Her mutation için: - -1. Input Zod ile parse edilir. -2. Session alınır. -3. Rol ve sahiplik doğrulanır. -4. İş kuralı doğrulanır. -5. Gerekirse transaction açılır. -6. Mutation uygulanır. -7. Audit/log kaydı yazılır. -8. İlgili route/tag revalidate edilir. -9. Tipli sonuç döndürülür. - -### 6.5 Yerel dosya depolama - -Supabase Storage yerine aşağıdaki model kullanılır: - -- Dosyanın binary içeriği `DATA_DIR/uploads` altında tutulur. -- DB'de `files` tablosu; `id`, `owner_id`, `kind`, `storage_key`, `original_name`, `mime_type`, `size_bytes`, `sha256`, `created_at` ve ilişkili resource bilgisini taşır. -- DB'ye absolute path yazılmaz. -- Kullanıcı tarafından gönderilen dosya adı disk path'i olarak kullanılmaz. -- Dosya uzantısı ve MIME yalnızca header'a güvenmeden doğrulanır. -- Avatar ve proje görselleri için boyut ve MIME allowlist uygulanır. -- Yazma önce geçici dosyaya yapılır; doğrulama sonrası atomik rename kullanılır. -- DB kaydı başarısız olursa dosya temizlenir; dosya yazımı başarısız olursa DB kaydı oluşturulmaz. -- Yetkili dosya Route Handler'ı DB sahiplik kontrolünden sonra stream eder. -- Private dosyalarda tahmin edilebilir doğrudan filesystem URL'si verilmez. - -İlk hedef yalnızca avatar ve proje kapak görselidir. Genel doküman yönetimi ayrı ürün fazıdır. - -### 6.6 UI bağımlılık stratejisi - -“Kendi UI'ımız” şu şekilde yorumlanacaktır: - -- Neta; bileşen API'sine, HTML yapısına, token'lara, stillere, varyantlara ve UX kararlarına sahip olur. -- Feature dosyaları üçüncü taraf görsel component import etmez. -- Dialog, select, dropdown, tooltip ve toast gibi erişilebilirlik açısından karmaşık davranışlarda yalnızca headless primitive kullanılabilir. -- Headless katman tek bir paketle sınırlandırılır ve yalnızca `components/ui` içinden import edilir. -- Lucide ikonlar korunur; ikinci bir ikon seti kullanılmaz. - -Önerilen bağımlılık temizliği: - -| Kategori | Plan | -| --- | --- | -| `poyraz-ui` | Tamamen kaldır | -| `@supabase/ssr`, `@supabase/supabase-js` | Runtime'dan tamamen kaldır | -| Dexie paketleri ve `lib/db.ts` | Offline sync kapsam dışıysa kaldır | -| `shadcn` CLI/runtime paketi | Üretim dependency'sinden kaldır | -| Tekil Radix paketleri + `radix-ui` tekrarları | Tek headless yaklaşımına indir | -| `@iconify/react` | Tüm ikonlar Lucide'a taşındıktan sonra kaldır | -| `uuid` | `crypto.randomUUID()` yeterliyse kaldır | -| `framer-motion` | Ölçülmüş bir ihtiyaç yoksa CSS transition'a indir ve kaldır | -| `@ducanh2912/next-pwa` | İlk hedef sürümde kaldır; PWA değeri ayrıca kanıtlanırsa geri ekle | -| Drizzle, Better Auth, `better-sqlite3` | Yerel runtime temel bağımlılığı olarak ekle | - -Paket sayısını azaltmak tek başına amaç değildir. Harici servis zorunluluklarını kaldırmak ve kalan paketlerin net bir sorumluluğu olmasını sağlamak asıl ölçüttür. - -### 6.7 PWA ve offline davranışı - -Mevcut uygulamada gerçek bir offline mutation/sync modeli yoktur. Bu nedenle ilk redesign release'inde: - -- PWA service worker kaldırılır. -- Dexie kaldırılır. -- Tarayıcıda stale auth veya eski dashboard verisi üretebilecek cache davranışı ortadan kaldırılır. -- İhtiyaç doğrulanırsa sonraki fazda yalnızca installable shell ve static asset cache geri eklenir. -- API, auth, portal ve kullanıcı verisi network-only kalır. - -## 7. Hedef veri modeli - -### 7.1 Veri tipi standartları - -- ID: SQLite `TEXT`, mevcut UUID'ler korunur, yeni ID için `crypto.randomUUID()`. -- Timestamp: UTC epoch millisecond tutan `INTEGER`; API/UI sınırında `Date` dönüşümü. -- Sadece gün ifade eden alan: `YYYY-MM-DD` biçiminde `TEXT`. -- Boolean: Drizzle `integer(..., { mode: "boolean" })`. -- Para: `amount_minor INTEGER` + ISO 4217 `currency TEXT`; JavaScript floating point para hesabı yapılmaz. -- Yüzde/oran: amaca göre integer basis point veya açıkça belgelenmiş numeric ölçek. -- JSON: SQLite `TEXT` JSON mode ve parse sınırında schema doğrulama. -- Enum benzeri alan: TypeScript union + DB `CHECK` constraint. -- Tüm mutable tablolarda `created_at` ve `updated_at`. - -Mevcut `numeric(12,2)` değerleri import sırasında iki ondalık desteklenen para birimleri için minor unit'e çevrilir. Farklı exponent gerektiren para birimleri desteklenecekse conversion tablosu migration başlamadan tanımlanır. - -### 7.2 Auth ve erişim tabloları - -- Better Auth tarafından üretilen user/session/account/verification tabloları. -- `profiles`: user ile bire bir; görünen ad, avatar file ID, locale, timezone ve `freelancer|client` rolü. -- `portal_invitations`: client, davet eden freelancer, token hash, son kullanma, kullanıldı zamanı. -- `audit_events`: kritik auth, import, settings ve portal olayları için küçük append-only kayıt. - -`clients.portal_user_id`, portal kullanıcısını ilgili müşteri kaydına bağlar. Bir portal user yalnızca bir client kaydına bağlı olacaksa unique constraint ile zorlanır. - -### 7.3 Domain tabloları - -İlk hedef şema, mevcut aktif davranışı koruyarak aşağıdaki tabloları içerir: - -- `clients` -- `client_activities` -- `projects` -- `project_planning_sections` -- `tasks` -- `calendar_events` -- `project_revisions` -- `finance_transactions` -- `proposals` -- `contracts` -- `invoices` -- `subscriptions` -- `journal_entries` -- `chat_sessions` -- `chat_messages` -- `app_settings` -- `files` - -`owner_id`, kaydın freelancer sahibini gösterir. `portal_user_id` veya `requested_by_user_id` sahiplik yerine aktörü gösterir. İki kavram karıştırılmaz. - -### 7.4 Günlük verisinin birleştirilmesi - -Mevcut `journals` ve `daily_logs` tek `journal_entries` modelinde birleştirilir: - -- `entry_type`: `daily_checkin` veya `journal`. -- `entry_date`. -- `content`. -- `mood_label`, `mood_score`, `energy_score`, `work_satisfaction_score` nullable alanları. -- Gerekliyse AI summary/sentiment alanları. -- Aynı gün için yalnızca `daily_checkin` kaydına unique kural; serbest journal girdisi birden fazla olabilir. - -Import sırasında hiçbir eski journal sessizce atılmaz. Çakışan veriler ayrı entry olarak korunur ve manifestte raporlanır. - -### 7.5 Embedding kararı - -`document_embeddings` aktif ürün akışında kullanılmadığı için ilk SQLite release'ine vector olarak taşınmaz. - -- Eski embedding kayıtları export arşivinde korunur. -- Chat bağlamı görev/proje/finans/journal sorgularından oluşturulur. -- Yerel arama ihtiyacı için önce SQLite FTS5 değerlendirilir. -- Gerçek RAG kullanım ihtiyacı kanıtlanırsa vector extension veya ayrı adapter için ADR açılır. - -### 7.6 İndeks planı - -Minimum indeksler: - -- `clients(owner_id, pipeline_stage, updated_at)`. -- `client_activities(owner_id, client_id, activity_date)`. -- `projects(owner_id, status, updated_at)` ve `projects(owner_id, client_id)`. -- `tasks(owner_id, status, due_at)` ve `tasks(owner_id, project_id, status)`. -- `calendar_events(owner_id, starts_at)`. -- `finance_transactions(owner_id, transaction_date, type)`. -- `finance_transactions(owner_id, project_id, payment_status)`. -- `journal_entries(owner_id, entry_date, entry_type)`. -- `project_revisions(project_id, status, created_at)`. -- `chat_sessions(owner_id, updated_at)` ve `chat_messages(session_id, created_at)`. -- `portal_invitations(token_hash)` unique. -- `files(owner_id, kind, created_at)` ve `files(storage_key)` unique. - -İndeksler varsayımla çoğaltılmaz. Referans seed üzerinde `EXPLAIN QUERY PLAN` ile kritik sorguların index kullandığı kanıtlanır. - -### 7.7 İş kuralı transaction'ları - -Transaction gerektiren örnekler: - -- Task status değişimi + auto project progress yeniden hesaplama. -- Client silme/arşivleme + portal erişiminin kapatılması. -- Davetin tüketilmesi + portal user-client bağının kurulması. -- Revizyon isteği + kota kontrolü + sayaç/usage güncellemesi. -- Invoice paid durumu + isteğe bağlı finance transaction oluşturma. -- Import batch'i + migration manifest kaydı. - -Proje progress trigger'ı uygulama service'ine taşınır ve aynı transaction içinde çalışır. Ayrıca drift kontrolü için idempotent `recalculateProjectProgress(projectId)` fonksiyonu bulunur. - -## 8. Next.js server-side tasarımı - -### 8.1 Veri okuma - -- Server Component sorguları doğrudan repository/service çağırır; kendi HTTP API'mize loopback fetch yapılmaz. -- Session lookup request içinde memoize edilir. -- User-specific veride global cache başlangıçta kapalı tutulur; tenant veri sızıntısı riski alınmaz. -- Dashboard tek bir dev sorgu dosyasında aggregate SQL ile hesaplanır. -- Listeler seçili kolon, deterministic order ve pagination kullanır. -- Detail ekranı bağımsız blokları paralel okuyabilir; aynı tabloyu tekrar tekrar sorgulamaz. -- Büyük sekmeler gerekirse alt route veya lazy fetch olur; ilk RSC payload'ına tüm geçmiş taşınmaz. - -### 8.2 Mutation sözleşmesi - -Tüm mutation'lar ortak bir sonuç şekli kullanır: - -```ts -type ActionResult = - | { ok: true; data: T } - | { ok: false; code: string; message: string; fieldErrors?: Record }; -``` - -Kurallar: - -- Kullanıcıya ham SQLite/stack hata metni dönmez. -- Unique/foreign key/check hataları bilinen domain hatasına çevrilir. -- Beklenen validation hataları log seviyesinde error değildir. -- Beklenmeyen hata request ID ile loglanır ve UI'da güvenli genel mesaj gösterilir. -- Idempotency gereken endpoint'lerde client request ID veya unique business key kullanılır. -- `revalidatePath`/tag yalnızca mutation başarıyla commit olduktan sonra çağrılır. - -### 8.3 AI Route Handler'ları - -- AI streaming Route Handler'da kalır ve Node runtime kullanır. -- Provider key yalnızca server'da çözülür. -- DB'de saklanan key AES-256-GCM gibi authenticated encryption ile şifrelenir; nonce/tag ile saklanır. -- Ayarlar ekranı kaydedilmiş key'i geri göstermez; yalnızca “tanımlı” bilgisi verir. -- Prompt bağlamı kolon ve satır limitiyle oluşturulur. -- Kullanıcı girdisi, context ve model cevabı için boyut limitleri bulunur. -- Timeout/abort ve provider hata eşlemesi uygulanır. -- Maliyet ve privacy nedeniyle AI özellikleri tamamen kapatılabilir. - -### 8.4 Health ve readiness - -- `/api/health/live`: process ayakta mı; DB'ye bağımlı olmayan hızlı 200. -- `/api/health/ready`: `SELECT 1`, migration version ve data dizininin yazılabilirliğini kontrol eder. -- Readiness endpoint'i secret döndürmez ve tablo detayını açığa çıkarmaz. -- Deploy platformu liveness yerine readiness kullanır. - -## 9. UI ve ürün deneyimi redesign yönü - -### 9.1 Bilgi mimarisi - -Önerilen ana navigasyon: - -- Bugün -- Projeler -- Görevler -- Müşteriler -- Takvim -- Finans -- İş Belgeleri -- Günlük -- Analizler -- AI Asistan -- Ayarlar - -“İş Belgeleri” proposal, contract, invoice ve subscription alanlarını tek grup altında toplar. Mobilde en sık dört alan alt navigasyonda; diğerleri menüde yer alabilir. Navigasyon gerçek kullanım ölçümüyle doğrulanmalıdır. - -### 9.2 Ekran ilkeleri - -- İlk ekran pazarlama sayfası değil, oturum varsa doğrudan çalışma alanıdır. -- Dashboard dekoratif metriklerden önce bugün yapılacak işler, geciken görevler, yaklaşan tahsilatlar ve aktif proje risklerini gösterir. -- Proje detayı tek çalışma alanıdır: özet, görevler, plan, finans, revizyonlar. -- Müşteri detayı iletişim, proje, finans ve activity geçmişini bir arada gösterir. -- Liste ekranları masaüstünde taranabilir tablo/liste, mobilde kontrollü satır/kart sunar. -- Uzun form dialog içine sıkıştırılmaz; mobilde sheet veya tam ekran form kullanılabilir. -- Her boş durum tek bir birincil aksiyon verir. -- Kritik silme işlemleri açık nesne adıyla onay ister. - -### 9.3 Internal UI bileşen envanteri - -İlk bileşen seti: - -- Temel: `Button`, `IconButton`, `LinkButton`, `Badge`, `Avatar`, `Separator`. -- Form: `Field`, `Label`, `Input`, `Textarea`, `Select`, `Checkbox`, `Switch`, `DateInput`, `MoneyInput`. -- Overlay: `Dialog`, `AlertDialog`, `Drawer`, `DropdownMenu`, `Tooltip`, `Toast`. -- Navigasyon: `Tabs`, `Sidebar`, `MobileNav`, `Breadcrumb`, `Pagination`. -- Veri: `DataTable`, `EmptyState`, `Skeleton`, `Progress`, `Stat`. -- Feedback: `InlineError`, `FormError`, `PendingButton`, `OfflineBanner` yalnızca gerçek anlamı varsa. - -Feature bileşenleri bu primitive'leri compose eder. Primitive içine domain metni veya business logic konmaz. - -### 9.4 Tasarım token'ları - -`--poyraz-*` değişkenleri semantik Neta token'larıyla değiştirilir: - -- Renk: background, surface, foreground, muted, border, accent, danger, success, warning. -- Tipografi: body, label, heading ölçekleri; viewport genişliğiyle font ölçeklenmez. -- Spacing: 4 px tabanlı sınırlı ölçek. -- Radius: kompakt operasyonel UI için en fazla 8 px varsayılan. -- Shadow: yalnızca overlay ve gerçek elevation için. -- Motion: 120-200 ms; `prefers-reduced-motion` desteği. -- Stable control height ve icon button ölçüleri. - -### 9.5 Etkileşim standardı - -- Tıklamadan sonra 100 ms içinde pending görünür. -- Mutation sırasında ilgili kontrol disabled olur; bütün sayfa gereksiz yere kilitlenmez. -- Uygun görev/status işlemlerinde optimistic update ve hata halinde rollback yapılır. -- Submit başarı mesajı kalıcı veriyle uyuşmadan gösterilmez. -- Route geçişinde link pending ve route skeleton birlikte çalışır. -- Form validation hem alan yanında hem özet seviyesinde anlaşılırdır. -- Klavye focus'u görünürdür; dialog kapanınca tetikleyiciye döner. -- Drag/drop için buton veya menü tabanlı alternatif bulunur. -- 320 px genişlikte horizontal taşma ve içerik çakışması olmaz. - -## 10. Güvenlik modeli - -### 10.1 Tehdit sınırları - -Korunacak varlıklar: - -- Freelancer ve client hesapları. -- Müşteri/proje/finans verileri. -- AI API anahtarları. -- Yüklenen görseller. -- Davet ve reset token'ları. -- Backup arşivleri. - -Ana riskler: - -- IDOR: başka kullanıcının resource ID'siyle veri erişimi. -- Portal üzerinden freelancer verisinin fazla görünmesi. -- CSRF/origin yanlış yapılandırması. -- Path traversal ve zararlı dosya upload. -- Brute force login/davet token denemesi. -- Log veya backup içinde secret sızıntısı. -- Eski session'ın parola değişiminden sonra açık kalması. -- SQLite veya upload volume izinlerinin fazla geniş olması. - -### 10.2 Zorunlu kontroller - -- Her service girişinde doğrulanmış session ve rol. -- Her repository mutation'ında `owner_id` veya portal ownership filtresi. -- Login ve token endpoint'lerinde process-local rate limit; reverse proxy rate limit önerisi. -- Form ve JSON body limitleri. -- Upload MIME, magic-byte, boyut ve path kontrolleri. -- Security header'ları: CSP planı, `X-Content-Type-Options`, frame policy, referrer policy. -- Secret'ların yalnızca environment'dan alınması ve Zod ile boot'ta doğrulanması. -- AI key encryption; backup'ın da hassas kabul edilmesi. -- Production loglarında parola, token, cookie, auth header, AI key ve tam prompt bulunmaması. -- Dependency audit ve image vulnerability scan. -- Non-root container user ve yalnızca `/app/data` için write izni. - -Process-local rate limit container restart ile sıfırlanır. Bu küçük self-host hedefi için başlangıç korumasıdır; internete açık kurulumlarda reverse proxy rate limit ayrıca belgelenir. - -## 11. Performans ve ölçek stratejisi - -### 11.1 Önce ölçüm - -Faz 0'da şu referans veri seti hazırlanır: - -- 500 müşteri. -- 1.000 proje. -- 10.000 görev. -- 20.000 finans hareketi. -- 5.000 takvim etkinliği. -- 2.000 journal entry. -- 100 chat session ve 5.000 mesaj. - -Hem tipik küçük veri hem stres fixture'ı tutulur. Ölçümler release ve donanım bilgisiyle kaydedilir. - -### 11.2 Query kuralları - -- `SELECT *` feature sorgularında yasaktır. -- Dashboard ve analytics hesapları SQL aggregate kullanır. -- Pagination default 50, izin verilen max 100 gibi açık limitlere sahiptir. -- Calendar yalnızca görünür tarih aralığını çeker. -- Finance varsayılan olarak dönem aralığı kullanır. -- Chat mesajları cursor ile yüklenir. -- Proje task count için tüm task satırları client'a taşınmaz. -- N+1 ilişkiler join veya toplu `IN` sorgusuyla çözülür. -- 100 ms üzerindeki query development ve production loglarında slow query olarak işaretlenir. - -### 11.3 React/Next.js kuralları - -- Server Component varsayılandır; etkileşim gereken küçük sınırlar Client Component olur. -- Büyük mevcut client dosyaları feature alt bileşenlerine bölünür. -- Liste verisinin ikinci kopyası gereksiz yere client state'e alınmaz. -- Grafik kütüphanesi yalnızca grafik görünen route chunk'ında yüklenir. -- Dialog/form kodu gerekirse lazy yüklenir. -- Next.js Image veya kontrollü image response kullanılmadan büyük original görsel listeye verilmez. -- Cache ancak ölçülmüş ihtiyaca ve doğru tenant anahtarına sahipse eklenir. - -## 12. Deploy ve operasyon tasarımı - -### 12.1 Docker image - -Multi-stage Dockerfile: - -1. Dependency stage: lockfile ile deterministik install. -2. Builder stage: Drizzle migration dosyalarını üretmeden, mevcut commit edilmiş migration'larla `next build`. -3. Runtime stage: standalone server, static/public dosyaları, migration runner ve migration SQL'leri. -4. Non-root user. -5. `/app/data` volume ve port 3000. - -Next config en az şunları içerir: - -- `output: "standalone"`. -- `better-sqlite3` için gerekli server external package ayarı. -- Artık gerek yoksa PWA wrapper'ın kaldırılması. - -Native SQLite modülünün doğru Linux ABI için image içinde kurulup çalıştığı CI Docker smoke testiyle doğrulanır. Host'taki `node_modules` image'a kopyalanmaz. - -### 12.2 Başlangıç sırası - -```text -validate environment -ensure DATA_DIR exists and is writable -acquire migration lock -create pre-migration backup when database exists -apply pending migrations -release lock -start Next.js standalone server -readiness becomes healthy -``` - -Migration başarısızsa server başlamaz. Başarısız migration ile kısmen çalışan uygulama sunulmaz. - -### 12.3 Environment değişkenleri - -Minimum hedef: - -```env -APP_URL=https://neta.example.com -BETTER_AUTH_SECRET=... -APP_ENCRYPTION_KEY=... -DATA_DIR=/app/data -PORT=3000 -HOSTNAME=0.0.0.0 -``` - -Opsiyonel: - -```env -OPENAI_API_KEY= -GOOGLE_GENERATIVE_AI_API_KEY= -GROQ_API_KEY= -LOG_LEVEL=info -MAX_UPLOAD_BYTES=5242880 -TRUSTED_ORIGINS=https://neta.example.com -``` - -`NEXT_PUBLIC_` ile secret tanımlanmaz. Eski Supabase değişkenleri final fazda env şemasından ve tüm deploy dokümanlarından silinir. - -### 12.4 Backup ve restore - -Backup paketi şu içerikleri taşır: - -- SQLite online backup çıktısı. -- `uploads/` ağacı. -- App version, schema version, timestamp ve file checksum içeren manifest. - -Kurallar: - -- Backup temp dosyaya oluşturulur, checksum sonrası atomik olarak final adına taşınır. -- Retention varsayılanı günlük 7, haftalık 4 gibi belgelenir fakat platform sahibi değiştirebilir. -- Aynı disk üzerindeki backup yalnızca hızlı rollback'tir; gerçek felaket kurtarma için dış hedefe kopyalama örneği verilir. -- Restore offline yapılır veya app maintenance moduna alınır. -- Restore önce arşiv checksum'ını ve schema version uyumluluğunu doğrular. -- Her release adayı temiz volume üzerinde restore tatbikatı yapar. - -## 13. Supabase'den veri geçiş stratejisi - -### 13.1 Geliştirme ve üretim ayrımı - -- Mevcut Supabase sürümü redesign boyunca production'da kalır. -- Yeni mimari ayrı branch ve ayrı test deployment'ında geliştirilir. -- İki sistem arasında production dual-write yapılmaz. -- Yeni sistem demo/fixture verisiyle geliştirilir. -- Kesimden önce tam migration en az iki kez prova edilir. - -### 13.2 Export aracı - -Migration-only araç, runtime uygulamasından ayrıdır. Supabase service-role erişimini yalnızca export sırasında kullanır ve final production image'a dahil edilmez. - -Export çıktısı: - -```text -export-YYYYMMDD-HHMMSS/ - manifest.json - auth-users.json - profiles.ndjson - clients.ndjson - projects.ndjson - ... - storage/ - avatars/ - project-assets/ - checksums.txt -``` - -Manifest her tablo için satır sayısı, export zamanı, source app/schema sürümü ve warning listesini içerir. API key gibi hassas alanlar terminale yazılmaz. - -### 13.3 Parola ve session gerçeği - -Supabase kullanıcı parolaları ve aktif session'lar taşınamaz kabul edilmelidir. - -- Freelancer ilk cutover girişinde yeni parola belirler veya güvenli bootstrap token kullanır. -- Client portal kullanıcıları için yeni davet linkleri üretilir. -- Eski session'lar geçersizdir. -- E-posta servisi zorunlu değilse davet/reset linki admin UI'dan bir kez gösterilir ve güvenli kanaldan paylaşılır. -- SMTP daha sonra opsiyonel adapter olabilir. - -### 13.4 Dönüşüm kuralları - -- UUID'ler korunur. -- `user_id`, hedefte `owner_id` olarak haritalanır. -- `client_auth_id`, yeni oluşturulan portal user ID'sine doğrudan taşınmaz; davet süreci sonrası bağlanır. -- PostgreSQL array alanları JSON'a dönüştürülür. -- `numeric` para değerleri minor unit integer'a kontrollü parse edilir. -- Timestamps UTC'ye normalize edilir. -- `done` kanonik task bitiş statüsüdür; `completed` legacy değerleri raporlanıp dönüştürülür. -- `project_planning_sections.category` kanonik alandır. -- Avatar ve project asset dosyaları indirilir, hash'lenir ve `files` metadata kayıtları oluşturulur. -- `document_embeddings` operasyonel DB'ye alınmaz; export arşivinde saklanır. -- AI API key varsa import anında yeni encryption key ile şifrelenir. - -### 13.5 Import doğrulamaları - -- Her tablo için source/export/import satır sayısı. -- Orphan foreign key sayısı sıfır. -- Freelancer bazında toplam income/expense karşılaştırması. -- Proje ve task status dağılımı karşılaştırması. -- Her dosyanın size ve checksum karşılaştırması. -- Portal client bağlantılarının raporu. -- Duplicate email, invoice number ve günlük kayıt çakışma raporu. -- Rastgele seçilmiş en az 20 resource için source-target alan karşılaştırması. - -### 13.6 Cutover akışı - -1. Bakım penceresini duyur. -2. Eski uygulamayı read-only/maintenance moda al. -3. Final export al ve checksum doğrula. -4. Yeni volume için pre-import snapshot al. -5. Import çalıştır. -6. Otomatik sayım ve finans toplamı kontrollerini çalıştır. -7. Freelancer smoke test yapar. -8. DNS/proxy yeni container'a alınır. -9. Readiness ve loglar izlenir. -10. Eski Supabase verisi belirlenen süre boyunca silinmeden read-only tutulur. - -Rollback sınırı: yeni sistemde yazma başladıktan sonra eski sisteme otomatik ters senkronizasyon yoktur. İlk saatlerde rollback gerekirse yeni yazılar export edilip manuel uzlaştırılmalıdır. Bu nedenle cutover sonrası kısa doğrulama penceresinde kritik yazılar sınırlanabilir. - -## 14. Test ve kalite stratejisi - -### 14.1 Test katmanları - -- Unit: para dönüşümü, tarih, validation, permission predicate, progress ve revizyon kotası. -- Repository integration: geçici SQLite dosyası, gerçek migration ve sorgular. -- Service integration: transaction, sahiplik ve hata dönüşümleri. -- Route/Action integration: auth yok, yanlış rol, yanlış owner ve doğru akış. -- E2E: setup, login, core CRUD, portal invite, dosya, AI kapalı modu, backup/restore smoke. -- Visual/responsive: kritik ekranların desktop ve mobile screenshot kontrolleri. -- Docker smoke: boş volume, dolu volume, migration upgrade ve restart. - -### 14.2 Planlanan script'ler - -```text -npm run lint -npm run typecheck -npm run test -npm run test:integration -npm run test:e2e -npm run build -npm run smoke:docker -npm run db:check -npm run backup -npm run restore:verify -- -``` - -### 14.3 CI kapısı - -Her merge için: - -- Lockfile değişikliği incelenir. -- Lint ve typecheck sıfır hata. -- Unit/integration testleri. -- Sıfır DB'den migration. -- Production build. -- Dependency/security audit raporu. - -Release adayı için ayrıca E2E, Docker smoke, upgrade migration, backup/restore ve migration rehearsal gerekir. - -## 15. Faz bazlı uygulama planı - -Her faz kendi kabul kapısını geçmeden sonraki faz “tamamlandı” sayılmaz. Bazı işler paralel geliştirilebilir; veri ve auth sınırını etkileyen işler aynı anda merge edilmemelidir. - -### Faz 0: Baseline, kararların kilitlenmesi ve çalışma güvenliği - -Amaç: Yeniden yazım başlamadan mevcut davranışı, veriyi ve performansı ölçülebilir hale getirmek. - -Yapılacaklar: - -- Kritik kullanıcı akışlarının mevcut ekran kaydı ve beklenen davranış matrisi. -- Supabase tablo/kolon/constraint/policy/RPC/storage envanteri. -- Poyraz component import ve varyant envanteri. -- Aktif, legacy ve kullanılmayan modüllerin sınıflandırılması. -- Referans küçük ve stres seed veri seti. -- Mevcut route/mutation süreleri ve client bundle ölçümü. -- Mevcut bilinen bug'ların regression test tanımına çevrilmesi. -- ADR'lerin repo içinde onaylanması: DB, auth, storage, UI, single-instance, PWA. -- Redesign branch ve release/cutover stratejisinin tanımlanması. -- Eski production için doğrulanmış backup alınması. - -Çıktılar: - -- Baseline raporu. -- Veri sözlüğü ve source-to-target mapping taslağı. -- ADR seti. -- Referans seed. -- Risk kayıt listesi. - -Çıkış kapısı: - -- Mevcut kritik akışlar belgeli. -- Veri kaybı riski taşıyan belirsiz tablo/alan kalmamış. -- Hedef kararlar sahip tarafından onaylı. -- Geri dönülebilir production backup doğrulanmış. - -### Faz 1: Runtime, SQLite ve deploy iskeleti - -Amaç: Feature taşımadan önce yeni platformun boş kurulum, migration, build ve restart davranışını kanıtlamak. - -Yapılacaklar: - -- Drizzle, `better-sqlite3` ve config validation kurulumu. -- DB singleton, PRAGMA ve transaction helper. -- İlk domain/auth migration iskeleti. -- Migration runner ve schema version kontrolü. -- `DATA_DIR` dizin yönetimi. -- Node runtime health/live ve health/ready endpoint'leri. -- Next standalone config. -- Multi-stage Dockerfile ve tek servis Compose. -- Non-root runtime ve volume izinleri. -- İlk backup/restore proof-of-concept. -- Temp SQLite kullanan integration test harness. - -Çıktılar: - -- Boş volume ile çalışan container. -- Restart sonrası veriyi koruyan örnek tablo testi. -- Migration ve health script'leri. -- İlk deploy smoke job'ı. - -Çıkış kapısı: - -- Tek komutla container çalışıyor. -- Migration idempotent. -- Readiness DB bozuk/yazılamaz durumda fail oluyor. -- Restart veriyi kaybetmiyor. -- Native SQLite modülü production image'da çalışıyor. - -### Faz 2: Auth, ilk kurulum ve server-side yetkilendirme - -Amaç: Supabase Auth/RLS'nin yerine güvenli bir uygulama kimlik ve policy katmanı koymak. - -Yapılacaklar: - -- Better Auth + Drizzle SQLite adapter. -- Auth Route Handler. -- `requireSession`, rol ve ownership helper'ları. -- `/setup`, `/login`, logout ve parola değiştirme. -- İlk freelancer oluşturulduktan sonra setup kilidi. -- Session rotation/revocation davranışı. -- Portal invitation token modeli; gerçek portal UI daha sonra. -- Auth event audit log. -- Login/token rate limit ve trusted origin ayarı. -- Cross-user ve cross-role negatif test matrisi. - -Çıktılar: - -- Supabase olmadan çalışan freelancer session'ı. -- Korunan dashboard layout. -- Güvenlik testleri. - -Çıkış kapısı: - -- İkinci public freelancer kaydı yapılamıyor. -- Auth olmayan kullanıcı hiçbir korumalı action/query çalıştıramıyor. -- Client rolü dashboard'a, freelancer portal route'una erişemiyor. -- Session cookie production ayarları doğrulanmış. - -### Faz 3: Neta UI sistemi ve uygulama kabuğu - -Amaç: Poyraz UI'ı feature feature kaldırabilecek sahipli ve erişilebilir bir görsel/etkileşim temeli oluşturmak. - -Yapılacaklar: - -- Semantik CSS token'ları ve typography/spacing/radius sistemi. -- Temel form, button, feedback, overlay, navigation ve data primitive'leri. -- Headless primitive bağımlılığını tek internal katmanda izole etme. -- Dashboard shell, portal shell, auth shell ve responsive navigation. -- Toast, inline error, pending button, route pending ve skeleton standardı. -- Dark mode kapsam kararı; desteklenmiyorsa eski yarım tema kodunu kaldırma. -- Erişilebilirlik testleri: keyboard, focus trap, labels, contrast, reduced motion. -- Poyraz component mapping ve codemod yapılabiliyorsa kontrollü mekanik geçiş. - -Çıktılar: - -- Internal UI component seti. -- Yeni shell ve auth ekranları. -- UI kullanım kuralları. - -Çıkış kapısı: - -- Yeni shell'de doğrudan `poyraz-ui` import yok. -- Primitive'ler desktop/mobile ve keyboard testlerini geçiyor. -- UI token'larında `--poyraz-*` kalmıyor. -- Feature'ların taşıma sırası için mapping tamam. - -### Faz 4: Çekirdek iş akışları - müşteriler, projeler, görevler, takvim - -Amaç: Freelancerın günlük kullandığı ana çalışma döngüsünü yeni DB/service/UI mimarisine taşımak. - -Taşıma sırası: - -1. Clients ve client activities. -2. Projects ve project planning sections. -3. Tasks ve auto project progress. -4. Calendar events. -5. Dashboard core metrics. - -Her feature için: - -- Drizzle schema, constraint ve indeks. -- Repository ve sahiplik filtreleri. -- Zod input/output contract. -- Transaction'lı service. -- Server Component query. -- Server Action mutation. -- Internal UI ile liste/detail/form. -- Pagination/tarih aralığı. -- Loading, empty, error, optimistic ve rollback halleri. -- Unit, integration ve E2E testi. -- Eski Supabase kodunun o feature için silinmesi. - -Özel düzeltmeler: - -- Task status kanoniği `todo|in_progress|done|cancelled` olarak kilitlenir. -- Auto progress aynı transaction'da hesaplanır. -- Planlama alanı `category` ve `sort_order` kullanır. -- Dashboard tüm satırları çekmeden aggregate SQL kullanır. -- Takvim görünür aralık dışında kayıt çekmez. - -Çıkış kapısı: - -- Core CRUD ve dashboard Supabase'siz çalışıyor. -- Cross-owner testleri geçiyor. -- 10.000 task fixture'ında listeler limitli ve index kullanıyor. -- Poyraz UI bu feature dosyalarından kaldırılmış. - -### Faz 5: Finans, iş belgeleri, günlük ve analizler - -Amaç: Para ve raporlama akışlarını doğru veri tipleri ve aggregate sorgularla taşımak. - -Yapılacaklar: - -- Finance transaction'larda minor unit dönüşümü. -- Proposals, contracts, invoices ve subscriptions CRUD/parite denetimi. -- Invoice number uniqueness ve status geçiş kuralları. -- Dönem bazlı finans sorguları ve pagination. -- `journals` + `daily_logs` -> `journal_entries` birleşimi. -- Dashboard/analytics RPC'lerinin tipli SQL query fonksiyonlarına çevrilmesi. -- Para, timezone, tarih ve chart payload testleri. -- CSV export gibi mevcut/istenen çıkışların server-side stream edilmesi. - -Çıkış kapısı: - -- Source fixture ile gelir, gider ve net sonuç kuruş seviyesinde eşit. -- Analytics tüm ham satırları istemciye göndermiyor. -- Günlük legacy verisi kayıpsız temsil edilebiliyor. -- Finans ekranları mobil ve desktop'ta taranabilir. - -### Faz 6: Yerel storage, profil ve proje görselleri - -Amaç: Supabase Storage'ı güvenli yerel dosya servisiyle değiştirmek. - -Yapılacaklar: - -- `files` tablosu ve storage service. -- Avatar upload/replace/delete. -- Proje kapak upload/replace/delete. -- Yetkili file serving Route Handler. -- MIME, magic-byte, boyut, checksum ve path traversal koruması. -- Orphan file tarama/temizleme dry-run komutu. -- Backup/restore içine uploads dahil etme. -- Büyük görsel ve cache header davranışını ölçme. - -Çıkış kapısı: - -- Freelancer başka owner dosyasını okuyamıyor. -- Portal yalnızca kendi projesinin izin verilen görselini görebiliyor. -- Geçersiz/çok büyük dosya diske kalıcı yazılmıyor. -- Replace/delete sonrası orphan oluşmuyor. -- Restore sonrasında tüm fixture dosyaları checksum eşleşiyor. - -### Faz 7: Müşteri portalı, davetler ve revizyonlar - -Amaç: Client rolünü RLS olmadan uçtan uca güvenli ve kolay kullanılır hale getirmek. - -Yapılacaklar: - -- Freelancer tarafından süreli portal daveti üretme/iptal/yenileme. -- Client parola belirleme ve daveti tek kullanımlık tüketme. -- Portal project list/detail, public tasks ve planning sections. -- Revision create/list/status yönetimi. -- Kota kontrolünü server transaction içinde zorunlu tutma. -- Project-client-requester ilişkisinin tek sorguda doğrulanması. -- Portal hesap devre dışı bırakma ve session iptali. -- Portal özel responsive shell ve erişilebilir durumlar. - -Çıkış kapısı: - -- Başka client'ın project/revision ID'siyle hiçbir veri okunamıyor veya yazılamıyor. -- Expired, revoked ve reused davet token'ları reddediliyor. -- Revision quota API/action doğrudan çağrılsa bile aşılamıyor. -- Portal hesabı kapatılınca aktif session erişimi kesiliyor. - -### Faz 8: AI/chat, performans ve UX sertleştirmesi - -Amaç: Kalan harici provider kullanımını opsiyonel, güvenli ve hızlı hale getirirken tüm ürünün hissedilen performansını tamamlamak. - -Yapılacaklar: - -- Chat sessions/messages server repository'ye taşıma; browser Supabase'i kaldırma. -- Provider config ve şifreli API key yönetimi. -- Chat streaming, abort, timeout ve error mapping. -- Finance analysis ve project risk query'lerini kanonik status/modelle düzeltme. -- AI kapalı veya key yok durumunda ürünün eksiksiz çalışması. -- Global route pending, optimistic mutation ve rollback denetimi. -- Büyük Client Component'leri bölme ve bundle analizi. -- Slow query raporu, query plan düzeltmeleri ve index sonlandırma. -- Mobile/touch, klavye ve erişilebilirlik turu. - -Çıkış kapısı: - -- Browser Supabase client kalmıyor. -- AI key hiçbir response/log içinde görünmüyor. -- Provider kapalıyken core app hata vermiyor. -- Referans performans bütçeleri karşılanıyor veya belgeli istisna var. -- Kritik UX akışlarında 100 ms içinde feedback var. - -### Faz 9: Supabase export/import, prova ve cutover hazırlığı - -Amaç: Gerçek production verisini kayıpsız taşıyabileceğimizi kanıtlamak. - -Yapılacaklar: - -- Versioned Supabase export aracı. -- Storage dosya export'u ve checksum. -- İdempotent SQLite import aracı ve dönüşüm raporu. -- Password/session reset ve portal re-invite planı. -- Satır sayısı, FK, finans toplamı ve örnek kayıt karşılaştırma aracı. -- Anonimleştirilmiş production benzeri veriyle en az iki prova. -- Maintenance, DNS, rollback ve iletişim runbook'u. -- Gerçek cutover için süre ölçümü ve disk kapasite hesabı. - -Çıkış kapısı: - -- İki ardışık prova aynı sayım/checksum sonuçlarını veriyor. -- Hiçbir unresolved orphan/duplicate yok veya onaylı dönüşüm kaydı var. -- Cutover süresi kabul edilmiş bakım penceresine sığıyor. -- Parola/davet iletişimi hazır. -- Rollback sorumlusu ve karar eşiği belirli. - -### Faz 10: Tek tuş deploy, operasyon, temizlik ve release - -Amaç: Yeni mimariyi kullanıcıların zahmetsizce kurabildiği ve bakımını yapabildiği final ürün haline getirmek. - -Yapılacaklar: - -- Final Dockerfile/Compose ve image metadata. -- Coolify ve Dokploy adım adım deploy dokümanı. -- Persistent volume, domain, TLS, health check ve replica=1 uyarıları. -- Backup schedule ve dış hedef örnekleri. -- Restore, upgrade ve rollback dokümanı. -- Supabase/Poyraz/Dexie/PWA/duplicate UI dependency kaldırma. -- `supabase/` tarihsel dosyalarını runtime dışı arşivleme veya release sonrası kaldırma kararı. -- README, `.env.example`, mimari, güvenlik ve troubleshooting dokümanlarının yenilenmesi. -- Final dependency audit, license audit ve image scan. -- Gerçek cutover ve gözlem penceresi. - -Çıkış kapısı: - -- Temiz sunucuda repo/image üzerinden tek servis kurulum başarıyla tamamlanıyor. -- Supabase ve Poyraz runtime referansı sıfır. -- Boş kurulum, upgrade, restart, backup ve restore smoke testleri geçiyor. -- README'deki her komut temiz ortamda doğrulanmış. -- Eski production rollback süresi tamamlanmadan silinmiyor. - -## 16. Faz bağımlılıkları ve paralel çalışma - -Temel sıra: - -```text -Faz 0 - -> Faz 1 - -> Faz 2 - -> Faz 3 - -> Faz 4 - -> Faz 5 - -> Faz 6 - -> Faz 7 - -> Faz 8 - -> Faz 9 - -> Faz 10 -``` - -Kontrollü paralellik: - -- Faz 3 UI primitive'leri, Faz 2 auth backend'i stabil olduğunda paralel geliştirilebilir. -- Faz 6 storage service'i, Faz 4'ün project schema'sı kilitlendikten sonra başlayabilir. -- Faz 9 export prototipi Faz 1'den sonra başlayabilir; final mapping Faz 8 bitmeden kilitlenmez. -- Faz 10 deploy dokümanı Faz 1'de taslaklanabilir; final testler tüm feature'lar taşındıktan sonra yapılır. - -Paralel çalışmada aynı anda iki farklı auth veya schema migration seti merge edilmez. - -## 17. Risk kaydı ve azaltma planı - -| Risk | Etki | Olasılık | Azaltma | -| --- | --- | --- | --- | -| SQLite volume kaybı | Kritik | Orta | Persistent volume doğrulaması, otomatik backup, dış kopya, restore tatbikatı | -| Çoklu replica yanlış konfigürasyonu | Yüksek | Orta | Replica=1 dokümanı, readiness/startup kontrolü, deploy template | -| RLS kaldırılırken IDOR | Kritik | Orta | Merkezi authorization helper, owner filtreli repository, negatif test matrisi | -| Supabase parolalarının taşınamaması | Orta | Yüksek | Planlı reset/bootstrap ve portal re-invite iletişimi | -| Native `better-sqlite3` image sorunu | Yüksek | Orta | Aynı Docker image'da build/run ve CI smoke | -| Para dönüşümünde yuvarlama | Kritik | Düşük-Orta | Decimal string parse, minor unit, toplam karşılaştırması | -| Dosya ve DB yedeğinin tutarsız olması | Yüksek | Orta | Manifest/checksum, kontrollü backup, restore testi | -| Büyük tek seferlik rewrite'ın uzaması | Yüksek | Orta | Dikey feature fazları, production'ı eski sürümde tutma, her faz kapısı | -| UI rewrite sırasında davranış kaybı | Orta | Orta | Component mapping, E2E ve ekran karşılaştırması | -| PWA cache'in eski session/veri sunması | Yüksek | Düşük-Orta | İlk release'te PWA kaldırma | -| AI key sızıntısı | Kritik | Düşük-Orta | Server-only erişim, encryption, log redaction, response testi | -| SQLite write lock | Orta | Düşük | WAL, busy timeout, kısa transaction, tek instance, stres testi | -| Migration cutover sonrası rollback | Yüksek | Orta | Maintenance pencere, smoke gate, eski sistemi read-only tutma, yeni yazı uzlaştırma planı | - -## 18. Release için genel Definition of Done - -Yeni self-hosted sürüm ancak aşağıdakilerin tamamı sağlandığında hazır kabul edilir: - -- Core ve portal kullanıcı akışları yeni DB/auth üzerinde çalışıyor. -- Browser bundle içinde DB/auth admin SDK yok. -- Supabase runtime package, env ve kod referansı yok. -- Poyraz UI import ve CSS token referansı yok. -- Tüm domain sorguları server-side ve sahiplik kontrollü. -- Migration'lar boş ve upgrade DB üzerinde başarılı. -- Production Docker image non-root çalışıyor. -- Tek persistent volume restart ve upgrade sonrası veriyi koruyor. -- Backup ile DB ve uploads birlikte geri yüklenebiliyor. -- AI tamamen opsiyonel; key yokken core ürün çalışıyor. -- Lint, typecheck, test, E2E, build ve Docker smoke temiz. -- Kritik desktop/mobile ekranlarda overflow, overlap ve erişilebilirlik bloklayıcısı yok. -- Performans bütçeleri ölçülmüş ve raporlanmış. -- Supabase migration provası tekrarlanabilir. -- Coolify ve Dokploy kurulum dokümanı temiz sunucuda doğrulanmış. -- Güvenlik, upgrade, backup, restore ve troubleshooting dokümanları güncel. - -## 19. Uygulama yaklaşımı - -En güvenli geliştirme yaklaşımı, eski production'ı yerinde tutup yeni mimariyi ayrı release hattında tamamlamaktır. Auth veya DB için geçici production dual-write yapılmamalıdır. Her feature yeni repository/service/UI katmanına tam geçtiğinde eski implementation o feature'dan kaldırılmalı ve faz checklist'i kanıtlarla kapatılmalıdır. - -İlk uygulama işi Faz 0 checklist'ini doldurmak ve ADR'leri onaylamak olmalıdır. Sonraki ilk teknik spike, boş volume üzerinde Next.js standalone + Better Auth + Drizzle + SQLite container'ının kurulup restart/migration davranışının kanıtlanmasıdır. Bu spike başarısız olursa feature rewrite'a başlamadan veritabanı veya auth kararı yeniden değerlendirilir. diff --git a/docs/19-self-hosted-redesign-checklist.md b/docs/19-self-hosted-redesign-checklist.md deleted file mode 100644 index 6d7d3f6..0000000 --- a/docs/19-self-hosted-redesign-checklist.md +++ /dev/null @@ -1,1463 +0,0 @@ ---- -title: Self-Hosted Redesign Faz Checklist'i -description: Supabase ve Poyraz UI'dan ayrılma çalışmasında her fazın sonunda tamamlanması, kanıtlanması ve onaylanması gereken ayrıntılı kontrol listesi. -order: 19 -status: active-template -last_updated: 2026-07-10 ---- - -# Neta Self-Hosted Redesign Faz Checklist'i - -## 1. Kullanım kuralları - -Bu checklist, [18-self-hosted-redesign-plani.md](./18-self-hosted-redesign-plani.md) içindeki Faz 0-10 ile bire bir eşleşir. Bir fazın kodu yazılmış olsa bile ilgili çıkış kapısının tüm bloklayıcı maddeleri tamamlanmadan faz kapatılmaz. - -İşaretleme standardı: - -- `[ ]`: Henüz doğrulanmadı. -- `[x]`: Doğrulandı ve kanıt bağlantısı/notu eklendi. -- `N/A - gerekçe`: Bu kurulum veya faz için uygulanamaz; gerekçe zorunludur. - -Her faz tamamlandığında aşağıdaki kayıt başlığı doldurulur: - -```text -Faz: -Tamamlanma tarihi: -Sorumlu: -İncelenen commit/tag: -Test ortamı: -Test veri seti: -Kanıt klasörü/PR bağlantısı: -Açık istisnalar: -Rollback referansı: -Onaylayan: -``` - -Kanıt olarak yalnızca “çalışıyor” notu yeterli değildir. İlgili maddeye göre komut çıktısı, test adı, ekran görüntüsü, ölçüm tablosu, migration raporu, checksum veya restore kaydı eklenmelidir. Secret, cookie, parola, davet token'ı ve AI API key kanıta dahil edilmez. - -## 2. Her faz için ortak kalite kapısı - -Bu bölüm her faz sonunda yeniden uygulanır. - -### 2.1 Kapsam ve kod bütünlüğü - -- [ ] Fazın plan dokümanındaki amacı ve kapsamı PR/release notunda yazıyor. -- [ ] Faz dışı davranış değişiklikleri ayrı kayda alınmış veya kapsamdan çıkarılmış. -- [ ] Yeni kod mevcut feature sınırlarına uygun; geçici kod için açık takip kaydı var. -- [ ] Aynı feature içinde iki farklı veri yolu veya auth yolu bırakılmamış. -- [ ] Client Component içine server-only modül, DB client, filesystem veya secret import edilmemiş. -- [ ] Yeni environment değişkenleri `.env.example` ve config validation şemasına eklenmiş. -- [ ] Secret değişkenlere `NEXT_PUBLIC_` prefix'i verilmemiş. -- [ ] Yeni dependency'nin amacı, lisansı ve runtime etkisi incelenmiş. -- [ ] Kullanılmayan import, dosya, flag ve geçici debug log bırakılmamış. -- [ ] Kullanıcı verisi veya secret loglayan kod bulunmadığı doğrulanmış. - -### 2.2 Statik kalite - -- [ ] `npm run lint` sıfır hata ile tamamlandı. -- [ ] `npm run typecheck` sıfır hata ile tamamlandı. -- [ ] `any`, non-null assertion ve type cast kullanımları gerekçeli veya kaldırılmış. -- [ ] Status/role/category değerleri kanonik type'tan geliyor; serbest string tekrarı yok. -- [ ] Validation schema ile TypeScript contract birbirinden kopuk değil. -- [ ] Production build warning'leri incelenmiş ve yeni kritik warning yok. - -### 2.3 Test ve build - -- [ ] Fazın unit testleri geçti. -- [ ] Fazın integration testleri geçti. -- [ ] Değişen kritik akışların negatif testleri geçti. -- [ ] `npm run build` geçti. -- [ ] Temiz veritabanında migration + seed + test geçti. -- [ ] Bir önceki fazın veritabanından upgrade migration testi geçti. -- [ ] İlgili E2E smoke akışları geçti. -- [ ] Testler local timezone veya çalışma sırasına bağımlı değil. - -### 2.4 Güvenlik - -- [ ] Auth olmayan kullanıcı için yeni query/mutation reddediliyor. -- [ ] Yanlış role sahip kullanıcı için yeni query/mutation reddediliyor. -- [ ] Başka owner'a ait bilinen UUID ile erişim testi reddediliyor. -- [ ] Input boyutu ve biçimi server sınırında doğrulanıyor. -- [ ] Ham DB hatası veya stack trace kullanıcıya dönmüyor. -- [ ] Log redaction kontrolü yapıldı. -- [ ] Yeni endpoint'in rate limit ihtiyacı değerlendirildi. -- [ ] CSRF/origin/cookie etkisi değerlendirildi. - -### 2.5 UX ve erişilebilirlik - -- [ ] Primary action tıklamasından sonra 100 ms içinde feedback var. -- [ ] Pending sırasında çift submit engelleniyor. -- [ ] Hata sonrası kullanıcı verisi gereksiz yere kaybolmuyor. -- [ ] Empty, loading, success ve error durumları mevcut. -- [ ] Klavye ile temel akış tamamlanabiliyor. -- [ ] Focus görünür ve overlay kapanınca mantıklı yere dönüyor. -- [ ] Form alanlarının label ve hata bağlantıları doğru. -- [ ] 320 px mobil, tablet ve desktop görünümü kontrol edildi. -- [ ] Metin, buton, badge ve tablo içeriklerinde taşma/çakışma yok. -- [ ] Reduced-motion davranışı kontrol edildi. - -### 2.6 Operasyon ve dokümantasyon - -- [ ] Yeni migration commit edilmiş ve sırası doğru. -- [ ] Backup/restore etkisi değerlendirildi. -- [ ] Health/readiness davranışı bozulmadı. -- [ ] Docker image build ve restart smoke geçti. -- [ ] İlgili kullanıcı ve operasyon dokümanı güncellendi. -- [ ] Bilinen risk veya ertelenen iş issue/backlog kaydında. -- [ ] Rollback yöntemi yazılı ve uygulanabilir. - -## 3. Faz 0 - Baseline, kararlar ve çalışma güvenliği - -Faz: -Faz 0 - Baseline, kararlar ve çalışma güvenliği -Tamamlanma tarihi: -Kısmi local baseline: 2026-07-10 -Sorumlu: -Codex -İncelenen commit/tag: -Çalışma ağacı; Faz 0 dokümanları henüz commit edilmedi -Test ortamı: -Local Windows/PowerShell workspace -Test veri seti: -Production Supabase export yok; seed stratejisi [phase-0-fixtures.md](./self-hosted-redesign/phase-0-fixtures.md) -Kanıt klasörü/PR bağlantısı: -[phase-0-baseline.md](./self-hosted-redesign/phase-0-baseline.md), [phase-0-data-mapping.md](./self-hosted-redesign/phase-0-data-mapping.md), [phase-0-adrs.md](./self-hosted-redesign/phase-0-adrs.md), [phase-0-regression-and-spike.md](./self-hosted-redesign/phase-0-regression-and-spike.md) -Açık istisnalar: -Production backup/export, storage ölçümü, gerçek ekran kayıtları ve production performans ölçümü bekliyor -Rollback referansı: -Dokümantasyon değişikliği; app runtime değişmedi -Onaylayan: -Ürün sahibi onayı bekliyor - -### 3.1 Repo ve bağımlılık envanteri - -- [x] Tüm route'lar ve route group'lar listelendi. Kanıt: [phase-0-baseline.md](./self-hosted-redesign/phase-0-baseline.md#route-envanteri) -- [x] Tüm Server Action dosyaları listelendi. Kanıt: [phase-0-baseline.md](./self-hosted-redesign/phase-0-baseline.md#route-envanteri) -- [x] Tüm Route Handler'lar listelendi. Kanıt: [phase-0-baseline.md](./self-hosted-redesign/phase-0-baseline.md#route-envanteri) -- [x] Browser Supabase client kullanan dosyalar listelendi. Kanıt: [phase-0-baseline.md](./self-hosted-redesign/phase-0-baseline.md#supabase-kullanım-envanteri) -- [x] Server Supabase client kullanan dosyalar listelendi. Kanıt: [phase-0-baseline.md](./self-hosted-redesign/phase-0-baseline.md#supabase-kullanım-envanteri) -- [x] Service-role client kullanan dosyalar listelendi. Kanıt: [phase-0-baseline.md](./self-hosted-redesign/phase-0-baseline.md#supabase-kullanım-envanteri) -- [x] Tüm `poyraz-ui` import'ları dosya ve import edilen component bazında listelendi. Kanıt: [phase-0-baseline.md](./self-hosted-redesign/phase-0-baseline.md#poyraz-ui-import-envanteri) -- [x] Internal `components/ui` bileşenlerinin aktif/kullanılmayan durumu belirlendi. Kanıt: [phase-0-baseline.md](./self-hosted-redesign/phase-0-baseline.md#internal-ui-durumu) -- [x] Kullanılmayan Dexie/IndexedDB kodu doğrulandı. Kanıt: [phase-0-baseline.md](./self-hosted-redesign/phase-0-baseline.md#dexieindexeddb-ve-pwa-baseline) -- [x] PWA service worker'ın cache kapsamı kaydedildi. Kanıt: [phase-0-baseline.md](./self-hosted-redesign/phase-0-baseline.md#dexieindexeddb-ve-pwa-baseline) -- [x] Package dependency'leri “kalacak/kaldırılacak/değerlendirilecek” olarak sınıflandırıldı. Kanıt: [phase-0-baseline.md](./self-hosted-redesign/phase-0-baseline.md#dependency-sınıflandırması) -- [x] Her kaldırılacak paketin replacement veya kaldırma gerekçesi yazıldı. Kanıt: [phase-0-baseline.md](./self-hosted-redesign/phase-0-baseline.md#dependency-sınıflandırması) - -### 3.2 Veri envanteri - -- [x] Supabase `auth.users` kullanım amacı belgelendi. Kanıt: [phase-0-data-mapping.md](./self-hosted-redesign/phase-0-data-mapping.md#source-to-target-mapping) -- [x] `profiles` kolonları ve role değerleri belgelendi. Kanıt: [phase-0-data-mapping.md](./self-hosted-redesign/phase-0-data-mapping.md#enumstatus-baseline) -- [x] `clients` ve portal user ilişkisi belgelendi. Kanıt: [phase-0-data-mapping.md](./self-hosted-redesign/phase-0-data-mapping.md#source-to-target-mapping) -- [x] `projects` kolonları, status/type/progress kuralları belgelendi. Kanıt: [phase-0-data-mapping.md](./self-hosted-redesign/phase-0-data-mapping.md#enumstatus-baseline) -- [ ] `tasks` kolonları ve bütün status değerleri production verisinden sayıldı. Bekliyor: production audit sorgusu [phase-0-data-mapping.md](./self-hosted-redesign/phase-0-data-mapping.md#production-audit-sorguları) -- [x] `calendar_events` type değerleri sayıldı. Kanıt: [phase-0-data-mapping.md](./self-hosted-redesign/phase-0-data-mapping.md#enumstatus-baseline) -- [ ] `finance_transactions` currency/type/payment status dağılımı sayıldı. Bekliyor: production audit sorgusu [phase-0-data-mapping.md](./self-hosted-redesign/phase-0-data-mapping.md#production-audit-sorguları) -- [ ] Proposal/contract/invoice/subscription status dağılımları sayıldı. Bekliyor: production audit sorgusu [phase-0-data-mapping.md](./self-hosted-redesign/phase-0-data-mapping.md#production-audit-sorguları) -- [ ] `journals` ve `daily_logs` satırları, tarih çakışmaları ve boş alanları raporlandı. Bekliyor: production export -- [ ] `project_planning_sections` category değerleri ve yanlış/legacy değerler raporlandı. Bekliyor: production audit; schema enum belgelendi -- [ ] `project_revisions` kota ve status verisi raporlandı. Bekliyor: production audit -- [ ] `chat_sessions`/`chat_messages` büyüklüğü raporlandı. Bekliyor: production audit -- [ ] `document_embeddings` aktif kullanım ve satır sayısı doğrulandı. Bekliyor: production audit -- [ ] `app_settings.api_key` dolu kayıtları sayıldı; değerler loglanmadı. Bekliyor: production audit; sorgu secret değer döndürmüyor -- [ ] Avatar bucket dosya sayısı ve toplam boyut ölçüldü. Bekliyor: Supabase storage audit -- [ ] Project-assets bucket dosya sayısı ve toplam boyut ölçüldü. Bekliyor: Supabase storage audit -- [ ] Storage metadata ile DB path referansları arasındaki orphan kayıtlar raporlandı. Bekliyor: Supabase storage audit -- [x] Her tablonun PK, FK, unique, check, trigger ve index listesi çıkarıldı. Kanıt: [phase-0-data-mapping.md](./self-hosted-redesign/phase-0-data-mapping.md#production-audit-sorguları) -- [x] Tüm RLS policy'leri resource ve operation bazında matrise işlendi. Kanıt: [phase-0-data-mapping.md](./self-hosted-redesign/phase-0-data-mapping.md#rls-policy-matrix) -- [x] Dashboard ve analytics RPC input/output sözleşmesi kaydedildi. Kanıt: [phase-0-baseline.md](./self-hosted-redesign/phase-0-baseline.md#supabase-kullanım-envanteri), `supabase/migrations/0012_add_analytics_rpcs.sql` - -### 3.3 Davranış baseline'ı - -- [ ] İlk admin setup akışı ekran ve adımlarıyla kaydedildi. Bekliyor: ekran kaydı; akış matrisi hazır [phase-0-regression-and-spike.md](./self-hosted-redesign/phase-0-regression-and-spike.md#behavior-smoke-matrix) -- [ ] Login/logout/parola değiştirme akışı kaydedildi. Bekliyor: ekran kaydı -- [ ] Client portal hesabı oluşturma akışı kaydedildi. Bekliyor: ekran kaydı -- [ ] Client create/edit/archive/delete akışları kaydedildi. Bekliyor: ekran kaydı -- [ ] Project create/edit/status/progress/plan akışları kaydedildi. Bekliyor: ekran kaydı -- [ ] Task create/edit/status/drag/drop/delete akışları kaydedildi. Bekliyor: ekran kaydı -- [ ] Calendar create/edit/delete ve tarih görünümü kaydedildi. Bekliyor: ekran kaydı -- [ ] Finance create/edit/delete/filter akışları kaydedildi. Bekliyor: ekran kaydı -- [ ] Proposal, contract, invoice ve subscription mevcut davranışı kaydedildi. Bekliyor: ekran kaydı -- [ ] Journal create/edit/delete akışı kaydedildi. Bekliyor: ekran kaydı -- [ ] Analytics tarih filtresi ve hesap sonuçları kaydedildi. Bekliyor: ekran kaydı -- [ ] AI chat session/message akışı kaydedildi. Bekliyor: ekran kaydı -- [ ] Finance analysis ve project risk davranışı kaydedildi. Bekliyor: ekran kaydı -- [ ] Profile/avatar/API key ayar akışları kaydedildi. Bekliyor: ekran kaydı -- [ ] Portal project/task/revision akışları kaydedildi. Bekliyor: ekran kaydı - -### 3.4 Bilinen problem baseline'ı - -- [x] Portal planlama `order_index`/`sort_order` problemi regression test maddesine çevrildi. Kanıt: REG-001 [phase-0-regression-and-spike.md](./self-hosted-redesign/phase-0-regression-and-spike.md#regression-test-backlog) -- [x] Project risk `completed`/`done` problemi regression test maddesine çevrildi. Kanıt: REG-002 [phase-0-regression-and-spike.md](./self-hosted-redesign/phase-0-regression-and-spike.md#regression-test-backlog) -- [x] Portal plan `type`/`category` problemi regression test maddesine çevrildi. Kanıt: REG-003 [phase-0-regression-and-spike.md](./self-hosted-redesign/phase-0-regression-and-spike.md#regression-test-backlog) -- [x] Revision quota server enforcement eksikliği regression test maddesine çevrildi. Kanıt: REG-004 [phase-0-regression-and-spike.md](./self-hosted-redesign/phase-0-regression-and-spike.md#regression-test-backlog) -- [x] Portal revision project/client ilişki açığı negatif test maddesine çevrildi. Kanıt: REG-005 [phase-0-regression-and-spike.md](./self-hosted-redesign/phase-0-regression-and-spike.md#regression-test-backlog) -- [x] Mevcut lint hata/uyarı listesi arşivlendi. Kanıt: `npm.cmd run lint` sonucu 34 error, 25 warning; özet [phase-0-baseline.md](./self-hosted-redesign/phase-0-baseline.md#local-doğrulama-sonuçları) -- [x] `select("*")`, limitsiz liste ve N+1 adayları kaydedildi. Kanıt: [phase-0-baseline.md](./self-hosted-redesign/phase-0-baseline.md#performans-baseline) -- [x] Pending/optimistic/rollback eksiği olan mutation'lar listelendi. Kanıt: [phase-0-baseline.md](./self-hosted-redesign/phase-0-baseline.md#davranış-baseline-matrisi) - -### 3.5 Performans baseline'ı - -- [ ] Referans test donanımı CPU/RAM/disk/Node sürümüyle kaydedildi. Kısmi: Node/npm/CPU identifier/logical processor/disk root kaydedildi; RAM bilgisi sandbox WMI/CIM erişimi nedeniyle alınamadı. Kanıt: [phase-0-baseline.md](./self-hosted-redesign/phase-0-baseline.md#local-doğrulama-sonuçları) -- [ ] Küçük fixture veri seti üretildi. Bekliyor: Drizzle schema sonrası gerçek seed; kapsam [phase-0-fixtures.md](./self-hosted-redesign/phase-0-fixtures.md#küçük-fixture-kapsamı) -- [ ] Stres fixture veri seti üretildi. Bekliyor: Drizzle schema sonrası gerçek seed; kapsam [phase-0-fixtures.md](./self-hosted-redesign/phase-0-fixtures.md#stres-fixture-kapsamı) -- [ ] Dashboard server süresi ve payload ölçüldü. Bekliyor: local/prod running environment -- [ ] Projects list/detail süreleri ölçüldü. Bekliyor: local/prod running environment -- [ ] Tasks list/kanban süreleri ölçüldü. Bekliyor: local/prod running environment -- [ ] Clients list/detail süreleri ölçüldü. Bekliyor: local/prod running environment -- [ ] Finance ve analytics süreleri ölçüldü. Bekliyor: local/prod running environment -- [ ] Portal list/detail süreleri ölçüldü. Bekliyor: local/prod running environment -- [ ] Ana route client JS boyutları kaydedildi. Bekliyor: production build analyze çıktısı -- [ ] En yavaş on DB/network işlemi kaydedildi. Bekliyor: running environment instrumentation -- [ ] Kullanıcı tıklaması ile ilk feedback arasındaki süre örnek akışlarda ölçüldü. Bekliyor: ekran kaydı veya Playwright ölçümü - -### 3.6 ADR ve kapsam onayı - -- [x] SQLite + `better-sqlite3` kararı onaylandı. Kanıt: ADR-0001 [phase-0-adrs.md](./self-hosted-redesign/phase-0-adrs.md#adr-0001-sqlite--better-sqlite3) -- [x] Drizzle schema/migration kararı onaylandı. Kanıt: ADR-0002 [phase-0-adrs.md](./self-hosted-redesign/phase-0-adrs.md#adr-0002-drizzle-orm-ve-kaynak-kontrollü-migration) -- [x] Better Auth kararı onaylandı. Kanıt: ADR-0003 [phase-0-adrs.md](./self-hosted-redesign/phase-0-adrs.md#adr-0003-better-auth) -- [x] Tek instance kısıtı onaylandı. Kanıt: ADR-0001 [phase-0-adrs.md](./self-hosted-redesign/phase-0-adrs.md#adr-0001-sqlite--better-sqlite3) -- [x] Yerel filesystem storage kararı onaylandı. Kanıt: ADR-0005 [phase-0-adrs.md](./self-hosted-redesign/phase-0-adrs.md#adr-0005-yerel-filesystem-storage) -- [x] Internal UI + tek headless primitive kararı onaylandı. Kanıt: ADR-0006 [phase-0-adrs.md](./self-hosted-redesign/phase-0-adrs.md#adr-0006-internal-neta-ui) -- [x] İlk release'te PWA/offline sync kaldırma kararı onaylandı. Kanıt: ADR-0007 [phase-0-adrs.md](./self-hosted-redesign/phase-0-adrs.md#adr-0007-pwaoffline-sync-ilk-release-kapsam-dışı) -- [x] Embedding'leri operasyonel hedefe taşımama kararı onaylandı. Kanıt: ADR-0008 [phase-0-adrs.md](./self-hosted-redesign/phase-0-adrs.md#adr-0008-embeddings-operasyonel-hedefe-taşınmayacak) -- [x] Para için minor unit standardı onaylandı. Kanıt: ADR-0009 [phase-0-adrs.md](./self-hosted-redesign/phase-0-adrs.md#adr-0009-para-integer-minor-unit) -- [x] `journals`/`daily_logs` birleşim kuralı onaylandı. Kanıt: ADR-0010 [phase-0-adrs.md](./self-hosted-redesign/phase-0-adrs.md#adr-0010-journals--daily_logs-birleşimi) -- [x] Production dual-write yapmama kararı onaylandı. Kanıt: ADR-0011 [phase-0-adrs.md](./self-hosted-redesign/phase-0-adrs.md#adr-0011-production-dual-write-yok) -- [x] Vercel'in yerel SQLite hedef deploy'u olmadığı açıkça kabul edildi. Kanıt: ADR-0012 [phase-0-adrs.md](./self-hosted-redesign/phase-0-adrs.md#adr-0012-vercel-hedef-deploy-değil) - -### 3.7 Faz 0 çıkış kapısı - -- [ ] Production Supabase backup'ı alındı. Bekliyor: production Supabase erişimi -- [ ] Backup'ın erişilebilirliği ve restore prosedürü doğrulandı. Bekliyor: production backup -- [ ] Source-to-target veri mapping taslağında sahipsiz alan yok. Bekliyor: production audit sonrası son kontrol; taslak [phase-0-data-mapping.md](./self-hosted-redesign/phase-0-data-mapping.md) -- [ ] Kritik akış matrisi ürün sahibi tarafından onaylandı. Bekliyor: ürün sahibi onayı; matris [phase-0-regression-and-spike.md](./self-hosted-redesign/phase-0-regression-and-spike.md#behavior-smoke-matrix) -- [x] ADR'ler onaylandı. Kanıt: [phase-0-adrs.md](./self-hosted-redesign/phase-0-adrs.md) -- [ ] Baseline raporu commit edildi. Bekliyor: kullanıcı commit talimatı veya ayrı commit -- [x] Faz 1 spike'ının başarı/başarısızlık ölçütleri yazıldı. Kanıt: [phase-0-regression-and-spike.md](./self-hosted-redesign/phase-0-regression-and-spike.md#faz-1-spike-kabul-kriterleri) -- [x] Faz 0 istisna listesi boş veya açıkça onaylı. Kanıt: [phase-0-baseline.md](./self-hosted-redesign/phase-0-baseline.md#faz-0-istisnaları) - -## 4. Faz 1 - Runtime, SQLite ve deploy iskeleti - -Faz: -Faz 1 - Runtime, SQLite ve deploy iskeleti -Tamamlanma tarihi: -Kısmi local runtime: 2026-07-10 -Sorumlu: -Codex -İncelenen commit/tag: -Çalışma ağacı; Faz 1 dosyaları henüz commit edilmedi -Test ortamı: -Local Windows/PowerShell workspace, Next dev server `127.0.0.1:3010` -Test veri seti: -Temp SQLite smoke data dir; production data kullanılmadı -Kanıt klasörü/PR bağlantısı: -[phase-1-runtime.md](./self-hosted-redesign/phase-1-runtime.md) -Açık istisnalar: -Docker daemon kapalı olduğu için Docker build/up/native SQLite container smoke ve container restart persistence testleri çalıştırılamadı -Rollback referansı: -Faz 1 henüz production'a alınmadı; yeni runtime dosyaları ve dependency ekleri geri alınabilir -Onaylayan: -Ürün sahibi onayı bekliyor - -### 4.1 Environment ve config - -- [x] Server config tek modülde Zod ile parse ediliyor. Kanıt: `server/config.ts`, [phase-1-runtime.md](./self-hosted-redesign/phase-1-runtime.md#config-davranışı) -- N/A - Eksik `DATA_DIR` boot hatası üretmiyor; Faz 1 kararı olarak development/test için `.data`, production için `/app/data` fallback kullanılıyor. Kanıt: [phase-1-runtime.md](./self-hosted-redesign/phase-1-runtime.md#config-davranışı) -- [x] Relative/absolute data path davranışı belgelendi. Kanıt: [phase-1-runtime.md](./self-hosted-redesign/phase-1-runtime.md#config-davranışı) -- [x] Production `DATA_DIR=/app/data` varsayımı doğrulandı. Kanıt: `Dockerfile`, `docker-compose.yml`, [phase-1-runtime.md](./self-hosted-redesign/phase-1-runtime.md#docker-durumu) -- [x] Uygulama data dizinini kontrollü oluşturuyor. Kanıt: `ensureDataDirectories`, `ensureDataLayout`, `npm.cmd run phase1:smoke` -- [ ] Data dizini yazılamazsa readiness fail ve server boot davranışı tanımlı. Kısmi: readiness kodu yazılabilirlik probe'u içeriyor; negatif permission testi Docker/OS seviyesinde henüz çalıştırılmadı. -- [x] Env doğrulama çıktısı secret değer göstermiyor. Kanıt: config modülü env dump/log üretmiyor. -- [x] Test environment kendi geçici data dizinini kullanıyor. Kanıt: `npm.cmd run phase1:smoke` - -### 4.2 SQLite client - -- [x] Tek process için singleton connection uygulanmış. Kanıt: `server/db/client.ts` -- [x] Development hot reload duplicate connection oluşturmuyor. Kanıt: `globalThis.__netaSqliteConnection` kullanımı -- [x] `foreign_keys=ON` doğrulanmış. Kanıt: `applyPragmas`, smoke migration -- [x] `journal_mode=WAL` doğrulanmış. Kanıt: `applyPragmas`, smoke migration -- [x] `synchronous=NORMAL` doğrulanmış. Kanıt: `applyPragmas` -- [x] `busy_timeout=5000` veya onaylı değer uygulanmış. Kanıt: `applyPragmas` -- [ ] DB açılış hatası güvenli şekilde loglanıyor. Bekliyor: structured logger/redaction katmanı Faz 8'e yakın netleştirilecek. -- [ ] Graceful process kapanış davranışı test edilmiş. Kısmi: `beforeExit` close handler var; process signal/container stop testi Docker daemon kapalı olduğu için çalıştırılamadı. -- [x] Transaction helper nested transaction kullanımını açıkça ele alıyor. Kanıt: `server/db/transaction.ts` -- N/A - Uzun network/filesystem operasyonunun transaction içine alınmadığı code review ile doğrulanmış. Faz 1'de domain transaction kullanan network/filesystem operasyonu yok. - -### 4.3 Drizzle migration - -- [x] Drizzle config yalnızca server dosyalarını işaret ediyor. Kanıt: `drizzle.config.ts` -- [ ] İlk migration commit edildi. Bekliyor: kullanıcı commit talimatı; migration dosyası üretildi. -- [x] Migration journal/schema version takip ediliyor. Kanıt: `server/db/migrations/meta/_journal.json` -- [x] Sıfır byte yeni DB'ye migration uygulanabiliyor. Kanıt: `npm.cmd run phase1:smoke` -- [x] Migration ikinci kez çalıştırıldığında veri veya şema bozulmuyor. Kanıt: `npm.cmd run db:migrate` ikinci çalışma başarılı -- [ ] Yarım/başarısız migration senaryosu kontrollü fail ediyor. Bekliyor: negatif migration fixture/test -- [x] Production'da `drizzle-kit push` kullanılmıyor. Kanıt: package scripts ve Docker startup yalnızca `scripts/migrate.mjs` -- [x] Migration SQL'i code review'da constraint/index açısından incelendi. Kanıt: `server/db/migrations/0000_wise_reaper.sql` -- [x] Migration dosyaları Docker runtime image içinde bulunuyor. Kanıt: `Dockerfile` copy step -- [x] Uygulama request alırken migration çalıştırmıyor. Kanıt: migration yalnızca script/Docker CMD içinde - -### 4.4 Health endpoint'leri - -- [x] `/api/health/live` DB kapalı olsa da process durumunu doğru veriyor. Kanıt: endpoint DB import etmiyor; local HTTP 200 [phase-1-runtime.md](./self-hosted-redesign/phase-1-runtime.md#health-endpoint-sonuçları) -- [x] `/api/health/ready` `SELECT 1` çalıştırıyor. Kanıt: `server/db/health.ts`, local HTTP 200 -- [ ] Readiness bekleyen migration varsa healthy dönmüyor. Kısmi: `runtime_checks` table check var; negatif HTTP testi henüz çalıştırılmadı. -- [ ] Readiness data dizini yazılamazsa healthy dönmüyor. Kısmi: write probe var; permission negatif testi çalıştırılmadı. -- [x] Health response secret/path/schema detayı sızdırmıyor. Kanıt: local response body [phase-1-runtime.md](./self-hosted-redesign/phase-1-runtime.md#health-endpoint-sonuçları) -- [x] Health endpoint auth gerektirmiyor fakat pahalı işlem yapmıyor. Kanıt: unauthenticated local HTTP 200; readiness sadece write probe + `SELECT 1` + table check -- [x] Platform health interval/timeout/retry değerleri belgelendi. Kanıt: `docker-compose.yml` healthcheck - -### 4.5 Dockerfile ve Compose - -- [x] Multi-stage Dockerfile kullanılıyor. Kanıt: `Dockerfile` -- [x] Install lockfile'a bağlı ve deterministik. Kanıt: `npm ci` Docker deps stage -- [x] Host `node_modules` image'a kopyalanmıyor. Kanıt: `.dockerignore` -- [x] `next.config` standalone output üretiyor. Kanıt: `next.config.ts`, `npm.cmd run build` -- [x] Standalone server, `public` ve `.next/static` doğru kopyalanıyor. Kanıt: `Dockerfile` -- [ ] `better-sqlite3` Linux runtime'da yükleniyor. Bekliyor: Docker daemon kapalı olduğu için container smoke çalıştırılamadı. -- [x] Runtime image gereksiz build tool taşımıyor. Kanıt: runtime stage `node:22-bookworm-slim`, build deps ayrı stage'de. -- [x] Container non-root user ile çalışıyor. Kanıt: `USER nextjs` -- [ ] Yalnızca `/app/data` yazılabilir olacak şekilde izinler test edildi. Kısmi: Dockerfile yalnızca `/app/data` ownership veriyor; container test çalışmadı. -- [x] Port ve hostname platformla uyumlu. Kanıt: `PORT=3000`, `HOSTNAME=0.0.0.0` -- [x] Compose tek application service içeriyor. Kanıt: `docker-compose.yml` -- [x] Compose named/bind volume açıkça tanımlı. Kanıt: `neta-data:/app/data` -- [x] Compose healthcheck readiness endpoint'ini kullanıyor. Kanıt: `docker-compose.yml` -- [x] Restart policy belgelendi. Kanıt: `restart: unless-stopped` -- [x] Replica sayısının 1 olması compose/deploy dokümanına yazıldı. Kanıt: [phase-1-runtime.md](./self-hosted-redesign/phase-1-runtime.md#docker-durumu) - -### 4.6 Persistence ve restart testleri - -- [ ] Boş volume ile container ilk boot tamamlandı. Bekliyor: Docker daemon kapalı. -- [x] Test kaydı yazıldı. Kanıt: `npm.cmd run phase1:smoke` -- [ ] Container normal restart edildi ve kayıt korundu. Kısmi local equivalent: DB reopen persistence smoke geçti; container restart bekliyor. -- [ ] Image yeniden build edilip aynı volume ile başlatıldı ve kayıt korundu. Bekliyor: Docker daemon kapalı. -- [ ] Container silinip volume korunarak yeniden oluşturuldu ve kayıt korundu. Bekliyor: Docker daemon kapalı. -- [x] Volume olmadan yapılan yanlış deploy'un veri kaybı riski dokümante edildi. Kanıt: [phase-1-runtime.md](./self-hosted-redesign/phase-1-runtime.md#docker-durumu) -- [x] İki instance aynı volume'a bağlandığında desteklenmediği açıkça test/dokümante edildi. Kanıt: [phase-1-runtime.md](./self-hosted-redesign/phase-1-runtime.md#docker-durumu); runtime multi-instance testi yapılmadı. - -### 4.7 Backup/restore proof-of-concept - -- [x] SQLite online backup yöntemi kullanılıyor; açık DB dosyası kör kopyalanmıyor. Kanıt: `scripts/backup.mjs` -- [ ] Backup manifest app/schema sürümünü içeriyor. Kısmi: manifest dosya listesi/checksum içeriyor; app/schema sürümü henüz eklenmedi. -- [x] Backup checksum üretiyor. Kanıt: `manifest.json` SHA-256 üretimi, `npm.cmd run phase1:smoke` -- [x] Boş target dizine restore edilebiliyor. Kanıt: `npm.cmd run phase1:smoke` -- [ ] Restore checksum hatasında duruyor. Bekliyor: manifest checksum validation implementasyonu -- [x] Restore üzerine yazmadan önce mevcut data için koruma/onay mekanizması var. Kanıt: `scripts/restore.mjs` `--force` guard -- [x] Restore sonrası migration version okunabiliyor. Kanıt: restore smoke `runtime_checks` row okuyor - -### 4.8 Faz 1 çıkış kapısı - -- [ ] `docker compose up` ile temiz kurulum healthy oldu. Bekliyor: Docker daemon kapalı. -- [x] Sıfır DB ve upgrade DB migration testleri geçti. Kanıt: `npm.cmd run phase1:smoke`, `npm.cmd run db:migrate` ikinci çalışma -- [ ] Restart persistence testi geçti. Kısmi local equivalent: DB reopen smoke geçti; container restart bekliyor. -- [ ] Native SQLite Docker smoke geçti. Bekliyor: Docker daemon kapalı. -- [ ] Readiness negatif senaryoları geçti. Bekliyor: permission/missing migration negatif HTTP testleri -- [x] Backup/restore POC geçti. Kanıt: `npm.cmd run phase1:smoke` -- [ ] Faz 1 performans ve image boyutu kaydedildi. Bekliyor: Docker image build -- [ ] Faz 2 auth için DB adapter hazır. Kısmi: Drizzle SQLite runtime ve migration zemini hazır; Better Auth adapter/schema Faz 2'de eklenecek. - -## 5. Faz 2 - Auth, setup ve yetkilendirme - -### 5.1 Better Auth kurulumu - -- [x] Better Auth config server-only modülde. Kanıt: `server/auth/auth.ts`, `npm run typecheck`, `npm run build` -- [x] Drizzle SQLite adapter doğru provider ile yapılandırılmış. Kanıt: `provider: "sqlite"` ve `npm run build` -- [x] Better Auth schema çıktısı migration'a dahil edilmiş. Kanıt: `server/db/migrations/0001_silky_jetstream.sql`, `npm run db:migrate`, `npm run phase2:smoke` -- [x] Auth GET/POST Route Handler çalışıyor. Kanıt: `app/api/auth/[...all]/route.ts`, `GET /api/auth/get-session -> 200 null` -- [x] `APP_URL`/base URL canonical origin ile eşleşiyor. Kanıt: `server/config.ts` -- [x] Trusted origin listesi wildcard içermiyor. Kanıt: `server/config.ts` -- [x] `BETTER_AUTH_SECRET` production'da zorunlu ve yüksek entropili. Kanıt: `server/config.ts`, `.env.example` -- [x] Auth secret log veya client bundle'a girmiyor. Kanıt: secret yalnız server-only auth/config modüllerinde kullanılıyor. -- [x] Cookie adı, path, `HttpOnly`, `SameSite` ve `Secure` ayarları doğrulandı. Kanıt: `server/auth/auth.ts` -- [ ] Reverse proxy arkasında HTTPS/cookie davranışı test edildi. - -### 5.2 İlk kurulum - -- [ ] Boş DB'de `/setup` erişilebilir. -- [ ] Dolu DB'de `/setup` hassas bilgi vermeden kapalı. -- [x] İlk freelancer oluşturma tek transaction/atomic guard ile korunuyor. Kanıt: `server/auth/setup.ts` -- [ ] Eşzamanlı iki setup isteğinden yalnızca biri başarılı oluyor. -- [x] İlk user profile rolü `freelancer`. Kanıt: `completeFirstFreelancerSetup` -- [x] Public genel register route'u yok veya kalıcı kapalı. Kanıt: Better Auth user create hook'u ilk freelancer guard'ına bağlı. -- [x] Setup input'u email normalize ve password policy uyguluyor. Kanıt: `server/auth/validation.ts` -- [ ] Setup başarı sonrası session/redirect doğru. -- [x] Setup olayı audit log'a secret olmadan yazılıyor. Kanıt: `auth_audit_events`, `server/auth/setup.ts` - -### 5.3 Session helper'ları - -- [x] `getSession` request içinde gereksiz tekrar DB sorgusu yapmıyor. Kanıt: React `cache()` ile `getSessionContext` -- [x] `requireSession` session yoksa standart davranış üretiyor. Kanıt: `/` ve `/portal` unauthenticated -> `307 /login` -- [x] `requireFreelancer` client rolünü reddediyor. Kanıt: `server/auth/session.ts` -- [x] `requireClientUser` freelancer rolünü reddediyor. Kanıt: `server/auth/session.ts` -- [x] Session user ve profile role uyumsuzluğu güvenli fail ediyor. Kanıt: profil yok/disabled ise session context `null` -- [x] Disabled user session'ı reddediliyor. Kanıt: `server/auth/session.ts` -- [x] Logout session'ı server tarafında iptal ediyor. Kanıt: `auth.api.signOut` -- [ ] Parola değişimi sonrası session revoke politikası test edildi. -- [ ] Expired session otomatik kabul edilmiyor. - -### 5.4 Ownership/policy helper'ları - -- [ ] `requireOwnedClient` owner predicate kullanıyor. -- [ ] `requireOwnedProject` owner predicate kullanıyor. -- [ ] Task erişimi project üzerinden dolaylıysa her iki bağ doğrulanıyor. -- [ ] Finance erişimi owner predicate kullanıyor. -- [ ] File erişimi owner/resource ilişkisini doğruluyor. -- [ ] Portal project erişimi portal user -> client -> project zincirini tek server akışında doğruluyor. -- [ ] Helper'lar resource bulunamadı ile yetkisiz ayrımında bilgi sızdırmıyor. -- [ ] Helper dışında doğrudan ID ile mutation yapılmasını engelleyen code review kuralı yazıldı. - -### 5.5 Login/logout/parola UX - -- [x] Yanlış email/parola genel hata veriyor; hesap varlığını açığa çıkarmıyor. Kanıt: `app/login/actions.ts` -- [x] Login pending ve double-submit koruması var. Kanıt: mevcut `SubmitButton` server action pending state'i kullanıyor. -- [x] Başarılı login role göre doğru alana yönlendiriyor. Kanıt: `app/login/actions.ts` -- [x] Logout tüm shell'lerden erişilebilir. Kanıt: dashboard shell mevcut logout action'ını kullanıyor. -- [ ] Parola formu mevcut parola/yenisi/onay validation'ına sahip. -- [ ] Parola policy metni ve server kuralı uyumlu. -- [ ] Login formu keyboard ve password manager ile çalışıyor. -- [x] Auth ekranlarında açık redirect parametresi saldırısı yok. Kanıt: login/signup action'ları redirect parametresi kabul etmiyor. - -### 5.6 Rate limit ve audit - -- [x] Login başarısız denemeleri IP+identifier bazında kontrollü sınırlanıyor. Kanıt: Better Auth `/sign-in/email` custom rate limit. -- [x] Setup endpoint'i rate limit altında. Kanıt: Better Auth `/sign-up/email` custom rate limit. -- [ ] Davet tüketim endpoint'i rate limit altında. -- [ ] Reverse proxy rate limit önerisi deploy dokümanında. -- [x] Audit log login başarısı/başarısızlığı için hassas veri taşımıyor. Kanıt: `recordAuthAuditEvent` password/session token yazmıyor. -- [ ] Log retention ve temizleme yaklaşımı belgelendi. - -### 5.7 Auth negatif test matrisi - -- [x] Session yokken dashboard redirect/401. Kanıt: `GET / -> 307 /login` -- [ ] Session yokken Server Action mutation reddi. -- [ ] Session yokken korumalı Route Handler reddi. -- [ ] Client rolü dashboard query reddi. -- [ ] Client rolü freelancer mutation reddi. -- [ ] Freelancer rolü portal-only mutation reddi. -- [ ] Başka freelancer owner ID'siyle client/project/task erişimi reddi. -- [ ] Expired/revoked session reddi. -- [ ] Sahte cookie veya değiştirilmiş session token reddi. -- [ ] Yanlış Origin ile auth mutation reddi. - -### 5.8 Faz 2 çıkış kapısı - -- [ ] Supabase olmadan setup-login-protected page-logout akışı geçti. -- [ ] İkinci public freelancer oluşturulamadı. -- [ ] Tüm negatif auth testleri geçti. -- [ ] Production proxy/TLS arkasında cookie testi geçti. -- [x] Auth migration boş ve upgrade DB'de geçti. Kanıt: `npm run db:migrate`, `npm run phase2:smoke` -- [ ] Security review bloklayıcı bulgu bırakmadı. -- [x] Faz 3 shell'in kullanacağı session/profile contract kilitlendi. Kanıt: `SessionContext` ve layout user contract'ı Better Auth profile'dan besleniyor. - -## 6. Faz 3 - Neta UI sistemi ve app shell - -### 6.1 Tasarım token'ları - -- [x] Renk token'ları semantik adlarla tanımlı. Kanıt: `app/globals.css` -- [x] `--poyraz-*` token'ları yeni shell kapsamında kullanılmıyor. Kanıt: `npm run phase3:ui-boundary` -- [x] Background/surface/border/text/interactive renkleri tek kaynaktan geliyor. Kanıt: `@theme inline` ve `:root` tokenları -- [x] Default, hover, active, focus, disabled ve danger halleri tanımlı. Kanıt: `components/ui/button.tsx`, `components/ui/input.tsx` -- [x] Typography ölçeği compact operasyonel UI'a uygun. Kanıt: shell/auth typography class'ları ve 14px body standardı -- [x] Font size viewport genişliğiyle ölçeklenmiyor. Kanıt: viewport tabanlı font-size kullanılmıyor. -- [x] Letter spacing negatif değil. Kanıt: `letter-spacing: 0` -- [x] Spacing ve control height ölçekleri tanımlı. Kanıt: internal primitive size sınıfları -- [x] Radius varsayılanı 8 px veya altında. Kanıt: `app/globals.css`, `components/ui/*` -- [x] Reduced motion token/kuralı var. Kanıt: `prefers-reduced-motion` kuralı -- [ ] Renk contrast ölçümleri kaydedildi. - -### 6.2 Primitive bileşenler - -- [x] `Button` tüm varyant ve boyutlarıyla hazır. Kanıt: `components/ui/button.tsx` -- [x] `IconButton` accessible name/tooltip kuralına sahip. Kanıt: `components/ui/button.tsx` -- [x] `Input` ve `Textarea` error/disabled/read-only halleri hazır. Kanıt: `components/ui/input.tsx` -- [x] `Label`/`Field` description/error ID bağlantılarını kuruyor. Kanıt: `components/ui/field.tsx` -- [ ] `Checkbox` ve `Switch` keyboard ile çalışıyor. -- [ ] `Select` keyboard/typeahead/focus ile çalışıyor. -- [ ] `Dialog` focus trap, Escape ve focus return davranışına sahip. -- [ ] `AlertDialog` destructive aksiyonu açıkça ayırıyor. -- [ ] `Drawer` mobil viewport ve scroll ile çalışıyor. -- [ ] `DropdownMenu` keyboard ve dışarı tıklama davranışına sahip. -- [ ] `Tabs` ARIA ve arrow-key davranışına sahip. -- [ ] `Tooltip` yalnız hover'a bağımlı değil. -- [x] `Toast` screen reader live region kullanıyor. Kanıt: `components/ui/toast.tsx` -- [x] `Skeleton` gerçek layout ölçülerini gereksiz kaydırmıyor. Kanıt: `components/ui/skeleton.tsx` -- [ ] `EmptyState` tek anlamlı primary action taşıyor. -- [ ] `Pagination` current/disabled durumlarını açıklıyor. -- [ ] `DataTable` mobil fallback stratejisine sahip. - -### 6.3 Dependency sınırı - -- [x] Headless UI paketi yalnız `components/ui` içinden import ediliyor. Kanıt: Radix/Base wrapper'ları `components/ui` altında. -- [ ] Feature dosyaları doğrudan Poyraz/Radix/Base UI import etmiyor. -- [x] İkonlar yalnız Lucide üzerinden geliyor veya istisna belgeli. Kanıt: yeni shell/auth/primitive ikonları Lucide kullanıyor; legacy `components/ui/icon.tsx` istisna olarak kaldı. -- [x] CVA/clsx/tailwind-merge kullanımı tek helper standardına indirildi. Kanıt: yeni primitive'ler `cn` helper'ını kullanıyor. -- [ ] Aynı işlevi gören iki toast/dialog/select implementation'ı yok. -- [x] Internal primitive public prop API'si yazılı ve tipli. Kanıt: primitive export tipleri ve `phase-3-ui.md` - -### 6.4 Shell ve navigasyon - -- [x] Dashboard shell role/session contract'ını server'dan alıyor. Kanıt: `app/(dashboard)/layout.tsx`, `components/layout/dashboard-shell.tsx` -- [x] Portal shell bağımsız ama aynı primitive'leri kullanıyor. Kanıt: `components/layout/app-shell.tsx`, `components/layout/portal-shell.tsx` -- [x] Auth shell responsive ve form odaklı. Kanıt: `components/auth/auth-page-shell.tsx` -- [x] Sidebar aktif route'u doğru gösteriyor. Kanıt: `aria-current` ve active route predicate -- [x] Link tıklamasında pending state var. Kanıt: `PendingLink` -- [x] Mobil menü route değişince kapanıyor. Kanıt: pathname'e bağlı mobile sidebar state -- [x] Mobil navigasyon içerikle çakışmıyor. Kanıt: fixed drawer + overlay + main layout -- [x] Header sabit ölçüde ve dinamik metinle layout kaydırmıyor. Kanıt: `h-14` mobile header -- [x] Uzun kullanıcı/proje adları truncate/wrap kuralına sahip. Kanıt: account menu `truncate` -- [x] Skip link veya eşdeğer keyboard ana içerik erişimi var. Kanıt: `Ana içeriğe geç` -- [x] Logout ve account menüsü keyboard ile kullanılabiliyor. Kanıt: button/menu roles, Escape/focus return - -### 6.5 Form ve feedback standardı - -- [ ] Ortak ActionResult UI adapter'ı var. -- [x] Pending button double-submit'i engelliyor. Kanıt: `SubmitButton`, `PendingSubmitButton` -- [ ] Field error server validation ile eşleşiyor. -- [x] Form-level error görünür ve screen reader tarafından okunuyor. Kanıt: `ErrorToaster` + `Toaster` live region -- [ ] Success toast yalnız commit sonrası gösteriliyor. -- [x] Error toast teknik detay göstermiyor. Kanıt: auth action generic error + `ErrorToaster` -- [ ] Optimistic rollback pattern'i örnek feature ile test edildi. -- [ ] Route skeleton ve link pending aynı anda çelişkili sinyal üretmiyor. - -### 6.6 Responsive ve görsel doğrulama - -- [ ] 320x568 auth/shell ekran görüntüsü kontrol edildi. -- [ ] 390x844 mobil ekran kontrol edildi. -- [ ] 768x1024 tablet kontrol edildi. -- [ ] 1440x900 desktop kontrol edildi. -- [ ] 1920x1080 geniş desktop kontrol edildi. -- [ ] Browser zoom %200 ile kritik shell kullanılabilir. -- [ ] Uzun Türkçe/İngilizce metinler buton ve navigation içinde test edildi. -- [ ] UI elementleri birbiriyle overlap etmiyor. -- [ ] Fixed/sticky alanlar içerik veya submit butonunu kapatmıyor. - -### 6.7 Faz 3 çıkış kapısı - -- [x] Yeni auth/dashboard/portal shell doğrudan Poyraz import etmiyor. Kanıt: `npm run phase3:ui-boundary` -- [x] Internal primitive test sayfası veya component testleri geçti. Kanıt: `npm run phase3:ui-boundary`, `npm run typecheck`, `npm run build` -- [ ] Keyboard/focus/contrast bloklayıcısı yok. -- [ ] Tüm hedef viewport screenshot'ları incelendi. -- [x] UI dependency sınırını denetleyen lint/import kuralı mevcut. Kanıt: `scripts/phase3-ui-boundary.mjs` -- [x] Feature mapping tablosunda her Poyraz component'in hedefi belli. Kanıt: `docs/self-hosted-redesign/phase-3-ui.md` -- [x] Faz 4 core feature'ları için UI API'si yeterli. Kanıt: button/input/textarea/field/card/skeleton/toast/app-shell seti hazır. - -## 7. Faz 4 - Core: clients, projects, tasks, calendar ve dashboard - -### 7.1 Ortak veri modeli - -- [ ] UUID text standardı uygulanmış. -- [ ] Timestamp/date standardı uygulanmış. -- [ ] `owner_id` tüm core tablolarda not null ve FK. -- [ ] FK on-delete davranışları ürün davranışıyla uyumlu. -- [ ] Status/type alanlarında DB check constraint var. -- [ ] Mutable tablolarda created/updated timestamp var. -- [ ] Kritik listeler için composite index migration'a ekli. -- [ ] Seed hem tipik hem stres verisi üretiyor. - -### 7.2 Clients - -- [ ] Client schema tüm aktif alanları kapsıyor. -- [ ] Pipeline stage kanonik enum/check kullanıyor. -- [ ] List query seçili kolon ve pagination kullanıyor. -- [ ] Search normalize edilmiş name/company/email alanlarında çalışıyor. -- [ ] Detail query activity'leri limit/cursor ile alıyor. -- [ ] Create ownership'i session'dan alıyor; input owner kabul etmiyor. -- [ ] Update `id + owner_id` predicate kullanıyor. -- [ ] Delete/archive ürün kararı uygulanmış. -- [ ] Client silmede bağlı project/finance davranışı test edilmiş. -- [ ] Pipeline drag/drop optimistic ve rollback'li. -- [ ] Başka owner client ID'si negatif testi geçiyor. -- [ ] Client CRUD E2E geçiyor. - -### 7.3 Client activities - -- [ ] Activity type constraint doğru. -- [ ] Activity client ve owner ilişkisi create sırasında doğrulanıyor. -- [ ] Activity başka owner client'ına eklenemiyor. -- [ ] Activity date timezone dönüşümü test edilmiş. -- [ ] Activity list deterministic order kullanıyor. -- [ ] Empty/loading/error state mevcut. - -### 7.4 Projects - -- [ ] Project schema type/status/progress constraints içeriyor. -- [ ] Progress 0-100 DB ve validation sınırında. -- [ ] Project-client ilişkisinde aynı owner doğrulanıyor. -- [ ] Side project client olmadan oluşturulabiliyor. -- [ ] Client project geçerli owned client gerektiriyor. -- [ ] Project list pagination ve filtre kullanıyor. -- [ ] Task stats aggregate sorguyla geliyor. -- [ ] Project detail query bağımsız blokları paralel/etkin alıyor. -- [ ] `select *` eşdeğeri sorgu yok. -- [ ] Cover image alanı Phase 6 gelene kadar güvenli nullable/fallback. -- [ ] Complete/cancel status geçiş kuralları test edildi. -- [ ] Başka owner project ID'si negatif testi geçiyor. -- [ ] Project CRUD E2E geçiyor. - -### 7.5 Project planning sections - -- [ ] Kanonik alan adı `category`. -- [ ] Kanonik sıra alanı `sort_order`. -- [ ] Legacy `type` veya `order_index` kodda kullanılmıyor. -- [ ] Category check constraint ürün listesiyle uyumlu. -- [ ] Create/update/delete project owner'ını doğruluyor. -- [ ] Reorder transaction veya idempotent batch update kullanıyor. -- [ ] Duplicate/collision sort order davranışı deterministic. -- [ ] Portalda gösterilebilir alan contract'ı ayrı test edilmiş. - -### 7.6 Tasks - -- [ ] Kanonik status `todo|in_progress|done|cancelled`. -- [ ] `completed` runtime kodda status olarak kullanılmıyor. -- [ ] Priority constraint doğru. -- [ ] Task-project-client ilişkileri aynı owner'a ait. -- [ ] Task list default limit ve cursor kullanıyor. -- [ ] Kanban yalnız ihtiyaç duyulan kolonları alıyor. -- [ ] Status drag/drop optimistic ve rollback'li. -- [ ] Liste “tamamla” aynı service/action yolunu kullanıyor. -- [ ] Double mutation ve stale optimistic state test edilmiş. -- [ ] Public-to-client flag yalnız owned project task'ında değiştirilebiliyor. -- [ ] Task delete sonrası auto project progress hesaplanıyor. -- [ ] Task project değişince eski ve yeni project progress hesaplanıyor. -- [ ] Auto progress update aynı transaction'da. -- [ ] Manual progress project task değişiminden etkilenmiyor. -- [ ] Zero-task auto progress sonucu tanımlı ve testli. -- [ ] 10.000 task query planı index kullanıyor. -- [ ] Task CRUD/status E2E geçiyor. - -### 7.7 Calendar - -- [ ] Event type constraint doğru. -- [ ] `ends_at >= starts_at` doğrulanıyor. -- [ ] Event ilişkili client/project/task ownership doğrulanıyor. -- [ ] Görünür tarih aralığı dışında kayıt çekilmiyor. -- [ ] Timezone dönüşümü create/edit/display için test edildi. -- [ ] DST geçiş günü testi var. -- [ ] Month/week navigation stale veri göstermiyor. -- [ ] Mobile event create/edit formu erişilebilir. -- [ ] Calendar CRUD E2E geçiyor. - -### 7.8 Dashboard - -- [ ] Dashboard tek tek tüm satırları istemciye taşımıyor. -- [ ] Active project count SQL aggregate. -- [ ] Completed task count `done` kullanıyor. -- [ ] Income/expense/net minor unit ile hesaplanıyor. -- [ ] Mood/daily trend hedef date range ile sınırlı. -- [ ] Recent projects/clients limitli ve deterministic order. -- [ ] Empty yeni kurulum dashboard'u anlamlı. -- [ ] Date filter URL/state contract'ı testli. -- [ ] Dashboard stres fixture DB süresi hedefte. -- [ ] Dashboard payload baseline ile karşılaştırıldı. - -### 7.9 Supabase/Poyraz feature temizliği - -- [ ] Clients feature içinde Supabase import kalmadı. -- [ ] Projects feature içinde Supabase import kalmadı. -- [ ] Tasks feature içinde Supabase import kalmadı. -- [ ] Calendar feature içinde Supabase import kalmadı. -- [ ] Dashboard içinde Supabase import kalmadı. -- [ ] Bu feature'larda Poyraz import kalmadı. -- [ ] Eski action/query dosyaları silindi veya yeni implementation'a dönüştü. -- [ ] Kullanılmayan RPC çağrıları kaldırıldı. - -### 7.10 Faz 4 çıkış kapısı - -- [ ] Core smoke matrisi desktop'ta geçti. -- [ ] Core smoke matrisi mobilde geçti. -- [ ] Cross-owner negatif matrisi geçti. -- [ ] Auto progress invariants testleri geçti. -- [ ] Stress fixture query plan ve süre raporu onaylandı. -- [ ] Core feature route'larında Supabase/Poyraz referansı sıfır. -- [ ] Faz 4 veritabanı upgrade/rollback backup testi geçti. - -## 8. Faz 5 - Finans, iş belgeleri, günlük ve analytics - -### 8.1 Para standardı - -- [ ] Tüm monetary alanlar minor unit integer. -- [ ] Currency ISO kodu normalize ediliyor. -- [ ] String decimal parser locale ayracını kontrollü ele alıyor. -- [ ] Floating point ile toplam yapılmıyor. -- [ ] Negative amount izinleri type/business rule ile açık. -- [ ] Büyük değer overflow sınırı test edilmiş. -- [ ] Formatlama locale ve currency ile doğru. -- [ ] Legacy `numeric(12,2)` conversion unit testleri var. - -### 8.2 Finance transactions - -- [ ] Type ve payment status constraints doğru. -- [ ] Client/project aynı owner'a ait. -- [ ] Date range zorunlu/default limitli. -- [ ] Pagination deterministic. -- [ ] Create/update/delete owner predicate kullanıyor. -- [ ] Gelir/gider/net aggregate DB'de hesaplanıyor. -- [ ] Project finance summary tüm satırı client'a taşımıyor. -- [ ] CSV/export varsa stream ve auth kontrolü kullanıyor. -- [ ] 20.000 finance fixture query planı index kullanıyor. -- [ ] Finance CRUD/filter E2E geçiyor. - -### 8.3 Proposals - -- [ ] Status transition matrisi yazılı ve enforce ediliyor. -- [ ] Client/project ownership doğrulanıyor. -- [ ] Valid-until date timezone kuralı belirli. -- [ ] Amount minor unit kullanıyor. -- [ ] CRUD validation ve cross-owner testleri geçiyor. -- [ ] Empty/loading/error/pending halleri var. - -### 8.4 Contracts - -- [ ] Proposal/client ilişkisi aynı owner'a ait. -- [ ] Contract status transition matrisi enforce ediliyor. -- [ ] Signed-at yalnız uygun transition'da set ediliyor. -- [ ] Content boyut limiti belirli. -- [ ] CRUD ve cross-owner testleri geçiyor. - -### 8.5 Invoices - -- [ ] Invoice number owner bazında unique. -- [ ] Tax rate temsil ve yuvarlama kuralı belirli. -- [ ] Issue/due/paid tarih invariant'ları var. -- [ ] Paid transition idempotent. -- [ ] Otomatik finance transaction oluşturuluyorsa tek transaction ve duplicate koruması var. -- [ ] Overdue hesaplama timezone/date standardıyla uyumlu. -- [ ] Invoice toplamları fixture ile kuruş seviyesinde doğrulandı. -- [ ] CRUD/status E2E geçiyor. - -### 8.6 Subscriptions - -- [ ] Billing cycle constraint doğru. -- [ ] Next billing date hesap kuralı ay sonlarını ele alıyor. -- [ ] Cancelled subscription tekrar charge/forecast'a girmiyor. -- [ ] Currency/amount standardı doğru. -- [ ] CRUD/filter E2E geçiyor. - -### 8.7 Journal birleşimi - -- [ ] `journal_entries` schema `daily_checkin` ve `journal` tiplerini kapsıyor. -- [ ] Daily checkin için owner+date unique kuralı var. -- [ ] Serbest journal aynı gün birden fazla kaydı destekliyor. -- [ ] Mood label ve score dönüşüm kuralı yazılı. -- [ ] Energy/satisfaction score sınırları enforce ediliyor. -- [ ] Legacy AI alanlarının korunma/drop kararı kaydedildi. -- [ ] Çakışan `journals`/`daily_logs` fixture'ı kayıpsız import ediliyor. -- [ ] Journal CRUD/filter E2E geçiyor. - -### 8.8 Analytics - -- [ ] Dashboard RPC çıktısının her alanı yeni query ile eşleşiyor veya değişiklik belgeli. -- [ ] Analytics RPC çıktısının her alanı yeni query ile eşleşiyor veya değişiklik belgeli. -- [ ] Task completion yalnız `done` kullanıyor. -- [ ] Date range dahil/haric sınırları testli. -- [ ] Project income grouping null project'i kontrollü adlandırıyor. -- [ ] Chart payload limitli ve sıralı. -- [ ] Raw finance/task/project satırları analytics client'a gitmiyor. -- [ ] Empty date range sonucu hata değil, boş/zero state. -- [ ] Stres fixture analytics süresi hedefte. - -### 8.9 Feature temizliği - -- [ ] Finance feature Supabase/Poyraz import'u içermiyor. -- [ ] Business feature'lar Supabase/Poyraz import'u içermiyor. -- [ ] Journal feature Supabase/Poyraz import'u içermiyor. -- [ ] Analytics feature Supabase/Poyraz import'u içermiyor. -- [ ] Eski aggregate RPC runtime çağrıları kaldırıldı. - -### 8.10 Faz 5 çıkış kapısı - -- [ ] Finans source/target fixture toplamları tam eşleşiyor. -- [ ] Para rounding testleri geçti. -- [ ] Tüm business status transition testleri geçti. -- [ ] Journal conflict fixture kayıpsız. -- [ ] Analytics payload ve performans hedefi geçti. -- [ ] Faz 5 route'larında Supabase/Poyraz referansı sıfır. - -## 9. Faz 6 - Storage, profil ve proje görselleri - -### 9.1 Files schema ve storage key - -- [ ] `files` tablosu owner, kind, key, MIME, size ve checksum içeriyor. -- [ ] `storage_key` unique. -- [ ] Absolute disk path DB'ye yazılmıyor. -- [ ] Original filename yalnız metadata/display için kullanılıyor. -- [ ] Storage key server tarafından üretiliyor. -- [ ] Resource ilişki modeli avatar/project asset için açık. -- [ ] Delete davranışı FK ve service düzeyinde belirli. - -### 9.2 Upload doğrulama - -- [ ] Maksimum byte limiti request okunurken uygulanıyor. -- [ ] Content-Type allowlist var. -- [ ] Magic-byte/file signature doğrulaması var. -- [ ] Double extension ve sahte MIME testleri var. -- [ ] Path traversal karakterleri storage key'e girmiyor. -- [ ] Boş/bozuk dosya reddediliyor. -- [ ] Upload temp dizine yazılıyor. -- [ ] Başarılı doğrulama sonrası atomik rename kullanılıyor. -- [ ] DB failure sonrası temp/final dosya temizleniyor. -- [ ] Disk full/permission error güvenli hata üretiyor. -- [ ] Upload log'u dosya içeriği veya hassas path göstermiyor. - -### 9.3 Dosya sunumu ve auth - -- [ ] File Route Handler session doğruluyor. -- [ ] Owner dosyası `id + owner_id` ilişkisiyle kontrol ediliyor. -- [ ] Portal file erişimi client->project zinciriyle kontrol ediliyor. -- [ ] Başka owner file UUID'si 404/uygun güvenli cevap veriyor. -- [ ] Response MIME ve `X-Content-Type-Options: nosniff` doğru. -- [ ] Private cache header'ı uygun. -- [ ] Range request gereksinimi değerlendirildi. -- [ ] Filename header injection testi var. -- [ ] Silinmiş metadata veya eksik disk dosyası kontrollü hata veriyor. - -### 9.4 Avatar akışı - -- [ ] Avatar upload/replace/delete çalışıyor. -- [ ] Eski avatar replace sonrası orphan kalmıyor. -- [ ] Avatar fallback initials doğru. -- [ ] Avatar UI büyük original dosyayı kontrolsüz indirmiyor. -- [ ] Profile update ile avatar update transaction/cleanup sınırı testli. -- [ ] Client portal avatar görünürlüğü ürün kararına uygun. - -### 9.5 Proje görseli akışı - -- [ ] Cover upload/replace/delete çalışıyor. -- [ ] Project ownership upload öncesi doğrulanıyor. -- [ ] Alt text input ve fallback kuralı var. -- [ ] Listede görünür olmayan tüm görseller için URL/metadata üretilmiyor. -- [ ] Broken image fallback var. -- [ ] Project silme sonrası asset cleanup politikası uygulanıyor. - -### 9.6 Orphan ve bakım araçları - -- [ ] DB'de olup diskte olmayan dosya raporu var. -- [ ] Diskte olup DB'de olmayan dosya raporu var. -- [ ] Cleanup varsayılan olarak dry-run. -- [ ] Gerçek delete açık onay/flag gerektiriyor. -- [ ] Cleanup uploads kökü dışına çıkamıyor. -- [ ] Cleanup sonucu audit/log kaydı oluşturuyor. - -### 9.7 Backup/restore - -- [ ] Backup DB ve uploads'u aynı manifestte kapsıyor. -- [ ] Her dosya checksum manifestte veya checksum dosyasında. -- [ ] Backup sırasında yeni upload davranışı tanımlı/testli. -- [ ] Restore sonrası metadata-file count eşleşiyor. -- [ ] Restore sonrası rastgele dosyalar checksum eşleşiyor. -- [ ] Backup arşivi secret kabul edilip izinleri sınırlandırılmış. - -### 9.8 Faz 6 çıkış kapısı - -- [ ] Avatar ve cover E2E akışları geçti. -- [ ] MIME/path/size saldırı testleri geçti. -- [ ] Cross-owner ve cross-client file testleri geçti. -- [ ] Orphan dry-run temiz sonuç veriyor. -- [ ] DB+uploads backup/restore tatbikatı geçti. -- [ ] Supabase Storage runtime çağrısı kalmadı. - -## 10. Faz 7 - Portal, davetler ve revizyonlar - -### 10.1 Davet modeli - -- [ ] Davet token'ı CSPRNG ile yeterli entropide üretiliyor. -- [ ] DB'de yalnız token hash saklanıyor. -- [ ] Davet client ve inviter owner ilişkisini doğruluyor. -- [ ] Davet expiry zorunlu. -- [ ] Davet tek kullanımlık. -- [ ] Revoke ve regenerate davranışı var. -- [ ] Aynı client için aktif davet sayısı kuralı belirli. -- [ ] Ham token log/audit/analytics'e girmiyor. -- [ ] Davet linki yalnız creation anında bir kez gösteriliyor. -- [ ] Open redirect veya host header ile yanlış origin linki üretilemiyor. - -### 10.2 Portal hesabı kurulumu - -- [ ] Valid token client adını minimum veriyle gösteriyor. -- [ ] Expired token genel güvenli hata gösteriyor. -- [ ] Revoked token reddediliyor. -- [ ] Used token tekrar reddediliyor. -- [ ] Parola policy uygulanıyor. -- [ ] Davet tüketimi + user oluşturma + client link atomic. -- [ ] Aynı token için eşzamanlı iki request'ten yalnız biri başarılı. -- [ ] Portal user role `client`. -- [ ] Portal user başka client kaydına bağlanamıyor. -- [ ] Setup sonrası session/redirect doğru. - -### 10.3 Portal veri erişimi - -- [ ] Project list yalnız bağlı client'ın projelerini gösteriyor. -- [ ] Project detail client-project ilişkisini sorguda doğruluyor. -- [ ] Planning section yalnız bağlı project için geliyor. -- [ ] Task list yalnız `is_public_to_client=true` kayıtları gösteriyor. -- [ ] Finance/internal notes portal payload'ına yanlışlıkla girmiyor. -- [ ] Owner/user ID gibi gereksiz internal alanlar portal response'ta yok. -- [ ] Başka client project ID'siyle list/detail erişimi reddediliyor. -- [ ] URL enumeration güvenli sonuç veriyor. - -### 10.4 Revizyon kuralları - -- [ ] Revision create server session'dan `requested_by` alıyor. -- [ ] Client ID input'a güvenmiyor; session ilişkisinden çözüyor. -- [ ] Project-client ilişkisi aynı sorgu/transaction içinde doğrulanıyor. -- [ ] Quota değeri negative olamıyor. -- [ ] Kullanılmış kota hesabının hangi status'ları saydığı belgeli. -- [ ] Quota check ve insert aynı transaction'da. -- [ ] Eşzamanlı iki son kota isteğinden yalnız biri başarılı. -- [ ] Action/Route doğrudan çağrılsa da quota aşılamıyor. -- [ ] Freelancer revision status transition'larını yönetebiliyor. -- [ ] Client izin verilmeyen status değişimini yapamıyor. -- [ ] Revision description boyut ve içerik validation'ına sahip. - -### 10.5 Hesap kapatma ve session - -- [ ] Freelancer portal erişimini devre dışı bırakabiliyor. -- [ ] Disable işlemi aktif session'ları revoke ediyor. -- [ ] Client record silme/archive ile portal account davranışı belirli. -- [ ] Re-enable/re-invite akışı belirli. -- [ ] Freelancer portal kullanıcısının parolasını göremiyor. -- [ ] Audit log invite/create/disable olaylarını secret olmadan kaydediyor. - -### 10.6 Portal UX - -- [ ] Portal shell freelancer navigation göstermiyor. -- [ ] Mobil project/task/revision akışları kullanılabilir. -- [ ] Empty project/task/revision durumları anlamlı. -- [ ] Revision submit pending/double-submit korumalı. -- [ ] Quota kalan bilgisi server gerçeğiyle uyumlu. -- [ ] Project status/progress erişilebilir biçimde gösteriliyor. -- [ ] Client logout/account alanı açık. - -### 10.7 Portal negatif test matrisi - -- [ ] Client A, Client B project list/detail erişimi reddi. -- [ ] Client A, Client B public task erişimi reddi. -- [ ] Client A, Client B planning section erişimi reddi. -- [ ] Client A, Client B revision okuma erişimi reddi. -- [ ] Client A'nın Client B project ID'sine kendi client ID'siyle revision eklemesi reddi. -- [ ] Freelancer'ın client-only revision create akışı reddi veya ürün kuralına uygun. -- [ ] Disabled client session reddi. -- [ ] Expired/revoked/reused invite reddi. - -### 10.8 Faz 7 çıkış kapısı - -- [ ] Invite -> set password -> portal -> revision E2E geçti. -- [ ] Tüm cross-client negatif testleri geçti. -- [ ] Quota concurrency testi geçti. -- [ ] Account disable session revoke testi geçti. -- [ ] Portal route'larında Supabase/Poyraz referansı sıfır. -- [ ] Portal güvenlik review bloklayıcı bulgu bırakmadı. - -## 11. Faz 8 - AI/chat, performans ve UX sertleştirme - -### 11.1 AI ayarları ve secret yönetimi - -- [ ] AI tamamen opsiyonel config. -- [ ] Key yokken core app build/boot/run ediyor. -- [ ] Env key ve user-saved key öncelik sırası belgeli. -- [ ] DB key authenticated encryption ile saklanıyor. -- [ ] Encryption nonce/tag doğru ve her kayıt için yeni. -- [ ] `APP_ENCRYPTION_KEY` eksikse şifreli key özelliği güvenli fail ediyor. -- [ ] Ayarlar ekranı kaydedilmiş key'i geri göstermiyor. -- [ ] Key update/delete akışı çalışıyor. -- [ ] Key hiçbir API response, RSC prop, log veya error'da görünmüyor. -- [ ] Encryption key rotation prosedürü yazıldı. - -### 11.2 Chat persistence - -- [ ] Chat session owner predicate kullanıyor. -- [ ] Chat message session ownership üzerinden doğrulanıyor. -- [ ] Browser Supabase client kaldırıldı. -- [ ] Session list limit/cursor kullanıyor. -- [ ] Message history limit/cursor kullanıyor. -- [ ] Session delete cascade davranışı testli. -- [ ] Empty/new session akışı doğru. -- [ ] Stream tamamlanmadan assistant message persistence davranışı belirli. -- [ ] Abort durumunda partial message politikası belirli. -- [ ] Retry duplicate message üretmiyor veya açıkça işaretli. - -### 11.3 AI endpoint güvenliği - -- [ ] Chat Route Handler session doğruluyor. -- [ ] Finance analysis session ve owner date range doğruluyor. -- [ ] Project risk project owner'ını doğruluyor. -- [ ] Project risk task complete statüsü `done`. -- [ ] Prompt input boyut limiti var. -- [ ] Context satır/karakter/token limiti var. -- [ ] Provider timeout ve abort var. -- [ ] Provider hata mesajı kullanıcıya güvenli çevriliyor. -- [ ] Endpoint rate limit uygulanmış. -- [ ] Prompt/response logging varsayılan olarak kapalı veya redacted. -- [ ] AI output güvenilir veri olarak DB mutation tetiklemiyor. - -### 11.4 Embedding/RAG temizliği - -- [ ] `document_embeddings` runtime kod referansı kaldırıldı veya açık feature flag altında. -- [ ] `match_documents` RPC çağrısı kaldırıldı. -- [ ] Legacy embedding export mapping'i Faz 9 için hazır. -- [ ] FTS/vector geleceği ayrı backlog/ADR'ye taşındı. - -### 11.5 Query performansı - -- [ ] Slow query threshold ve log formatı tanımlı. -- [ ] Dashboard query planı incelendi. -- [ ] Project list/detail query planı incelendi. -- [ ] Task list/kanban query planı incelendi. -- [ ] Client list/detail query planı incelendi. -- [ ] Finance/analytics query planı incelendi. -- [ ] Portal list/detail query planı incelendi. -- [ ] Chat history query planı incelendi. -- [ ] Tüm kritik query'ler stres fixture'ında index kullanıyor. -- [ ] Gereksiz index'ler write maliyeti açısından gözden geçirildi. -- [ ] 100 ms üstü query varsa gerekçe ve takip kaydı var. - -### 11.6 RSC ve client bundle - -- [ ] Büyük Client Component dosyaları sorumluluklara bölündü. -- [ ] Server render edilebilecek statik alanlar Client Component değil. -- [ ] Recharts yalnız analytics route'unda yükleniyor. -- [ ] DnD yalnız gerekli route'larda yükleniyor. -- [ ] Dialog/form chunk'ları gerektiğinde lazy. -- [ ] Client'a gönderilen props minimum ve serializable. -- [ ] Duplicate date/format/helper kütüphanesi yok. -- [ ] Ana route bundle ölçümleri Faz 0 ile karşılaştırıldı. -- [ ] Beklenmeyen bundle artışı gerekçeli. - -### 11.7 UX tutarlılık turu - -- [ ] Tüm create formlarında pending/double-submit standardı. -- [ ] Tüm update formlarında pending ve field error standardı. -- [ ] Tüm delete aksiyonlarında nesne adı ve onay standardı. -- [ ] Task/project/pipeline optimistic rollback çalışıyor. -- [ ] Sidebar ve kart navigasyonunda pending feedback var. -- [ ] Kritik route'larda layout'a benzeyen skeleton var. -- [ ] Hata state'i retry veya geri dönüş aksiyonu sunuyor. -- [ ] Empty state'ler yanlış dekoratif metin yerine aksiyon sunuyor. -- [ ] Mobile uzun form submit butonu erişilebilir. -- [ ] Drag/drop olmayan alternatif status kontrolü var. -- [ ] Toast sayısı ve süresi kullanıcıyı boğmıyor. - -### 11.8 Erişilebilirlik turu - -- [ ] Auth akışı yalnız klavye ile tamamlandı. -- [ ] Client/project/task CRUD yalnız klavye ile tamamlandı. -- [ ] Portal invite/revision yalnız klavye ile tamamlandı. -- [ ] Dialog focus trap/return tüm feature'larda doğru. -- [ ] Tab sırası mantıklı. -- [ ] Icon-only button accessible name taşıyor. -- [ ] Grafiklerin metinsel özeti var. -- [ ] Status yalnız renkle anlatılmıyor. -- [ ] Kontrast bloklayıcısı yok. -- [ ] %200 zoom'da core akışlar tamamlanabiliyor. - -### 11.9 Performans bütçesi - -- [ ] Referans donanım bilgisi raporda. -- [ ] Dashboard DB süresi hedefte veya istisna onaylı. -- [ ] Liste mutation DB süresi hedefte veya istisna onaylı. -- [ ] Tıklama-feedback süresi 100 ms altında. -- [ ] Liste payload'ı kayıt sayısıyla limitsiz büyümüyor. -- [ ] Stress fixture'da memory kullanımı stabil. -- [ ] 20 dakikalık temel kullanımda connection/file descriptor leak yok. -- [ ] AI stream core request thread'lerini kilitlemiyor. - -### 11.10 Faz 8 çıkış kapısı - -- [ ] Browser Supabase client referansı sıfır. -- [ ] AI key sızıntı testleri geçti. -- [ ] AI disabled E2E geçti. -- [ ] Performance raporu hedefleri karşıladı veya onaylı istisnalar var. -- [ ] Core ve portal accessibility smoke geçti. -- [ ] UX mutation matrisi tutarlı. -- [ ] Faz 9 için target schema ve dönüşüm kuralları donduruldu. - -## 12. Faz 9 - Supabase export/import ve cutover provası - -### 12.1 Export aracı güvenliği - -- [ ] Export aracı production runtime dependency'si değil. -- [ ] Supabase service-role key yalnız migration ortamında okunuyor. -- [ ] Key command argument veya process listesinde görünmüyor. -- [ ] Export log'u hassas kolon değerlerini göstermiyor. -- [ ] Çıktı dizini restrictive izinlerle oluşturuluyor. -- [ ] Export yarıda kalırsa incomplete manifest ile açıkça işaretleniyor. -- [ ] Export tekrar çalıştırıldığında önceki çıktıyı sessizce ezmiyor. -- [ ] Source schema/app version manifestte. - -### 12.2 Tablo export'u - -- [ ] Auth user ID/email/role mapping export edildi; password/session export edilmiyor. -- [ ] Profiles export edildi. -- [ ] Clients export edildi. -- [ ] Client activities export edildi. -- [ ] Projects export edildi. -- [ ] Planning sections export edildi. -- [ ] Tasks export edildi. -- [ ] Calendar events export edildi. -- [ ] Finance transactions export edildi. -- [ ] Proposals export edildi. -- [ ] Contracts export edildi. -- [ ] Invoices export edildi. -- [ ] Subscriptions export edildi. -- [ ] Journals export edildi. -- [ ] Daily logs export edildi. -- [ ] Project revisions export edildi. -- [ ] Chat sessions/messages export edildi. -- [ ] App settings export edildi ve API key loglanmadı. -- [ ] Document embeddings ayrı arşiv olarak export edildi. -- [ ] Her tablo satır sayısı manifestte. -- [ ] Pagination export sırasında kayıt atlamıyor/çoğaltmıyor. - -### 12.3 Storage export'u - -- [ ] Avatar object listesi export edildi. -- [ ] Project asset object listesi export edildi. -- [ ] Her object size ve checksum kaydedildi. -- [ ] Eksik/erişilemeyen object warning olarak manifestte. -- [ ] Aynı storage key collision raporlandı. -- [ ] DB'de referanslı ama storage'da olmayan path raporlandı. -- [ ] Storage'da olup DB'de referanssız object raporlandı. - -### 12.4 Import dönüşümleri - -- [ ] UUID'ler korunuyor. -- [ ] `user_id -> owner_id` mapping deterministic. -- [ ] Freelancer auth hesabı bootstrap/reset planına göre oluşturuluyor. -- [ ] Client auth bağlantıları davet bekleyen durumda işaretleniyor. -- [ ] PostgreSQL timestamp'leri UTC epoch'a doğru dönüşüyor. -- [ ] Date alanları gün kayması olmadan dönüşüyor. -- [ ] Numeric para değerleri decimal string üzerinden minor unit'e dönüşüyor. -- [ ] Array ve JSON alanları schema doğrulamasından geçiyor. -- [ ] `completed -> done` legacy status dönüşümü raporlu. -- [ ] Unknown status/category değerleri sessizce default olmuyor. -- [ ] Planning `category/sort_order` mapping doğru. -- [ ] Journal ve daily log birleşimi kayıpsız. -- [ ] App settings API key yeni key ile şifreleniyor. -- [ ] Embeddings operasyonel DB'ye yazılmıyor. -- [ ] Storage dosyaları yeni key yapısına taşınıyor. -- [ ] File metadata checksum/size ile oluşturuluyor. - -### 12.5 Import idempotency ve failure - -- [ ] Import batch ID/manifest hash ile takip ediliyor. -- [ ] Aynı export ikinci kez çalıştırılırsa duplicate üretmiyor veya açıkça reddediyor. -- [ ] Tablo import transaction sınırları belgeli. -- [ ] Yarım import sonrası temiz retry prosedürü var. -- [ ] Fatal dönüşüm hatası sessizce skip edilmiyor. -- [ ] Warning ve error ayrımı manifest/report içinde. -- [ ] Disk kapasitesi import öncesi kontrol ediliyor. -- [ ] Import target'ta mevcut production veri varsa koruma/onay var. - -### 12.6 Otomatik doğrulama - -- [ ] Her tablo source/export/import row count eşleşiyor. -- [ ] FK integrity check temiz. -- [ ] Orphan client/project/task/finance sayısı sıfır. -- [ ] User bazında gelir toplamı eşleşiyor. -- [ ] User bazında gider toplamı eşleşiyor. -- [ ] Currency bazında toplamlar eşleşiyor. -- [ ] Project status dağılımı eşleşiyor. -- [ ] Task status dağılımı dönüşüm raporuyla eşleşiyor. -- [ ] Revision status/kota verisi eşleşiyor. -- [ ] Journal source kayıtlarının her biri target ID/mapping'e sahip. -- [ ] File count/size/checksum eşleşiyor. -- [ ] Duplicate email/invoice/daily checkin raporu temiz veya çözümü onaylı. -- [ ] `PRAGMA foreign_key_check` temiz. -- [ ] `PRAGMA integrity_check` sonucu `ok`. - -### 12.7 Manuel örnekleme - -- [ ] En az 5 client alan bazında source-target karşılaştırıldı. -- [ ] En az 5 project ve plan section karşılaştırıldı. -- [ ] En az 10 task ve status/due date karşılaştırıldı. -- [ ] En az 10 finance kaydı ve formatlanmış tutar karşılaştırıldı. -- [ ] En az 5 invoice/proposal/contract/subscription karşılaştırıldı. -- [ ] En az 5 journal/daily log karşılaştırıldı. -- [ ] En az 5 chat session/message geçmişi karşılaştırıldı. -- [ ] En az 5 avatar/project image görüntülenip checksum doğrulandı. -- [ ] Bir client portal ilişkisi davet sonrası manuel test edildi. - -### 12.8 Prova - -- [ ] Prova 1 anonimleştirilmiş production snapshot ile tamamlandı. -- [ ] Prova 1 toplam süre kaydedildi. -- [ ] Prova 1 disk kullanım tepe değeri kaydedildi. -- [ ] Prova 1 tüm warning/error çözüldü veya onaylandı. -- [ ] Prova 2 temiz volume üzerinde aynı snapshot ile tamamlandı. -- [ ] Prova 2 row count/checksum sonucu Prova 1 ile aynı. -- [ ] Prova 2 sonrası full E2E smoke geçti. -- [ ] Prova 2 sonrası backup/restore geçti. -- [ ] Tahmini final downtime kabul edilen pencereye sığıyor. - -### 12.9 Parola/davet iletişimi - -- [ ] Freelancer yeni parola/bootstrap yöntemi hazır. -- [ ] Bootstrap token tek kullanımlık ve süreli. -- [ ] Client portal kullanıcı listesi çıkarıldı. -- [ ] Re-invite link üretim akışı hazır. -- [ ] Kullanıcıya iletilecek metin hazır. -- [ ] Ham token toplu log/export dosyasına yazılmıyor. -- [ ] SMTP yok senaryosunda güvenli manuel paylaşım yöntemi yazılı. - -### 12.10 Cutover ve rollback runbook'u - -- [ ] Maintenance başlangıç/bitiş iletişimi hazır. -- [ ] Eski app read-only/maintenance yöntemi testli. -- [ ] Final export komutu ve sorumlusu belirli. -- [ ] Import komutu ve sorumlusu belirli. -- [ ] Otomatik doğrulama komutu belirli. -- [ ] Freelancer smoke test listesi hazır. -- [ ] DNS/reverse proxy değişim adımı yazılı. -- [ ] Health/log gözlem adımı yazılı. -- [ ] Rollback karar eşiği ve karar sahibi belirli. -- [ ] Eski sistemi tekrar açma adımı testli. -- [ ] Yeni sistemde oluşan yazıları uzlaştırma yöntemi yazılı. -- [ ] Eski Supabase'i silmeme süresi belirli. - -### 12.11 Faz 9 çıkış kapısı - -- [ ] İki deterministik prova tamamlandı. -- [ ] Row count, finance ve checksum kontrolleri temiz. -- [ ] Password/session/re-invite planı onaylandı. -- [ ] Cutover süresi ve disk ihtiyacı onaylandı. -- [ ] Rollback runbook'u tabletop tatbikatından geçti. -- [ ] Unresolved migration error yok. -- [ ] Final export/import araç sürümleri tag'lendi. - -## 13. Faz 10 - One-click deploy, operasyon, temizlik ve release - -### 13.1 Final dependency temizliği - -- [ ] `@supabase/ssr` package.json/lockfile'dan kaldırıldı. -- [ ] `@supabase/supabase-js` runtime package.json/lockfile'dan kaldırıldı. -- [ ] `poyraz-ui` kaldırıldı. -- [ ] Dexie paketleri kaldırıldı. -- [ ] PWA paketi ilk release kararına göre kaldırıldı. -- [ ] `shadcn` gereksiz runtime dependency kaldırıldı. -- [ ] Duplicate Radix/Base UI paketleri tek yaklaşıma indirildi. -- [ ] `@iconify/react` kullanımı yoksa kaldırıldı. -- [ ] `uuid` kullanımı yoksa kaldırıldı. -- [ ] `framer-motion` ölçülmüş kullanım yoksa kaldırıldı. -- [ ] `npm ls` invalid/extraneous dependency göstermiyor. -- [ ] Lockfile temiz install ile yeniden doğrulandı. - -### 13.2 Kod referansı temizliği - -- [ ] `rg '@supabase|lib/supabase'` runtime kodda sonuç vermiyor. -- [ ] `rg 'poyraz-ui|--poyraz-'` runtime kod/CSS'te sonuç vermiyor. -- [ ] `rg 'NEXT_PUBLIC_SUPABASE|SUPABASE_SERVICE_ROLE'` aktif config/dokümanda sonuç vermiyor. -- [ ] Browser DB client bulunmuyor. -- [ ] Service-role kavramı runtime'da bulunmuyor. -- [ ] Eski RPC isimleri runtime'da bulunmuyor. -- [ ] Eski Storage bucket çağrıları runtime'da bulunmuyor. -- [ ] `lib/db.ts` Dexie prototipi kaldırıldı. -- [ ] Kullanılmayan Supabase auth helper/middleware/proxy kodu kaldırıldı. -- [ ] Legacy status/type/order field kullanımları tarandı. - -### 13.3 Supabase tarihsel dosyaları - -- [ ] `supabase/` klasörünün arşivleme veya silme kararı kaydedildi. -- [ ] Tarihsel SQL runtime build context dışında. -- [ ] Migration export aracı production image dışında. -- [ ] Eski docs/database içeriği “legacy Supabase” olarak açık etiketli veya arşivli. -- [ ] Kullanıcı yanlışlıkla eski Supabase setup'ını çalıştırmaya yönlendirilmiyor. - -### 13.4 Final Docker/Compose - -- [ ] Image version/commit OCI label içeriyor. -- [ ] Multi-arch gereksinimi belirlendi; desteklenen mimariler yazılı. -- [ ] AMD64 image smoke geçti. -- [ ] ARM64 destekleniyorsa native SQLite smoke geçti. -- [ ] Container non-root. -- [ ] Read-only root filesystem uygulanabiliyorsa testli; write yalnız data/tmp. -- [ ] Persistent volume `/app/data` açık. -- [ ] Healthcheck readiness endpoint'i kullanıyor. -- [ ] Stop grace period yeterli. -- [ ] Replica=1 uyarısı belirgin. -- [ ] Rolling update yerine uygun recreate stratejisi belgeli. -- [ ] Image clean install/build ile üretiliyor. -- [ ] Final image içinde source secret veya `.env` yok. -- [ ] Image vulnerability scan bloklayıcı kritik bulgu göstermiyor. - -### 13.5 Coolify doğrulaması - -- [ ] Git/Docker image kaynağıyla yeni app oluşturuldu. -- [ ] Persistent volume doğru path'e bağlandı. -- [ ] Required env secret'lar eklendi. -- [ ] Domain ve TLS çalışıyor. -- [ ] Health check healthy. -- [ ] İlk setup tamamlandı. -- [ ] Restart sonrası veri korundu. -- [ ] Upgrade sonrası migration ve veri koruma geçti. -- [ ] Backup schedule çalıştı. -- [ ] Restore tatbikatı ayrı test app'inde geçti. -- [ ] Replica ayarının 1 olduğu doğrulandı. - -### 13.6 Dokploy doğrulaması - -- [ ] Git/Docker image kaynağıyla yeni app oluşturuldu. -- [ ] Persistent volume doğru path'e bağlandı. -- [ ] Required env secret'lar eklendi. -- [ ] Domain ve TLS çalışıyor. -- [ ] Health check healthy. -- [ ] İlk setup tamamlandı. -- [ ] Restart sonrası veri korundu. -- [ ] Upgrade sonrası migration ve veri koruma geçti. -- [ ] Backup schedule çalıştı. -- [ ] Restore tatbikatı ayrı test app'inde geçti. -- [ ] Replica ayarının 1 olduğu doğrulandı. - -### 13.7 Operasyon dokümanları - -- [ ] README yeni mimariyi doğru anlatıyor. -- [ ] `.env.example` yalnız yeni değişkenleri içeriyor. -- [ ] Local development adımları temiz makinede test edildi. -- [ ] Docker quick start adımları temiz makinede test edildi. -- [ ] Coolify dokümanı ekran/alan adlarıyla güncel. -- [ ] Dokploy dokümanı ekran/alan adlarıyla güncel. -- [ ] Upgrade dokümanı migration ve pre-backup adımlarını içeriyor. -- [ ] Backup dokümanı schedule/retention/dış kopyayı içeriyor. -- [ ] Restore dokümanı offline/maintenance ve doğrulamayı içeriyor. -- [ ] Troubleshooting `SQLITE_BUSY`, permission, disk full ve migration hatalarını içeriyor. -- [ ] Security dokümanı secret, reverse proxy, rate limit ve volume iznini içeriyor. -- [ ] Single-instance ve NFS kullanmama uyarıları belirgin. - -### 13.8 Full regression matrisi - -- [ ] Fresh setup. -- [ ] Login/logout. -- [ ] Password change/session revoke. -- [ ] Client CRUD/pipeline/activity. -- [ ] Project CRUD/status/progress/planning. -- [ ] Task CRUD/list/kanban/auto progress. -- [ ] Calendar CRUD/date navigation. -- [ ] Finance CRUD/filter/aggregate. -- [ ] Proposal/contract/invoice/subscription CRUD/status. -- [ ] Journal CRUD/daily checkin. -- [ ] Dashboard/analytics date ranges. -- [ ] Avatar/project file upload/replace/delete. -- [ ] Portal invite/setup/login. -- [ ] Portal project/public task/planning. -- [ ] Portal revision/quota. -- [ ] Portal disable/session revoke. -- [ ] Chat session/message streaming. -- [ ] AI disabled mode. -- [ ] AI provider failure/timeout. -- [ ] Mobile core flows. -- [ ] Keyboard-only core flows. - -### 13.9 Final teknik kapı - -- [ ] `npm ci` temiz ortamda geçti. -- [ ] `npm run lint` geçti. -- [ ] `npm run typecheck` geçti. -- [ ] `npm run test` geçti. -- [ ] `npm run test:integration` geçti. -- [ ] `npm run test:e2e` geçti. -- [ ] `npm run db:check` geçti. -- [ ] `npm run build` geçti. -- [ ] `npm run smoke:docker` geçti. -- [ ] Fresh DB migration geçti. -- [ ] Previous release DB upgrade geçti. -- [ ] Backup/restore geçti. -- [ ] Dependency audit incelendi. -- [ ] Container/image scan incelendi. -- [ ] Performance budget raporu onaylandı. -- [ ] Accessibility bloklayıcı bulgu yok. - -### 13.10 Cutover günü - -- [ ] Cutover başlamadan sorumlular ve iletişim kanalı hazır. -- [ ] Eski production sağlıklı ve son backup mevcut. -- [ ] Bakım modu açıldı. -- [ ] Eski sistemde yeni yazma olmadığı doğrulandı. -- [ ] Final Supabase export tamamlandı. -- [ ] Export manifest/checksum doğrulandı. -- [ ] Yeni target volume boş/uygun olduğu doğrulandı. -- [ ] Final import tamamlandı. -- [ ] Import doğrulama raporu temiz. -- [ ] Freelancer hesabı bootstrap/reset tamamlandı. -- [ ] İç smoke: dashboard, client, project, task, finance geçti. -- [ ] İç smoke: storage geçti. -- [ ] İç smoke: portal invite/login/revision geçti. -- [ ] Readiness healthy. -- [ ] Error loglarında kritik hata yok. -- [ ] DNS/reverse proxy yeni app'e geçirildi. -- [ ] Dış domain/TLS/login testi geçti. -- [ ] Kullanıcı bakım modu kaldırıldı. -- [ ] Cutover bitiş zamanı kaydedildi. -- [ ] Eski Supabase read-only ve erişilebilir bırakıldı. - -### 13.11 İlk 24 saat gözlem - -- [ ] İlk 15 dakika health ve error log izlendi. -- [ ] İlk 1 saat login/session hataları incelendi. -- [ ] İlk 1 saat SQLite busy/lock hataları incelendi. -- [ ] Disk kullanım artışı incelendi. -- [ ] Upload/download hataları incelendi. -- [ ] AI provider hataları core app'ten ayrışıyor. -- [ ] Backup schedule ilk çalışmasını tamamladı. -- [ ] Kullanıcı bildirimi/geri bildirim kanalı izlendi. -- [ ] Rollback eşiği aşılmadı veya karar kaydedildi. -- [ ] 24 saat sonunda durum raporu yazıldı. - -### 13.12 İlk 7 gün ve kapanış - -- [ ] Günlük backup'lar başarıyla çalıştı. -- [ ] En az bir backup ayrı test ortamına restore edildi. -- [ ] Disk kapasite trendi incelendi. -- [ ] Slow query raporu incelendi. -- [ ] Error rate ve auth failure trendi incelendi. -- [ ] Portal davet/reset problemleri çözüldü. -- [ ] Kritik kullanıcı UX geri bildirimleri triage edildi. -- [ ] Eski sistem saklama süresinin bitiş tarihi tekrar doğrulandı. -- [ ] Release retrospective ve kalan backlog yazıldı. - -### 13.13 Faz 10 ve proje kapanış kapısı - -- [ ] Coolify temiz kurulum doğrulandı. -- [ ] Dokploy temiz kurulum doğrulandı. -- [ ] Runtime Supabase/Poyraz referansı sıfır. -- [ ] Full regression ve final teknik kapı temiz. -- [ ] Gerçek cutover tamamlandı. -- [ ] İlk 24 saat ve 7 gün gözlem kriterleri karşılandı. -- [ ] Backup/restore operasyonu gerçek release verisiyle doğrulandı. -- [ ] Dokümanlar release tag'iyle uyumlu. -- [ ] Açık bloklayıcı güvenlik/veri kaybı problemi yok. -- [ ] Proje Definition of Done ürün sahibi ve teknik sorumlu tarafından onaylandı. - -## 14. Release sonrası periyodik operasyon checklist'i - -Bu bölüm faz çalışması tamamlandıktan sonra aylık veya her release için kullanılmalıdır. - -### Her release - -- [ ] Release öncesi backup başarılı. -- [ ] Migration diff incelendi. -- [ ] Upgrade test fixture üzerinde geçti. -- [ ] Docker smoke geçti. -- [ ] Dependency ve image scan incelendi. -- [ ] Release sonrası readiness/log kontrol edildi. -- [ ] Rollback image/tag erişilebilir. - -### Aylık - -- [ ] Son backup'ların checksum'ları doğrulandı. -- [ ] Rastgele bir backup restore edildi. -- [ ] Disk kullanımı ve kalan kapasite incelendi. -- [ ] SQLite integrity check çalıştı. -- [ ] Orphan file dry-run çalıştı. -- [ ] Slow query ve `SQLITE_BUSY` kayıtları incelendi. -- [ ] Disabled/expired session ve invitation temizliği çalıştı. -- [ ] Audit log retention çalıştı. -- [ ] Reverse proxy TLS ve security header'ları kontrol edildi. - -### Altı aylık veya büyük sürüm öncesi - -- [ ] Tam felaket kurtarma tatbikatı yapıldı. -- [ ] Yeni temiz sunucuda kurulum dokümanı test edildi. -- [ ] Secret rotation prosedürü test edildi. -- [ ] AI encryption key rotation prosedürü test edildi. -- [ ] Veri büyümesi SQLite sınırları açısından değerlendirildi. -- [ ] Tek instance modelinin hâlâ yeterli olduğu doğrulandı. -- [ ] PostgreSQL'e geçiş eşiği gerekip gerekmediği değerlendirildi.