Files
neta/docs/self-hosted-redesign/neta-react-native-mobile-master-plan.md
T

1697 lines
64 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: Neta React Native Mobil Uygulama Ana Planı
description: Domain ile self-hosted Neta instance'larına bağlanan freelancer ve müşteri mobil uygulaması için ürün, API, mimari, ekran ve yayın planı.
status: planned
current_phase: "phase-0"
last_updated: 2026-07-25
owners:
- mobile
- backend-api
- product
related_documents:
- phase-9-mobile-api.md
- adr-0018-device-pairing.md
- neta-multilingual-i18n-master-plan.md
- neta-self-hosted-v3-master-plan.md
---
# Neta React Native Mobil Uygulama Ana Planı
## 1. Neta nedir?
Neta; freelancer'ların ve küçük stüdyoların kendi iş süreçlerini tek bir
self-hosted sistemden yönetebildiği, aynı zamanda müşterilerine ayrı portal hesabı
açabildiği bir iş ve iletişim platformudur.
Freelancer tarafında Neta'nın ana sorumlulukları:
- Müşteri ve müşteri ilişkilerini yönetmek.
- Proje, proje planı, görev, ilerleme ve revizyon süreçlerini takip etmek.
- Takvim, finans, günlük ve analiz verilerini tek yerde toplamak.
- Teklif, fatura, sözleşme ve abonelik gibi ticari kayıtları yönetmek.
- Yapay zekâ destekli sohbet, proje risk analizi ve finans analizi sunmak.
- Workspace adı, light/dark logo, favicon, renkler, görünüm, dil ve AI
sağlayıcısı gibi instance ayarlarını self-host eden kişinin yönetmesini sağlamak.
- Türkçe ve İngilizce ile başlamak; yeni dillerin ve domain içerik
çevirilerinin admin tarafından eklenebilmesini sağlamak.
Müşteri portalı tarafında Neta'nın ana sorumlulukları:
- Müşterinin kendisiyle paylaşılan projeleri ve ilerlemeyi görmesi.
- Public olarak paylaşılan görevleri takip etmesi.
- Proje planını ve proje detayını kendi dilinde incelemesi.
- Revizyon hakkını görmesi ve yeni revizyon talebi oluşturması.
- Profil, şifre, tema ve adminin aktif ettiği diller arasında kendi tercihini
yönetmesi.
Mobil uygulama ayrı bir SaaS backend'e bağlanmayacaktır. Her kullanıcı,
kendisinin veya hizmet aldığı freelancer'ın self-host ettiği Neta domain'ine
bağlanır. Dolayısıyla mobil uygulama genel bir Neta istemcisidir; veri sahibi,
kimlik sağlayıcısı ve iş mantığı girilen domain'deki Neta instance'ıdır.
## 2. Mobil ürün vizyonu
Temel akış:
```text
Uygulama açılır
-> Kullanıcı Neta domain'ini girer
-> Instance discovery ve güvenlik kontrolü yapılır
-> Workspace markası, tema, diller ve yetenekler yüklenir
-> Kullanıcı email/şifre ile giriş yapar
-> /api/v1/me kullanıcı rolünü döndürür
-> Freelancer ise yönetim uygulaması açılır
-> Client ise müşteri portalı açılır
```
Tek bir iOS/Android uygulama paketi iki rolü de destekleyecektir. Aynı domain
ekranı, aynı auth altyapısı ve aynı API client kullanılır; authenticated shell
ve izin verilen ekranlar role/capability ile ayrılır.
### 2.1. Birinci sürüm hedefi
Birinci üretim sürümünde:
- iOS ve Android desteklenecek.
- Domain discovery, email/şifre girişi, güvenli oturum ve çıkış olacak.
- Freelancer için dashboard, müşteriler, projeler, görevler, takvim, finans,
günlük, analiz, AI sohbet ve temel ayarlar bulunacak.
- Müşteri için portal dashboard, projeler, proje detayı, görevler,
revizyonlar ve kişisel ayarlar bulunacak.
- Instance branding, light/dark tema ve instance tarafından yönetilen diller
mobilde uygulanacak.
- Dinamik içerik formları aktif diller kadar tab/panel sunacak.
- Read cache bulunacak; internet olmadan yapılan mutation ilk sürümde sessizce
kuyruğa alınmayacak.
- Tek aktif instance ile başlanacak; veri modeli birden fazla kayıtlı instance'a
geçişi engellemeyecek.
### 2.2. İlk sürüm dışında kalabilecekler
- Tam offline mutation ve çakışma çözümü.
- Apple/Google sosyal giriş.
- Tablet için tamamen ayrı bilgi mimarisi; responsive two-pane destek yeterli.
- Müşteri ile freelancer arasında gerçek zamanlı genel mesajlaşma; mevcut AI
sohbetiyle karıştırılmayacak.
- Her self-hosted instance için ayrı App Store binary/white-label build.
- Background sync ile sınırsız veri indirme.
## 3. Mevcut codebase incelemesi ve mobil hazırlık durumu
Web uygulaması Next.js 16, React 19, Better Auth, SQLite, better-sqlite3 ve
Drizzle ORM üzerindedir. Supabase uygulama runtime'ından çıkarılmıştır.
Domain iş kuralları `DomainService` ve owner/client scope kontrolleri içinde
toplandığı için aynı servislerin REST API route'larından tekrar kullanılması
mümkündür.
### 3.1. Bugün hazır olan mobil sözleşmeler
| Endpoint | Durum | Mobilde kullanımı |
| --- | --- | --- |
| `GET /.well-known/neta` | Hazır | Domain discovery, instance ID, API linkleri, diller ve capability |
| `GET /api/v1/meta` | Hazır | Workspace, branding, minimum client sürümü ve capability |
| `GET /api/v1/health` | Hazır | Instance readiness kontrolü |
| `GET /api/v1/me` | Hazır | User, role, client bağı, tercih ve locale sonucu |
| `PATCH /api/v1/me/preferences` | Hazır | Kullanıcı dil ve tema tercihi |
| `GET /api/v1/localization/catalog` | Hazır | Instance tarafından özelleştirilen UI katalogları |
| `/api/auth/*` | Web için hazır | Better Auth native entegrasyonu ve multi-domain testi gerekli |
| `POST /api/files` | Web API olarak hazır | v1 envelope, absolute URL ve mobil upload kontratı gerekli |
| `GET /api/files/:id` | Hazır | Yetkili dosya görüntüleme; native auth testi gerekli |
### 3.2. Mobil için henüz eksik backend yüzeyi
Müşteri, proje, görev, takvim, finans, günlük ve business işlemlerinin
çoğu Server Action veya doğrudan server component veri yüklemesi kullanıyor.
Mobil uygulama Server Action çağırmayacak. Bunlar `/api/v1` altında kaynak
API'lerine dönüştürülmelidir.
Mevcut `DomainService` şu alanları destekliyor ve yeni API route'ları bu katmanı
kullanmalıdır:
- Clients ve client activities.
- Projects, planning sections, project tasks ve revisions.
- Tasks.
- Calendar events.
- Finance transactions.
- Journal entries.
- Chat sessions ve messages.
- Dashboard ve analytics hesapları.
- Proposals, contracts, invoices ve subscriptions.
### 3.3. Mevcut auth kararındaki açık nokta
`phase-9-mobile-api.md` bugün Better Auth cookie session'ını ilan ediyor;
`adr-0018-device-pairing.md` ise owner cihazları için opaque access/refresh token
pairing modelini kabul edilmiş fakat uygulanmamış karar olarak tutuyor.
Güncel Better Auth, Expo istemcisi için `@better-auth/expo` ile cookie'leri
`expo-secure-store` içinde saklayan resmi bir native akış sunuyor. Hızlı MVP
için en kısa yol budur; fakat mevcut ADR sessizce geçersiz sayılamaz.
Faz 0'da zorunlu karar:
1. Multi-domain runtime base URL ile Better Auth Expo entegrasyon spike'ı yapılır.
2. Cookie izolasyonu, revoke, şifre değişikliği, disabled user ve restore
davranışı test edilir.
3. Sonuç yeterliyse ADR-0018, resmi native secure-cookie modelini ilk sürüm
olarak kabul edecek biçimde revize edilir; device pairing ikinci güvenlik modu
olur.
4. Sonuç yeterli değilse ADR-0018 aynen uygulanır ve owner mobil girişi pairing
tamamlanmadan production'a çıkmaz.
5. Client portal oturumu için de ayrı lifecycle kararı kayda geçirilir.
Bu planın geri kalanı hızlı MVP için resmi Better Auth Expo secure-cookie
entegrasyonunu varsayar; Faz 0 kalite kapısı bu varsayımı onaylamak zorundadır.
## 4. Temel mimari kararlar
### 4.1. React Native dağıtımı
Tercih edilen başlangıç:
- Expo tabanlı React Native.
- Expo Router ile typed file-based routing.
- TypeScript strict mode.
- iOS ve Android için development build; Expo Go yalnız ilk UI spike'larında.
- EAS Build kolay yol olarak desteklenir; local Xcode/Gradle build zorunlu fallback
olarak belgelenir. Self-host backend kullanmak EAS'e bağımlı değildir.
Expo Router yeni Expo projeleri için resmi öneridir ve typed route, deep link ve
native stack/tab yapısı sağlar. Kaynaklar:
- [Expo Router introduction](https://docs.expo.dev/router/introduction/)
- [Expo authentication and protected routes](https://docs.expo.dev/router/advanced/authentication/)
- [Better Auth Expo integration](https://better-auth.com/docs/integrations/expo)
- [Expo local data storage guidance](https://docs.expo.dev/develop/user-interface/store-data/)
Sürüm numaraları plana sabitlenmeyecek. Mobil uygulama bootstrap edildiği gün
stabil Expo SDK ve onunla uyumlu React Native sürümü seçilip lockfile'a
sabitlenecektir; canary/beta sürüm production tabanı olmayacaktır.
### 4.2. Repository yerleşimi
Mevcut Next.js kökünü taşımak ilk mobil fazda gereksiz risk yaratır. Önerilen
kademeli workspace yapısı:
```text
neta/
app/ # mevcut Next.js web uygulaması
server/ # mevcut backend/domain katmanı
mobile/ # Expo React Native uygulaması
src/app/ # Expo Router route'ları
src/features/ # dikey feature modülleri
src/components/ # mobil ortak UI
src/lib/ # API, auth, i18n, theme, storage
assets/
app.config.ts
eas.json
package.json
packages/
api-contracts/ # transport-safe tip/schema ve API contract'ları
design-tokens/ # DOM bağımsız semantik tokenlar
pnpm-workspace.yaml
```
Kurallar:
- Web uygulaması ilk aşamada `apps/web` altına taşınmayacak.
- `server-only`, Next.js, Drizzle veya better-sqlite3 mobil bundle'a import
edilmeyecek.
- Paylaşılan paketlerde yalnız JSON-safe tipler, Zod şemaları, enumlar ve saf
yardımcılar bulunacak.
- API contract paketinin runtime bağımlılığı minimum tutulacak.
### 4.3. Poyraz UI ve mobil tasarım sistemi
Mevcut `poyraz-ui` React, Tailwind, Radix ve web DOM odaklıdır; React Native
içinde doğrudan kullanılamaz. Mobilde tasarım dili korunacak, web component
implementasyonu taşınmayacaktır.
Mobil UI yaklaşımı:
- `packages/design-tokens`: renk rolleri, spacing, radius, typography ve shadow
değerleri.
- `mobile/src/components/ui`: `Button`, `TextField`, `SelectSheet`, `Card`,
`StatCard`, `Badge`, `Tabs`, `SegmentedControl`, `Dialog`, `BottomSheet`,
`Toast`, `EmptyState`, `Skeleton`, `Screen`, `Header` gibi Neta primitives.
- Başlangıçta React Native `StyleSheet` ve semantik tokenlar kullanılacak;
yalnız gerçek ihtiyaç varsa yeni styling dependency eklenecek.
- Web'deki `default`, `secondary` ve `shine` davranışı native press/animation
diliyle yeniden yorumlanacak. Hover mobil kontrat değildir; pressed, focused,
disabled ve loading state'leri tanımlanacak.
- Light/dark kontrastı ve dynamic primary/accent renkleri aynı semantik rollerle
uygulanacak.
### 4.4. İstemci katmanları
```text
Screen / Route
-> Feature hook
-> Query veya mutation
-> Instance-bound API client
-> /api/v1
-> auth/actor
-> DomainService
-> repository / SQLite
```
Ekranlar ham `fetch` çağrısı yapmaz. Her istek aktif instance kaydından türetilen
API client üzerinden gider.
### 4.5. İstemci state sınırı
- Server state: TanStack Query.
- Küçük local UI state: React state/reducer.
- Aktif instance, onboarding ve public metadata: küçük bir external store veya
context; büyük global state kütüphanesi ilk günden eklenmez.
- Token/cookie: SecureStore ve Better Auth native adapter.
- Secret olmayan instance listesi, katalog cache metadata'sı ve query cache:
AsyncStorage veya seçilen kalıcı cache adapter.
- Form state: Basit formlarda controlled input; çok dilli/büyük formlarda
React Hook Form ve ortak Zod şemaları.
## 5. Domain bağlantısı ve instance discovery
### 5.1. Domain giriş ekranı
Alanlar ve davranış:
- Tek input: `neta.example.com` veya `https://neta.example.com`.
- Kullanıcı protokol yazmazsa production'da `https://` eklenir.
- Path, query, fragment ve URL credential reddedilir.
- Domain normalize edilince ekranda son origin gösterilir.
- `Bağlan` aksiyonu loading, timeout ve tekrar dene durumuna sahiptir.
- Son başarılı instance, oturum yoksa hızlı seçim kartı olarak gösterilebilir.
- QR ile instance URL okuma ikinci iterasyonda eklenebilir; QR içeriği yine aynı
validasyondan geçer.
### 5.2. Discovery state machine
```text
idle
-> normalizing
-> discovering
-> validating-discovery
-> checking-health
-> loading-meta
-> loading-public-catalog
-> ready-for-auth
Her adım -> recoverable-error | incompatible | unhealthy | tls-error
```
Sıralama:
1. Origin normalize edilir.
2. `GET /.well-known/neta` en fazla tanımlı timeout ile çağrılır.
3. En fazla üç redirect izlenir; HTTPS'ten HTTP'ye downgrade reddedilir.
4. `protocol === "neta"` ve desteklenen `discoveryVersion` doğrulanır.
5. Discovery içindeki API URL'lerinin aynı güvenilir origin'de kaldığı
doğrulanır.
6. `GET /api/v1/health` ile DB/migration readiness kontrol edilir.
7. `GET /api/v1/meta` alınır; `instance.id === discovery.instanceId`
doğrulanır.
8. Mobil client sürümü `minimumSupportedVersion` ile karşılaştırılır.
9. Platform ve gerekli capability kontrol edilir.
10. Branding ve public localization catalog yüklenir.
11. Secret olmayan instance metadata'sı yerel kayda yazılır.
12. Auth ekranı workspace logosu ve adıyla açılır.
Temel mobil uyumluluğu `capabilities` string listesinde `mobile-v1` ile ilan
edilir. Sürüm, durum ve rol/erişim detayları ayrı `capabilityDetails` listesinden
okunur; `planned` kayıtlar kullanılabilir feature olarak değerlendirilmez.
### 5.3. HTTP geliştirme politikası
- Production binary remote HTTP origin'e credential göndermez.
- `localhost`, `127.0.0.1`, Android emulator `10.0.2.2` ve açıkça tanımlanmış
LAN development adresleri yalnız development build'de kullanılabilir.
- TLS sertifika hatası için `yine de devam et` butonu production'da bulunmaz.
- Instance origin değişirse credential otomatik taşınmaz.
- Aynı origin daha sonra farklı `instanceId` döndürürse restore/yeni instance
uyarısı verilir ve eski session silinir.
### 5.4. Yerel instance kaydı
```ts
type StoredInstance = {
origin: string;
instanceId: string;
apiBaseUrl: string;
workspaceName: string;
lightLogoUrl: string | null;
darkLogoUrl: string | null;
faviconUrl: string | null;
discoveryVersion: number;
apiVersion: string;
catalogVersion: number;
lastConnectedAt: string;
};
```
Secret storage key'leri `instanceId` ile namespace edilir. Aynı kullanıcının
farklı Neta kurulumlarındaki cookie veya tokenları birbirine karışmaz.
## 6. Authentication ve oturum yönetimi
### 6.1. Login akışı
1. Instance discovery tamamlanır.
2. Runtime `baseURL = instance.origin` olan Better Auth native client oluşturulur.
3. Kullanıcı email ve şifre girer.
4. Better Auth `signIn.email` akışı kullanılır.
5. Native cookie/session materyali SecureStore'da instance'a özel prefix ile tutulur.
6. `GET /api/v1/me` çağrılır.
7. `role=freelancer` owner shell'e, `role=client` portal shell'e gider.
8. `disabled`, eksik client bağı veya süresi geçmiş session 401 olarak temizlenir.
Login ekranında dil seçici olmayacak. Public auth ekranı instance default locale
ile gelir. Girişten sonra `/me.localization.resolvedLocale` kullanılır.
### 6.2. Server tarafında gerekli auth değişiklikleri
- `@better-auth/expo` server plugin'i eklenir.
- `neta://` production scheme trusted origin allowlist'e eklenir.
- Development `exp://` wildcard'ları yalnız development config'de açılır.
- Native login, logout, session refresh, password change ve cookie propagation
gerçek cihazda test edilir.
- CORS/header davranışı reverse proxy arkasında test edilir; native client
geldi diye web origin kontrolleri gevşetilmez.
- Auth audit event'lerine `client: mobile`, platform ve app version gibi hassas
olmayan alanlar eklenebilir.
- Rate limit login ve password endpoint'lerinde korunur.
### 6.3. Session davranışı
- App foreground'a geldiğinde session tamamen her render'da değil, stale süresi
dolmuşsa kontrol edilir.
- Her authenticated 401 sonrası tek bir session yenileme/doğrulama denemesi yapılır.
- Yenileme başarısızsa query cache temizlenir ve login ekranına gidilir.
- Logout server'a gönderilir; başarısız olsa bile cihazdaki session materyali
güvenli biçimde temizlenir ve kullanıcı bilgilendirilir.
- Şifre değişikliğinde server politikasına göre mevcut/tüm session'lar revoke edilir.
- App switcher snapshot'larında hassas finans ve profil verisi gizlenebilir.
### 6.4. Register ve invitation
- Mobil uygulamadan ilk self-host admin hesabı oluşturmak v1 hedefi değildir;
instance ilk kurulumu web üzerinden tamamlanır.
- Portal müşterisi davet linkini mobilde açtığında universal link ile app'e
gelebilir.
- Davet kabul akışı ilk sürümde güvenli web ekranına yönlendirilebilir; tam
native kabul daha sonraki fazda API sözleşmesiyle eklenir.
- Password reset linkleri deep link ile mobile dönebilir; ilk iterasyonda web
fallback her zaman korunur.
## 7. API v1 genel sözleşmesi
### 7.1. Ortak yanıt
Başarı:
```json
{
"ok": true,
"data": {}
}
```
Hata:
```json
{
"ok": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Debug/fallback message",
"details": {
"messageKey": "validation.project.nameRequired",
"fieldErrors": {
"name": ["validation.required"]
}
}
}
}
```
Mobil mantık `message` string'ine bağlanmaz. Akış `code`, alan hataları
`fieldErrors`, kullanıcı metni `messageKey` ile çözülür.
### 7.2. Ortak request header'ları
- `Authorization` veya Better Auth native session header/cookie'si.
- `Accept: application/json`.
- `Accept-Language: <resolved user locale>`.
- `X-Neta-Client: mobile`.
- `X-Neta-Client-Version: <semver>`.
- `X-Neta-Platform: ios|android`.
- Mutation'larda `Idempotency-Key` desteklenmesi önerilir.
### 7.3. Listeleme sözleşmesi
Yeni liste endpoint'leri baştan cursor pagination ile tasarlanır:
```http
GET /api/v1/projects?cursor=opaque&limit=30&status=active&search=neta
```
```json
{
"ok": true,
"data": {
"items": [],
"pageInfo": {
"nextCursor": null,
"hasNextPage": false
}
}
}
```
- `limit` default 30, maksimum 100.
- Cursor opaque'tir; client DB ID/timestamp birleşimini varsaymaz.
- Filtre ve sort allowlist ile doğrulanır.
- Search normalize edilir ve maksimum uzunluğa sahiptir.
### 7.4. Tarih, para ve ID
- Timestamp: UTC ISO-8601.
- Yalnız takvim günü ifade eden alan: `YYYY-MM-DD`.
- Para: integer minor unit + ISO 4217 currency.
- Yüzde: integer 0100 veya sözleşmede belirtilen basis point.
- ID: opaque string; client UUID olduğunu varsaymaz.
- Kullanıcı timezone'u `/me/preferences` içinde döner ve görsel formatlamada
kullanılır.
### 7.5. Lokalize resource sözleşmesi
Detay yanıtı:
```json
{
"resource": {},
"localized": {},
"locale": "en",
"fallbackChain": ["en", "tr"]
}
```
Owner edit formu `resource` ve tüm `translations` verisini alır. Portal/read-only
ekran normalde `localized` alanını kullanır. Owner mutation:
```json
{
"status": "active",
"translations": {
"tr": { "name": "Neta Mobil", "description": "..." },
"en": { "name": "Neta Mobile", "description": "..." }
}
}
```
### 7.6. Eşzamanlı güncelleme
- Update response `updatedAt` veya açık `version` alanı döndürür.
- Client mutation son bilinen version'ı gönderir.
- Eski kayda yazma `409 CONFLICT` döndürür.
- Mobil form kullanıcıya `Sunucudaki değişikliği yükle` ve kontrollü yeniden
uygulama seçeneği sunar; sessiz overwrite yapmaz.
## 8. Endpoint envanteri
Bu bölüm hedef API'yi tanımlar. `Hazır` olmayan endpoint'ler, ilgili ekran
yazılmadan önce backend fazında tamamlanacaktır.
### 8.1. Public, discovery ve localization
| Method | Endpoint | Amaç | Durum |
| --- | --- | --- | --- |
| GET | `/.well-known/neta` | Instance discovery | Hazır |
| GET | `/api/v1/meta` | Marka, sürüm, capability | Hazır |
| GET | `/api/v1/health` | Readiness | Hazır |
| GET | `/api/v1/localization/catalog` | UI katalog indirme | Hazır |
### 8.2. Session ve kullanıcı
| Method | Endpoint | Rol | Amaç |
| --- | --- | --- | --- |
| POST | `/api/auth/sign-in/email` | Public | Better Auth login |
| POST | `/api/auth/sign-out` | Session | Logout |
| GET | `/api/v1/me` | Session | Rol, profil, tercih, locale |
| PATCH | `/api/v1/me/preferences` | Owner/client | Dil, tema, timezone ve desteklenen tercih alanları |
| PATCH | `/api/v1/me/profile` | Owner/client | Display name ve avatar metadata |
| POST | `/api/v1/me/password` | Owner/client | Şifre değiştirme |
| GET | `/api/v1/me/sessions` | Owner/client | Aktif cihaz/session listesi; auth modeli kararına bağlı |
| DELETE | `/api/v1/me/sessions/:id` | Owner/client | Session revoke; auth modeli kararına bağlı |
### 8.3. Owner dashboard ve analytics
| Method | Endpoint | Amaç |
| --- | --- | --- |
| GET | `/api/v1/dashboard?range=month` | Stat kartları, finans/mood trendi, son projeler/müşteriler |
| GET | `/api/v1/analytics?range=month` | Gelir-gider, proje, görev ve performans analizleri |
Dashboard toplu response vermelidir; mobil ilk açılışta 810 ayrı request
atılmamalıdır.
### 8.4. Clients
| Method | Endpoint | Amaç |
| --- | --- | --- |
| GET | `/api/v1/clients` | Liste, search, status ve pipeline filtreleri |
| POST | `/api/v1/clients` | Çok dilli müşteri oluşturma |
| GET | `/api/v1/clients/:id` | Detay, ilişkiler ve portal durumu |
| PATCH | `/api/v1/clients/:id` | Bilgi, durum, pipeline ve çeviri güncelleme |
| DELETE | `/api/v1/clients/:id` | Archive/delete politikasına göre kaldırma |
| GET | `/api/v1/clients/:id/activities` | Not, arama, toplantı, email aktiviteleri |
| POST | `/api/v1/clients/:id/activities` | Aktivite ekleme |
| POST | `/api/v1/clients/:id/portal-invitations` | Portal hesabı/daveti ve default locale |
| PATCH | `/api/v1/clients/:id/portal-locale` | Admin tarafından başlangıç dilini güncelleme |
### 8.5. Projects, plan, revisions ve assets
| Method | Endpoint | Amaç |
| --- | --- | --- |
| GET | `/api/v1/projects` | Liste, filtre, search |
| POST | `/api/v1/projects` | Proje ve localized alanlar oluşturma |
| GET | `/api/v1/projects/:id` | Detay, müşteri, ilerleme, çeviriler |
| PATCH | `/api/v1/projects/:id` | Proje güncelleme ve tamamlama |
| DELETE | `/api/v1/projects/:id` | Proje kaldırma |
| GET | `/api/v1/projects/:id/planning-sections` | Plan bölümleri |
| POST | `/api/v1/projects/:id/planning-sections` | Plan bölümü ekleme |
| PATCH | `/api/v1/projects/:id/planning-sections/:sectionId` | Plan güncelleme/sıralama |
| DELETE | `/api/v1/projects/:id/planning-sections/:sectionId` | Plan bölümü silme |
| GET | `/api/v1/projects/:id/revisions` | Owner revizyon listesi ve allowance |
| PATCH | `/api/v1/projects/:id/revisions/:revisionId` | Revizyon durumu |
| GET | `/api/v1/projects/:id/assets` | Proje dosyaları |
| POST | `/api/v1/projects/:id/assets` | Multipart dosya yükleme |
| DELETE | `/api/v1/projects/:id/assets/:assetId` | Proje dosyası silme |
### 8.6. Tasks
| Method | Endpoint | Amaç |
| --- | --- | --- |
| GET | `/api/v1/tasks` | Liste; status, priority, project, client ve tarih filtresi |
| POST | `/api/v1/tasks` | Localized görev oluşturma |
| GET | `/api/v1/tasks/:id` | Görev detayı |
| PATCH | `/api/v1/tasks/:id` | Alan/status güncelleme |
| DELETE | `/api/v1/tasks/:id` | Görev silme |
| POST | `/api/v1/tasks/:id/complete` | Idempotent tamamlama kısayolu |
Drag/drop mutation tek tek tüm task objesini değil `{status, position?}`
patch'ini göndermelidir. Mevcut schema kalıcı task sırası tutmuyorsa mobilde
görsel sıra değiştirme ilk sürümde server sırası vaadi vermemelidir.
### 8.7. Calendar
| Method | Endpoint | Amaç |
| --- | --- | --- |
| GET | `/api/v1/calendar/events?from=&to=` | Aralık bazlı etkinlik listesi |
| POST | `/api/v1/calendar/events` | Etkinlik oluşturma |
| GET | `/api/v1/calendar/events/:id` | Etkinlik detayı |
| PATCH | `/api/v1/calendar/events/:id` | Etkinlik güncelleme |
| DELETE | `/api/v1/calendar/events/:id` | Etkinlik silme |
Calendar API sınırsız tüm kayıtları döndürmez. Aylık görünüm bir
önceki ve sonraki görünen haftayı kapsayan date range ister.
### 8.8. Finance
| Method | Endpoint | Amaç |
| --- | --- | --- |
| GET | `/api/v1/finance/summary?month=` | Gelir, gider, brüt, KDV tahmini, net, bekleyen |
| GET | `/api/v1/finance/transactions` | Cursor listesi ve filtreler |
| POST | `/api/v1/finance/transactions` | Gelir/gider oluşturma |
| GET | `/api/v1/finance/transactions/:id` | Detay |
| PATCH | `/api/v1/finance/transactions/:id` | Güncelleme |
| DELETE | `/api/v1/finance/transactions/:id` | Silme |
| POST | `/api/v1/finance/analysis` | AI finans analizi; stabil v1 error/stream kontratı |
Vergi/KDV sonuçları hukuki/mali tavsiye olarak sunulmaz. Oran instance ayarına
taşınmadığı sürece UI hard-coded `%20` varsayımı yapmamalıdır.
### 8.9. Journal
| Method | Endpoint | Amaç |
| --- | --- | --- |
| GET | `/api/v1/journal/entries?from=&to=` | Tarih aralığı günlükleri |
| PUT | `/api/v1/journal/entries/:date` | Gün bazında idempotent create/update |
| GET | `/api/v1/journal/entries/:id` | Detay |
| PATCH | `/api/v1/journal/entries/:id` | Tarih/içerik güncelleme |
| DELETE | `/api/v1/journal/entries/:id` | Silme |
### 8.10. AI chat ve analizler
| Method | Endpoint | Amaç |
| --- | --- | --- |
| GET | `/api/v1/chat/sessions` | Sohbet listesi |
| POST | `/api/v1/chat/sessions` | Yeni sohbet |
| DELETE | `/api/v1/chat/sessions/:id` | Sohbeti silme |
| GET | `/api/v1/chat/sessions/:id/messages` | Mesaj geçmişi |
| POST | `/api/v1/chat/sessions/:id/messages` | Streaming AI mesajı |
| POST | `/api/v1/projects/:id/risk-analysis` | Proje risk analizi |
- Mobil stream formatı AI SDK'nin web hook'una kapalı olmamalı; SSE veya açık
NDJSON kontratı belgelenmelidir.
- Abort/cancel desteklenir.
- `UPSTREAM_ERROR`, `UPSTREAM_TIMEOUT`, `SERVICE_UNAVAILABLE` ayrı gösterilir.
- API provider key ve model secret hiçbir response'a girmez.
### 8.11. Business
| Kaynak | Endpoint kökü | İşlemler |
| --- | --- | --- |
| Proposals | `/api/v1/business/proposals` | List, create, detail, update, delete |
| Contracts | `/api/v1/business/contracts` | List, create, detail, update, delete |
| Invoices | `/api/v1/business/invoices` | List, create, detail, update, delete |
| Subscriptions | `/api/v1/business/subscriptions` | List, create, detail, update, delete |
Web'de bazı business ekranları diğer core ekranlar kadar tamamlanmış değil.
Mobil parity, backend/domain modeli olmayan görsel vaatler üretmemeli; önce web ve
API davranışının product acceptance kriteri yazılmalıdır.
### 8.12. Owner settings
| Method | Endpoint | Amaç |
| --- | --- | --- |
| GET/PATCH | `/api/v1/settings/general` | Workspace, footer ve genel ayarlar |
| GET/PATCH | `/api/v1/settings/appearance` | Renkler, radius ve default tema |
| POST | `/api/v1/settings/appearance/assets` | Light logo, dark logo ve favicon upload |
| DELETE | `/api/v1/settings/appearance/assets/:kind` | Marka asset'i kaldırma |
| GET/PATCH | `/api/v1/settings/ai` | Provider/model/key yönetimi; key response'ta maskeli |
| GET | `/api/v1/settings/locales` | Dil listesi ve kullanım durumu |
| POST | `/api/v1/settings/locales` | Draft dil ekleme |
| GET/PATCH | `/api/v1/settings/locales/:code` | Dil metadata/lifecycle |
| GET/PUT | `/api/v1/settings/locales/:code/translations` | UI çeviri editörü |
| POST | `/api/v1/settings/locales/import` | Translation import |
| GET | `/api/v1/settings/locales/export` | Translation export |
AI key mutation ayrı step-up auth veya mevcut şifre onayı gerektirebilir.
Mevcut key mobil cihaza geri döndürülmez.
### 8.13. Portal API
Portal endpoint'leri ayrı isim alanında olmalı ve `clientId` query/body'den
güven kaynağı olarak alınmamalıdır. Client scope session'dan türetilir.
| Method | Endpoint | Amaç |
| --- | --- | --- |
| GET | `/api/v1/portal/dashboard` | Müşteri stats, projeler ve ilerleme |
| GET | `/api/v1/portal/projects` | Session client'ın projeleri |
| GET | `/api/v1/portal/projects/:id` | Localized proje, plan, public tasks, allowance ve revisions |
| GET | `/api/v1/portal/tasks` | Yalnız client'a public görevler |
| GET | `/api/v1/portal/revisions` | Müşterinin revizyonları |
| POST | `/api/v1/portal/projects/:id/revisions` | Kaynak locale ile revizyon talebi |
| GET/PATCH | `/api/v1/portal/profile` | Kendi profil bilgisi |
Cross-client negatif testleri her endpoint için zorunludur. Portal client owner
endpoint'lerini capability görse bile çağıramaz.
## 9. Mobil navigasyon ve route yapısı
### 9.1. Expo Router taslağı
```text
mobile/src/app/
_layout.tsx
index.tsx # bootstrap kararı
(connection)/
connect.tsx
checking.tsx
incompatible.tsx
(auth)/
login.tsx
forgot-password.tsx
(owner)/
_layout.tsx
(tabs)/
index.tsx # dashboard
work.tsx # clients/projects/tasks hub
calendar.tsx
finance.tsx
more.tsx
analytics/index.tsx
clients/index.tsx
clients/[id].tsx
projects/index.tsx
projects/[id].tsx
tasks/index.tsx
journal/index.tsx
chat/index.tsx
chat/[id].tsx
business/proposals/index.tsx
business/contracts/index.tsx
business/invoices/index.tsx
business/subscriptions/index.tsx
settings/_layout.tsx
settings/general.tsx
settings/appearance.tsx
settings/profile.tsx
settings/security.tsx
settings/ai.tsx
settings/language.tsx
settings/languages/index.tsx
settings/languages/[code].tsx
settings/languages/[code]/translations.tsx
(portal)/
_layout.tsx
(tabs)/
index.tsx # portal dashboard
projects.tsx
tasks.tsx
revisions.tsx
settings.tsx
projects/[id].tsx
settings/profile.tsx
settings/security.tsx
settings/appearance.tsx
settings/language.tsx
(modals)/
client-form.tsx
client-activity-form.tsx
portal-invitation.tsx
project-form.tsx
planning-section-form.tsx
task-form.tsx
calendar-event-form.tsx
finance-transaction-form.tsx
journal-entry-form.tsx
revision-request.tsx
```
Route grupları security boundary değildir. Her API request server tarafında actor
ve role kontrolünden geçer.
### 9.2. Owner tab yapısı
Telefon alt navigasyonu en fazla beş ana hedef taşır:
1. Ana Sayfa
2. İşler: Müşteriler, projeler ve görevler hub'ı
3. Takvim
4. Finans
5. Daha Fazla: Analiz, günlük, AI, business ve ayarlar
Müşteriler/projeler/görevler sık kullanılıyorsa `İşler` ekranında son
kayıtlar ve büyük hızlı aksiyonlar bulunur. Tablet'te side rail kullanılabilir.
### 9.3. Portal tab yapısı
1. Ana Sayfa
2. Projeler
3. Görevler
4. Revizyonlar
5. Ayarlar
## 10. Ekran ve feature planı
### 10.1. Ortak bootstrap ekranları
#### Splash/bootstrap
- Kayıtlı instance ve session var mı kontrol eder.
- Branding cache varsa doğru light/dark logo ile açılır.
- Session kararı tamamlanmadan owner veya portal ekranı flash etmez.
- Migration/restore nedeniyle instance ID değiştiğinde connect ekranına döner.
#### Domain connect
- Domain input, son instance, hata detayı ve retry.
- DNS bulunamadı, timeout, TLS, Neta değil, eski API, bakım ve min version
hataları ayrı kullanıcı mesajlarına sahiptir.
#### Login
- Instance logosu, workspace adı, email, şifre, şifreyi göster ve unuttum.
- Domain değiştir aksiyonu.
- Dil seçici yok; instance default catalog kullanılır.
- Rate limit ve disabled account hataları genel `hatalı istek` altında kaybolmaz.
### 10.2. Owner dashboard
- Range seçici: hafta/ay/yıl veya backend'in desteklediği mevcut range'ler.
- Net kazanç, aktif proje, tamamlanan görev ve ortalama mood stat kartları.
- Gelir/gider özeti.
- Mood ve enerji trendi.
- Son projeler ve son müşteriler.
- Pull-to-refresh ve cache timestamp.
- Boş veride ilk kayıt CTA'ları.
- Grafikler screen reader için metinsel özet de sunar.
### 10.3. Analytics
- Tarih aralığı seçimi.
- Gelir/gider/net trendi.
- Proje status dağılımı.
- Görev tamamlama ve performans.
- Proje bazlı gelir.
- Grafik tooltip'leri locale-aware para/tarih formatlar.
- Dar ekranda chart yatay taşmaz; gerekirse kart bazlı swipe kullanılır.
### 10.4. Clients
#### Liste
- Search, status ve pipeline filtresi.
- Kart ve kompakt liste seçeneği; kanban ikinci iterasyon olabilir.
- Telefon/email kısayolları izin ve platform API'siyle açılır.
- Yeni müşteri FAB/header action.
#### Oluşturma/düzenleme
- Name, company, email, phone, website, status, pipeline, follow-up ve notes.
- Çevrilebilir alanlar aktif locale tab/picker'larında.
- Default locale zorunlu; diğer locale'ler eksik kaydedilebilir.
#### Detay
- Özet, iletişim, pipeline, portal hesabı durumu.
- Projeler ve finans ilişkileri.
- Aktivite timeline ve not ekleme.
- Portal daveti oluşturma; aktif dillerden client default locale seçimi.
- Archive/destructive aksiyon confirmation.
### 10.5. Projects
#### Liste
- Search, status, type ve client filtresi.
- Progress, deadline, client ve budget özeti.
- Yeni proje formu; client project/side project ilişki kuralı.
#### Proje detayı
Native segmented tab:
- Genel: description, status, tarih, budget ve progress.
- Plan: category bazlı planning sections; create/edit/delete/reorder.
- Görevler: proje task'ları, public flag ve hızlı status.
- Revizyonlar: talepler, allowance ve owner status update.
- Dosyalar: cover ve portal-visible proje assets.
- Ayarlar: manual/auto progress, revision quota, complete ve delete.
Plan ve project edit formları aktif locale sayısı kadar dil paneli sunar.
### 10.6. Tasks
- Liste ve kanban segmented control.
- Status, priority, client, project ve tarih filtreleri.
- Task detail sheet/screen.
- Create/edit: title, description, status, priority, schedule, due time,
estimated/actual minute, project, client, public-to-client.
- Multilingual title/description.
- Swipe action yalnız açık undo veya confirmation politikasıyla kullanılır.
- Optimistic status update; hata durumunda rollback ve toast.
### 10.7. Calendar
- Month ve agenda görünümü.
- Gün seçilince etkinlik listesi.
- Etkinlik türü, başlangıç/bitiş, project/client/task ilişkisi.
- Native date/time picker.
- Locale, timezone ve daylight-saving doğru işlenir.
- Task deadlines ve finance events server tarafından event olarak dönüyorsa
source/read-only bilgisi açık olur; client sentetik duplicate üretmez.
### 10.8. Finance
- Ay seçici.
- Horizontal stat carousel: aylık gelir, gider, brüt, vergi/KDV, net, bekleyen.
- Scroll indicator görsel olarak gereksizse gizlenir; accessibility swipe korunur.
- Transaction search/filter, income/expense ve payment status.
- Create/edit: amount minor conversion, currency, date, category, status,
project/client ve localized description/category alanları.
- Silme confirmation.
- AI analysis sheet; loading, timeout, provider eksik ve retry.
- Finans verisi log/analytics payload'larında varsayılan olarak redacted olur.
### 10.9. Journal
- Tarih bazlı liste/takvim.
- Mood, energy, work satisfaction score.
- Mood label ve note için localized form.
- Aynı tarih için create/update tek idempotent akış.
- Günlük içeriği hassas kabul edilir; notification preview ve crash log'a girmez.
### 10.10. AI chat
- Session listesi, yeni sohbet, silme.
- Mesaj geçmişi ve streaming cevap.
- Klavye, safe area, auto-scroll ve uzun mesaj performansı.
- Stop generation ve retry.
- AI provider ayarlanmamışsa doğrudan ilgili ayar ekranına CTA.
- User mesajı kaynak locale ile saklanır; AI output otomatik domain çevirisi sayılmaz.
### 10.11. Business
- Teklifler: liste, create/edit, client/project, amount, status, validity.
- Sözleşmeler: liste, detail, content, proposal/client, status, signed date.
- Faturalar: liste, detail, invoice number, amount, tax, dates, payment status.
- Abonelikler: liste, create/edit, billing cycle, next billing date, status.
- PDF oluşturma/paylaşma backend tarafında gerçek feature olmadan mobilde
gösterilmez.
### 10.12. Owner settings
#### Genel
- Workspace/firma/freelance adı.
- Portal footer ve server'da var olan genel metadata alanları.
- Değişiklik sonrası discovery/meta cache invalidate edilir.
#### Görünüm
- Primary/accent renk.
- Instance default color mode ve kişisel color mode ayrı anlatılır.
- Light logo, dark logo ve favicon image picker/upload.
- Upload crop/preview, boyut ve MIME hatası.
- Mobil app aktif temaya göre doğru logoyu anında yeniler.
#### Profil
- Display name, email read/edit politikası ve avatar.
#### Güvenlik
- Şifre değiştirme.
- Auth modeli destekliyorsa cihaz/session listesi ve revoke.
#### AI
- Gemini/OpenAI/Groq/Ollama provider, model ve yeni API key.
- Mevcut secret geri okunmaz; yalnız configured/masked state.
#### Kişisel dil
- Yalnız active instance dilleri.
- Değişiklik `/me/preferences` üzerinden kaydedilir.
- Catalog/query cache locale ile birlikte atomik değişir.
#### Dil yönetimi
- Dil listesi, default, status, fallback ve tamamlanma.
- Draft dil ekleme ve metadata.
- Translation editor mobilde namespace -> filtre -> key listesi olarak parçalanır.
- Büyük import/export dosyaları native share/file picker kullanır.
- Dil lifecycle gibi riskli owner ayarları step-up confirmation gerektirir.
### 10.13. Portal dashboard
- Aktif/tamamlanan proje, tamamlanan görev ve bekleyen revizyon statları.
- Proje progress kartları.
- Freelancer tarafından tanımlanan portal footer/branding.
- Yalnız session client'a ait veriler.
### 10.14. Portal projects ve project detail
- Project list: localized name/description, status, deadline ve progress.
- Project detail: genel, plan, public tasks ve revisions.
- Revision allowance ve `Revizyon talep et` formu.
- Revizyon description kullanıcının yazdığı dilde saklanır; `sourceLocale`
zorunlu gönderilir.
- Başka client project ID'si 404/forbidden ile korunur ve veri sızdırmaz.
### 10.15. Portal tasks ve revisions
- Yalnız `isPublicToClient=true` task'lar.
- Project adı, status, deadline ve description localized.
- Revizyon listesi, status, tarih, project bağı ve orijinal client mesajı.
### 10.16. Portal settings
- Profil.
- Şifre/güvenlik.
- Light/dark/system kişisel tercih.
- Adminin active yaptığı diller arasında dil tercihi.
- Adminin client için atadığı `clientDefaultLocale` bilgi olarak gösterilir;
kullanıcı tercihi bunu ezebilir.
- Portal kullanıcısı instance branding, AI veya dil kataloğu yönetemez.
## 11. Localization mimarisi
### 11.1. İki ayrı dil katmanı
1. Uygulamanın domain bağlanmadan önceki metinleri: mobil binary içinde bundled
Türkçe/İngilizce `bootstrap` kataloğu.
2. Instance'a bağlandıktan sonraki metinler: Neta catalog endpoint'inden gelen,
admin tarafından override edilebilen katalog.
Yeni `mobile` namespace'leri server katalog registry'sine eklenmelidir:
```text
mobile-common
mobile-connection
mobile-auth
mobile-owner
mobile-portal
mobile-settings
mobile-errors
mobile-accessibility
```
Web ve mobil aynı anlamdaki status/validation key'lerini tekrar kullanabilir.
Layout'a özgü metinler mobil namespace'te kalır. Admin yeni dil eklediğinde mobil
namespace'leri de translation editor'da görür.
### 11.2. Locale çözümü
Public connect/login:
```text
instanceDefaultLocale -> bundled tr
```
Owner:
```text
userPreferenceLocale -> instanceDefaultLocale -> built-in tr
```
Portal:
```text
userPreferenceLocale -> clientDefaultLocale -> instanceDefaultLocale -> built-in tr
```
Bu karar `/api/v1/me` ile gelir; mobil client kendi alternatif öncelik sırasını
icat etmez.
### 11.3. Catalog cache
- Cache key: `instanceId + locale + namespaceSet + catalogVersion`.
- Catalog version aynıysa cached messages kullanılır.
- Version değişince yeni catalog atomik indirilir; yarım katalog UI'a uygulanmaz.
- Missing key development'ta raporlanır, production'da fallback kullanılır.
- Raw key production UI'da görünmemesi release testidir.
- RTL locale aktif edilirse `I18nManager` restart gereksinimi kontrollü UX ile
uygulanır; sadece text-align değiştirmek yeterli kabul edilmez.
### 11.4. Çok dilli domain formları
- Active locale'ler server sırasıyla tab/segmented dropdown olur.
- Default locale ilk ve zorunludur.
- Tab badge eksik zorunlu alanı gösterir.
- Tarih, status, para, relation, checkbox ve file alanları dil tab'ları dışındadır.
- Metin alanları registry'deki entity/field tanımından gelir; ekranlar kendi
farklı translation payload formatını oluşturmaz.
- Server `UNSUPPORTED_LOCALE` döndürürse metadata/catalog yenilenir ve formdaki
artık aktif olmayan dil korunarak kullanıcıya gösterilir.
## 12. Branding ve tema
Mobil tema `GET /api/v1/meta` alanlarından oluşur:
- `primaryColor`
- `accentColor`
- `defaultColorMode`
- `radiusScale`
- `lightLogoUrl`
- `darkLogoUrl`
- `iconUrl/faviconUrl`
Kurallar:
- Kullanıcının `/me.preferences.colorMode` değeri instance default'u ezer.
- `system`, cihaz renk modunu takip eder.
- Light mod light logo, dark mod dark logo kullanır.
- Bir logo eksikse diğeri fallback olabilir; kontrast garantisi olmadığı için
nötr workspace placeholder da hazır tutulur.
- Remote renklerden semantic token seti üretilirken minimum kontrast kontrolü
yapılır; okunmaz renk için güvenli foreground otomatik seçilir.
- App icon ve native splash her instance'a göre runtime değişmez. Bunlar genel
Neta markasıdır; instance favicon/logo uygulama içinde kullanılır.
- Remote SVG kullanılacaksa sanitizer/render desteği ayrı test edilir. MVP'de
backend'in kabul ettiği PNG/JPEG/WebP formatları tercih edilir.
## 13. Veri cache, offline ve mutation davranışı
### 13.1. Query key standardı
```ts
[instanceId, role, locale, resource, filters]
```
Örnek:
```ts
[instanceId, "freelancer", "tr", "projects", { status: "active" }]
```
Instance, rol veya locale değişince yanlış kullanıcı verisinin görünmesi bu
ayrımla engellenir.
### 13.2. Cache politikası
- Meta/catalog: version bazlı uzun cache.
- Dashboard/finance: kısa stale time.
- Detail/list: orta stale time ve foreground refresh.
- Chat messages: aktif session'da kısa cache/stream.
- Profile/security: no sensitive persistent cache veya alan bazlı redaction.
- Logout/instance switch: ilgili instance+user query cache temizlenir.
### 13.3. Offline v1
- Son başarılı read verisi `Son güncelleme` bilgisiyle gösterilebilir.
- Mutation başlatılırken network yoksa form kaybolmaz; kullanıcıya bağlantı
gerektiği söylenir.
- Otomatik kalıcı mutation queue v1'de yoktur; duplicate finans kaydı/revizyon
gibi riskleri önler.
- Optimistic update yalnız task status gibi kolay rollback edilebilir işlemlerde.
- Create/delete finance, project ve revision server onayından önce kalıcı
başarılı gösterilmez.
### 13.4. Gelecek offline queue gereksinimleri
- Idempotency key.
- Mutation dependency graph.
- Conflict/version kontrolü.
- Kullanıcıya görünür pending/failed queue.
- Logout ve instance switch'te pending data kararı.
- Hassas payload'lar için encrypted local database.
## 14. Hata yönetimi ve kullanıcı geri bildirimi
| Kod/durum | Mobil davranış |
| --- | --- |
| `VALIDATION_ERROR` | Alan hataları formda, genel hata summary'de |
| `UNAUTHENTICATED` | Session temizle, login'e git, draft formu mümkünse koru |
| `FORBIDDEN` | Yetki ekranı; route'u gizlemek tek başına yeterli değil |
| `NOT_FOUND` | Detail not-found ve listeye dön |
| `CONFLICT` | Server state refresh ve conflict UI |
| `UNSUPPORTED_LOCALE` | Locale metadata/catalog refresh |
| `UPSTREAM_TIMEOUT` | AI için tekrar dene; core data mutation tekrar edilmez |
| `SERVICE_UNAVAILABLE` | Instance bakım/readiness mesajı |
| Network timeout | Offline banner ve kontrollü retry |
| TLS error | Credential göndermeden bağlantıyı durdur |
| API major incompatible | App update veya desteklenmeyen instance ekranı |
Her error objesi internal URL, SQL, stack trace, token veya secret içermemelidir.
## 15. Dosya ve medya yönetimi
- Image picker permission yalnız aksiyon anında istenir.
- Dosya MIME, extension ve 5 MB server limiti upload öncesi gösterilir.
- Upload `multipart/form-data` olur; auth header/cookie korunur.
- Progress, cancel ve retry bulunur.
- Server response absolute veya instance-bound URL döndürmelidir; mobil client
farklı origin varsaymaz.
- Private/portal/public branding visibility kuralları server'da uygulanır.
- Portal-visible olmayan project asset client'a URL olarak bile dönmez.
- EXIF/location metadata temizleme politikası backend veya upload öncesi için
ayrı acceptance kriteridir.
## 16. Güvenlik modeli
### 16.1. Zorunlu kurallar
- Remote instance için HTTPS.
- Session/token yalnız SecureStore/Keychain/Keystore destekli alanda.
- Password hiçbir local storage, log, crash report veya analytics event'ine girmez.
- API key mobilde geri okunabilir biçimde tutulmaz.
- Owner/client authorization her endpoint'te server actor'dan türetilir.
- Portal query'lerinden gelen `clientId` yetki kaynağı değildir.
- Loglar request/response body'yi varsayılan olarak kaydetmez.
- Clipboard'a kopyalanan hassas bilgiler minimize edilir.
- Jailbreak/root detection tek başına auth kontrolü sayılmaz.
- Certificate pinning self-host ve değişken domain modelinde varsayılan olamaz;
opsiyonel instance fingerprint/pin ancak ayrı tasarımla gelir.
### 16.2. Threat cases
- Kötü niyetli discovery belgesinin başka origin'e auth URL vermesi.
- DNS rebinding/redirect ile HTTPS downgrade.
- Aynı origin'in restore sonrası farklı instance ID döndürmesi.
- Shared device'da kullanıcı A cache'inin kullanıcı B'ye görünmesi.
- Client'ın başka client project/task ID'sini tahmin etmesi.
- Retry sonucu duplicate finance/revision oluşması.
- AI error/log içine provider secret sızması.
- Remote logo/file ile dev payload veya aşırı bellek kullanımı.
## 17. Performans hedefleri
- Warm start'ta cached shell/logo hemen; auth doğrulama arka planda.
- Discovery ve meta request'leri timeout/abort destekler.
- Dashboard tek aggregate endpoint kullanır.
- Listeler cursor pagination ve virtualized list kullanır.
- Chart library yalnız gerçek chart ekranlarında lazy load edilir.
- Remote image boyutları sınırlanır ve cache edilir.
- Locale catalog namespace bazlı indirilir.
- Project detail'in tüm tab verileri ilk render'da zorunlu değilse lazy query olur.
- Chat message listesi uzun session'larda virtualized olur.
Ölçülecek metrikler:
- Cold start -> connect/login shell.
- Warm start -> authenticated shell.
- Dashboard usable data time.
- P50/P95 API latency endpoint ailesi bazında.
- JS crash-free session.
- Auth/session failure oranı.
- Catalog ve branding cache hit oranı.
Telemetry self-host ilkesine uygun opt-in olmalı; merkezi Neta sunucusuna içerik
gönderilmemelidir.
## 18. Erişilebilirlik ve cihaz uyumu
- Minimum 44x44 iOS / uygun Android touch target.
- Dynamic font ve text scaling.
- Sadece renkle durum anlatılmaz.
- Icon button'larda localized accessibility label.
- Form error summary screen reader tarafından okunur.
- Chart'lar metinsel summary sunar.
- Dark/light kontrast semantik token testinden geçer.
- Keyboard avoidance ve focus order test edilir.
- Safe area, notch ve Android navigation bar uyumu.
- RTL layout mirror testi.
- 14 inç web davranışı mobil acceptance değildir; telefon, küçük telefon
ve tablet ayrı screenshot testlerine girer.
## 19. Test stratejisi
### 19.1. Unit
- URL normalize ve origin validation.
- Discovery/meta schema parse.
- SemVer minimum client kontrolü.
- Error mapping.
- Money/date/locale format.
- Theme token derivation ve foreground contrast.
- Translation fallback.
- Query key isolation.
### 19.2. Contract/integration
- Her `/api/v1` endpoint için request/response schema.
- API version header ve envelope.
- Owner/client pozitif ve negatif auth.
- Cursor pagination determinism.
- Localized resource ve translation mutation.
- Idempotency ve conflict.
- File visibility.
- AI timeout/error/stream.
### 19.3. Mobil component
- Loading, empty, error, content.
- Light/dark ve custom primary.
- TR/EN, uzun custom locale ve RTL.
- Form validation ve locale tab errors.
- Offline banner ve mutation guard.
### 19.4. E2E
En az iki gerçek self-host fixture:
1. Default branding, TR default, freelancer.
2. Custom branding, EN veya custom locale, portal client.
Kritik E2E senaryoları:
- Domain -> discovery -> login -> owner dashboard.
- Domain -> login -> portal dashboard.
- Yanlış domain/TLS/API version.
- Session expiry ve logout.
- Client create -> portal invite locale.
- Project create with TR/EN -> client EN portal read.
- Task create/public -> portal task visibility.
- Revision request -> owner status update.
- Finance create/edit/delete.
- Theme/logo switch.
- Locale/catalog version switch.
- Cross-client project access negative.
### 19.5. Release gate
```text
mobile lint
mobile typecheck
mobile unit tests
API contract tests
i18n key parity + raw key scan
owner/client authorization negative tests
iOS build
Android build
smoke against packaged self-host instance
```
## 20. CI/CD ve yayın
- PR: lint, typecheck, unit, API contract ve i18n gate.
- Main/nightly: iOS simulator ve Android emulator E2E.
- Release candidate: TestFlight + Play Internal Testing.
- Production: staged rollout ve crash-free takip.
- `NETA_MINIMUM_MOBILE_VERSION` yalnız gerçekten zorunlu protokol/güvenlik
durumunda yükseltilir.
- Mobil app version, native build number ve API contract version ayrıdır.
- OTA update kullanılırsa native runtime version ile uyumluluk korunur; native
module gerektiren değişiklik OTA ile zorlanmaz.
- Privacy policy; girilen domain, cihazda tutulan metadata, opsiyonel telemetry ve
crash reporting davranışını açıkça anlatır.
## 21. Faz bazlı uygulama planı
Bir faz, checklist ve acceptance kriterleri tamamlanmadan `completed` sayılmaz.
Backend endpoint'i olmayan mobil ekran mock data ile bitmiş işaretlenmez.
### Faz 0 — Baseline, kararlar ve mobil API gap analizi
- [ ] Mevcut web route, Server Action, DomainService ve schema envanteri snapshot'lanır.
- [ ] Owner ve portal ekran parity matrisi onaylanır.
- [ ] Expo stabil SDK/RN/Node/pnpm sürümleri seçilir.
- [ ] Better Auth Expo multi-domain spike gerçek cihazda yapılır.
- [ ] Cookie/session izolasyonu iki farklı instance ile test edilir.
- [ ] ADR-0018 secure-cookie veya device-pairing sonucuna göre revize edilir.
- [ ] Portal client auth lifecycle kararı yazılır.
- [ ] Poyraz UI web sınırı ve mobil token kontratı kaydedilir.
- [ ] API endpoint backlog'u issue/fazlarla eşleştirilir.
- [ ] MVP, parity ve post-v1 kapsamı product tarafından onaylanır.
Tamamlanma kriteri: Auth ve repository mimarisi açık karar, spike kanıtı ve
güncellenmiş ADR ile sabittir.
### Faz 1 — Workspace ve Expo temel uygulama
- [ ] `mobile/` Expo Router TypeScript app oluşturulur.
- [ ] pnpm workspace mevcut web root'unu bozmadan kurulur.
- [ ] iOS ve Android development build alınır.
- [ ] Environment ve app config yapısı kurulur.
- [ ] Typed routes, protected route grupları ve error boundary kurulur.
- [ ] Lint, typecheck, unit test ve CI scriptleri eklenir.
- [ ] SecureStore ve non-secret storage adapter'ları ayrılır.
- [ ] Network state ve app lifecycle provider eklenir.
### Faz 2 — Mobil design system ve tema
- [ ] Shared semantik design token paketi oluşturulur.
- [ ] Light/dark/system theme provider yazılır.
- [ ] Dynamic primary/accent ve kontrast çözümü uygulanır.
- [ ] Temel UI primitives tamamlanır.
- [ ] Loading/empty/error/skeleton/toast pattern'leri sabitlenir.
- [ ] Phone/tablet safe-area ve typography kuralları yazılır.
- [ ] UI katalog key'leri `mobile-*` namespace'lerine eklenir.
- [ ] Light/dark ve TR/EN component screenshot testleri eklenir.
### Faz 3 — Domain discovery ve instance bootstrap
- [ ] Domain normalize/validation saf modülü yazılır.
- [ ] Discovery, health ve meta client'ları yazılır.
- [ ] Redirect/origin/TLS/min-version/capability kontrolleri uygulanır.
- [ ] Instance registry ve instanceId değişim davranışı uygulanır.
- [ ] Domain connect/checking/error/incompatible ekranları tamamlanır.
- [ ] Branding ve public catalog bootstrap edilir.
- [ ] Localhost/emulator development policy test edilir.
### Faz 4 — Native auth, session ve role shell
- [ ] Server Better Auth Expo plugin ve trusted origin değişiklikleri yapılır.
- [ ] Instance-bound native auth client factory yazılır.
- [ ] Secure storage prefix instanceId ile izole edilir.
- [ ] Login, logout, expiry ve foreground session kontrolü tamamlanır.
- [ ] `/api/v1/me` ile owner/client route kararı uygulanır.
- [ ] Owner ve portal navigation shell'leri tamamlanır.
- [ ] Disabled user, password change ve revoke testleri geçer.
- [ ] Auth audit ve rate limit regression testleri geçer.
### Faz 5 — API contract paketi ve resource altyapısı
- [ ] `packages/api-contracts` transport-safe hale getirilir.
- [ ] Envelope, error, pagination ve localized response şemaları eklenir.
- [ ] Instance-bound fetch client, timeout, abort ve request metadata eklenir.
- [ ] Query client, query key factory ve cache persistence kurulur.
- [ ] API route helper'ları actor/role/locale/pagination için ortaklaştırılır.
- [ ] Idempotency ve optimistic concurrency kararı uygulanır.
- [ ] API OpenAPI veya machine-readable contract üretimi kararlaştırılır.
### Faz 6 — Owner dashboard ve analytics
- [ ] Dashboard aggregate API yazılır ve owner scope testi eklenir.
- [ ] Analytics range API yazılır.
- [ ] Dashboard ekranı tüm states ile tamamlanır.
- [ ] Analytics ekranı ve accessible chart summary tamamlanır.
- [ ] Para/tarih/locale format testleri geçer.
- [ ] Request count ve P95 hedefi ölçülür.
### Faz 7 — Clients dikey dilimi
- [ ] Clients list/detail/create/update/archive API'leri yazılır.
- [ ] Activity ve portal invitation API'leri v1'e alınır.
- [ ] Client list/filter/search ekranı tamamlanır.
- [ ] Client multilingual form tamamlanır.
- [ ] Client detail/activity/portal locale akışı tamamlanır.
- [ ] Portal invite duplicate/conflict ve owner-only testleri geçer.
### Faz 8 — Projects dikey dilimi
- [ ] Projects CRUD/list/detail API'leri yazılır.
- [ ] Planning sections ve revision owner API'leri yazılır.
- [ ] Project list ve multilingual create/edit tamamlanır.
- [ ] Project detail tabları tamamlanır.
- [ ] Progress/revision quota/complete/delete akışları test edilir.
- [ ] Client-project relation ve cross-owner negatifleri geçer.
### Faz 9 — Tasks dikey dilimi
- [ ] Tasks CRUD/filter API'leri yazılır.
- [ ] List/kanban görünümü tamamlanır.
- [ ] Multilingual task form tamamlanır.
- [ ] Optimistic status/complete ve rollback tamamlanır.
- [ ] Project auto-progress regression testleri geçer.
- [ ] Portal visibility server testi geçer.
### Faz 10 — Calendar dikey dilimi
- [ ] Date-range event API'leri yazılır.
- [ ] Month/agenda ekranı tamamlanır.
- [ ] Multilingual event form ve native date picker tamamlanır.
- [ ] Timezone/DST/start-end validation testleri geçer.
- [ ] Project/client/task ownership negatifleri geçer.
### Faz 11 — Finance dikey dilimi
- [ ] Summary ve transaction CRUD API'leri yazılır.
- [ ] Stat carousel ve transaction list/filter tamamlanır.
- [ ] Multilingual finance form ve money conversion test edilir.
- [ ] AI finance analysis v1 endpoint/error kontratına alınır.
- [ ] Duplicate mutation/idempotency testi geçer.
- [ ] Hassas veri log redaction testi geçer.
### Faz 12 — Journal dikey dilimi
- [ ] Range ve idempotent date upsert API'leri yazılır.
- [ ] Journal list/calendar ekranı tamamlanır.
- [ ] Mood/energy/satisfaction ve multilingual note formu tamamlanır.
- [ ] Same-date conflict ve offline guard testleri geçer.
- [ ] Hassas content telemetry kontrolü geçer.
### Faz 13 — AI chat ve project risk
- [ ] Chat session/message API'leri v1'e taşınır.
- [ ] Native streaming protokolü belgelenir ve uygulanır.
- [ ] Session list/chat detail/composer tamamlanır.
- [ ] Cancel/retry/timeout/provider-missing UX tamamlanır.
- [ ] Project risk analysis mobil action'la entegre edilir.
- [ ] Secret/error leakage testleri geçer.
### Faz 14 — Business modülleri
- [ ] Proposals API ve mobil ekranları tamamlanır.
- [ ] Contracts API ve mobil ekranları tamamlanır.
- [ ] Invoices API ve mobil ekranları tamamlanır.
- [ ] Subscriptions API ve mobil ekranları tamamlanır.
- [ ] Money/status/date ve owner-scope testleri geçer.
- [ ] Web'de eksik kalan product davranışları ayrıca tamamlanır veya feature
capability ile planned tutulur.
### Faz 15 — Owner profil, güvenlik ve instance ayarları
- [ ] Me profile/password/session API'leri tamamlanır.
- [ ] General/appearance/AI settings API'leri tamamlanır.
- [ ] Profil ve güvenlik ekranları tamamlanır.
- [ ] Workspace ve appearance ekranları tamamlanır.
- [ ] Light/dark logo ve favicon upload/remove tamamlanır.
- [ ] AI provider/key formu secret-safe tamamlanır.
- [ ] Meta/discovery/cache invalidation testi geçer.
### Faz 16 — Dil tercihi, dil yönetimi ve çok dilli formlar
- [ ] `mobile-*` TR/EN katalog parity yüzde 100 olur.
- [ ] Catalog version/cache/fallback runtime tamamlanır.
- [ ] Owner kişisel dil ekranı tamamlanır.
- [ ] Locale list/create/detail/lifecycle API ve ekranları tamamlanır.
- [ ] Translation editor ve import/export tamamlanır.
- [ ] Tüm owner form entity'leri ortak localized form contract'ına geçer.
- [ ] Custom locale ve RTL E2E geçer.
- [ ] Production raw-key taraması sıfır sonuç verir.
### Faz 17 — Portal API ve authorization hardening
- [ ] Portal dashboard/projects/tasks/revisions API'leri yazılır.
- [ ] Portal profile API tamamlanır.
- [ ] Localized response/fallback portal kontratı uygulanır.
- [ ] Her endpoint için cross-client ve owner/client role negatifleri yazılır.
- [ ] Public task ve portal asset visibility testleri geçer.
- [ ] Revision allowance ve sourceLocale testleri geçer.
### Faz 18 — Portal mobil ekranları
- [ ] Portal dashboard tamamlanır.
- [ ] Project list ve project detail tabları tamamlanır.
- [ ] Public tasks tamamlanır.
- [ ] Revision list/create tamamlanır.
- [ ] Profile/security/appearance/language ayarları tamamlanır.
- [ ] Admin branding ve client locale davranışı E2E geçer.
- [ ] Owner route'ları portal bundle UI'ında görünmez ve API'de forbidden'dır.
### Faz 19 — Dosya, medya, invitation ve deep link
- [ ] File endpoint'leri v1 envelope ve absolute URL kontratına alınır.
- [ ] Avatar, light logo, dark logo, favicon, cover ve project asset upload tamamlanır.
- [ ] Upload progress/cancel/retry tamamlanır.
- [ ] Universal/app link kurulumu yapılır.
- [ ] Portal invitation ve password reset web fallback ile test edilir.
- [ ] File visibility/MIME/size/EXIF güvenlik testleri geçer.
### Faz 20 — Offline read cache, performans ve accessibility
- [ ] Query persistence hassasiyet matrisiyle etkinleştirilir.
- [ ] Offline banner, stale timestamp ve mutation guard tamamlanır.
- [ ] Liste virtualization ve image cache uygulanır.
- [ ] Cold/warm start ve dashboard performans budget'ları geçer.
- [ ] Dynamic type, screen reader, keyboard ve touch target audit geçer.
- [ ] Light/dark/custom color ve RTL accessibility testleri geçer.
- [ ] Küçük telefon ve tablet responsive testleri geçer.
### Faz 21 — Bildirim altyapısı ve background davranışı
- [ ] Bildirimlerin self-host backend ile nasıl gönderileceği için ADR yazılır.
- [ ] Expo push relay kullanımının privacy/self-host etkisi açıklanır.
- [ ] Device registration/revoke endpoint'leri tasarlanır.
- [ ] Görev deadline, revizyon ve proje update event kapsamı belirlenir.
- [ ] Notification deep link auth ve instance kontrolünden geçer.
- [ ] Hassas içerik lock-screen preview'da varsayılan olarak gösterilmez.
Bu faz ilk store release için zorunlu olmayabilir; capability `planned` kaldığı
sürece UI da sunulmaz.
### Faz 22 — Production hardening ve store release
- [ ] Tüm release gate'ler CI'da geçer.
- [ ] Gerçek Dokploy/reverse-proxy self-host instance ile smoke geçer.
- [ ] iOS TestFlight ve Play Internal Testing kabulü tamamlanır.
- [ ] Privacy policy, support ve domain troubleshooting dokümanı yayınlanır.
- [ ] App Store/Play metadata ve screenshot'lar TR/EN hazırlanır.
- [ ] Crash/log redaction ve opt-in telemetry doğrulanır.
- [ ] Minimum mobile version ve API compatibility senaryosu test edilir.
- [ ] Rollback, staged rollout ve hotfix prosedürü yazılır.
- [ ] Owner ve portal E2E acceptance imzası alınır.
### Faz 23 — Device pairing ve gelişmiş oturum yönetimi
Bu fazın kapsamı Faz 0 auth kararına bağlıdır. Pairing production blocker
olarak kalırsa Faz 4'e çekilir.
- [ ] Pairing code/challenge schema ve rate limit uygulanır.
- [ ] Exchange/access/refresh rotation uygulanır.
- [ ] SecureStore token family entegrasyonu tamamlanır.
- [ ] Device list/revoke UI tamamlanır.
- [ ] Refresh reuse -> family compromised akışı test edilir.
- [ ] Password change/disabled user/tüm cihazlardan çıkış revoke eder.
- [ ] Backup restore token epoch rotate eder.
- [ ] Raw token/secret log ve DB'de bulunmaz.
## 22. Milestone ve hızlı teslim sırası
### Milestone A — Bağlanabilir uygulama
Faz 05:
- Domain girilir.
- Neta instance tanınır.
- Marka/dil yüklenir.
- Kullanıcı giriş yapar.
- Rolüne uygun boş shell açılır.
### Milestone B — Freelancer core MVP
Faz 613:
- Dashboard, analiz, müşteri, proje, görev, takvim, finans, günlük ve AI.
- Bu noktada mobil uygulama freelancer'ın günlük ana işlerini karşılar.
### Milestone C — Tam owner yönetimi
Faz 1416:
- Business ve tüm ayarlar.
- Instance branding/dil/AI yönetimi.
- Çok dilli içerik parity.
### Milestone D — Müşteri portalı
Faz 1719:
- Portal API hardening.
- Portal ekranları.
- Dosyalar, invitation ve deep link.
### Milestone E — Store kalitesi
Faz 2023:
- Offline read, performans, accessibility, opsiyonel notification.
- Production hardening ve gerekiyorsa pairing.
## 23. Definition of Done
Bir feature yalnız UI göründüğünde tamamlanmış sayılmaz. Her feature için:
- [ ] API v1 contract ve stable error code var.
- [ ] Owner/client authorization server tarafında testli.
- [ ] Loading, empty, error, offline ve content state'leri var.
- [ ] Light/dark ve custom branding doğru.
- [ ] TR/EN ve custom locale fallback doğru.
- [ ] Dinamik metin alanlarında translation payload doğru.
- [ ] Accessibility label, focus ve touch target doğru.
- [ ] Query invalidation/cache isolation doğru.
- [ ] Mutation duplicate/conflict davranışı tanımlı.
- [ ] Secret/PII log redaction doğru.
- [ ] Unit + contract + en az bir E2E happy path geçiyor.
- [ ] Plan faz checklist'i ve ilgili teknik doküman güncel.
## 24. Başlamadan önce cevaplanması gereken ürün kararları
Bu sorular Faz 0'da cevaplanmalı; uygulama bootstrap'ını bloke etmek zorunda
değildir fakat ilgili feature fazını bloke eder:
1. Tek aktif instance yeterli mi, yoksa ilk sürümde hızlı instance switch olacak mı?
2. Owner mobil login email/şifre mi, pairing mi, yoksa ikisi birden mi olacak?
3. Müşteri invitation kabulü ilk sürümde native mi web fallback mi olacak?
4. Business ekranları MVP mi, parity milestone'u mu?
5. Mobilde admin dil translation editor gerçekten gerekli mi, yoksa ilk sürümde
dil seçimi yeterli ve katalog yönetimi web-only olabilir mi?
6. Push notification ilk store release blocker mı?
7. Tablet ilk release acceptance kapsamında mı?
8. Self-host instance'lar için merkezi telemetry tamamen kapalı mı, opt-in mi?
## 25. İlk uygulanacak teknik dilim
En hızlı ve riski en erken azaltan ilk uygulama dilimi:
```text
Faz 0 auth spike
-> mobile workspace bootstrap
-> domain connect
-> discovery/meta/health
-> instance branding + catalog
-> Better Auth native login
-> /api/v1/me
-> role-based owner/portal shell
```
Bu dilim tamamlandığında henüz bütün ekranlar yazılmamış olsa bile projenin
en kritik vaadi kanıtlanmış olur: tek bir React Native uygulaması, kullanıcının
girdiği herhangi bir uyumlu self-hosted Neta domain'ini güvenli biçimde tanır,
o instance'ın markasına ve diline bürünür, kullanıcıyı doğrular ve freelancer
veya müşteri deneyimine doğru yönlendirir.