Files
kakeibo/docs/MEMORY.md
T
2026-11-12 02:16:00 +03:00

13 KiB
Raw Blame History

🧠 Proje Hafızası

▶️ Sıradaki Adım

Faz 3 – Adım 3: Dokploy Application (kakeibo-app, Gitea repo, Dockerfile), ortam değişkenleri, domain kakeibo.ta1sph.website (HTTPS), deploy, health kontrolü. Kullanıcı süreçten yoruldu → kısa ve net adımlar, gereksiz tur yok.

📌 Alınan Kararlar

  • Yerel demo hesapları (kakeibo_dev): demo@ornek.com / demo12345 (owner, "Demo Hanesi") · es@ornek.com / demo12345 (member, aynı hane). npm run db:reset silerse API ile yeniden oluştur (ileride db:seed).
  • Sürüm kontrolü: Gitea (https://gitea.ta1sph.info/suphicakir/kakeibo.git), dal main.
  • Her adım sonunda Claude commit atar ve haber verir; push'u kullanıcı kendi uygulamasıyla yapar (Claude git push çalıştırmaz).
  • Node v26 (LTS) sistemde mevcut; ayrı kurulum gerekmedi.
  • Yerel MongoDB host portu 27020 (27017 sistem mongod, 27018/27019 başka projeler).
  • Frontend lint aracı: oxlint (Vite şablonu varsayılanı), ESLint yerine.
  • Veri modeli v1 onaylandı (2026-11-11): ölçekli tam sayı (_e6), tarih YYYY-MM-DD metin, dönem bitişi hariç, kullanıcı = tek hane, ayarlar haneye gömülü, haftalık bütçe hesaplanır.
  • Model yaklaşımı: #[serde(flatten)] yerine ortak alanlar models/common.rs yardımcılarıyla (new_meta, scope, touch). Modeller ilgili adımda eklenir.
  • households.household_id = _id (scope filtresi her yerde aynı).
  • Auth: JWT (HS256, jsonwebtoken rust_crypto) kakeibo_session cookie'de; HttpOnly, SameSite=Lax, Secure yalnızca APP_URL https ise. Beni hatırla → 30 gün Max-Age; değilse 12 saat JWT + oturum cookie'si. Kayıttan sonra 30 gün.
  • Giriş sınırı: e-posta başına 15 dk'da 5 hatalı deneme (bellek içi, auth/limiter.rs). Olmayan kullanıcıda da sahte argon2 doğrulaması (zamanlama sızıntısı yok).
  • Hata kodları: {error:{code,message}}; invalid_credentials, unauthorized, bad_request, conflict, too_many_requests.
  • Hane izolasyonu kuralı: hane kimliği her zaman AuthUser.household_id'den alınır, asla URL/gövdeden. Başka hanenin kaydı → 404 (403 değil; varlığı sızdırılmaz).
  • AuthUser her istekte DB'den kullanıcıyı doğrular (silinen kullanıcı → 401, rol DB'den). Owner-only işlemler: auth.require_owner()?.
  • Davet: 8 karakter (31 harflik okunaklı alfabe), 7 gün, tek kullanım; find_one_and_update ile atomik claim, kayıt transaction'ı içinde.
  • Kategoriler/ödeme türleri: tüm üyeler yönetir; silme yok (pasife alma); grup sonradan değişmez; ad grup içinde benzersiz (büyük/küçük harf duyarsız, pasifler dahil); PATCH'te version → iyimser kilit (409); sıralama tam liste ister.
  • Tasarım: ana renk indigo (oklch(0.42 0.13 268)), grup renkleri Okabe-Ito (needs #0072b2, wants #cc79a7, culture #009e73, unexpected #d55e00), *-fg tonları AA (açık ≥5.0, koyu ≥9) hesaplanarak doğrulandı. Gelir #15803d, gider #c62828, uyarı #b45309.
  • Tema seçimi localStorage (kakeibo-theme), yalnızca cihaz kolaylığı; ileride users.preferences.theme ile senkron olabilir.
  • parseMoney: virgül varsa ondalık; virgül yoksa son noktadan sonra 1–2 rakam → ondalık ("1.25" = 1,25 ₺; "1.250" = 1250 ₺).
  • Logo: Taslak A (indigo zemin, spiral krem defter, ¥) seçildi. Kaynak frontend/brand/logo.svg + logo-fullbleed.svg (maskable/Apple, içerik %82). Uygulama içi components/logo.tsx aynı çizim (elle senkron tutulmalı). Manifest Faz 10'da (vite-plugin-pwa).
  • ts-rs 12: backend/.cargo/config.toml → TS_RS_EXPORT_DIR=../frontend/src/types. TS adları: User, HouseholdSummary, Household, Member, Invite, CatalogItem, Catalog{Create,Update,Order}Request, RegisterRequest, LoginRequest, MeResponse, HealthResponse, ApiErrorBody, Group, Role.
  • QueryClient: 4xx tekrar denenmez; herhangi bir sorgu 401 alırsa me = null. Çıkışta qc.clear().
  • Adresler Türkçe: / (Panel), /defter, /plan, /birikim, /diger (mobil), /degerlendirme, /raporlar, /ayarlar, /giris, /kayit. Mobil alt menü: Panel, Defter, Plan, Birikim, Diğer.
  • Çıkış: qc.clear() KULLANMA (açık ekranlar silinen sorguya bağlı kalıyor) → önce me=null, sonra removeQueries (me hariç).
  • Canlıda SPA yönlendirmesi (Axum: bilinmeyen yol → index.html) Faz 3'te yapılmalı.
  • Kayıt ekranı: "Yeni hane kur" / "Davetle katıl"; davet bağlantısı /kayit?davet=KOD. Sunucu 409 → e-posta alanı, "Davet…" 400 → kod alanı.
  • Yönlendirme sonrası toast için mutateAsync + await kullanıldı (mutate() callback'leri bileşen kalkınca çalışmayabilir).
  • Kayıt politikası (kullanıcı kararı, 2026-11-12): Seçenek 1 → REGISTRATION=invite_only varsayılan; sistemde hiç hane yokken ilk kayıt yeni hane kurar (sunucu sahibi), sonra yalnızca davetle. open isteğe bağlı. Canlıda ilk hesabı kullanıcı /kayit'tan açar; demo hesaplar canlıya taşınmaz.
  • Prettier ayarı eklendi (önceden yoktu → VS Code kaydedince çift tırnağa çevirebilirdi).
  • Canlı imaj: node:26-alpine → rust:1.99-slim-trixie → debian:trixie-slim (ca-certificates + curl, uid 10001 kakeibo), 174 MB. Docker katman önbelleği için sahte lib/main ile bağımlılık derlemesi; kalıntılar *kakeibo* + .fingerprint silinir, gerçek kaynak touchlanır (yoksa sahte lib kullanılıyordu).
  • Önbellek: HTML no-cache, /assets/* 1 yıl immutable, diğer statik 1 saat. Bilinmeyen /api/* → JSON 404.
  • Canlı: domain kakeibo.ta1sph.website (DNS → 159.146.61.151, ev dış IP'si olmalı), Gitea Dokploy'a bağlı. Canlı MongoDB = ayrı Dokploy servisi kakeibo-kakeibomongo-fibzhc (rs0), kullanıcı kakeibo_app (readWrite/kakeibo).
  • Sürümler: Rust 1.99.1 (edition 2024), Axum 0.8, React 19, Vite 8, TypeScript 7, Tailwind 4.3, shadcn 4.23, Vitest 5, react-router 8, TanStack Query 5.

❓ Açık Konular

  • Canlı MongoDB auth kapalı (Dokploy replica set betiği keyFile kullanmıyor, özel Command'ı yok sayıyor). İç ağda, port kapalı. Ayrıntı: docs/DEPLOY.md §4.
  • Üye çıkarma / rol değiştirme / sahipliği devretme henüz yok (Ayarlar ekranıyla birlikte, Faz 2+).
  • Kapalı dönem yeniden açılırken başka açık dönem varsa davranış (Faz 6).
  • Altın kuru için veri kaynağı seçimi (Faz 8).
  • Aylık değerlendirme çıktı formatı kullanıcıdan gelecek (Faz 9).
  • Canlı MongoDB kurulum şekli (konteyner mi, doğrudan mı) Faz 3'te birlikte kontrol edilecek.

📝 İlerleme Günlüğü

2026-11-11 — Faz 0

  • Adım 1: Ortam kontrol edildi. CachyOS, fish. Node 26, npm 12, Docker 29 + Compose 5, Git, VS Code, gcc mevcut. Rust ve cargo-watch eksik; kurulum komutları verildi.
  • Adım 2: .vscode/ (extensions, settings, tasks, launch), .gitignore, .env.example ve monorepo klasörleri oluşturuldu. git init -b main.
  • Adım 3: CLAUDE.md, docs/MEMORY.md, docs/PHASES.md oluşturuldu. Gitea remote eklendi, ilk commit push edildi.
  • Adım 4: Rust kuruldu. docker-compose.dev.yml (mongo:7, rs0, healthcheck ile otomatik rs.initiate). Backend: Axum, yalnızca GET /api/health. Frontend: Vite react-ts şablonu, /api proxy → 8080, geçici durum ekranı. Kök package.json: concurrently ile npm run dev. Uçtan uca test edildi (Mongo PRIMARY, proxy çalışıyor).
  • Adım 5: docs/DATA_MODEL.md hazırlandı ve onaylandı. Faz 0 tamamlandı.

2026-11-11 — Faz 1

  • Adım 1: config.rs (env + doğrulama, JWT_SECRET ≥ 32), db.rs (5 sn timeout + ping), error.rs (AppError → {error:{code,message}} Türkçe; 5xx detayı yalnızca logda), state.rs, routes/ (health: DB yoksa 503). Açılışta DB/ayar hatasında anlaşılır log + çıkış kodu 1. Elle test: 4 senaryo geçti.
  • Adım 2: db/ modülü: col sabitleri, migrations.rs (schema_migrations, v1 = koleksiyonları oluştur), indexes.rs (DATA_MODEL §4 + tüm hane koleksiyonlarına (household_id, updated_at)). models/common.rs: UUID v7, new_meta, scope, touch. Açılışta db::prepare. 4 birim testi; idempotency ve tek açık dönem indeksi elle doğrulandı. uuid (v7) eklendi.
  • Adım 3: Kimlik doğrulama: auth/ (password argon2id + spawn_blocking, jwt, limiter, session cookie + AuthUser extractor), extract.rs (ValidJson = JSON + validator, Türkçe 400), services/account.rs (kayıt tek transaction: hane + owner + 13 kategori + 4 ödeme türü), services/seed.rs, routes/auth.rs (register/login/logout/me). Yeni crate'ler: argon2, jsonwebtoken, axum-extra(cookie), validator, time. 11 birim testi; 13 senaryo curl ile, rollback DB'de doğrulandı.
  • Adım 4: AuthUser DB doğrulaması + require_owner, services/invite.rs (create/list_active/revoke/claim), kayıt davet koduyla member olarak katılma (services/account.rs yeniden düzenlendi), routes/household.rs (GET /household, invites GET/POST/DELETE). 13 birim testi; 15 senaryo e2e (izolasyon 404, member 403, kod tekrar kullanımı, rollback) geçti.
  • Adım 5: models/group.rs, services/catalog.rs (kategori + ödeme türü ortak: list/create/update/reorder), routes/catalog.rs. Backend lib+bin'e ayrıldı (AppState::new). Entegrasyon testleri: tests/isolation.rs (3), tests/catalog.rs (4) — toplam 22 test. İzolasyon testi, kasıtlı açık eklenerek doğrulandı (yakaladı). db:reset artık test DB'lerini de siler. Dev-deps: tower, http-body-util. Faz 1 tamamlandı.

2026-11-12 — Faz 2

  • Adım 1: Tailwind v4 (@tailwindcss/vite), shadcn init (radix, preset nova; cn paketi = shadcn'in clsx+tailwind-merge yerine geçeni, incelendi), Inter (@fontsource-variable, çevrimdışı). index.css: grup + durum token'ları, odak halkası, money utility, reduced-motion. lib/format.ts (+22 vitest), lib/theme.tsx, lib/groups.ts, components/theme-toggle.tsx. Butonlar 44/48 px'e büyütüldü. Geçici önizleme ekranı (App.tsx), 375 px headless ekran görüntüsüyle iki temada kontrol edildi.
  • Adım 2: 3 logo taslağı (A indigo defter, B açık defter + para, C hanko) 512/64/32/16 px önizlemeyle sunuldu; kullanıcı A'yı seçti. scripts/icons.sh (npm run icons): favicon.svg/.ico, icon-192/512, icon-maskable-512, apple-touch-icon (180), brand/icon-1024 (Tauri). Maskable güvenli alan görsel olarak doğrulandı. index.html: ikon linkleri, theme-color, description.
  • Adım 3: ts-rs eklendi (17 tip), health ve hata gövdesi struct'a çevrildi (ApiErrorBody). Frontend: @tanstack/react-query, lib/api.ts (+7 vitest), lib/query.ts, lib/auth.ts, main.tsx'te QueryClientProvider. Geçici oturum paneli. Tarayıcı e2e (CDP betiği): yanlış şifre mesajı, giriş, yenilemede kalıcılık, httpOnly (document.cookie'de yok), çıkış — hepsi geçti.
  • Adım 4: react-router 8 (createBrowserRouter), RequireAuth/RequireGuest/Splash, AppLayout (masaüstü kenar çubuğu + mobil üst çubuk + 5'li alt menü, safe-area), Diğer sayfası, 7 yer tutucu sayfa, 404, lib/strings.ts, useDocumentTitle, lib/return-path.ts (+10 test, açık yönlendirme koruması), ThemeToggle compact. Tasarım önizlemesi → /dev/tasarim (yalnızca DEV). CDP e2e (10 kontrol) iki hata buldu, düzeltildi: giriş sonrası donus yarışı, çıkışta qc.clear(). Masaüstü içerik boşluğu düzeltildi.
  • Adım 5: react-hook-form, zod 4, @hookform/resolvers, sonner; shadcn input/label/checkbox/card (44 px / 20 px'e büyütüldü). components/form-field.tsx, components/toaster.tsx, features/auth/ (auth-shell, login-page, register-page, schemas + 8 vitest). Metinler t.auth. CDP e2e 11 kontrol geçti (boş form, yanlış şifre, giriş + toast, davet linki, kayıtlı e-posta → alan hatası, geçersiz davet → alan hatası, yeni hane). Frontend 47 test. Faz 2 tamamlandı.

2026-11-12 — Faz 3 öncesi

  • Kullanıcı api.http'deki kayıt örneğini (yeni@ornek.com) hesap sandı → dosya başlığına hazır hesaplar kutusu ve "bu bir KAYIT isteğidir" uyarısı eklendi.
  • Kayıt politikası: config.rs RegistrationMode, AppError::RegistrationClosed (403), account::new_household_allowed, GET /api/auth/registration (RegistrationInfo TS tipi). tests/registration.rs (2). Kayıt ekranı kapalıyken yalnızca davet modu + açıklama. .env/.env.example: REGISTRATION=invite_only. Prettier (.prettierrc.json, .prettierignore, format / format:check), tüm src biçimlendirildi (yalnızca boşluk).

2026-11-12 — Faz 3

  • Adım 1: tower-http (fs, compression gzip/br, trace). routes::app() + routes/spa.rs (ServeDir + index.html fallback + cache middleware), API fallback JSON 404, STATIC_DIR config, graceful shutdown (SIGTERM/Ctrl+C). Dockerfile, .dockerignore, docs/DEPLOY.md başlatıldı. İmaj yerelde çalıştırıldı (host network, 8090): 10 kontrol + tarayıcı ekran görüntüsü geçti. İlk derlemede Docker önbellek hilesi hatası (sahte lib.rs) bulundu, düzeltildi.
  • Adım 2: Mevcut tek MongoDB (butcem-mongo) Bütçem'e ait → kullanıcı ayrı MongoDB seçti. Dokploy MongoDB (replica set) kuruldu, kakeibo_app oluşturuldu, port yayını yok (iki servis de null). Sorunlar: kullanıcı şifreyi komuta düz yazıp paylaştı; Dokploy betiği root şifresini servis Args'ına düz yazıyor → iki şifre de mongosh içinde üretilerek yenilendi. passwordPrompt yapıştırma hatası (U_STRINGPREP). Auth açma denemesi: Dokploy özel Command'ı uygulamadı → auth kapalı kabul edildi (açık konu).