feat(api): complete phase 9 mobile contracts
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
---
|
||||
title: ADR-0018 — Mobil Device Pairing ve Token Lifecycle
|
||||
status: accepted-design-not-implemented
|
||||
date: 2026-07-17
|
||||
---
|
||||
|
||||
# ADR-0018 — Mobil device pairing ve token lifecycle
|
||||
|
||||
## Bağlam
|
||||
|
||||
React Native istemcisi kullanıcı tarafından girilen self-hosted Neta URL'sine bağlanacak. Web session cookie'sini kopyalamak, uzun ömürlü API key vermek veya owner şifresini cihazda sürekli saklamak güvenli bir pairing modeli değildir.
|
||||
|
||||
Faz 9 yalnızca discovery ve API v1 temelini yayınlar. Pairing/token endpoint'leri bu ADR uygulanmadan açılmaz.
|
||||
|
||||
## Karar
|
||||
|
||||
İlk device pairing sürümü owner cihazları için tek kullanımlık, kısa ömürlü bir pairing challenge ve DB-backed opaque token modeli kullanacaktır.
|
||||
|
||||
Planlanan endpoint'ler:
|
||||
|
||||
```text
|
||||
POST /api/v1/pairing-codes
|
||||
POST /api/v1/device-sessions/exchange
|
||||
POST /api/v1/device-sessions/refresh
|
||||
GET /api/v1/device-sessions
|
||||
DELETE /api/v1/device-sessions/:id
|
||||
```
|
||||
|
||||
### Pairing oluşturma
|
||||
|
||||
- Yalnızca aktif freelancer session'ı pairing oluşturabilir.
|
||||
- Browser owner'dan güncel şifre veya eşdeğer step-up doğrulaması istenir.
|
||||
- QR modu 256-bit rastgele secret taşır.
|
||||
- Manuel giriş modu 10 karakter Crockford Base32 kod kullanır; benzer karakterler kullanılmaz.
|
||||
- DB'de yalnızca HMAC/SHA-256 digest saklanır; raw secret yalnızca bir kez gösterilir.
|
||||
- Challenge en fazla 5 dakika geçerlidir ve tek kullanımlıdır.
|
||||
- Challenge; creator, expiry, attempt count, requested scopes ve durum içerir.
|
||||
- Aynı owner için en fazla üç aktif challenge bulunabilir.
|
||||
- Beş başarısız deneme challenge'ı kilitler.
|
||||
- Oluşturma ve exchange IP/instance seviyesinde rate limit ve auth audit event üretir.
|
||||
|
||||
### Exchange
|
||||
|
||||
Mobil istemci şu bilgileri gönderir:
|
||||
|
||||
- Pairing secret/code
|
||||
- Cihazda üretilmiş opaque install ID
|
||||
- Kullanıcının verdiği device name
|
||||
- Platform (`ios`/`android`)
|
||||
- App version
|
||||
- OS version'ın hassas olmayan major bilgisi
|
||||
|
||||
Server challenge'ı `BEGIN IMMEDIATE` transaction içinde doğrular ve tüketir. Aynı transaction device session/token family kaydını oluşturur. Başarısız exchange challenge'ı tüketmez; attempt sayısını artırır.
|
||||
|
||||
Owner role/scopeları server tarafından atanır. İstemci owner/user ID veya scope seçemez.
|
||||
|
||||
### Token modeli
|
||||
|
||||
- Tokenlar JWT değil, 256-bit opaque random bearer değerleridir.
|
||||
- DB'de yalnızca keyed digest saklanır.
|
||||
- Access token varsayılan 15 dakika geçerlidir.
|
||||
- Refresh token varsayılan 30 gün geçerlidir.
|
||||
- Her refresh işleminde access ve refresh token birlikte rotate edilir.
|
||||
- Eski refresh token yeniden kullanılırsa token family `compromised` olur ve family içindeki tüm tokenlar atomik revoke edilir.
|
||||
- Aynı cihaz için eşzamanlı refresh yarışı kısa grace/replay kaydıyla açıkça yönetilir; iki aktif refresh token bırakılmaz.
|
||||
- Bearer token yalnızca `Authorization: Bearer` header'ında kabul edilir; query, URL veya log'a yazılmaz.
|
||||
- Raw tokenlar API response dışında hiçbir log/audit kaydına girmez.
|
||||
- React Native tokenları iOS Keychain/Android Keystore destekli secure storage'da tutar.
|
||||
- İlk sürüm bearer modelidir. Device-bound public key/DPoP ayrı ADR olmadan eklenmez.
|
||||
|
||||
### Scope
|
||||
|
||||
İlk pairing yalnızca freelancer cihazı içindir. Token scope'ları explicit allowlist'tir:
|
||||
|
||||
```text
|
||||
profile:read
|
||||
clients:read
|
||||
projects:read
|
||||
tasks:read
|
||||
calendar:read
|
||||
finance:read
|
||||
journal:read
|
||||
```
|
||||
|
||||
Mutation scope'ları ilgili `/api/v1` resource endpoint'leri ve authorization testleri yayınlandıkça ayrı ayrı eklenir. `*` veya implicit admin scope kullanılmaz.
|
||||
|
||||
Client portal pairing'i owner pairing'inden ayrı ürün/güvenlik kararıdır; ilk implementasyona dahil değildir.
|
||||
|
||||
## Device token lifecycle
|
||||
|
||||
Durumlar:
|
||||
|
||||
```text
|
||||
pending_pairing -> active -> expired
|
||||
-> revoked
|
||||
-> compromised
|
||||
```
|
||||
|
||||
- `pending_pairing`: Challenge üretildi, token yok.
|
||||
- `active`: Exchange tamamlandı ve token family kullanılabilir.
|
||||
- `expired`: Refresh lifetime sona erdi.
|
||||
- `revoked`: Owner, kullanıcı disable, şifre güvenlik olayı veya “tüm cihazlardan çıkış” nedeniyle kapatıldı.
|
||||
- `compromised`: Refresh reuse veya güvenlik sinyali tespit edildi.
|
||||
|
||||
Kurallar:
|
||||
|
||||
- Owner dashboard'u cihaz adı, platform, oluşturulma, son kullanım ve yaklaşık IP bilgisini görür.
|
||||
- Owner tek cihazı veya tüm cihazları revoke edebilir.
|
||||
- Client/freelancer hesabı disable edildiğinde tüm device session'lar transaction içinde revoke edilir.
|
||||
- Owner şifresi değiştiğinde varsayılan politika tüm device session'ları revoke etmektir.
|
||||
- 30 gün kullanılmayan device session expire edilir.
|
||||
- Son kullanım zamanı en fazla beş dakikada bir coalesce edilerek yazılır.
|
||||
- Token cleanup job'u uygulama başlangıcında ve kontrollü periyotta expired kayıtları temizler; aktif request path'i toplu cleanup yapmaz.
|
||||
|
||||
## Backup ve restore güvenliği
|
||||
|
||||
Eski DB backup'ı revoke edilmiş token kayıtlarını yeniden aktif hale getirebilir. Pairing implementasyonunun release blocker'ı:
|
||||
|
||||
1. `instance_settings` içinde bir device token epoch tutulur.
|
||||
2. Bütün token digest doğrulamaları bu epoch'a bağlanır.
|
||||
3. `db:restore` başarılı atomik swap sonrasında epoch'u yeni random değerle rotate eder.
|
||||
4. Böylece restore tüm eski device tokenları otomatik geçersiz kılar.
|
||||
5. Owner restore sonrasında cihazları yeniden pair eder.
|
||||
|
||||
Bu mekanizma uygulanmadan device token endpoint'leri yayınlanamaz.
|
||||
|
||||
## HTTPS ve transport
|
||||
|
||||
- Remote pairing, exchange, refresh ve authenticated API için HTTPS zorunludur.
|
||||
- Reverse proxy `X-Forwarded-Proto`/canonical origin'i doğru iletmelidir.
|
||||
- HTTP yalnızca loopback/emulator geliştirme ortamında kabul edilir ve production token üretmez.
|
||||
- TLS sertifika hatası kullanıcı tarafından sessizce bypass edilemez.
|
||||
- Discovery API origin değiştirirse mobil istemci kullanıcı onayı olmadan credential göndermez.
|
||||
|
||||
## Audit ve privacy
|
||||
|
||||
Audit event'leri:
|
||||
|
||||
- `pairing_created`
|
||||
- `pairing_failed`
|
||||
- `pairing_consumed`
|
||||
- `device_session_refreshed`
|
||||
- `device_session_revoked`
|
||||
- `device_token_reuse_detected`
|
||||
|
||||
Audit metadata raw token, pairing secret, tam IP geçmişi veya gereksiz device fingerprint içermez. Device name kullanıcı tarafından değiştirilebilir ve output-encode edilir.
|
||||
|
||||
## Uygulama öncesi zorunlu testler
|
||||
|
||||
- Pairing raw secret'ın DB/log'da bulunmaması
|
||||
- Expired, consumed, locked ve brute-force challenge negatifleri
|
||||
- Concurrent double exchange'de yalnızca bir başarı
|
||||
- Owner/client role ve cross-owner negatifleri
|
||||
- Access expiry ve refresh rotation
|
||||
- Refresh reuse ile family revoke
|
||||
- Disabled user ve password change revoke
|
||||
- Restore sonrası token epoch invalidation
|
||||
- HTTPS/loopback policy
|
||||
- Tokenların URL, error ve audit output'una sızmaması
|
||||
|
||||
## Sonuç
|
||||
|
||||
Faz 9'da capability `auth.device-pairing` değeri `planned` kalır. Bu ADR'ın schema, service, rate-limit, restore epoch ve negatif test maddeleri tamamlanmadan `pairing-codes` veya `device-sessions` route'u oluşturulmaz.
|
||||
@@ -2,7 +2,7 @@
|
||||
title: Neta Self-Hosted v3 Ana Dönüşüm Planı
|
||||
description: Supabase çıkışı, SQLite tabanlı backend, Better Auth, Poyraz UI v3 ve instance özelleştirmesi için ana yol haritası.
|
||||
status: active
|
||||
current_phase: "9 — Mobil API hazırlığı"
|
||||
current_phase: "10 — Kullanıcı yönlendirmeli sayfa tasarımları"
|
||||
last_updated: 2026-07-17
|
||||
---
|
||||
|
||||
@@ -527,7 +527,7 @@ Faz 5'in başlangıç noktası freelancer runtime'ındaki Supabase erişimleridi
|
||||
- [x] Portal backend'i Faz 6 sözleşmesine göre tamamlandı.
|
||||
- [x] AI/chat ve business backend'i Faz 7 sözleşmesine göre tamamlandı.
|
||||
- [x] Import ve runtime Supabase temizliği Faz 8'de tamamlandı.
|
||||
- [ ] Mobil API sınırı Faz 9'da tamamlandı.
|
||||
- [x] Mobil API sınırı Faz 9'da tamamlandı.
|
||||
|
||||
## 15. Revizyon güvenliği ve kota işlemi
|
||||
|
||||
@@ -580,13 +580,13 @@ Mobil hazırlık checklist'i:
|
||||
|
||||
- [x] API response envelope standardı tanımlandı.
|
||||
- [x] API hata kodları tanımlandı.
|
||||
- [ ] API sürümleme stratejisi tanımlandı.
|
||||
- [ ] Instance metadata sözleşmesi tanımlandı.
|
||||
- [ ] Minimum desteklenen client sürümü alanı düşünüldü.
|
||||
- [ ] Capability listesi sözleşmesi düşünüldü.
|
||||
- [x] API sürümleme stratejisi tanımlandı.
|
||||
- [x] Instance metadata sözleşmesi tanımlandı.
|
||||
- [x] Minimum desteklenen client sürümü alanı düşünüldü.
|
||||
- [x] Capability listesi sözleşmesi düşünüldü.
|
||||
- [x] Service katmanı cookie/Next.js objelerine bağımlı değil.
|
||||
- [ ] Mobil pairing ilk release kapsamı dışında tutuldu.
|
||||
- [ ] Gelecekte HTTPS zorunluluğu belgelendi.
|
||||
- [x] Mobil pairing ilk release kapsamı dışında tutuldu.
|
||||
- [x] Gelecekte HTTPS zorunluluğu belgelendi.
|
||||
|
||||
## 17. Supabase veri import ve cutover planı
|
||||
|
||||
@@ -744,7 +744,7 @@ Mümkün olduğunda küçük ve doğrudan test araçları tercih edilir; test al
|
||||
- [x] Branding ayarları belgelendi.
|
||||
- [x] Backup/restore belgelendi.
|
||||
- [x] Upgrade/migration akışı belgelendi.
|
||||
- [ ] Mobil API sınırı belgelendi.
|
||||
- [x] Mobil API sınırı belgelendi.
|
||||
- [x] Eski ve çelişkili Supabase belgeleri archive veya kaldırıldı.
|
||||
- [x] ADR-0006 Poyraz UI v3 kararıyla güncellendi.
|
||||
- [x] ADR-0007 ile PWA runtime durumu uyumlu hale getirildi.
|
||||
@@ -984,11 +984,24 @@ Faz 8 tamamlanma notu (2026-07-17):
|
||||
|
||||
Amaç: React Native geliştirmesine başlamadan önce instance keşif ve stabil API sınırını tamamlamak.
|
||||
|
||||
- [ ] `/api/v1` sözleşmesi yayınlandı.
|
||||
- [ ] `/.well-known/neta` sözleşmesi yayınlandı.
|
||||
- [ ] Instance metadata ve capability modeli tamamlandı.
|
||||
- [ ] Pairing güvenlik tasarımı ayrı ADR olarak yazıldı.
|
||||
- [ ] Device token lifecycle tasarlandı.
|
||||
- [x] `/api/v1` sözleşmesi yayınlandı.
|
||||
- [x] `/.well-known/neta` sözleşmesi yayınlandı.
|
||||
- [x] Instance metadata ve capability modeli tamamlandı.
|
||||
- [x] Pairing güvenlik tasarımı ayrı ADR olarak yazıldı.
|
||||
- [x] Device token lifecycle tasarlandı.
|
||||
|
||||
Faz 9 tamamlanma notu (2026-07-17):
|
||||
|
||||
- `/.well-known/neta`; protocol/discovery sürümü, kalıcı instance kimliği, application adı, mutlak API/meta/health URL'leri ve HTTPS politikasını public discovery belgesi olarak yayınlar.
|
||||
- `/api/v1/meta`; server/API sürümü, instance/organization kimliği, absolute branding asset URL'leri, SemVer minimum mobil sürümü, platformlar, auth yöntemi, capability durumları ve navigasyon linklerini standart success envelope içinde döndürür.
|
||||
- `/api/v1/health` SQLite/migration readiness'i v1 envelope ve `SERVICE_UNAVAILABLE` hata koduyla sunar. `/api/v1/me` yalnızca geçerli Better Auth session'ıyla güvenli user/role/client bağı ve session expiry döndürür; token/password/secret içermez.
|
||||
- `instance_settings` ve migration `0007`; ilk discovery isteğinde concurrency-safe oluşturulan UUID'yi backup/restore ile korunacak kalıcı instance kimliği yapar. Domain veya marka adı kimlik olarak kullanılmaz.
|
||||
- API major sürümü URL'de `/api/v1` olarak kilitlendi. Additive alan/capability değişiklikleri v1 içinde; alan silme, tip/anlam/auth kırılması yeni major içinde yapılacaktır. Tüm v1 yanıtları `X-Neta-API-Version: 1` taşır.
|
||||
- `NETA_MINIMUM_MOBILE_VERSION` opsiyonel SemVer alt sınırı olarak eklendi. Bilinmeyen capability/alanları yok sayma ve `planned` capability'yi kullanmama kuralı belgelendi.
|
||||
- Pairing runtime'a sahte/eksik endpoint olarak eklenmedi; `auth.device-pairing` capability'si `planned` durumundadır. Ayrı ADR-0018; tek kullanımlık challenge, rate limit, hash-only secret, opaque access/refresh token rotation, reuse detection, scope, revoke/expire/compromised lifecycle, secure storage ve restore sonrası token epoch invalidation gereksinimlerini kilitler.
|
||||
- Mobil URL bağlantı algoritması; origin normalizasyonu, HTTPS, redirect/downgrade koruması, discovery/meta instance ID eşlemesi ve kimlik değişiminde credential'ı sessizce kullanmama kurallarıyla `phase-9-mobile-api.md` belgesinde yayınlandı.
|
||||
- `phase9:api-boundary` pairing route'larının tasarım uygulanmadan açılmadığını ve API/service sınırını doğrular. `phase9:smoke`; eşzamanlı discovery, metadata, minimum sürüm, capabilities, health, anonymous/owner/client `/me`, disabled client reddi ve absolute branding URL akışlarını gerçek Next.js + Better Auth üzerinde doğrular.
|
||||
- Typecheck, hedefli ESLint, migration drift kontrolü, production build, Faz 8 source/build artifact sınırı ve `git diff --check` başarılıdır.
|
||||
|
||||
Çıkış kriteri: Mobil istemci backend'in iç uygulama detaylarına bağımlı olmadan entegrasyona başlayabilir.
|
||||
|
||||
@@ -1002,8 +1015,8 @@ Başlangıç koşulları:
|
||||
- [x] Faz 6 portal backend geçişi tamamlandı.
|
||||
- [x] Faz 7 kapsamındaki runtime modülleri tamamlandı veya açıkça ertelendi.
|
||||
- [x] Faz 8 Supabase runtime temizliği ve release hardening tamamlandı.
|
||||
- [ ] Faz 9 mobil API hazırlığı tamamlandı.
|
||||
- [ ] Tasarım sırasında kullanılacak backend veri sözleşmeleri stabil.
|
||||
- [x] Faz 9 mobil API hazırlığı tamamlandı.
|
||||
- [x] Tasarım sırasında kullanılacak backend veri sözleşmeleri stabil.
|
||||
|
||||
Sayfa grupları:
|
||||
|
||||
@@ -1051,7 +1064,7 @@ Her sayfa için tasarım kabul checklist'i:
|
||||
- [x] Hedef schema tamamlandı.
|
||||
- [x] Service/repository sınırı tamamlandı.
|
||||
- [x] Server-side authorization tamamlandı.
|
||||
- [ ] API v1 sınırı hazırlandı.
|
||||
- [x] API v1 sınırı hazırlandı.
|
||||
|
||||
### Supabase çıkışı
|
||||
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
---
|
||||
title: Faz 9 — Mobil API ve Instance Discovery Sözleşmesi
|
||||
description: React Native istemcileri için discovery, API v1, metadata, capability, sürümleme ve güvenlik sınırı.
|
||||
status: completed
|
||||
last_updated: 2026-07-17
|
||||
---
|
||||
|
||||
# Faz 9 — Mobil API ve instance discovery
|
||||
|
||||
Bu faz mobil uygulamanın Neta backend iç yapısını bilmeden bir self-hosted instance'ı tanımasını sağlar. Mobil uygulamanın kendisi ve device pairing implementasyonu kapsam dışıdır.
|
||||
|
||||
## 1. Bağlantı akışı
|
||||
|
||||
Kullanıcı mobil uygulamaya instance URL'sini girer:
|
||||
|
||||
```text
|
||||
https://neta.example.com
|
||||
```
|
||||
|
||||
İstemci:
|
||||
|
||||
1. URL'yi yalnızca origin olacak şekilde normalize eder; credential, query ve fragment kabul etmez.
|
||||
2. Production'da HTTPS olmayan remote origin'i reddeder. HTTP yalnızca `localhost`, `127.0.0.1` ve emulator geliştirme adresleri için açık kullanıcı onayıyla kullanılabilir.
|
||||
3. `GET /.well-known/neta` çağrısını yapar.
|
||||
4. `protocol=neta` ve desteklenen `discoveryVersion` değerini doğrular.
|
||||
5. Discovery belgesindeki API URL'lerinin beklenen origin'den çıkmadığını doğrular.
|
||||
6. `GET /api/v1/meta` çağrısını yapar ve `instance.id` değerini discovery `instanceId` değeriyle karşılaştırır.
|
||||
7. Daha önce kaydedilmiş aynı origin farklı bir `instanceId` döndürürse bunu yeni/restore edilmiş instance olarak kullanıcıya açıkça gösterir; mevcut credential'ı sessizce yeniden kullanmaz.
|
||||
8. Minimum client sürümünü ve capability listesini değerlendirir.
|
||||
9. Instance kaydını `origin + instanceId + applicationName + iconUrl` ile yerel güvenli metadata alanına kaydeder.
|
||||
|
||||
Redirect takibi en fazla üç hop olmalı ve HTTPS'ten HTTP'ye downgrade edilmemelidir. Discovery veya meta içindeki URL kullanıcı girdisinden bağımsız güven kaynağı sayılmaz.
|
||||
|
||||
## 2. Endpoint özeti
|
||||
|
||||
| Endpoint | Auth | Cache | Amaç |
|
||||
| --- | --- | --- | --- |
|
||||
| `GET /.well-known/neta` | Public | 60 saniye public | Instance ve API keşfi |
|
||||
| `GET /api/v1/meta` | Public | 60 saniye public | Marka, sürüm ve capability bilgisi |
|
||||
| `GET /api/v1/health` | Public | No-store | DB/migration readiness |
|
||||
| `GET /api/v1/me` | Better Auth session | Private/no-store | Güvenli kullanıcı/session özeti |
|
||||
|
||||
Public endpoint'ler session oluşturmaz ve secret dönmez. `/me` geçersiz, süresi dolmuş veya disabled hesaba ait session için `401 UNAUTHENTICATED` döndürür.
|
||||
|
||||
## 3. Discovery v1
|
||||
|
||||
Örnek:
|
||||
|
||||
```json
|
||||
{
|
||||
"protocol": "neta",
|
||||
"discoveryVersion": 1,
|
||||
"instanceId": "6d26e558-9c93-4cd8-93a1-5c8d5166045a",
|
||||
"applicationName": "Poyraz Studio",
|
||||
"api": {
|
||||
"version": "1",
|
||||
"baseUrl": "https://neta.example.com/api/v1",
|
||||
"metaUrl": "https://neta.example.com/api/v1/meta",
|
||||
"healthUrl": "https://neta.example.com/api/v1/health"
|
||||
},
|
||||
"security": {
|
||||
"httpsRequired": true,
|
||||
"insecureLoopbackAllowed": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`instanceId` ilk discovery isteğinde kriptografik UUID olarak oluşturulur, `instance_settings` tablosunda saklanır ve backup/restore ile korunur. Domain veya marka adı instance kimliği değildir.
|
||||
|
||||
## 4. API v1 envelope
|
||||
|
||||
Başarılı yanıt:
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"data": {}
|
||||
}
|
||||
```
|
||||
|
||||
Hata:
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": false,
|
||||
"error": {
|
||||
"code": "UNAUTHENTICATED",
|
||||
"message": "Geçerli bir oturum gerekli.",
|
||||
"details": {}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`details` opsiyoneldir. `/api/v1` yanıtları `X-Neta-API-Version: 1` header'ı taşır. Mobil istemci kullanıcıya göstereceği metni `message` alanından alabilir; program akışını yalnızca stabil `code` üzerinden kurmalıdır.
|
||||
|
||||
Mevcut hata kodları:
|
||||
|
||||
- `VALIDATION_ERROR`
|
||||
- `UNAUTHENTICATED`
|
||||
- `FORBIDDEN`
|
||||
- `NOT_FOUND`
|
||||
- `CONFLICT`
|
||||
- `INVARIANT_VIOLATION`
|
||||
- `UPSTREAM_ERROR`
|
||||
- `UPSTREAM_TIMEOUT`
|
||||
- `SERVICE_UNAVAILABLE`
|
||||
- `INTERNAL_ERROR`
|
||||
|
||||
## 5. Metadata ve capability
|
||||
|
||||
`/api/v1/meta` şu grupları döndürür:
|
||||
|
||||
- Protokol/discovery/API major sürümü
|
||||
- Neta server package sürümü
|
||||
- Kalıcı instance kimliği ve oluşturulma zamanı
|
||||
- Application/organization adı
|
||||
- Mobil için absolute logo/icon URL'leri ve semantic marka bilgisi
|
||||
- Minimum desteklenen mobil client sürümü
|
||||
- `ios` ve `android` platform listesi
|
||||
- Authentication durumu
|
||||
- Capability listesi
|
||||
- Discovery, API, health ve me linkleri
|
||||
|
||||
Capability kaydı:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "portal.client",
|
||||
"version": 1,
|
||||
"status": "available",
|
||||
"access": "client"
|
||||
}
|
||||
```
|
||||
|
||||
İstemci bilinmeyen capability ID ve alanlarını yok saymalıdır. `status=planned`, endpoint'in kullanılabilir olduğu anlamına gelmez.
|
||||
|
||||
İlk capability seti:
|
||||
|
||||
- `instance.discovery`
|
||||
- `instance.branding`
|
||||
- `auth.better-auth-cookie`
|
||||
- `files.local`
|
||||
- `freelancer.core`
|
||||
- `portal.client`
|
||||
- `ai.assistant`
|
||||
- `auth.device-pairing` — `planned`
|
||||
|
||||
## 6. Minimum mobil sürüm
|
||||
|
||||
Instance sahibi opsiyonel SemVer tabanını environment ile ilan edebilir:
|
||||
|
||||
```env
|
||||
NETA_MINIMUM_MOBILE_VERSION=1.2.0
|
||||
```
|
||||
|
||||
Boşsa metadata `minimumSupportedVersion: null` döndürür ve server sürüm zorlaması yapmaz. İlk mobil release yayınlandığında istemci kendi sürümünü SemVer olarak karşılaştırır:
|
||||
|
||||
- Client sürümü minimumdan düşükse authenticated mutation başlatmaz.
|
||||
- Discovery/meta/health erişimini korur.
|
||||
- Kullanıcıya upgrade gereksinimini gösterir.
|
||||
- Pre-release SemVer yalnızca test kanallarında kullanılmalıdır.
|
||||
|
||||
## 7. API sürümleme politikası
|
||||
|
||||
- Major sürüm URL'dedir: `/api/v1`.
|
||||
- Yeni opsiyonel alan, yeni endpoint ve yeni capability additive değişikliktir; v1 içinde yapılabilir.
|
||||
- Alan silme, alan tipini değiştirme, mevcut enum anlamını değiştirme veya auth modelini kırma yeni major `/api/v2` gerektirir.
|
||||
- ID'ler opaque string kabul edilir; UUID formatına client iş mantığı bağlanmaz.
|
||||
- Timestamp'ler UTC ISO-8601 string'dir.
|
||||
- Para değerleri ilgili resource API'leri yayınlandığında integer minor unit olacaktır.
|
||||
- Liste endpoint'leri yayınlandığında cursor pagination kullanacaktır; offset sözleşmesi varsayılmaz.
|
||||
- İstemci bilinmeyen JSON alanlarını ve enum/capability değerlerini forward-compatible biçimde yok sayar.
|
||||
- Eski major kaldırılmadan önce metadata capability ve release notlarıyla deprecation duyurulur.
|
||||
|
||||
## 8. Authentication sınırı
|
||||
|
||||
Bugünkü `/me`, Better Auth cookie session'ını doğrular; web ve entegrasyon smoke testleri aynı güvenli session adapter'ını kullanır. Session token, password hash veya AI secret yanıt içine girmez.
|
||||
|
||||
React Native için kalıcı bearer/device session üretimi bu fazda uygulanmadı. Mobil istemci `auth.device-pairing.status=planned` gördüğünde pairing UI'ını etkinleştirmemelidir. Gelecek güvenlik ve lifecycle kararı [ADR-0018](adr-0018-device-pairing.md) belgesindedir.
|
||||
|
||||
## 9. Test ve kalite kapısı
|
||||
|
||||
`pnpm phase9:smoke` şunları gerçek Next.js ve Better Auth akışında doğrular:
|
||||
|
||||
- Eşzamanlı discovery isteklerinde tek ve kalıcı instance ID
|
||||
- Discovery/meta ID ve absolute URL tutarlılığı
|
||||
- Public cache ve session oluşturmama davranışı
|
||||
- API version header ve envelope
|
||||
- Readiness health
|
||||
- Minimum client sürümü ve capability modeli
|
||||
- Anonymous `/me` negatif testi
|
||||
- Freelancer `/me`
|
||||
- Client `/me` ve client kimlik bağı
|
||||
- Disabled client session reddi
|
||||
- Branding değişikliğinin absolute mobile metadata'ya yansıması
|
||||
- Pairing route'larının implementasyon tamamlanmadan yayınlanmaması
|
||||
Reference in New Issue
Block a user