AG
EN

// work / fivucsas

FIVUCSAS

Çok kiracılı bir biyometrik kimlik doğrulama platformu — yüz, ses, MRZ ve aktif canlılık — gömülebilir bir widget olarak paketlenmiş. Kendi kendine barındırılan, KVKK uyumlu, WebAuthn öncelikli.

Rol
Baş geliştirici — tam yığın, makine öğrenmesi ve altyapı · RollingCat Software
Tarih
Mar 2026 – Haz 2026

Yığın

  • Java 21
  • Spring Boot 3
  • Python
  • FastAPI
  • PostgreSQL 16
  • pgvector
  • React 18
  • Kotlin Multiplatform
  • WebAuthn
  • OAuth 2.0
  • OIDC
  • Flyway
  • Docker
  • Traefik
  • Loki + Promtail + Grafana

Problem

Biyometrik kimlik doğrulamayı benimsemek zordur çünkü onu entegre etmek genellikle ham yüz ve ses verisini işlemeyi, sahtecilik saldırılarını savuşturmayı ve katı gizlilik yasalarına uymayı gerektirir — çoğu ekibin üstlenemeyeceği bir iş. Amaç, biyometrik girişi bir siteye reCAPTCHA kadar kolay eklenebilir hâle getirmekti; üstelik entegre eden taraf biyometrik veriye hiç dokunmadan.

Kısıtlar

  • Biyometrik veri hiçbir zaman şifresiz olarak depolanmamalı ve gömme çıkarımı hiçbir zaman halka açık internetten erişilebilir olmamalı.
  • KVKK uyumluluğu sonradan eklenecek bir özellik değil, kesin bir gerekliliktir.
  • Her kiracı kuruluş, veritabanı düzeyinde diğer tüm kiracılardan yalıtılmış olmalıdır.

Yaklaşım

Platform üç çalışma ekseni hâlinde ayrılır — doğruluk kaynağı olan bir Spring Boot kimlik çekirdeği, tüm biyometrik işlemeye sahip özel bir FastAPI ML yan-süreci ve ince istemciler (React web, Kotlin Multiplatform mobil ve masaüstü ile gömülebilir bir widget). Widget, tüm meydan okuma akışını reCAPTCHA'nın bir meydan okumayı sunduğu gibi sunar.

Önemli kararlar

  • ML yan-sürecini kimlik çekirdeğinden ayrı bir dağıtılabilir olarak ayır

    Biyometrik işlemci API ile yalnızca özel bir Docker ağı üzerinden konuşur ve asla halka açık değildir. ML yığını API'ye dokunmadan yükseltilebilir ve gömme çıkarımı internetten yapısal olarak erişilemezdir.

  • Çok kiracılılığı bir uygulama filtresi değil, bir veritabanı meselesi yap

    Her kuruluş şema düzeyinde yalıtılmıştır; dolayısıyla bir geliştiricinin eklemeyi unutabileceği bir "WHERE tenant_id = ?" koşulu yoktur. Kiracı yalıtımı bir uygulama hatasıyla atlanamaz.

  • Gömme şifreleme anahtarı eksik olduğunda hızlı başarısız ol

    Gömmeler bekleme hâlinde Fernet ile şifrelenir ve yalnızca kosinüs benzerliği çalıştığı anda süreç içinde çözülür. Uygulama anahtar olmadan açılmayı reddeder; böylece her saklı gömmeyi geçersiz kılacak bir varsayılana sessizce geri dönemez.

Mimari

Tarayıcılar ve mobil istemciler, bir Traefik ters proxy'si üzerinden Spring Boot kimlik çekirdeğine ulaşır. Kimlik çekirdeği, pgvector'lü PostgreSQL 16'ya sahiptir ve FastAPI biyometrik işlemcisiyle halka açık internetin erişemediği özel bir Docker ağı üzerinden konuşur. Loki, Promtail ve Grafana tüm yığını gözlemler.

flowchart TB
  client["Clients<br/>React web · KMP mobile/desktop · embeddable widget"]
  traefik["Traefik reverse proxy"]
  api["Identity Core API<br/>Spring Boot 3 · Java 21"]
  db[("PostgreSQL 16<br/>+ pgvector")]
  ml["Biometric Processor<br/>FastAPI · Python"]
  obs["Loki · Promtail · Grafana"]

  client --> traefik --> api
  api --> db
  api -. private docker network .-> ml
  api --> obs
  ml --> obs
Bir Traefik proxy'sinin arkasında üç çalışma ekseni; ML yan-süreci yalnızca özel ağdadır.

Sonuç

FIVUCSAS, gömülebilir bir widget, WebAuthn/FIDO2 passkey'leri ve ekran tekrarını ve önceden kaydedilmiş saldırıları savuşturan rastgele bir aktif canlılık meydan okumasıyla, kendi kendine barındırılan çok kiracılı bir platform olarak canlıda çalışır. Depo, üçüncü taraf güvenlik incelemesi tamamlanana dek özeldir; kaynak erişimi talep üzerine mümkündür.

Rakamlarla

  • 55+ Flyway migrasyonları
  • 13 users satırının ardındaki FK-kademeli tablo
  • 3 Çalışma ekseni (API · ML · istemciler)
  • Fernet Bekleme hâlinde gömme şifrelemesi
  • SHA-256 Model teslim bütünlüğü
  • WebAuthn Birincil giriş faktörü

Aşağıdaki yapılandırılmış bölümler Türkçe mevcuttur; ayrıntılı anlatım İngilizce yazılmıştır. Tam Türkçe çeviri henüz mevcut değildir.

Derinlemesine

FIVUCSAS — Face and Identity Verification Using Cloud-based SaaS — began as my senior engineering project at Marmara University and now ships under RollingCat Software, the umbrella name I publish some of my work under. This case study is the architecture story; for the war stories — the three production incidents the team learned the most from — see the companion write-up.

The shape of the system

The core insight that shaped almost every decision was simple to state and hard to enforce: biometric data must never sit unencrypted at rest, and the embedding extraction process must never be reachable from the internet. Everything else fell out of that.

That single constraint is why the ML stack lives in a separate FastAPI sidecar on a private Docker network rather than inside the Spring Boot API. The identity core is the authoritative source of truth for tenants, users, sessions, audit logs, and MFA factors (TOTP, WebAuthn, NFC, biometric). The biometric processor owns the face mesh, embedding extraction, and active-liveness puzzle scoring, and it answers only to the API — never to a browser.

Active liveness as the differentiator

The “Biometric Puzzle” is the part I am proudest of. Instead of a single still frame — which a printed photo or a screen replay can defeat — the widget prompts a randomized sequence of facial actions: smile, blink, look left, look right. The randomization is what makes a pre-recorded attack impractical: the attacker cannot know the sequence in advance. The widget exposes this whole flow the way reCAPTCHA exposes a challenge, so a tenant integrates against the smallest possible surface.

Privacy and tenancy by construction

Two design choices keep the platform honest:

  • Schema-per-tenant isolation. Tenant boundaries are a database concern, not an application filter. There is no shared table where a forgotten predicate leaks one organization’s data to another.
  • Fail-fast configuration. The application refuses to start without the embedding encryption key. A fail-soft default would silently invalidate every stored embedding — exactly the kind of irreversible data corruption that is far better to catch at boot than in production.

Operational posture

The platform is self-hosted on a Hetzner CX43 box behind Traefik, observed with Loki + Promtail + Grafana, and backed up with pgBackRest WAL archiving for point-in-time recovery. Security hygiene is part of the workflow, not an afterthought: gitleaks runs in CI, GitHub secret-scanning and push-protection are on, and every new OAuth endpoint gets a permitAll-chain grep as part of PR review.

The source is private until a third-party security review completes. Source access is available on request.

Tüm vaka çalışmaları