74 lines
3.7 KiB
Markdown
74 lines
3.7 KiB
Markdown
# 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:
|
||
|
||
```text
|
||
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.
|