Files
neta/docs/self-hosted-redesign/phase-6-portal-backend.md
T

3.7 KiB
Raw Blame History

Faz 6 — Müşteri portalı backend geçişi

Tarih: 2026-07-16

Kapsam

Bu faz, mevcut portal görsel yapısını koruyarak tüm portal veri okumalarını ve revizyon mutation akışını Supabase'ten Better Auth + SQLite + domain service katmanına taşır.

Taşınan route'lar:

  • /portal
  • /portal/projects
  • /portal/projects/:id
  • /portal/tasks
  • /portal/revisions
  • portal layout/session/branding adapter'ı
  • proje detayındaki revizyon talebi Server Action'ı

Veri sözleşmeleri

Portal alanı Yeni kaynak
Client kimliği Better Auth session + iki yönlü app_profiles.client_id / clients.auth_user_id bağı
Proje listesi ve detayı client-scoped DomainService.listProjects/getProject
Public görevler DomainService.listTasks; is_public_to_client = true repository filtresi
Planning section client project scope doğrulamasından sonra listPlanningSections
Revizyon geçmişi project/client scoped revision repository
Revizyon talebi actor-derived client, aktif proje ve kota kontrolüyle BEGIN IMMEDIATE transaction
Proje dosyaları authenticated local file route; yalnızca portal visibility
Marka verisi server-rendered local branding service

Yetkilendirme

  • Portal actor yalnızca requirePortalBackend() tarafından Better Auth session'dan üretilir.
  • Browser'dan clientId, owner ID veya auth user ID alınmaz.
  • Client proje repository sorguları projects.client_id, clients.id ve clients.auth_user_id bağını birlikte doğrular.
  • Spoofed authUserId + clientId actor kombinasyonu proje, görev, revizyon ve dosya erişiminde reddedilir.
  • Project detail, planning, public task ve revision sorguları foreign project için NOT_FOUND davranışı verir.
  • Private veya başka client'a ait project asset portal tarafından okunamaz.
  • Revision action yalnızca projectId ve açıklama alır; client kimliği session actor'dan türetilir.

Revizyon kotası

Portal detay adapter'ı toplam kotayı değil server-side hesaplanan kalan hakkı gösterir:

used = rejected olmayan revision kayıtları
remaining = max(project.revision_quota - used, 0)
canRequest = project active && remaining > 0

Talep anındaki nihai kontrol UI sonucuna güvenmez. Service transaction içinde client-project eşleşmesini, proje durumunu ve kullanılmış kotayı yeniden hesaplar. Başarısız insert kota tüketmez.

Dosya ve branding

  • Portal-visible proje dosyası client session ile okunabilir.
  • Private proje dosyası aynı project client'ı tarafından dahi okunamaz.
  • Başka client'a ait portal-visible dosya NOT_FOUND döner.
  • Client/file scope kontrolünde clients.auth_user_id bağı ayrıca doğrulanır.
  • Portal layout application name ve logoları local branding service'ten server-side render eder.

Doğrulama

  • pnpm phase6:portal-boundary: sekiz portal runtime dosyasında Supabase import/env/erişimi olmadığını ve tüm server adapter'ların session-derived portal actor kullandığını doğrular.
  • pnpm phase2:domain-smoke: cross-client, spoofed actor, private task, foreign planning/revision, inactive project ve kota negatiflerini doğrular.
  • pnpm phase3:storage-smoke: portal/private/foreign/spoofed file authorization'ını doğrular.
  • pnpm phase6:smoke: Better Auth client cookie ile beş portal route'unu SSR eder; local branding, public/private task ayrımı, planning ve revision geçmişini doğrular; foreign project route'unun 404 olduğunu kontrol eder.
  • pnpm typecheck: başarılı.
  • Faz 6 dosyalarında hedefli ESLint: başarılı.
  • pnpm build: başarılı.
  • git diff --check: başarılı.

Portal tasarımı ve UX revizyonu Faz 10'a; chat/AI ve business backend'i Faz 7'ye bırakılmıştır.