feat(api): complete phase 9 mobile contracts

This commit is contained in:
poyrazavsever
2026-07-17 09:38:22 +03:00
parent 46a746d2d4
commit b04031a3e3
25 changed files with 4896 additions and 19 deletions
@@ -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ı