Teknik özet

Platform gerçekte nasıl çalışıyor.

Bugün çalışan bileşenlerin bölüm bölüm açıklaması. Projeksiyon yok, karşılaştırma yok — sadece repoya işlenmiş ve üretimde gözlenebilir parçalar.

Çalışma zamanı mimarisi

Platform Node.js 22 backend (ESM, TypeScript kaynakları build sırasında düz JS'e derleniyor) üzerinde çalışıyor ve önünde bir Next.js kontrol paneli var. Backend HTTP API'yi sunuyor; ayrı bir BullMQ worker Redis üzerinden arka plan işlerini tüketiyor.

PostgreSQL tenant verilerini tutuyor — filo, kiralamalar, rezervasyonlar, uygunluk, insight'lar, kullanım olayları ve yalnız-ekleme (append-only) denetim tablosu. Yerel bir SQLite veritabanı eski analytics okuma yolunu koruyor.

AI katmanı sağlayıcıları zincirliyor: birincil hedef Anthropic Claude; OpenAI ve Gemini fallback olarak duruyor. Seçim her istekte provider modülünde yapılıyor.

Her deploy edilebilir image, main'e push'ta Jenkins tarafından build ediliyor ve gitops manifestlerinden ArgoCD tarafından çıkarılıyor. Backend ve ingest cron iki ayrı image ve iki ayrı Jenkins job'u.

Committed artefacts
  • Backend Dockerfile: Dockerfile
  • Ingest cron Dockerfile: cron/Dockerfile
  • Backend Jenkins pipeline: Jenkinsfile

Hash zincirli denetim defteri

Denetim olayları saas.audit_events tablosuna yazılıyor. Her satır, önceki satırın hash'i ile kendi kanonik payload'ının birleştirilmesiyle üretilen SHA-256 hash'i saklıyor; bu nedenle geçmiş bir satırla oynanırsa sonraki tüm hash'ler geçersiz oluyor.

Her tenant zincirinin ilk satırı sabit bir öncül hash'e sahip sentinel satır. Ekleme, önceki hash'i okuyup bir sonrakini atomik olarak hesaplayan bir SECURITY DEFINER fonksiyonu içinde yapılıyor.

  • row_hash = sha256(prev_hash || canonical_payload)
  • canonical_payload olayın kararlı bir JSON serileştirmesi
  • zincir tenant başına — çapraz tenant okumaları RLS tarafından bloklanıyor

Zincir doğrulama endpoint'i

Backend POST /api/v1/public/trust/verify-chain endpoint'ini sunuyor. Bir tenant slug'ı verildiğinde o tenant'ın zincirini baştan sona geziyor, her hash'i yeniden hesaplıyor ve kaç olayın doğrulandığını, ilk-son hash'i, snapshot'ın oluşturulma zamanını içeren bir snapshot döndürüyor.

Endpoint public ancak yalnız-okuma ve rate-limitli. Trust sayfası bunu canlı kanıt için tüketiyor; aynı şekil burada da belgeleniyor ki dış doğrulayıcılar da doğrudan çağırabilsin.

  • İstek: { tenant_slug: string }
  • Yanıt: { snapshot: { events_verified, first_hash, last_hash, snapshot_generated_at, api_version } }
  • api_version v1 olarak donduruldu (LP5.a Sprint 1)

Release Certificate v1

Her sürüm change-safety/ altına işlenen bir Release Certificate JSON'u ile kapanıyor. Sertifika sprint'i, commit SHA'yı, her Change Safety gate'inin sonucunu, kayıtlı istisnaları ve imzayı taşıyor.

Şema v1 olarak donduruldu. Downstream araçlar sertifikayı okuyarak hangi gate'in çalıştığını, kararını ve kanıtın nerede durduğunu öğreniyor.

  • sprint — sprint kimliği
  • commit_sha — deploy edilen commit
  • gates — { replay, snapshot_diff, journey, manifest } sonuçları
  • exceptions — charter referanslı kayıtlı override'lar
  • signed_off_by — onaylayan kimlik
  • evidence_ref — kanıt paketinin yolu

Kanıt paketi (evidence bundle) şekli

Her sürüm artefaktlarını change-safety/evidence/<track>/<milestone>/ altında tutuyor. Paket, tüm dosyaları ve checksum'larını listeleyen bir manifest.json ve düz cümlelerle yazılmış bir status.txt taşıyor.

Paket, sürümün kanıt kaynağı. Paketin içindeki bir dosyayla desteklenmeyen bir iddia, sürüm kaydının parçası değildir.

  • manifest.json — [{ path, sha256, bytes }] paket içeriği üzerinde
  • status.txt — insan-okur çıktı, gate başına bir cümle
  • screenshots/ — gate anında yakalanan görsel regresyonlar
  • lighthouse/ — gate'in gerektirdiği durumlarda performans koşuları

Tenant izolasyonu

Her tenant satırı tenant_id kolonu taşıyor. PostgreSQL row-level security policy'leri her sorguya app.current_tenant değerini bağlıyor; böylece çağıranlar yalnızca kendi tenant'larına ait satırları görüyor.

Çapraz tenant okumaları yalnızca açıkça çapraz-tenant olarak işaretlenmiş bir SECURITY DEFINER fonksiyonundan izinli ve bu yalnızca küçük, denetim altındaki bir system_admin yüzey kümesinden çağrılıyor.

JWT claim'i tenant'ı belirliyor. Query string tenant seçimi için asla güvenilir sayılmıyor.

saas.audit_events

saas.audit_events tablosu API üzerinden akan her durum değiştiren olayı kayıt altına alıyor. Her olay tenant, aktör, olay tipi, kanonik payload ve yukarıda anlatılan zincire bağlayan hash çiftini taşıyor.

Olay tipleri AuditEventType enum'undan geliyor; her route üzerindeki OpenAPI x-audit-event annotasyonu hangi olayları ürettiğini beyan ediyor ve bir test annotasyon ile enum arasında kayma olmamasını koruyor.

  • tenant_id, actor_id, event_type
  • payload (kanonik JSON)
  • prev_hash, row_hash
  • created_at

Karar platformu (bugün)

Karar platformu, algılanan örüntüleri kayıtlı sonuçlara dönüştüren katman. Bugün repoda mevcut üç parçadan oluşuyor:

Kural'lar KPI serileri üzerinde koşulları tanımlıyor. Aksiyon'lar bir kuralın önerebileceği tipli operasyonlar. Çalıştırma defteri hangi kuralın tetiklendiğini, hangi aksiyonun seçildiğini ve ortaya çıkan olayı — denetim zincirine bağlantısıyla birlikte — kaydediyor.

  • Kural tablosu — KPI katmanı üzerinde bildirimsel koşullar
  • Aksiyon registry — bir kuralın önerebileceği tipli operasyon kataloğu
  • Çalıştırma defteri — kural → aksiyon → sonuç için yalnız-ekleme kayıt

Güven vs. Mühendislik

/trust müşteriye dönük yüzey. Platformun verilerine güvenilip güvenilemeyeceğine karar veren biri tarafından okunmak üzere tasarlandı: canlı bir hash zinciri doğrulayıcıya, örnek bir Release Certificate'a ve kısa bir incident kütüphanesine bağlanıyor.

/engineering — bu sayfa — aynı bileşenlerin teknik açıklaması. Bir mühendisin, parçaların nasıl birleştiğini müşteri yüzeyi üzerinden çıkarım yapmak zorunda kalmadan okuyabilmesi için var.

İki sayfa aynı sistemi anlatıyor. Hiçbir sayfa bugün repoda mevcut olmayan bir işlevi reklam etmiyor.

Bu sayfanın kapsamı

Bu sayfa, bugün repoya işlenmiş ve üretimde gözlenebilir bileşenleri anlatıyor. Benchmark, başka sistemlerle karşılaştırma veya ileriye dönük ifade içermiyor. Bir iddia spesifikleştiğinde, işlenmiş artefaktın göreli yolu birlikte gösteriliyor.