WEB / WEB-17.S02
GraphQL, streaming ve message authorization
Her operation, field ve event için güncel permission kararını connection’dan ayır.
1. Core · Mekanizma
Hareket olmadan bütün senaryoları oku
Title izinli
- Read message hazır
Consumer, note-A için notes.read action’ı ve title alanını seçerek GraphQL read mesajını hazırlar. API’nin Duru/tenant-A context’i bu örnekte önceden tanımlıdır; bu mesajın güncel izni henüz kararlaştırılmaz.
- Consumer
- notes.read message ready; title yok
- API / policy
- Policy bekliyor; title yok
- Public note store
- note-A sabit; read yok
- Message alındı
API tamamlanmış message arrival’ı kaydeder; connection kabulü field veya zaman gate’ini çözmez.
- Consumer
- notes.read message ready; title yok
- API / policy
- notes.read geldi; current gate pending
- Public note store
- note-A sabit; read yok
- Current gate allow
Object, field, cost ve current context koşulları ayrı kabul edildi; store read artık hazırlanabilir.
- Consumer
- notes.read message ready; title yok
- API / policy
- Object/field/current allow; store read ready
- Public note store
- note-A sabit; read yok
- Read store’a ulaştı
Store approved read’in tamamlanmış arrival’ını görür; title projection henüz yerel olarak okunmamıştır.
- Consumer
- notes.read message ready; title yok
- API / policy
- Object/field/current allow; store read ready
- Public note store
- Approved note-A read received; body pending
- Title projection
Store yerel read-only işlemle Tea & Bread başlığını hazırlar; nesne üzerinde mutation yoktur.
- Consumer
- notes.read message ready; title yok
- API / policy
- Object/field/current allow; store read ready
- Public note store
- Tea & Bread title body ready; mutation=false
- Title API’ye geldi
Title body store’dan API’ye ulaştı; API kendi response projection’ını bir sonraki yerel adımda seçer.
- Consumer
- notes.read message ready; title yok
- API / policy
- Title received; API projection pending
- Public note store
- Tea & Bread title body ready; mutation=false
- Response hazır
Seçilen GraphQL projection title’ı içerir; bu fixture actual GraphQL parser veya HTTP status testi değildir.
- Consumer
- notes.read message ready; title yok
- API / policy
- GraphQL title response ready; no mutation
- Public note store
- Tea & Bread title body ready; mutation=false
- Title teslim edildi
Consumer’a tamamlanmış response arrival’ında title teslim edilir; sadece izinli read projection’ı taşınır.
- Consumer
- Received title=Tea & Bread; mutation=false
- API / policy
- GraphQL title response ready; no mutation
- Public note store
- Tea & Bread title body ready; mutation=false
Field reddi
- Read message hazır
Consumer, note-A için notes.read action’ı ve title alanını seçerek GraphQL read mesajını hazırlar. API’nin Duru/tenant-A context’i bu örnekte önceden tanımlıdır; bu mesajın güncel izni henüz kararlaştırılmaz.
- Consumer
- notes.read message ready; title yok
- API / policy
- Policy bekliyor; title yok
- Public note store
- note-A sabit; read yok
- Message alındı
API tamamlanmış message arrival’ı kaydeder; connection kabulü field veya zaman gate’ini çözmez.
- Consumer
- notes.read message ready; title yok
- API / policy
- notes.read geldi; current gate pending
- Public note store
- note-A sabit; read yok
- Current context
API object ve operation context’ini yerel olarak değerlendirir; store’a henüz hiçbir read çıkmaz.
- Consumer
- notes.read message ready; title yok
- API / policy
- Object/action known; field/time gate pending
- Public note store
- note-A sabit; read yok
- Permission reddi
Object, current context ve cost koşulları geçer, fakat fieldAllowed=false’tur. Nullable title için korunan değer okunmaz; store’a hiçbir read çıkmadan title=null ve error path note/title sonucu hazırlanabilir.
- Consumer
- notes.read message ready; title yok
- API / policy
- Nullable title field denied; value=null
- Public note store
- note-A sabit; read yok
- Denial response
API, data.note.title=null ve errors içinde path=[note,title] içeren GraphQL envelope’ını hazırlar. expectedBody=null korunan title projection’ının yokluğudur; envelope yokluğu veya belirli HTTP status demek değildir.
- Consumer
- notes.read message ready; title yok
- API / policy
- Denial response ready; protected title absent
- Public note store
- note-A sabit; read yok
- Denial alındı
Consumer denial response arrival’ını görür; body içindeki diagnostic korunan title içermez.
- Consumer
- GraphQL null title + errors alındı
- API / policy
- Denial response ready; protected title absent
- Public note store
- note-A sabit; read yok
- Result yorumlandı
Consumer yerel olarak sonucunu yorumlar; schema veya açık channel permission yerine sayılmaz.
- Consumer
- Title değeri yok; HTTP status ayrı
- API / policy
- Denial response ready; protected title absent
- Public note store
- note-A sabit; read yok
Message expired
- Read message hazır
Consumer, note-A için notes.read action’ı ve title alanını seçerek WebSocket read mesajını hazırlar. API’nin Duru/tenant-A context’i bu örnekte önceden tanımlıdır; bu mesajın güncel izni henüz kararlaştırılmaz.
- Consumer
- notes.read message ready; title yok
- API / policy
- Policy bekliyor; title yok
- Public note store
- note-A sabit; read yok
- Message alındı
API tamamlanmış message arrival’ı kaydeder; connection kabulü field veya zaman gate’ini çözmez.
- Consumer
- notes.read message ready; title yok
- API / policy
- notes.read geldi; current gate pending
- Public note store
- note-A sabit; read yok
- Current context
API object ve operation context’ini yerel olarak değerlendirir; store’a henüz hiçbir read çıkmaz.
- Consumer
- notes.read message ready; title yok
- API / policy
- Object/action known; field/time gate pending
- Public note store
- note-A sabit; read yok
- Permission reddi
WebSocket daha önce kabul edilmiştir, fakat now=120 ile validUntil=120 sınırında current=false olur. Bu uygulamada equality geçersizdir; yeni message reddedilir, store read ve korunan title hazırlığı yapılmaz.
- Consumer
- notes.read message ready; title yok
- API / policy
- now=validUntil; message permission expired
- Public note store
- note-A sabit; read yok
- Denial response
API, süresi dolan message için güvenli denial response’unu hazırlar; title içermez. Bu dal WebSocket message kararıdır, GraphQL null+errors envelope’ı veya connection close sonucu değildir.
- Consumer
- notes.read message ready; title yok
- API / policy
- Denial response ready; protected title absent
- Public note store
- note-A sabit; read yok
- Denial alındı
Consumer denial response arrival’ını görür; body içindeki diagnostic korunan title içermez.
- Consumer
- Message denial alındı; title yok
- API / policy
- Denial response ready; protected title absent
- Public note store
- note-A sabit; read yok
- Result yorumlandı
Consumer yerel olarak sonucunu yorumlar; schema veya açık channel permission yerine sayılmaz.
- Consumer
- Yeni title yok; eski data geri çekilmedi
- API / policy
- Denial response ready; protected title absent
- Public note store
- note-A sabit; read yok
Event tutuldu
- Subscription context
Önceden kabul edilmiş stream vardır; bu başlangıç yeni event için permission iddiası değildir.
- Consumer
- Subscription önce kabul edildi; yeni title yok
- API / policy
- Önceki admission var; güncel izin bekliyor
- Public note store
- note-A sabit; read yok
- Event adaylığı
Server yerel olarak yeni note event’ini değerlendirir; consumer’a henüz hiçbir event teslim edilmez.
- Consumer
- Subscription önce kabul edildi; yeni title yok
- API / policy
- Yeni event candidate; projection yok
- Public note store
- note-A sabit; read yok
- Current policy deny
note-A için yeni SSE event’inde subscriptionAllowed=false verilmiştir. Önceki admission, event ID veya cursor bu ret koşulunu değiştirmez; title projection’ı hazırlanmaz.
- Consumer
- Subscription önce kabul edildi; yeni title yok
- API / policy
- Revoked; protected title body absent
- Public note store
- note-A sabit; read yok
- Delivery tutuldu
Yeni event server’da tutulur; client close/reconnect gözlemi veya önceki verinin silinmesi modellenmez.
- Consumer
- Subscription önce kabul edildi; yeni title yok
- API / policy
- Event delivery=0; mutation=false; title absent
- Public note store
- note-A sabit; read yok
ROLLER · STATE · VERİ AKIŞI
Resolver bir permission sınırıdır
GraphQL schema, hangi field ve type’ların ifade edilebildiğini söyler; Duru’nun belirli note üzerinde hangi property’yi okuyabileceğini söylemez. Parse ve validation tamamlandıktan sonra resolver, authenticated actor, object ilişkisi, action ve field policy’sini aynı context içinde değerlendirmelidir. Atlas Notları yalnız note-A başlığını okumayı modeller. title nullable olarak seçilmiştir: field reddedilirse değer null olur ve errors içinde ilgili response path bulunur; izinli kardeş field’lar ayrı değerlendirilebilir. Non-Null kullanılsaydı null, uygun nullable parent’a kadar yayılabilirdi. Bu seçim uygulamanın authorization error politikasını görünür kılar; GraphQL standardı belirli bir access-control kütüphanesi veya evrensel HTTP status zorunlu kılmaz. data ve errors birlikte bulunması, korunan title’ın döndüğü anlamına gelmez.
Cost, type ve permission ayrı sorulardır
Bir resolver izinli olsa bile liste büyüklüğü ve tekrar eden alt seçimler kaynak tüketimini değiştirebilir. Query cost bu nedenle ayrı bir admission kararıdır; depth tek başına tüm fan-out’u açıklamaz. Defterde kullanılan title=1 ve liste sınırı=10 uygulamanın seçtiği öğretim değerleridir, GraphQL’in sabit katsayıları değildir. Cost kabulü permission vermez; permission kabulü de sınırsız iş bütçesi vermez. Node ve relationship üzerinden ulaşılan aynı nesneye farklı yolların policy’yi atlamadan aynı kararı uygulaması gerekir. Cache veya batch loader kullanılıyorsa key ve sonuç projection’ı actor/tenant/field bağlamına uygun olmalıdır. Sahne query parser, HTTP binding, gerçek resolver veya cache çalıştırmaz; izinli title projection’ının hangi koşullardan sonra hazırlanabileceğini adım adım gösterir.
WebSocket connection’dan message’a
WebSocket handshake’in kabul edilmesi bir communication channel açar. Bu karar tüm gelecekteki message’lara ve object’lere otomatik permission vermez. Browser Origin kontrolü, beklenen web application’dan gelen açılış isteğini değerlendirmeye yarar; non-browser client için bağımsız identity kanıtı değildir. Cookie’nin gönderilip gönderilmemesi de cookie ve browser kurallarına bağlıdır. Message handler, tanımlı shape ve action’ı çözüp güncel actor/session durumunu ve object policy’sini yeniden kullanır. Defterin expired dalında channel daha önce kabul edilmiştir, fakat now=120 ve validUntil=120 iken yeni notes.read message’ı reddedilir. Bu uygulamada equality geçersiz sayılır; WebSocket protokolü kendi başına böyle bir session timer tanımlamaz. Store’a read teslim edilmez ve title body hazırlanmaz.
SSE subscription’ın ömrü
SSE normalde server’dan client’a event akıtır; EventSource bir iki yönlü command channel değildir. İlk subscription admission’ı kadar, gelecekteki her event’in recipient ve object kapsamı da önemlidir. event id ve reconnect cursor hangi noktadan devam edileceğini anlatır; actor identity veya yeni permission yaratmaz. Subscription revoked olduğunda yeni title event’i tutulur. Sahnenin bu dalı server’ın yerel gate kararında biter: client’ın close gözlemi, reconnect ve daha önce aldığı verinin geri çekilmesi simüle edilmez. Ağ kapandığında EventSource yeniden bağlanmayı deneyebilir; server yeni admission’ı güncel context ile değerlendirmelidir. retry süresi transport davranışına yardım eder, exactly-once business delivery veya tüm event’lerin kayıpsız tekrarını garanti etmez. Kaynak aktarımı ile policy kararı aynı state olarak sunulmaz.
gRPC ve SOAP’a kısa fakat doğru giriş
gRPC bir service method çağrısını typed input/output ile ifade eder; Protocol Buffers yaygın varsayılandır. Unary, server streaming, client streaming ve bidirectional streaming farklı message akışlarıdır. Tek RPC içindeki stream ordering, başka RPC’nin veya business action’ın permission’ı değildir. Channel credentials ile call credentials farklı kapsamlardır; uygulama yine method ve object için karar verir. SOAP 1.2 ise XML Envelope içinde isteğe bağlı Header ve zorunlu Body yapısını tanımlar. Header’ın hangi node’da işlendiği ve Body’nin ultimate recipient’a yönelmesi, içerideki notes.read işleminin izinli olduğunu kanıtlamaz. Security gibi özellikler ek binding/extension ve uygulama profilinde tanımlanır. Defter yalnız bu karşılaştırmanın typed ledger’ıdır: gerçek protobuf message, SOAP XML parser, WS-Security signature veya remote RPC çalıştırılmamıştır.
2. Red · Güven ve etki
Hareket olmadan bütün senaryoları oku
Field reddi
- Operation koşulları seçildi
field-denied row’u GraphQL için connectionAccepted=true, objectAllowed=true ve fieldAllowed=false içerir. İzinli object, title property’sinin otomatik açılması değildir.
- Operation koşulları
- GraphQL field gate
- Current policy gate
- Policy pending
- Resource projection
- Title hazırlanmadı
- Bağımsız gate koşulu ayrıldı
costAllowed=true ve subscriptionAllowed=true olsa da fieldAllowed=false kalır. Cost budget’ın geçmesi field permission sağlamaz.
- Operation koşulları
- Other gates=true
- Current policy gate
- Field=false
- Resource projection
- Resource delivery pending
- Operation policy reddi verildi
expectedAllowed=false, expectedResourceDelivery=false ve expectedMutation=false’tur. Handler protected title projection’ını hazırlamaz.
- Operation koşulları
- Allowed=false
- Current policy gate
- Mutation=false
- Resource projection
- Protected body=null
- Response ile protected data ayrıldı
Selected nullable title schema’da graphqlEnvelope data.note.title=null ve errors path note/title içerir. Protected body null olması bütün envelope’ın yokluğu değildir.
- Operation koşulları
- Permission deny known
- Current policy gate
- Null title + errors
- Resource projection
- Mutation=false
- Transport policy’ye dönüştürülmedi
GraphQL HTTP status bu envelope’dan otomatik türetilmez. Typed selection, cost sınırı ve resource/property permission ayrı contract katmanlarıdır.
- Operation koşulları
- Channel ≠ operation grant
- Current policy gate
- Policy gate independent
- Resource projection
- No extra status claim
- Ret kapsamı resource kararında kaldı
Bilinen sonuç title delivery ve mutation’ın olmamasıdır. Gerçek GraphQL engine veya HTTP adapter’ın çalıştığı değil, bu nullable policy ledger’ının anlamı gösterilir.
- Operation koşulları
- No resource delivery
- Current policy gate
- No mutation
- Resource projection
- Runtime adapter unobserved
Context expired
- Operation koşulları seçildi
expired row’u WebSocket için connectionAccepted=true ve validUntil=120 içerir. Profile now=120 seçer; açık channel context lifetime’ını uzatmaz.
- Operation koşulları
- now=120; validUntil=120
- Current policy gate
- Policy pending
- Resource projection
- Title hazırlanmadı
- Bağımsız gate koşulu ayrıldı
Object, field, subscription ve cost koşulları true’dur fakat current=false’tur. Diğer olumlu alanlar expired context’i current yapmaz.
- Operation koşulları
- Other gates=true
- Current policy gate
- Current=false
- Resource projection
- Resource delivery pending
- Operation policy reddi verildi
expectedAllowed=false, expectedResourceDelivery=false ve expectedMutation=false’tur. Handler protected title projection’ını hazırlamaz.
- Operation koşulları
- Allowed=false
- Current policy gate
- Mutation=false
- Resource projection
- Protected body=null
- Response ile protected data ayrıldı
Bu row yeni resource body teslim etmez. Önceden teslim edilmiş data’nın browser hafızasından silindiği veya connection’ın otomatik kapandığı sonucu eklenmez.
- Operation koşulları
- Permission deny known
- Current policy gate
- No new delivery
- Resource projection
- Mutation=false
- Transport policy’ye dönüştürülmedi
WebSocket connection credentials, her yeni message’ın current actor/action/object koşullarını sağlamaz. Bu aynı ayrım streamed gRPC message için de application policy sorusudur.
- Operation koşulları
- Channel ≠ operation grant
- Current policy gate
- Policy gate independent
- Resource projection
- No extra status claim
- Ret kapsamı resource kararında kaldı
Bilinen sonuç zaman sınırındaki yeni read’in reddidir. Gerçek stream backpressure, Origin/Cookie enforcement veya revocation dağıtımı ayrıca gözlem ister.
- Operation koşulları
- No resource delivery
- Current policy gate
- No mutation
- Resource projection
- Runtime adapter unobserved
VARSAYIM · SINIR · KONTROL
Açık channel’a fazla anlam yüklemek
İncelenecek varsayım “connection kabul edildi, artık bu actor’ın bütün message’ları izinli” cümlesidir. Bunun yanlış sonuca dönüşmesi için uygulamanın current session, operation ve object kararını channel başlangıcındaki boolean’a indirgemesi gerekir. Defterde connectionAccepted=true ile messageAllowed=false aynı anda doğrudur; zaman sınırı dolduğunda store’a hiçbir yeni read gitmez. SSE’de de kabul edilmiş subscription ile yeni event delivery’si farklıdır. Red perspektif, açık channel’ın kendi başına bir zafiyet olduğunu iddia etmez: handler’ın güncel permission kontrolünü nereye koyduğunu ve hangi verinin o kontrolden önce hazırlandığını sorar. Revocation’ın nasıl yayıldığı hakkında kanıt yoksa sonuç “revocation çalışıyor” veya “çalışmıyor” değildir; bu bağımlılık unknown olarak kaydedilir. Önceden teslim edilmiş title’ın hafızadan silindiği de varsayılmaz.
Schema başarısından business yetkisine sıçramak
İkinci varsayım, type validation ve makul query cost sağlandığında resolver’ın object ve field policy’sine gerek kalmadığıdır. Bu karışıklığın etkisi sadece mutation değildir; title projection’ı da izin gerektiren bir disclosure olabilir. Buradaki note halka açık bir öğretim nesnesi olsa bile handler’ın selected title gate’i açıkça modellenir. Field-denied dalında response skeleton ve errors gönderilebilir, fakat korunan title değeri yoktur; “body yok” ifadesi tüm GraphQL envelope’ın yokluğunu değil title projection’ının yokluğunu anlatır. Typed gRPC request veya iyi biçimli SOAP Envelope da aynı business kararı devralmaz. Red inceleme yöntemi sabit policy satırlarının conjunction’ını izlemektir: operation, object, field ve zaman koşullarından hangisinin kanıtlandığı ayrı tutulur. Query çalıştırma, endpoint keşfi veya permission atlama denemesi bu örneğin bir parçası değildir.
3. Blue · Güvenli geliştirme ve savunma
Hareket olmadan bütün senaryoları oku
Event gate kapalı
- SSE subscription row’u okundu
revoked row’unda connectionAccepted=true ve current=true’dur. subscriptionAllowed=false olması yeni event için ayrı policy ret koşuludur.
- Message/event evidence
- SSE connection accepted
- Policy context review
- Subscription allowed=false
- Delivery conclusion
- Delivery pending
- Event ile stream lifetime ayrıldı
SSE server’dan client’a event taşır. Daha önce kabul edilmiş subscription veya cursor, yeni event için resource permission yerine geçmez.
- Message/event evidence
- Direction: server → client
- Policy context review
- Cursor ≠ permission
- Delivery conclusion
- New event gate required
- Negatif delivery sonucu eşleştirildi
expectedAllowed=false, expectedResourceDelivery=false ve expectedBody=null’dır. Beklenen yokluk yeni title event’inin client’a taşınmamasıdır.
- Message/event evidence
- Allowed=false
- Policy context review
- Resource delivery=false
- Delivery conclusion
- Body=null
- Historical data silindi sayılmadı
Bu ret daha önce teslim edilmiş title’ın yok edildiğini göstermez. Yeni delivery sınırı ile geçmiş client data lifetime’ı farklı sorulardır.
- Message/event evidence
- New event withheld
- Policy context review
- Old delivery not retracted
- Delivery conclusion
- Mutation=false
- Revocation propagation kanıtı istenildi
Row subscriptionAllowed=false’ı önkoşul verir. Bu değerin bütün subscriber’lara ne zaman yayıldığını görmek için adapter ve policy revision gözlemi gerekir.
- Message/event evidence
- Declared revocation known
- Policy context review
- Propagation evidence missing
- Delivery conclusion
- Distributed result UNKNOWN
- Event sonucu diğer protokole taşınmadı
Bu SSE gate’i gRPC veya SOAP’ın otomatik aynı kararı verdiğini kanıtlamaz. SOAP Body action’ı ve gRPC method/message kendi approved handler policy’sine bağlanır.
- Message/event evidence
- SSE denial known
- Policy context review
- RPC/SOAP adapters separate
- Delivery conclusion
- No universal enforcement claim
Context eksik
- Missing context kaydı seçildi
unknownEvidence contextPresent=false ve permission=null içerir. Bu known field denial veya expired row ile aynı evidence durumu değildir.
- Message/event evidence
- Context present=false
- Policy context review
- Permission=null
- Delivery conclusion
- Decision pending
- Permission hesaplanmadığı korundu
Subject, tenant, action ve resource context’i bulunmadığı için permission sonucu bilinmez kalır. Channel alias’ını actor authority diye kullanmak bu boşluğu doldurmaz.
- Message/event evidence
- Policy inputs missing
- Policy context review
- Permission UNKNOWN
- Delivery conclusion
- No guessed actor
- Güvenli sonuç ayrı belirlendi
expectedAllowed=false ve expectedResourceDelivery=false güvenli sonuçtur. Bu boolean, eksik permission kanıtının verified false’a dönüştüğü anlamına gelmez.
- Message/event evidence
- Safe allow=false
- Policy context review
- Knowledge remains UNKNOWN
- Delivery conclusion
- Delivery=false
- Body ve mutation yokluğu birlikte tutuldu
expectedBody=null ve expectedMutation=false’tur. İnceleme yalnız error metnine değil, resource delivery ve write’ın gerçekleşmemesi koşullarına da bakar.
- Message/event evidence
- Body=null
- Policy context review
- Mutation=false
- Delivery conclusion
- Negative boundaries retained
- Cost budget permission sayılmadı
titleWeight=1 ve listLimit=10 bu profile ait maliyet tercihidir. Bunlar universal GraphQL sabitleri veya eksik identity yerine kullanılacak gate’ler değildir.
- Message/event evidence
- Selected cost policy
- Policy context review
- Cost ≠ identity
- Delivery conclusion
- Context still missing
- Unknown nedeni teşhis için bırakıldı
Known deny ve context loss ayrı reason’larla izlenmelidir. No-delivery güvenli olsa da hangi trust kaynağının eksik olduğu bulunmadan policy’nin doğru çalıştığı söylenmez.
- Message/event evidence
- No delivery known
- Policy context review
- Missing provenance unresolved
- Delivery conclusion
- No clean policy claim
UYGULAMA · GÜVENLİK KONTROLÜ · DOĞRULAMA
Bir policy, farklı delivery biçimleri
Blue tasarımında readTitle kararı actor, tenant, note-A, action ve property girdileriyle tanımlanır. GraphQL resolver, WebSocket message handler, SSE event filter ve gRPC method aynı policy sonucunu kendi delivery formatına taşır; sadece connection seviyesinde kontrol bırakılmaz. SOAP için de parser’dan çıkan Body action’ı approved application handler’a bağlanır. Bunun tek global boolean olması gerekmez: resource policy ve field projection ayrı ve okunabilir kalabilir. Cost/size sınırı permission gate’inden bağımsız bir bütçedir. Subscription expiry ve revocation davranışının uygulama tarafından belirlendiği belgelenir; açık bir channel’a sonsuz identity ömrü verilmez. Cache key’leri ve batch context’i policy girdilerini kaybetmez. Client’a gönderilen hata güvenli ve anlaşılır olurken internal karar nedeni, actor context ve policy revision erişim kontrollü telemetry’de tutulur.
Sonuç kadar yokluğu da doğrulamak
Olumlu fixture, izinli read’in title projection’ını üretmesini kontrol eder; olumsuz fixture aynı zamanda store delivery=0, mutation=false ve protectedBody=null sonuçlarını kontrol eder. GraphQL field denial için null+errors shape’i seçilen nullable schema ile uyumlu olmalıdır; HTTP status buradan otomatik türetilmez. WebSocket’te daha önce kabul edilmiş connection’ın zaman sınırında yeni message’ı açmadığı, SSE’de revoked subscription’ın yeni event’i client’a taşımadığı ayrı satırlardır. Missing-policy dalı false ile aynı kanıt değildir: permissionUnknown olarak saklanıp güvenli sonuç deny seçilir. Bu ayrım operasyonel teşhiste yararlıdır; reddin gerçekten policy sonucu mu yoksa context kaybı mı olduğunu gösterir. Animasyon bütün bu sonuçları supplied ledger üzerinden deterministik oynatır. Gerçek browser Origin/Cookie enforcement, stream backpressure, RPC server veya subscription adapter için ayrıca entegrasyon kanıtı gerekir.
ŞİMDİ VAKAYA UYGULA
Connection, schema ve budget geçse bile hangi gate yeni delivery’yi durdurur?
GraphQL field, WebSocket message ve SSE event kendi güncel policy koşulunu ister. Null protected body, nullable error envelope ve missing context farklı sonuçlardır.
Vakadaki doğrulanmış actor, tenant ilişkisi ve requested action için gereken kararları ayır. Authentication veya proof başarısını object permission yerine kullanma.
Bağlı vaka dosyasını aç ↗ÖRNEĞİ BİRLİKTE OKUYALIM
Atlas Notları — karar defteri
Bir alan seç; hangi sonucu desteklediğini ve nerede yetersiz kaldığını incele.
Ham kaydı ve alan açıklamalarını oku
{
"profile": {
"noteId": "note-A",
"title": "Tea & Bread",
"actor": "Duru",
"tenant": "tenant-A",
"action": "notes.read",
"field": "title",
"now": 120,
"selectedNullableTitle": true,
"actualProtocols": false
},
"rows": [
{
"case": "normal",
"channel": "graphql",
"connectionAccepted": true,
"contextPresent": true,
"current": true,
"objectAllowed": true,
"fieldAllowed": true,
"subscriptionAllowed": true,
"costAllowed": true,
"expectedAllowed": true,
"expectedBody": {
"title": "Tea & Bread"
},
"expectedResourceDelivery": true,
"expectedMutation": false
},
{
"case": "field-denied",
"channel": "graphql",
"connectionAccepted": true,
"contextPresent": true,
"current": true,
"objectAllowed": true,
"fieldAllowed": false,
"subscriptionAllowed": true,
"costAllowed": true,
"expectedAllowed": false,
"expectedBody": null,
"expectedResourceDelivery": false,
"expectedMutation": false,
"graphqlEnvelope": {
"data": {
"note": {
"title": null
}
},
"errors": [
{
"message": "Field not permitted",
"path": [
"note",
"title"
]
}
]
}
},
{
"case": "expired",
"channel": "websocket",
"connectionAccepted": true,
"contextPresent": true,
"current": false,
"validUntil": 120,
"objectAllowed": true,
"fieldAllowed": true,
"subscriptionAllowed": true,
"costAllowed": true,
"expectedAllowed": false,
"expectedBody": null,
"expectedResourceDelivery": false,
"expectedMutation": false
},
{
"case": "revoked",
"channel": "sse",
"connectionAccepted": true,
"contextPresent": true,
"current": true,
"objectAllowed": true,
"fieldAllowed": true,
"subscriptionAllowed": false,
"costAllowed": true,
"expectedAllowed": false,
"expectedBody": null,
"expectedResourceDelivery": false,
"expectedMutation": false
}
],
"costPolicy": {
"titleWeight": 1,
"listLimit": 10,
"specUniversalConstants": false
},
"protocolLedger": [
{
"protocol": "GraphQL",
"unit": "operation/field",
"permission": "object + field",
"transportStatusDerived": false
},
{
"protocol": "WebSocket",
"unit": "application message",
"permission": "current actor + action + object",
"originIsNonBrowserIdentity": false
},
{
"protocol": "SSE",
"unit": "subscription/event",
"direction": "server to client",
"cursorIsPermission": false,
"exactlyOnce": false
},
{
"protocol": "gRPC",
"unit": "service method and streamed message",
"modes": [
"unary",
"server-streaming",
"client-streaming",
"bidirectional-streaming"
],
"channelCredentialsAreMethodPermission": false
},
{
"protocol": "SOAP 1.2",
"unit": "Envelope / optional Header / required Body",
"coreProvidesUniversalAuthz": false
}
],
"unknownEvidence": {
"contextPresent": false,
"permission": null,
"expectedAllowed": false,
"expectedBody": null,
"expectedResourceDelivery": false,
"expectedMutation": false
},
"boundaries": {
"actualResolver": false,
"actualOriginCookieEnforcement": false,
"actualStream": false,
"actualRPC": false,
"actualSOAP": false
}
}- rows
- Channel kabulü ve güncel permission conjunction’ı; null korunan title’ın yokluğudur.
- protocolLedger
- Protocol biçimi ile business kararının karşılaştırması; gerçek wire capture değildir.
- unknownEvidence
- Eksik context ayrı unknown kanıtı ve güvenli deny sonucudur.
Sabit public note ledger’ı; gerçek query, socket, EventSource, protobuf veya SOAP XML çalışmaz.
İki yanlış kanı
Schema geçerliyse her field okunabilir.
Schema validation ile object/field authorization farklı kararlardır.
Açık stream sürekli permission demektir.
Yeni message/event için güncel context gerekir; cursor permission değildir.
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 connectionAccepted=true, fakat now=validUntil=120 ve current=false. Sonraki message için note body gönderilir mi?
- Hayır. expectedResourceDelivery=false.
- Evet. İlk handshake bütün sonraki message’ları süresiz authorize eder.
Gerekçeli cevabı oku
Hayır. expectedResourceDelivery=false. — Kurulmuş connection süresi dolan authorization context’ini geçerli yapmaz. Bu message için body ve mutation yoktur.
Field-denied için expectedBody=null, fakat GraphQL envelope data ve errors içeriyor. Protected title’ın teslim edildiği anlamına mı gelir?
Dersten seçilen artifact alanları; öğretim örneği
- rows[1].fieldAllowed
- false
- rows[1].expectedBody
- null
- rows[1].graphqlEnvelope
- {"data":{"note":{"title":null}},"errors":[{"message":"Field not permitted","path":["note","title"]}]}
- Evet. Envelope’da data kelimesi varsa bütün title değerleri açılmıştır.
- Hayır. Nullable title null; errors field ret nedenini bildirir.
Gerekçeli cevabı oku
Hayır. Nullable title null; errors field ret nedenini bildirir. — Bu schema’da title nullable. data.note.title=null protected title verisi değildir. Data+errors şekli tek başına belirli HTTP status’u da kanıtlamaz.
SSE subscription revoked olunca connection açık kalsa da event duruyor. gRPC method ve streamed message için aynı ayrım neden gerekir?
Gerekçeli cevabı oku
Channel kurulması sonraki event veya message’lara genel izin vermez. SSE cursor continuation bilgisidir; subscription izni veya exactly-once değildir. gRPC channel credential’ları service method ve streamed message policy’sinin yerine geçmez. GraphQL’de object yanında field ve cost koşulları da gerekir; burada cost değerleri profile’a ait, universal spec sabitleri değildir. Context yoksa delivery durur; gerçek resolver, stream, RPC veya SOAP çalıştırılmaz.
□ Channel kabulünü per-operation authorization saymadım.
□ Subscription/cursor ve cost policy kapsamlarını ayrı belirttim.
Uygulama konsolunu aç · request / response / browser
Request, URL, cookie ve DOM örneklerini ayrıca aç
Kaynaklar ve kapsam
- GraphQL September 2025 Specification§6.4.2 Value Resolution; §6.4.3 Value Completion · §6.4.4 Handling Execution Errors; §7.1.1/3/5/6 response/data/errors · §6.2.3.2 response stream event execution
- OWASP GraphQL Cheat SheetQuery Cost Analysis · Access Control: object, edge/node and field/resolver checks
- OWASP WebSocket Security Cheat SheetOrigin Header Validation · Session Management; Message-Level Authorization
- RFC 6455 WebSocket Protocol§10.1 Non-Browser Clients; §10.2 Origin Considerations
- MDN Using server-sent eventsClosing event streams · Event stream format: id and retry
- gRPC Core conceptsService definition; four RPC method types and ordering within an individual RPC
- gRPC AuthenticationSupported auth mechanisms; Authentication API: channel and call credentials
- SOAP 1.2 Part 1 Messaging Framework§1.2 Conformance; §1.5.1 protocol concepts · §1.5.2 Envelope/Header/Body definitions