Files
neta/docs/self-hosted-redesign/phase-9-mobile-api.md
T

205 lines
7.7 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: 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ı
- Workspace adı, meta title ve kısa uygulama adı
- Mobil için ayrı light/dark logo, favicon absolute 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.
`instance.workspaceName` kullanıcıya gösterilecek firma/freelance çalışma alanı adıdır.
`instance.metaTitle` web metadata başlığıdır. `branding.lightLogoUrl`,
`branding.darkLogoUrl` ve `branding.faviconUrl` absolute URL döner; mobil istemci
aktif renk moduna göre doğru logoyu seçmeli ve eksik yeni alanlarda eski
`applicationName` / `iconUrl` alanlarına geriye uyumlu fallback uygulamalıdır.
Authenticated `/api/v1/me` yanıtındaki `preferences.colorMode`, kullanıcının
`light`, `dark` veya `system` tercihini taşır.
İ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ı