Akışlar ve Çözümleme
Fraud kararı sabit bir kural kümesiyle değil, yayınladığınız akışlarla verilir. Bir akışı işlem tipine göre kapsamlarsınız (kart ödemesi, havale, cüzdan çekimi…); karar isteği geldiğinde sistem eşleşen yayınlanmış akışların hepsini çözümler, koşar ve sonuçları tek karar altında birleştirir.
Bu sayfa çözümlemenin nasıl işlediğini anlatır — yani "isteğim hangi akışlara düştü?" sorusunun cevabını. Uç sözleşmesi için: Karar API'si.
Kuralları tetikleyen uç
Yayınladığınız akış (ve içindeki kurallar) tek bir çağrıyla tetiklenir:
POST /api/v1/fraud/decisions/evaluate
Authorization: Bearer <access-token>Token'ı Ed25519 imzanızla POST /api/v1/auth/token'dan alırsınız. Gereken yetki: fraud:view_decisions. Ayrıntı ve tam alan sözlüğü: Karar API'si.
İstekteki hangi alan hangi ekseni sürer
Çözümlemeyi siz yönlendirirsiniz — hangi akışların koşacağı, gövdede gönderdiğiniz şu alanlardan türer:
| Çözümleme ekseni | İstekte nereden gelir |
|---|---|
merchantId | Token'ınızdan — gövdede göndermezsiniz |
merchantGroupIds | Token bağlamınızdan |
subjectType | Gövdedeki işlem tipi (payment, bankTransfer, billPayment … hangi objeyi doldurduğunuz) |
productContext | Gövdede; verilmezse direct_api |
integrationMode | Gövdede |
| Akış adı | metadata.fraudFlowName (ya da liveFraudFlowName / flowName) |
curl -X POST "https://api-gateway.lunixi.com/api/v1/fraud/decisions/evaluate" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"bankTransfer": { "amount": 250000, "currency": "TRY", "iban": "TR33…" },
"customer": { "id": "cust_84213" },
"productContext": "direct_api"
}'Bu çağrı bank_transfer işlem tipine kapsamlanmış akışlarınızın hepsini bulur, koşar ve birleşik kararı döndürür. Yanıtta hangi akışların koştuğu ve hangi kuralların eşleştiği açıklanabilirlik alanlarında ve multiFlow bloğunda gelir — kararın neden verildiğini oradan okursunuz.
Geçmişe dayanan kurallar (hız/velocity, temel çizgi sapması) için ayrıca olay besleyin: POST /api/v1/fraud/events/transactions (tekli) ve /batch (toplu). Karar çağrısı tek bir işleme bakar; "bu müşteri son 24 saatte 12 işlem yaptı" bilgisi olay omurgasından gelir. Bu uçlar Ed25519 imzalıdır, Bearer değil.
Akış hangi eksenlerde kapsamlanır
Bir akış yayınlanırken aşağıdaki boyutlarla daraltılabilir. Boş bırakılan boyut "hepsi" demektir — o eksende her değere uyar.
| Boyut | Örnek değer | Boş bırakılırsa |
|---|---|---|
merchantId | Belirli bir merchant | Global akış — tüm merchant'lara uyar |
merchantGroupIds | Merchant grubu listesi | Grup eşleşmesi aranmaz |
flowType | fraud_decision | — |
subjectType | card_payment, bank_transfer … | Her işlem tipine uyar |
integrationMode | Entegrasyon biçimi | Hepsine uyar |
productContext | direct_api (varsayılan) | Hepsine uyar |
subjectType değerleri işlem tipini taşır: card_payment · bank_transfer · eft · fast · crypto_transfer · wallet_deposit · wallet_withdrawal · wallet_payment · wallet_transfer · bill_payment · loan · payout · refund · cash_in · cash_out · international_transfer
Yalnız published ve isActive akışlar çözümlemeye girer. Taslak ya da pasif bir akış, kapsamı ne kadar dar olursa olsun hiç değerlendirilmez. Ayrıca karar yolunda yalnız triggerType='inline_request' akışlar koşar: event, kafka ya da schedule tetikleyicili akışlar kendi tetikleyicilerinde koşar, karar yoluna girmez — aksi hâlde aynı akış iki kez koşardı.
Çözümleme: eşleşen akışların hepsi koşar
Kapsam eksenleri değişmedi — merchantId · merchantGroupIds · flowType · subjectType · integrationMode · productContext (boş kolon = hepsine uyar). Değişen şey seçim adımı: sistem artık en dar kapsamlı tek akışı seçmez. Süzgeçten geçen yayınlanmış akışların hepsi çözülür ve executionMode alanına göre iki şeritten birinde koşar: sync akışlar karar yanıtını üretir, async akışlar kararı bekletmeden arka planda koşar.
sync olanlar birleşip kararı üretir, async olanlar kararı bekletmeden arka planda koşar.Sync şerit: bağımsız koşum, tek karar
executionMode='sync' akışların her biri sıfır taban state ile bağımsız koşar: akışların sırası sonucu etkilemez, bir akış diğerinin skorunu ya da reason code'larını görmez. Koşum bitince sonuçlar tek karar altında birleştirilir:
| Boyut | Birleştirme kuralı |
|---|---|
| Karar | En şiddetli kazanır: allow < force_3d < review < block |
| Skor | Akış başına tavan (varsayılan 100) + toplam tavan (varsayılan 250). Tavan aşıldığında yanıtta multi_flow_score_capped reason code'u görünür |
| Akış hatası | Diğer akışlar devam eder; hata veren akış skippedFlows'a girer ve karar en az review seviyesine yükselir (flow_failed_fail_closed:<akış-adı> reason code'u). Mevcut bir block asla aşağı çekilmez |
| Süre bütçesi | İstek başına varsayılan 25 sn. Bütçe dolarsa kalan akışlar koşulmaz ve skippedFlows'ta budget_exceeded nedeniyle listelenir |
Üç seviyeli zaman sınırı
Süre bütçesi tek katman değildir; iç içe üç sınır vardır ve dıştaki içtekini bağlar:
| Seviye | Varsayılan | Aşılırsa |
|---|---|---|
| Düğüm | 8 sn | O düğüm hata verir |
| Akış | 20 sn | O akış atlanır, skippedFlows'a girer |
| İstek (tüm akışlar) | 25 sn | Kalan akışlar koşulmaz, budget_exceeded |
Bir düğümün kendi timeoutMs ayarı varsa o kullanılır — ama akış deadline'ını aşamaz; kalan süre neyse düğüm onunla sınırlanır.
Düğüm zaman aşımı, düğüm hatasıdır. continueOnError tanımlıysa hata dalına gider; tanımlı değilse akışın fail-closed duruşu devreye girer ve karar en az reviewe yükselir.
Pratik sonucu: http_request ya da grpc_call düğümünde yavaş bir dış servis, yalnız o düğümü değil kararın tamamını etkileyebilir. Dış çağrı yapan düğümlere kendi timeoutMs'ini vermek, bu davranışı sizin kontrolünüze alır.
Koşulmamış akış allow değildir. Bütçe nedeniyle atlanan akış, koşup temiz çıkan akıştan skippedFlows alanıyla ayırt edilir — izleme kurarken budget_exceeded nedenini ayrı sayın.
Açıklanabilirlikteki flowPath artık akış-öneklidir: her adım flow:<akış-adı>/<düğüm-id> biçiminde gelir — hangi düğümün hangi akışa ait olduğunu yanıttan okursunuz.
Async şerit: kararı bekletmez
executionMode='async' akışlar karar yanıtını bekletmez: koşum kuyruğa alınır, yanıtta asyncFlows listesinde queued durumuyla görünür ve arka planda aynı motorla koşar. Sonuç koşum kaydına yazılır — ayrıntı için aşağıdaki Async sonuçların iletimi bölümüne bakın.
Async sonuç advisory'dir: senkron verilmiş kararı geriye dönük değiştirmez. Akışın case açma ve aksiyon gibi yan etkileri ise normal işler.
Yanıttaki multiFlow bloğu
Karar yanıtına additive bir alan eklendi — mevcut alanlar değişmedi:
{
"multiFlow": {
"enabled": true,
"executedFlows": ["kart-hiz-kurallari", "cihaz-itibari"],
"skippedFlows": [
{ "name": "agir-analiz", "reason": "budget_exceeded" }
],
"asyncFlows": [
{ "name": "vaka-taramasi", "status": "queued" }
]
}
}gRPC telinde aynı blok multiFlowJson alanında JSON string olarak taşınır.
Belirli bir akışı adıyla çağırma
İstek metadata içinde akış adı gönderirseniz çözümleme doğrudan o ada kilitlenir — çoklu çözümleme o istekte yalnız adı verilen akışı koşar:
{ "metadata": { "fraudFlowName": "yuksek-riskli-havale" } }Kabul edilen anahtarlar: liveFraudFlowName, fraudFlowName, flowName. Bu, kanarya/deneme akışlarını sınamanın yoludur — üretimde varsayılanı ezmek için kullanmayın.
Async sonuçların iletimi
executionMode='async' akışların sonucu koşum kaydına yazılır.
Bu sonuçların size iletimi platform webhook olaylarıyla yapılacaktır — çok yakında. Platform webhook'larının kurulumu, imza doğrulaması ve yeniden deneme davranışı için: Webhook kurulumu.
Switch düğümünde eksik/bozuk veri: condition ve op farkı
Switch düğümünde bir case iki biçimde yazılabilir ve ikisinin eksik/bozuk veri (örneğin sayı beklenen alanda metin) davranışı bilinçli olarak farklıdır:
| Case biçimi | Eksik/bozuk operand olursa | Neden |
|---|---|---|
condition (tam kural DSL'i) | Case eşleşmiş sayılır ve o dala gidilir (fail-closed) | Kural motorunun güvenlik doktrini: tip oynanmış bir istek block yönlü kontrolü sessizce atlatamaz |
Basit op değer eşleme (eq, gt, in...) | Case atlanır, akış default dala düşer ve indeterminateCases alanında görünür (fail-safe) | Yönlendirme amaçlı ucuz eşlemede eksik veri akışı kilitlemesin, ama görünür olsun |
Akış yazarı kuralı: karar-kritik (block yönlü) kontrolü condition ile yazın —
fail-closed davranış istersiniz. Yönlendirme amaçlı ucuz eşlemeyi op ile yazın —
eksik veri default'a düşsün ve indeterminateCases ile görünür olsun.
Gelen webhook tetiği (triggerType: webhook)
webhook tetikli bir akış, bir event-stream bağlantı profili üzerinden dışarıdan
tetiklenir. Zincir:
- Panelden bir bağlantı profili tanımlanır (kaynak:
webhook; imza secret'ı profildedir). - Dış sistem şu adrese POST atar:
POST /api/v1/fraud/database-events/{connectionProfileId}/webhook/{routingKey}— imzax-event-signature, zaman damgasıx-event-timestampheader'ında taşınır. - İmza doğrulanır (HMAC + zaman penceresi); ardından
triggerTypedeğeriwebhookveyaeventolan vetriggerConfig.webhookPathdeğeriroutingKeyile eşleşen yayınlanmış akışlar koşturulur.
Bu gelen tetik yalnız akışı çalıştırır; imza secret'ı bağlantı profilinde tutulur.
executionMode rehberi
| Mod | Ne için |
|---|---|
sync | Karar anını etkileyen hızlı kontroller — hız kuralları, eşikler, liste kontrolleri |
async | Ağır analiz, raporlama ve vaka akışları — karar gecikmesine girmemesi gereken her şey |
Hiç akış eşleşmezse
Yapılandırılmamış bir merchant sessizce allow almaz. Hiçbir capability paketi, kural grubu ve akış çözümlenemezse istek fraud.decision.unconfigured sebep koduyla işaretlenir ve politika varsayılanına düşer (FRAUD_UNCONFIGURED_DECISION, varsayılan review).
Bu bilinçli bir tasarım: önceki davranışta yapılandırılmamış merchant ile açıkça temiz çıkmış bir ödeme birbirinden ayırt edilemiyordu. Entegrasyonunuzu kurarken fraud.decision.unconfigured sebep kodunu izleyin — akışınız yayına girmediyse bunu üretimde görürsünüz.
Capability paketleri
Akışlar tek başına da koşar, ama üzerlerinde bir capability paketi katmanı vardır: paket, bir karar için hangi yeteneklerin hangi sırayla ve hangi hata politikasıyla çalışacağını tarif eder ve gerektiğinde birden çok akışı orkestre eder.
| Durum | Ne koşar |
|---|---|
| Merchant için capability paketi çözümlendi | Paket koşar; akışları o orkestre eder |
| Paket yok | Eşleşen yayınlanmış akışlar çoklu çözümlemeyle doğrudan koşar |
| İkisi de yok | fraud.decision.unconfigured → politika varsayılanı |
Akış çalışırken hata alırsa karar fail-closed davranır: o ana kadar toplanan kanıt (capability, kural grubu, canlı sinyaller) geçerli sayılır ve karar en az review seviyesine yükseltilir — mevcut bir block asla aşağı çekilmez.
Akış içinde kendi kodunuzu çalıştırmak
Kural düğümleri bir eşiği veya karşılaştırmayı ifade etmeye yeter; ama bazı politikalar kural diliyle yazılamaz — bir skorun kendi formülünüzle hesaplanması, bir dış yanıtın ayrıştırılması, iş kuralına özgü bir dönüşüm. Bunun için akışa script düğümü koyarsınız ve kendi JavaScript'inizi çalıştırırsınız.
Script varlığının yaşam döngüsü
| Aşama | Ne olur |
|---|---|
| Taslak | Kaynak kodu, giriş/çıkış şeması, süre ve bellek tavanı tanımlanır |
| Statik analiz | Yayın öncesi zorunlu kapı. import / export, require(), eval gibi desenler bloklanır. Sonuç: clean · warning · blocked |
| Yayın | Yalnız analizi geçen kod yayınlanabilir; kaynak özeti (sourceHash) kaydedilir |
| Devre dışı | Yayından kaldırılır; akış onu çağıramaz |
Nasıl çalışır
Kod, fraud servisinin içinde değil, ayrı bir yürütme servisinde koşar: gerçek bir V8 izolatı (isolated-vm) içinde, kendi heap tavanıyla, kendi süre sınırıyla. İzolatlar belirli sayıda işten sonra geri dönüştürülür, çıktı ve log boyutu tavanlanır.
Script'iniz ağa çıkamaz, dosya sistemine erişemez, başka bir modül yükleyemez. Dışarıdan veri gerekiyorsa bunu akışın kendi düğümleriyle (http-request, database-lookup, redis-get) getirir, script'e girdi olarak verirsiniz.
İki mod
| Mod | Kullanım |
|---|---|
sync_transform | Saf dönüşüm — girdi al, değer döndür. Sıcak yolda tercih edilir |
async_script | Beklemeli işlem gerektiren, daha uzun soluklu mantık |
Her çalıştırma denetime yazılır: success · failed · timeout. Süre tavanını aşan bir script akışı kilitlemez — hata olarak döner ve akışın fail-closed duruşu devreye girer.
İlgili
- Karar API'si —
POST /api/v1/fraud/decisions/evaluatealan sözlüğü - Karar Kayıtları —
GET /api/v1/fraud/decision-logs