Hacker DirectoryHacker Directory
Öğrenmeye devam et
ENHTML kaydet ↓

WEB / WEB-17.04

WebSocket, SSE ve webhooks

Açık kanal ve doğrulanmış event hangi permission ve iş sonucunu henüz kanıtlamaz?

CORE · RED · BLUE · ARTIFACT · PRACTICE

1. Core · Mekanizma

Hareket olmadan bütün senaryoları oku

İzinli message

  1. Message hazır

    Browser, kurulmuş channel üzerinden book-read action’ı ve book-A nesnesi için mesajını hazırlar. API’nin session context’i reader-A/tenant-A olarak önceden tanımlıdır; bu mesaj henüz API’ye ulaşmamıştır.

    Browser
    book-read / book-A hazır; title yok
    Atlas API
    Channel hazır; message yok
    Book service
    Request yok; effect yok
    Event provider
    Bu akışta kullanılmaz
  2. Message geldi

    book-read/book-A mesajı API’ye ulaştı. API, mesajdaki nesne seçimini kendi reader-A/tenant-A session context’iyle değerlendirir; object tenant ve read izni henüz karara bağlanmamıştır.

    Browser
    book-read / book-A hazır; title yok
    Atlas API
    Message geldi; policy bekliyor
    Book service
    Request yok; effect yok
    Event provider
    Bu akışta kullanılmaz
  3. Local message gate

    Güncel session geçerlidir ve book-A tenant-A’ya aittir. reader-A için book-read izni verilir; API, subject/object/action context’iyle service read request’ini hazırlar.

    Browser
    book-read / book-A hazır; title yok
    Atlas API
    Message allowed; service request hazır
    Book service
    Request yok; effect yok
    Event provider
    Bu akışta kullanılmaz
  4. Service request geldi

    Book service read request’ini teslim alır; local policy ve lookup henüz değerlendirilmemiştir.

    Browser
    book-read / book-A hazır; title yok
    Atlas API
    Message allowed; service request hazır
    Book service
    Read request geldi; lookup bekliyor
    Event provider
    Bu akışta kullanılmaz
  5. Local service read

    Service, verilen read context’ini kendi policy’siyle kabul eder; book-A için Atlas Notları başlığını yerel lookup ile okur ve response’u hazırlar. Henüz API bu response’u almamıştır.

    Browser
    book-read / book-A hazır; title yok
    Atlas API
    Message allowed; service request hazır
    Book service
    book-A title hazır; effect yok
    Event provider
    Bu akışta kullanılmaz
  6. Service result geldi

    Service response API’ye ulaştı; browser message’ı henüz hazırlanmadı veya gönderilmedi.

    Browser
    book-read / book-A hazır; title yok
    Atlas API
    Service result geldi; mapping bekliyor
    Book service
    book-A title hazır; effect yok
    Event provider
    Bu akışta kullanılmaz
  7. Local channel mapping

    API result schema’sı ile correlation’ı kontrol eder; Browser’a iletilecek title message’ı hazırlar.

    Browser
    book-read / book-A hazır; title yok
    Atlas API
    Browser title message hazır
    Book service
    book-A title hazır; effect yok
    Event provider
    Bu akışta kullanılmaz
  8. Title message geldi

    Atlas Notları başlığını taşıyan WebSocket message Browser’a ulaştı. Başlık artık Browser’da bilinir; application message’ın alınması DOM’a uygulandığını veya handshake/frame parsing’in burada çalıştığını kanıtlamaz.

    Browser
    Başlık alındı: Atlas Notları; DOM ayrı
    Atlas API
    Browser title message hazır
    Book service
    book-A title hazır; effect yok
    Event provider
    Bu akışta kullanılmaz

Message reddi

  1. Normal read hazır

    Browser, kurulmuş channel üzerinden book-read action’ı ve book-A nesnesi için mesajını hazırlar. API’nin session context’i reader-A/tenant-A olarak önceden tanımlıdır; bu mesaj henüz API’ye ulaşmamıştır.

    Browser
    book-read / book-A hazır; title yok
    Atlas API
    Channel hazır; message yok
    Book service
    Request yok; effect yok
    Event provider
    Bu akışta kullanılmaz
  2. Message geldi

    book-read/book-A mesajı API’ye ulaştı. API, mesajdaki nesne seçimini kendi reader-A/tenant-A session context’iyle değerlendirir; object tenant ve read izni henüz karara bağlanmamıştır.

    Browser
    book-read / book-A hazır; title yok
    Atlas API
    Message geldi; policy bekliyor
    Book service
    Request yok; effect yok
    Event provider
    Bu akışta kullanılmaz
  3. Local deny

    Session geçerli olsa da reader-A tenant-A içindedir, book-A ise bu dalda tenant-B’ye aittir. Object read reddedilir; service’e hiçbir request hazırlanmaz ve yalnız denial message hazırlanır.

    Browser
    book-read / book-A hazır; title yok
    Atlas API
    Policy reddi; denial hazır
    Book service
    Request yok; effect yok
    Event provider
    Bu akışta kullanılmaz
  4. Denial geldi

    Denial response Browser’a ulaşır; service’e request çıkmamış ve Browser’a resource title verilmemiştir.

    Browser
    Denial alındı; title yok
    Atlas API
    Policy reddi; denial hazır
    Book service
    Request yok; effect yok
    Event provider
    Bu akışta kullanılmaz

SSE duplicate

  1. Resume sonrası

    Örnekte reconnect/history seçimi tamamlanmıştır; API event-2 block’unu hazırlar, Browser henüz almaz.

    Browser
    lastID event-1; apply=0
    Atlas API
    SSE established; event-2 block hazır
    Book service
    Bu akışta kullanılmaz
    Event provider
    Bu akışta kullanılmaz
  2. Block geldi

    Tam SSE text block Browser’a ulaşır; parse ve dispatch henüz gerçekleşmediğinden app apply count değişmez.

    Browser
    Block geldi; parse bekliyor; apply=0
    Atlas API
    SSE established; event-2 block hazır
    Book service
    Bu akışta kullanılmaz
    Event provider
    Bu akışta kullanılmaz
  3. Local event parse

    Örneğin block parser’ı blank line sonrasında event-2/data/retry alanlarını okur; app apply henüz yapılmamıştır.

    Browser
    lastID event-2; event hazır; apply=0
    Atlas API
    SSE established; event-2 block hazır
    Book service
    Bu akışta kullanılmaz
    Event provider
    Bu akışta kullanılmaz
  4. Local apply

    Application seen-ID set’ine event-2 ekler ve title’ı bir kez uygular; bu durable transaction kanıtı değildir.

    Browser
    event-2 seen; apply=1
    Atlas API
    SSE established; event-2 block hazır
    Book service
    Bu akışta kullanılmaz
    Event provider
    Bu akışta kullanılmaz
  5. Normal duplicate hazır

    Delivery history aynı event-2 block’unu tekrar hazırlar; ilk delivery ikinci arrival’ı engelleyen exactly-once garantisi değildir.

    Browser
    event-2 seen; apply=1
    Atlas API
    Duplicate event-2 block hazır
    Book service
    Bu akışta kullanılmaz
    Event provider
    Bu akışta kullanılmaz
  6. Duplicate block geldi

    İkinci block Browser’a ulaşır; ilk title apply korunur ve duplicate için dedupe henüz değerlendirilmemiştir.

    Browser
    Duplicate block geldi; apply=1; bekliyor
    Atlas API
    Duplicate event-2 block hazır
    Book service
    Bu akışta kullanılmaz
    Event provider
    Bu akışta kullanılmaz
  7. Local parse tekrar

    Parser tekrar event-2 üretir; aynı last ID business acknowledgement veya unique event garantisi sayılmaz.

    Browser
    event-2 tekrar parse edildi; apply=1
    Atlas API
    Duplicate event-2 block hazır
    Book service
    Bu akışta kullanılmaz
    Event provider
    Bu akışta kullanılmaz
  8. Local dedupe

    App seen-ID set’i duplicate’i tanır ve ikinci apply yapmaz; bu sabit örneğin final apply count değeri 1 kalır.

    Browser
    Duplicate atlandı; apply=1
    Atlas API
    Duplicate event-2 block hazır
    Book service
    Bu akışta kullanılmaz
    Event provider
    Bu akışta kullanılmaz

Webhook duplicate

  1. Receipt hazır

    Provider event-W delivery’sini hazırlar; receiver bu event’i daha önce processed sayar, yeni receipt henüz gelmemiştir.

    Browser
    Bu akışta kullanılmaz
    Atlas API
    event-W processed; effect=1; receipt yok
    Book service
    Yeni job yok; effect=1
    Event provider
    event-W delivery hazır
  2. Webhook geldi

    HTTP event receipt API’ye ulaşır; exact-byte integrity ve delivery freshness koşulları henüz değerlendirilmemiştir.

    Browser
    Bu akışta kullanılmaz
    Atlas API
    Raw receipt geldi; verification bekliyor
    Book service
    Yeni job yok; effect=1
    Event provider
    event-W delivery hazır
  3. Local receipt gate

    Bu örnekte güvenilen endpoint key’i ve tam raw body üzerindeki signature sonucu olumlu verilmiştir. now=1000 ile signedTime=970 arasındaki 30 birim, tolerance=60 içindedir; duplicate kararı henüz değerlendirilmez.

    Browser
    Bu akışta kullanılmaz
    Atlas API
    Receipt koşulu olumlu; dedupe bekliyor
    Book service
    Yeni job yok; effect=1
    Event provider
    event-W delivery hazır
  4. Local idempotency

    Ledger consumer-A/event-W anahtarını zaten processed bulur; ikinci iş açılmaz, effect count 1 kalır ve 200 receipt hazırlanır.

    Browser
    Bu akışta kullanılmaz
    Atlas API
    Duplicate kabul edildi; effect=1; 200 hazır
    Book service
    Yeni job yok; effect=1
    Event provider
    event-W delivery hazır
  5. Receipt ack geldi

    Provider receiver’ın 200 receipt’ini alır; bu sonuç yeni business job completion veya Browser update değildir.

    Browser
    Bu akışta kullanılmaz
    Atlas API
    Duplicate kabul edildi; effect=1; 200 hazır
    Book service
    Yeni job yok; effect=1
    Event provider
    200 receipt alındı; effect sonucu bilinmez

ROLLER · STATE · VERİ AKIŞI

WebSocket message, frame ve permission

WebSocket uzun ömürlü, iki yönlü bir message kanalıdır; Browser ile server birbirinden bağımsız application message gönderebilir. HTTP/1.1 profile opening handshake’ı GET/Upgrade ve başarılı 101 ile kurar. HTTP/2’de RFC 8441 desteği negotiate edilmişse extended CONNECT ve :protocol=websocket kullanılır; Connection/Upgrade header’ları ve H1’in 101 cevabı buraya kopyalanmaz. Bir H2 stream WebSocket taşırken aynı connection’daki diğer stream’ler HTTP işine devam edebilir. Her Browser/proxy kombinasyonunun bu profile’ı desteklediği varsayılmaz.

Bir text message bir veya daha fazla WebSocket frame’e bölünebilir; frame sınırı TCP segment veya application JSON field sınırı değildir. Masking payload confidentiality sağlamaz; wss ve doğru TLS peer kontrolü ayrı konudur. Atlas örneği authenticated connection ile başlar, fakat book-read message geldiğinde subject/object/action policy yeniden değerlendirilir. İzinli mesaj API’den book service’e read request üretir; izin reddinde service’e request çıkmaz. Sahne handshake yerine kurulmuş kanalın message kararını izler.

SSE: event almak, işi onaylamak değildir

Server-Sent Events HTTP response body’sinde server’dan Browser’a text/event-stream taşır; EventSource aynı stream’de Browser→server application message göndermez. UTF-8 satırlarda data event payload’ını, event listener seçimini, id reconnect bağlamını, sayısal retry ise yeniden bağlanma zamanını etkiler. Blank line birikmiş data’nın dispatch edilmesini tetikler; yalnız TCP chunk gelmesi tam event oluştuğunu göstermez. Örnekteki block id:event-2 ve book title datası içerir; parser line buffer’ı ile UI state ayrı tutulur.

EventSource reconnect sırasında nonempty last event ID string’ini Last-Event-ID header’ıyla bildirir. Server’ın history’den ne kadarını tekrar sunacağı application contract’ıdır. Event ID almak business transaction commit’ini kanıtlamaz; duplicate event için app dedupe gerekir. Retry sonrası aynı event-2 gelebilir; örnekte UI apply count 1 kalır. History süresi dolduysa full snapshot refresh gibi recovery gerekir. Sahne reconnect/history seçimi tamamlandıktan sonra başlar; gerçek EventSource ve retry timer davranışını göstermez.

Webhook: provider’dan receiver’a ayrı request

Webhook Browser’da açılan stream değildir; provider server event’i receiver’a ayrı HTTP request olarak yollar. Receipt response’unun 2xx olması event’in kabul edildiğini bildirir, downstream business işinin bittiğini otomatik söylemez. Stripe provider profile duplicate delivery ve sıra dışı arrival ihtimalini açıklar. Atlas örneği generic book.updated event alias’ı kullanır; gerçek Stripe event veya account verisi içermez. Browser’ın API’den book okumasıyla provider’ın webhook teslimi direction, authentication ve lifetime bakımından farklıdır.

Receipt integrity için provider profile’ın exact raw bytes doğrulaması ve trusted endpoint key provenance’ı gerekir. Parse edilip yeniden serialize edilen eşdeğer JSON aynı bytes değildir. Signed delivery timestamp freshness kontrolü event created zamanından ayrıdır; retry yeni delivery timestamp taşıyabilir. Valid receipt yine duplicate olabilir. Idempotency ledger consumer-A/event-W anahtarını processed sayar ve ikinci business effect üretmeden receipt’i kabul eder. Crypto sonucu başlangıç koşulu olarak verilmiştir; bu ledger signature verification sonucu değildir.

2. Red · Güven ve etki

Hareket olmadan bütün senaryoları oku

Message yetkisi

  1. Channel ve message context ayrıldı

    Channel kurulmuş ve session valid olarak tanımlıdır. policy-denied message row’unda reader-A tenant-A içindedir ama istenen object tenant-B’ye aittir.

    Channel/body kaydı
    Channel established
    Resource/verification gate
    Object tenant-B
    Delivery/effect sınırı
    Service call yok
  2. Action ve object sınırı seçildi

    Action book-read’tir. Message’ın doğru shape’te olması veya açık connection’dan gelmesi foreign-tenant object için permission vermez.

    Channel/body kaydı
    Action: book-read
    Resource/verification gate
    Subject tenant-A ≠ object tenant-B
    Delivery/effect sınırı
    Policy bekliyor
  3. Per-message policy reddi belirlendi

    Row expected=false bildirir. Gate object/action context’ini kontrol eder; handshake’in kabul edilmiş olması bu ret kararını allow’a dönüştürmez.

    Channel/body kaydı
    Session valid=true
    Resource/verification gate
    Object permission=false
    Delivery/effect sınırı
    Service call withheld
  4. Downstream transfer üretilmedi

    Foreign object için book data hazırlanmaz ve service’e read dispatch yapılmaz. Denial sonrası service’in unchanged kalması bu branch’in somut sınırıdır.

    Channel/body kaydı
    Message received in ledger
    Resource/verification gate
    Policy deny known
    Delivery/effect sınırı
    No downstream read
  5. Connection lifetime izinle eşitlenmedi

    Long-lived channel session koşullarının değişmesini engellemez. Bu row bilinen tenant mismatch’ini gösterir; logout, expiry veya heartbeat sonucu ayrıca değerlendirilir.

    Channel/body kaydı
    Tenant mismatch known
    Resource/verification gate
    Lifetime policy separate
    Delivery/effect sınırı
    No object body
  6. Handshake protokolü ayrı bırakıldı

    HTTP/1.1 Upgrade ile negotiated HTTP/2 extended CONNECT farklı bootstrap profilleridir. Bu application permission row’u frame parsing veya bu bootstrap’ların çalıştığını kanıtlamaz.

    Channel/body kaydı
    Application deny known
    Resource/verification gate
    Bootstrap profile separate
    Delivery/effect sınırı
    No broader protocol claim

Signed byte bağı

  1. Webhook body iki biçimde okundu

    rawBody ile reserializedBody aynı eventId, type ve bookId değerlerini taşıyabilir. Field sırası ve whitespace değiştiği için byte representation’ları aynı değildir.

    Channel/body kaydı
    Event: event-W
    Resource/verification gate
    Two byte representations
    Delivery/effect sınırı
    Verification bekliyor
  2. Verification girdisi sınırlandı

    Exact byte verification signed body’ye bağlıdır. JSON değerlerini okuyup yeniden serialize etmek, imzalanan byte dizisini koruduğu varsayımıyla kullanılmaz.

    Channel/body kaydı
    Values may match
    Resource/verification gate
    Bytes differ
    Delivery/effect sınırı
    Raw body gerekli
  3. Key provenance ayrı kontrol sayıldı

    untrusted-key row’unda signatureValidDeclared=true olsa bile keyProvenanceDeclared=false’tur. Matematiksel signature sonucu trusted endpoint key kaynağının yerine geçmez.

    Channel/body kaydı
    Signature declared=true
    Resource/verification gate
    Key provenance=false
    Delivery/effect sınırı
    Receipt pending
  4. Receipt gate reddi belirlendi

    Bu row receiptAccepted=false ve newEffect=0 bildirir. Fresh signed time ve eşleşen bytes, güvenilmeyen key kaynağıyla birlikte acceptance üretmez.

    Channel/body kaydı
    Integrity condition declared
    Resource/verification gate
    Receipt accepted=false
    Delivery/effect sınırı
    New effect=0
  5. Signature uniqueness sayılmadı

    Trusted normal signature bile aynı event’in daha önce işlenmediğini söylemez. Signature, freshness ve consumer/event dedupe üç ayrı karardır.

    Channel/body kaydı
    Signature ≠ uniqueness
    Resource/verification gate
    Freshness separate
    Delivery/effect sınırı
    Dedupe separate
  6. Kavram byte fixture’ında tutuldu

    Burada iki inert string ve declared receipt tablosu karşılaştırılır. Gerçek SDK verification, key yönetimi veya provider delivery’si gözlenmiş sayılmaz.

    Channel/body kaydı
    Bytes comparison known
    Resource/verification gate
    Key denial known
    Delivery/effect sınırı
    No live delivery claim

VARSAYIM · SINIR · KONTROL

Established channel’ı sınırsız izin sanmak

WebSocket handshake kabulünden sonra her message’ı aynı yetkiyle geçirmek yanlış varsayımdır. Session’ın süresi dolabilir, object başka tenant’a ait olabilir veya action channel profile’da bulunmayabilir. Message schema’sı geçse bile resource kararı gerekir. Policy-denied akışı book-read message’ı teslim alır; object permission koşulu sağlanmadığında service call üretmez ve denial döndürür. Bu durum channel kabulüyle message authority’sinin neden ayrı tutulduğunu gösterir.

Service’in yalnız API connection’ına güvenmesi de aynı sorunu downstream’e taşır. API’den gelen request doğru subject/object/context’i taşımalı; service kendi policy’sini uygulamalıdır. Browser Origin header’ı handshake review’inde yararlıdır, fakat her client için signed identity veya business permission kanıtı değildir. WSS kullanımı bütün application işlerini onaylamaz. İncelemede mesajı hazırlayan taraf, trusted context’i kuran bileşen ve deny sonrasında gerçekleşmeyen transfer ayrı izlenir.

Teslim edildi ile bir kez işlendi ayrımı

SSE lastEventId bir client acknowledgement protokolü değildir; handler’ın UI’a uygulaması ile parser’ın ID güncellemesi farklı olaylardır. Webhook signature-valid sonucu da exactly-once delivery vaat etmez. Duplicate receipt ikinci business effect’e dönüşüyorsa signature idempotency yerine kullanılmış olabilir. Signature kontrolünden önce JSON normalize etmek başka bir sorundur: eşdeğer değer ağacı signed byte representation’ı değiştirebilir. Örneğin iki inert raw-body string’i arasındaki fark, değer eşitliği ile byte eşitliğinin ayrımını gösterir.

Receipt’leri event created timestamp sırasına dizmek business order garantisi vermez; ayrı event’ler aynı saniyeyi paylaşabilir. Freshness kabulü consumer’ın event ID’yi hiç görmediğini de söylemez. Duplicate retention window, durable queue ve transaction sınırı birbiriyle uyumlu olmalıdır. Bellekte processed alias’ın doğru çalışması crash sonrası veya concurrent worker’larda tek etki garantisi değildir. Artifact first, duplicate ve stale receipt kararlarını ayırır; delivery history ile business effect history ayrı tutulur.

3. Blue · Güvenli geliştirme ve savunma

Hareket olmadan bütün senaryoları oku

SSE duplicate

  1. Event stream alanları okundu

    SSE block id=event-2, event=book, retry=1000 ve data=Atlas Notları içerir. retry değeri reconnect tercihi bildirir; kesin teslim süresi veya application ack değildir.

    Delivery observation
    id=event-2
    ID/time/consumer bağı
    retry=1000
    İnceleme sonucu
    Apply count bekliyor
  2. Teslim geçmişi kayda bağlandı

    eventDeliveries içinde event-2 iki kez vardır. Bu önceden kurulmuş history, stream transport’ın exactly-once olduğu iddiasıyla okunmaz.

    Delivery observation
    Deliveries: event-2 × 2
    ID/time/consumer bağı
    Exactly-once=false
    İnceleme sonucu
    App dedupe inceleniyor
  3. Parser ID ve effect ayrıldı

    Last-Event-ID state’i event’in işlenip UI’a uygulandığını tek başına kanıtlamaz. Seen-ID dedupe kararı ayrı application state’idir.

    Delivery observation
    Parser/event ID state
    ID/time/consumer bağı
    Application seen-ID state
    İnceleme sonucu
    Ack=false
  4. Beklenen apply sayısı eşleştirildi

    expectedApplyCount=1 seçilen duplicate history için beklenen sonuçtur. İki delivery ile tek effect arasındaki fark application dedupe’dan gelir, stream’in duplicate üretmemesinden değil.

    Delivery observation
    Delivery count=2
    ID/time/consumer bağı
    Expected apply count=1
    İnceleme sonucu
    Dedupe boundary known
  5. Resume garantisi genişletilmedi

    Bu history retained event’lerin nasıl bulunacağını bütünüyle göstermez. Expired cursor recovery ve server history retention için ayrı contract ve gözlem gerekir.

    Delivery observation
    Duplicate history known
    ID/time/consumer bağı
    Retention evidence separate
    İnceleme sonucu
    No universal resume guarantee
  6. İnceleme sonucu application’a bağlandı

    İki ordinary event kaydını tek apply’a indiren policy incelenir. Gerçek browser reconnect, wall-clock delay veya durable effect garantisi bu tuple’dan çıkarılmaz.

    Delivery observation
    Expected apply=1
    ID/time/consumer bağı
    Transport not exactly-once
    İnceleme sonucu
    Runtime recovery unobserved

Receipt ve effect

  1. Signed time ve event zamanı ayrıldı

    eventCreated=800, deliverySignedTime=970 ve now=1000’dır. Freshness bu örnekte delivery signature zamanına bağlanır; event oluşturma zamanı business order garantisi değildir.

    Delivery observation
    Signed time=970
    ID/time/consumer bağı
    now=1000; tolerance=60
    İnceleme sonucu
    Receipt review pending
  2. Freshness koşulu değerlendirildi

    Normal signed time 30 birim önce olup seçilen 60 birim tolerance içindedir. Bu tolerance örneğin policy’sidir; provider’ın default değeri diye okunmaz.

    Delivery observation
    Age=30
    ID/time/consumer bağı
    Selected tolerance=60
    İnceleme sonucu
    Freshness acceptable
  3. İşlenmiş event bağı bulundu

    initialProcessed içinde consumer-A/event-W vardır ve initialEffectCount=1’dir. Bu kayıt duplicate receipt’ten önce kurulmuş history’dir.

    Delivery observation
    Consumer/event already retained
    ID/time/consumer bağı
    Initial effect count=1
    İnceleme sonucu
    Duplicate branch selected
  4. Receipt kabulü yeni effect yaratmadı

    duplicate row receiptAccepted=true ve newEffect=0 bildirir. duplicateReceiptStatus=200 olabilirken finalEffectCount=1 kalır; ack ile yeni business effect aynı şey değildir.

    Delivery observation
    Receipt accepted=true
    ID/time/consumer bağı
    New effect=0
    İnceleme sonucu
    Final effect count=1
  5. Stale receipt farklı nedenle ayrıldı

    stale-declared row signedTime=900 ile now=1000 arasındaki 100 birim nedeniyle seçilen tolerance’ı aşar. Bu ret duplicate dedupe kararıyla karıştırılmaz.

    Delivery observation
    Duplicate: accepted, no effect
    ID/time/consumer bağı
    Stale: not accepted
    İnceleme sonucu
    Causes separate
  6. Durability ve concurrency bilinmez bırakıldı

    Bu ledger receipt ve effect kararlarını ayırır. concurrencyExecuted=false olduğu için crash recovery veya paralel worker’larda tek effect garantisi çıkarılamaz.

    Delivery observation
    Receipt/effect split known
    ID/time/consumer bağı
    Concurrency unobserved
    İnceleme sonucu
    No durability guarantee

UYGULAMA · GÜVENLİK KONTROLÜ · DOĞRULAMA

Message sınırında karar ve lifetime

Channel profile message type, action, allowed object scope, size ve rate limit’i tanımlar. Server session/context’i trusted kaynaktan kurar, her message’ın object/action iznini değerlendirir ve protected data’yı ancak allow sonrasında üretir. Session expiry/logout sonrası channel invalidation davranışı belirlenir; yalnız handshake’te login kontrolü uzun connection’a yetmez. Proxy timeout, application heartbeat ve protocol ping/pong farklı liveness sinyalleridir; pong book-read permission kanıtı değildir.

API→service request gerekli minimum subject/resource context’ini taşır; service return shape’i ayrıca doğrulanır. Browser message schema ve correlation alias’ını eşleştirir; eski reply yeni read sonucu sayılmaz. Modelde local policy deny sonrasında service kartı değişmez: request çıkmaması kontrolün durduğu boundary’yi gösterir. Handshake, TLS, frame parsing ve flow control farklı katmanlardır; application state gözlemi bu protocol katmanlarının doğru çalıştığını tek başına kanıtlamaz.

Resume, receipt ve durable effect ledger

SSE contract retained history, Last-Event-ID yorumu, expired-cursor recovery ve app-level dedupe davranışını açıklar. Örnekte event-2 iki kez teslim edilse de UI apply count 1 kalır; parser ID state ile app seen-ID set farklıdır. Client close ve server’ın HTTP 204 ile reconnect’i durdurması recovery tasarımına girer. Sayısal retry alanı delivery guarantee değildir; Browser backoff ve network koşulları nedeniyle kesin wall-clock schedule sonucu çıkarılmaz.

Webhook receiver raw body’yi verification için korur, approved endpoint key’ini trusted configuration’dan seçer ve signed delivery time’ı tolerance policy’siyle değerlendirir. Artifact’teki 60 saniye eğitim için seçilmiştir; Stripe library’nin varsayılan 5 dakika değeriyle karıştırılmaz. Integrity/freshness sonrasında consumer/event key’i durable acceptance ve business effect ile aynı tutarlılık sınırına bağlanır; erken 2xx kayıp işi gizlememelidir. Duplicate receipt başarılı ack alabilir, fakat effect count değişmez. Crash recovery ve concurrent storage atomicity için kalıcı ledger ve commit davranışı ayrıca gerekir.

ŞİMDİ VAKAYA UYGULA

Açık channel veya accepted receipt hangi iş kararını kanıtlamaz?

WebSocket object policy, SSE event dedupe ve webhook receipt farklı gate’lerdir. Normal delivery history, signed bytes ve effect sayısı kendi bağlamıyla okunur.

Vakadaki API contract’ı ile browser’ın okuyabildiği representation’ı ayrı incele. Envelope, data, error ve resource permission için hangi gözlemin yeterli olduğunu tartış.

Bağlı vaka dosyasını aç ↗

ÖRNEĞİ BİRLİKTE OKUYALIM

Atlas channel ve receipt karar tablosu

Bir alan seç; hangi sonucu desteklediğini ve nerede yetersiz kaldığını incele.

Ham kaydı ve alan açıklamalarını oku
{
  "profile": {
    "actualNetwork": false,
    "actualProtocol": false,
    "actualCrypto": false,
    "channelEstablishedDeclared": true,
    "sessionValidDeclared": true,
    "serviceTransport": "ordinary owned read request",
    "webhookProviderExample": "Stripe documentation only; generic Atlas aliases"
  },
  "channelComparison": [
    {
      "kind": "WebSocket",
      "direction": "browser <-> API",
      "lifetime": "established bidirectional message channel"
    },
    {
      "kind": "SSE",
      "direction": "API -> browser",
      "lifetime": "HTTP event stream"
    },
    {
      "kind": "Webhook",
      "direction": "provider -> owned API receiver",
      "lifetime": "separate HTTP deliveries"
    }
  ],
  "websocketProfiles": [
    {
      "http": "HTTP/1.1",
      "method": "GET",
      "bootstrap": "Upgrade",
      "success": 101,
      "stream": "connection"
    },
    {
      "http": "HTTP/2 with RFC8441 negotiated support",
      "method": "CONNECT",
      "protocol": "websocket",
      "success": 200,
      "stream": "single H2 stream",
      "connectionUpgradeHeaders": false
    }
  ],
  "messageLayers": {
    "application": "one JSON book-read message",
    "websocketFrames": "one or more; boundaries not fixed by app",
    "tcpSegments": "byte stream segmentation independent",
    "maskingIsEncryption": false
  },
  "messageRows": [
    {
      "case": "normal",
      "subject": "reader-A",
      "tenant": "tenant-A",
      "objectTenant": "tenant-A",
      "action": "book-read",
      "sessionValid": true,
      "expected": true
    },
    {
      "case": "policy-denied",
      "subject": "reader-A",
      "tenant": "tenant-A",
      "objectTenant": "tenant-B",
      "action": "book-read",
      "sessionValid": true,
      "expected": false
    }
  ],
  "sse": {
    "block": "id: event-2\nevent: book\nretry: 1000\ndata: Atlas Notları\n\n",
    "initialLastId": "event-1",
    "parsed": {
      "id": "event-2",
      "event": "book",
      "retry": 1000,
      "data": "Atlas Notları"
    },
    "eventDeliveries": [
      "event-2",
      "event-2"
    ],
    "expectedApplyCount": 1,
    "selectedHistoryEstablishedBeforeScene": true,
    "exactlyOnceTransport": false,
    "appAck": false
  },
  "webhook": {
    "rawBody": "{\"eventId\":\"event-W\",\"type\":\"book.updated\",\"bookId\":\"book-A\"}",
    "reserializedBody": "{\"bookId\": \"book-A\", \"eventId\": \"event-W\", \"type\": \"book.updated\"}",
    "configuredKeyAlias": "trusted-endpoint-key-A",
    "consumer": "consumer-A",
    "eventId": "event-W",
    "eventCreated": 800,
    "deliverySignedTime": 970,
    "now": 1000,
    "tolerance": 60,
    "toleranceIsProviderDefault": false,
    "signatureValidDeclared": true,
    "exactBytesVerifiedDeclared": true,
    "keyProvenanceDeclared": true,
    "initialProcessed": [
      "consumer-A/event-W"
    ],
    "initialEffectCount": 1,
    "receiptRows": [
      {
        "case": "first",
        "signedTime": 970,
        "now": 1000,
        "signatureValidDeclared": true,
        "exactBytesVerifiedDeclared": true,
        "keyProvenanceDeclared": true,
        "previouslyProcessed": false,
        "receiptAccepted": true,
        "newEffect": 1
      },
      {
        "case": "duplicate",
        "signedTime": 970,
        "now": 1000,
        "signatureValidDeclared": true,
        "exactBytesVerifiedDeclared": true,
        "keyProvenanceDeclared": true,
        "previouslyProcessed": true,
        "receiptAccepted": true,
        "newEffect": 0
      },
      {
        "case": "stale-declared",
        "signedTime": 900,
        "now": 1000,
        "signatureValidDeclared": true,
        "exactBytesVerifiedDeclared": true,
        "keyProvenanceDeclared": true,
        "previouslyProcessed": false,
        "receiptAccepted": false,
        "newEffect": 0
      },
      {
        "case": "untrusted-key",
        "signedTime": 970,
        "now": 1000,
        "signatureValidDeclared": true,
        "exactBytesVerifiedDeclared": true,
        "keyProvenanceDeclared": false,
        "previouslyProcessed": false,
        "receiptAccepted": false,
        "newEffect": 0
      }
    ],
    "finalEffectCount": 1,
    "duplicateReceiptStatus": 200,
    "concurrencyExecuted": false
  },
  "boundaries": {
    "connectionGrantsObjectPermission": false,
    "receiptEqualsBusinessCompletion": false,
    "eventCreatedOrdersBusiness": false,
    "signatureMeansUnique": false
  }
}
channelComparison
Üç farklı actor direction ve lifetime.
websocketProfiles
H1 Upgrade ile negotiated H2 extended CONNECT farklıdır.
messageRows
Established connection sonrası seçilmiş per-message resource gate.
sse
Normal event block, parser ID ve ayrı app apply count.
webhook
Raw bytes ve declared integrity/freshness/idempotency receipt ledger.

Inert event/read verisi ve başlangıç koşulu olarak verilen crypto sonucu kullanılır. Raw-body farkı ve gate kararları, gerçek channel/reconnect/SDK/signature/queue veya concurrent durable storage çalışması değildir.

İki yanlış kanı

Authenticated WebSocket her message’a izin verir.

Her action/object için trusted session/context policy gerekir; established channel yalnız taşıma durumudur.

Signed webhook ve SSE ID exactly-once iş sağlar.

Integrity ve resume bağlamı duplicate teslimi kaldırmaz; application idempotency ve durable effect sınırı ayrıdır.

SIRA SENDE

Bu hikâyeyi sen çöz.

Sonucu tahmin et, kanıtın sınırını bul ve nedenini kendi cümlenle anlat.

WebSocket sessionValid=true. Message içindeki object tenant-B’ye, subject tenant-A’ya ait. Message kabul edilir mi?

  1. Evet. Opening handshake sonraki bütün object’lere izin verir.
  2. Hayır. Message policy-denied olur.
Gerekçeli cevabı oku

Hayır. Message policy-denied olur. — Kurulmuş channel her message için object izni sağlamaz. Güncel tenant ve action koşulları ayrıca doğrulanır.

Duplicate receipt için accepted=true, fakat newEffect=0. Bu çelişki mi?

Dersten seçilen artifact alanları; öğretim örneği

webhook.receiptRows[1]
{"case":"duplicate","signedTime":970,"now":1000,"signatureValidDeclared":true,"exactBytesVerifiedDeclared":true,"keyProvenanceDeclared":true,"previouslyProcessed":true,"receiptAccepted":true,"newEffect":0}
webhook.finalEffectCount
1
  1. Hayır. Duplicate kabul edilir; effect tekrar uygulanmaz.
  2. Evet. Kabul edilen her delivery yeni write gerektirir.
Gerekçeli cevabı oku

Hayır. Duplicate kabul edilir; effect tekrar uygulanmaz. — previouslyProcessed=true, consumer’ın event dedupe context’ini gösterir. Geçerli signature, event’in ilk kez geldiğini garanti etmez.

SSE retry/id, WebSocket frame’leri ve webhook’ın alınan body byte’larını doğrulaması hangi ayrı sınırları açıklar?

Gerekçeli cevabı oku

SSE’nin server→client stream’inde id, reconnect sırasında history ile ilişki kurmaya yardım eder; exactly-once veya application ACK sağlamaz. WebSocket message birden fazla frame’e bölünebilir; TCP segment sınırları ayrıdır ve masking encryption değildir. Webhook doğrulaması güvenilen endpoint key’iyle tam olarak alınan byte’lar üzerinden yapılır. Aynı JSON object’i yeniden serialize etmek aynı signed byte’ları üreteceğini garanti etmez.

□ SSE id’yi exactly-once garantisi saymadım.

□ WebSocket framing ile webhook byte doğrulamasını ayırdım.

Uygulama konsolunu aç · request / response / browser
Request, URL, cookie ve DOM örneklerini ayrıca aç

Kaynaklar ve kapsam