WEB / WEB-18.S01
SQL ve NoSQL’de query/data ayrımı
Public catalog’da typed intent’in, uygulamanın seçtiği query’nin ve projection sonucu verinin sahiplerini izle.
1. Core · Mekanizma
Hareket olmadan bütün senaryoları oku
Bağlanan SQL title
- Catalog isteği hazır
Caller’ın catalog intent’i backend=sql; title=O'Reilly; sort=id değerlerini taşır. Query builder bu alanları doğrulayacaktır; statement/filter veya tamamlanmış row sonucu henüz yoktur.
- Girdi bilgileri
- backend=sql; title=O'Reilly; sort=id
- Query builder
- Query contract yok
- Data owner
- Arama yok; count=0
- Sonuç görünümü
- Sonuç yok
- Field type kararı
Closed backend/title/sort field set’i, izinli backend enum’u ve scalar title koşulu geçer. Title 1–40 code point sınırındadır; sort’un türü string olsa da izinli değeri sonraki aşamada kontrol edilir.
- Girdi bilgileri
- backend=sql; title=O'Reilly; sort=id
- Query builder
- Alan türleri doğrulandı
- Data owner
- Arama yok; count=0
- Sonuç görünümü
- Sonuç yok
- Query contract seçimi
sort=id, uygulamanın sabit by-id SELECT’ini seçer. title ve visibility için bound tuple O'Reilly/public’tir; bu değerler statement syntax’ına birleştirilmez.
- Girdi bilgileri
- backend=sql; title=O'Reilly; sort=id
- Query builder
- by-id + bağlanan değerler
- Data owner
- Arama yok; count=0
- Sonuç görünümü
- Sonuç yok
- Local lookup kararı
Local SQLite SELECT tamamlanır: title=O'Reilly ve visibility=public koşulları id=2 kaydını bulur; queries=1 olur. Seed data değişmez, result view henüz projection’ı tüketmemiştir.
- Girdi bilgileri
- backend=sql; title=O'Reilly; sort=id
- Query builder
- by-id + bağlanan değerler
- Data owner
- Arama tamam; count=1; rows=1
- Sonuç görünümü
- Sonuç yok
- Projection hazır
Tamamlanan aramanın row’ları yalnız id/title projection’ına alınır. Reddedilen dalda rows null kalır; consumer henüz sonuç göstermez.
- Girdi bilgileri
- backend=sql; title=O'Reilly; sort=id
- Query builder
- by-id + bağlanan değerler
- Data owner
- Projection tamam; rows=1; count=1
- Sonuç görünümü
- Sonuç yok
- Sonuç görünümü kararı
Görünüm yalnız projection’ı tamamlanmış sonucu kullanır. Reddedilen işlem, başarı veya eşleşmeyen arama gibi gösterilmez; başlangıç verisi değişmez.
- Girdi bilgileri
- backend=sql; title=O'Reilly; sort=id
- Query builder
- by-id + bağlanan değerler
- Data owner
- Projection tamam; rows=1; count=1
- Sonuç görünümü
- Public sonuç: id=2, title=O'Reilly
Scalar filter
- Catalog isteği hazır
Caller’ın catalog intent’i backend=document; title=Tea; sort=id değerlerini taşır. Query builder bu alanları doğrulayacaktır; statement/filter veya tamamlanmış row sonucu henüz yoktur.
- Girdi bilgileri
- backend=document; title=Tea; sort=id
- Query builder
- Query contract yok
- Data owner
- Arama yok; count=0
- Sonuç görünümü
- Sonuç yok
- Field type kararı
Closed backend/title/sort field set’i, izinli backend enum’u ve scalar title koşulu geçer. Title 1–40 code point sınırındadır; sort’un türü string olsa da izinli değeri sonraki aşamada kontrol edilir.
- Girdi bilgileri
- backend=document; title=Tea; sort=id
- Query builder
- Alan türleri doğrulandı
- Data owner
- Arama yok; count=0
- Sonuç görünümü
- Sonuç yok
- Query contract seçimi
Uygulama kabul edilen Tea string’inden {title:Tea,visibility:public} equality filter’ını oluşturur ve sort=id seçer. Caller object’i filter olarak kopyalanmaz; bu dar matcher MongoDB değildir.
- Girdi bilgileri
- backend=document; title=Tea; sort=id
- Query builder
- Scalar public filter
- Data owner
- Arama yok; count=0
- Sonuç görünümü
- Sonuç yok
- Local lookup kararı
Yerel literal matcher, title=Tea ve visibility=public için id=1 ile id=3 kayıtlarını bulur ve id sırasına koyar. queries=1 ve iki eşleşme vardır; view henüz bu sonucu kullanmaz.
- Girdi bilgileri
- backend=document; title=Tea; sort=id
- Query builder
- Scalar public filter
- Data owner
- Arama tamam; count=1; rows=2
- Sonuç görünümü
- Sonuç yok
- Projection hazır
Tamamlanan aramanın row’ları yalnız id/title projection’ına alınır. Reddedilen dalda rows null kalır; consumer henüz sonuç göstermez.
- Girdi bilgileri
- backend=document; title=Tea; sort=id
- Query builder
- Scalar public filter
- Data owner
- Projection tamam; rows=2; count=1
- Sonuç görünümü
- Sonuç yok
- Sonuç görünümü kararı
Görünüm yalnız projection’ı tamamlanmış sonucu kullanır. Reddedilen işlem, başarı veya eşleşmeyen arama gibi gösterilmez; başlangıç verisi değişmez.
- Girdi bilgileri
- backend=document; title=Tea; sort=id
- Query builder
- Scalar public filter
- Data owner
- Projection tamam; rows=2; count=1
- Sonuç görünümü
- Public sonuç: Tea, id=1 ve id=3
Object title
- Catalog isteği hazır
Caller’ın catalog intent’i backend=document; title={display:Tea}; sort=id değerlerini taşır. Query builder bu alanları doğrulayacaktır; statement/filter veya tamamlanmış row sonucu henüz yoktur.
- Girdi bilgileri
- backend=document; title={display:Tea}; sort=id
- Query builder
- Query contract yok
- Data owner
- Arama yok; count=0
- Sonuç görünümü
- Sonuç yok
- Field type kararı
title={display:Tea} geçerli plain object olabilir, fakat title:string koşulunu sağlamaz. Reason field-type olur; sort kontrolü, query factory ve data-owner lookup başlatılmaz.
- Girdi bilgileri
- backend=document; title={display:Tea}; sort=id
- Query builder
- Reddedildi: field-type
- Data owner
- Arama yok; count=0
- Sonuç görünümü
- Sonuç yok
- Query contract seçimi
Tür kabul edildikten sonra sort enum seçilir. Bilinmeyen sort için statement üretilmez; tür kontrolü başarısızsa sort değerlendirilmez.
- Girdi bilgileri
- backend=document; title={display:Tea}; sort=id
- Query builder
- Sort değerlendirilmedi
- Data owner
- Arama yok; count=0
- Sonuç görünümü
- Sonuç yok
- Local lookup kararı
Bu ret dalında SQLite driver veya literal document matcher çağrılmaz. queries=0, gerçekten çalışmış bir query’nin boş sonucu değildir; daha önceki sonuç bu intent’e aktarılmaz.
- Girdi bilgileri
- backend=document; title={display:Tea}; sort=id
- Query builder
- Sort değerlendirilmedi
- Data owner
- Arama yok; count=0
- Sonuç görünümü
- Sonuç yok
- Projection yapılmadı
Lookup yapılmadığından projection üretilemez; rows=null kalır. Kabul edilip Bread için eşleşmeyen query’nin rows=[] sonucuyla farklıdır; seed data değişmez.
- Girdi bilgileri
- backend=document; title={display:Tea}; sort=id
- Query builder
- Sort değerlendirilmedi
- Data owner
- Rows null; count=0
- Sonuç görünümü
- Sonuç yok
- Sonuç görünümü kararı
Görünüm yalnız projection’ı tamamlanmış sonucu kullanır. Reddedilen işlem, başarı veya eşleşmeyen arama gibi gösterilmez; başlangıç verisi değişmez.
- Girdi bilgileri
- backend=document; title={display:Tea}; sort=id
- Query builder
- Sort değerlendirilmedi
- Data owner
- Rows null; count=0
- Sonuç görünümü
- Sonuç yok; field-type
Bilinmeyen sort
- Catalog isteği hazır
Caller’ın catalog intent’i backend=sql; title=Tea; sort=rating değerlerini taşır. Query builder bu alanları doğrulayacaktır; statement/filter veya tamamlanmış row sonucu henüz yoktur.
- Girdi bilgileri
- backend=sql; title=Tea; sort=rating
- Query builder
- Query contract yok
- Data owner
- Arama yok; count=0
- Sonuç görünümü
- Sonuç yok
- Field type kararı
İzin verilen alanlar ve scalar title/string türü değerlendirilir. Sıradan display object bu dalda title değeri olarak kabul edilmez.
- Girdi bilgileri
- backend=sql; title=Tea; sort=rating
- Query builder
- Alan türleri doğrulandı
- Data owner
- Arama yok; count=0
- Sonuç görünümü
- Sonuç yok
- Query contract seçimi
Backend ve scalar title türleri uygundur; sort=rating ise izinli id/title enum’unda değildir. Reason unknown-sort olur; statementId=null, filter=null ve queries=0 korunur.
- Girdi bilgileri
- backend=sql; title=Tea; sort=rating
- Query builder
- Reddedildi: unknown-sort
- Data owner
- Arama yok; count=0
- Sonuç görünümü
- Sonuç yok
- Local lookup kararı
Bu ret dalında SQLite driver veya literal document matcher çağrılmaz. queries=0, gerçekten çalışmış bir query’nin boş sonucu değildir; daha önceki sonuç bu intent’e aktarılmaz.
- Girdi bilgileri
- backend=sql; title=Tea; sort=rating
- Query builder
- Reddedildi: unknown-sort
- Data owner
- Arama yok; count=0
- Sonuç görünümü
- Sonuç yok
- Projection yapılmadı
Lookup yapılmadığından projection üretilemez; rows=null kalır. Kabul edilip Bread için eşleşmeyen query’nin rows=[] sonucuyla farklıdır; seed data değişmez.
- Girdi bilgileri
- backend=sql; title=Tea; sort=rating
- Query builder
- Reddedildi: unknown-sort
- Data owner
- Rows null; count=0
- Sonuç görünümü
- Sonuç yok
- Sonuç görünümü kararı
Görünüm yalnız projection’ı tamamlanmış sonucu kullanır. Reddedilen işlem, başarı veya eşleşmeyen arama gibi gösterilmez; başlangıç verisi değişmez.
- Girdi bilgileri
- backend=sql; title=Tea; sort=rating
- Query builder
- Reddedildi: unknown-sort
- Data owner
- Rows null; count=0
- Sonuç görünümü
- Sonuç yok; unknown-sort
ROLLER · STATE · VERİ AKIŞI
Query yapısı ve aranan değer farklı sahiplerde
Atlas public catalog, title için exact match ve iki onaylı sort seçeneği sunar. Kullanıcı bir kitabın adını verir; uygulama hangi table, field, comparison ve projection kullanılacağını seçer. O'Reilly sıradan bir title’dır. Apostrophe olması onu hatalı business input yapmaz. Bu örnekte SQL statement sabittir, title ve public visibility ayrı bound values olarak driver’a gider. Statement içinde kitabın adı bir syntax parçası olarak birleştirilmez.
Query/data ayrımı parser’dan önce başlar. Handler yalnız backend, title ve sort alanları olan typed bir intent üretir. Backend bu eğitim modelinde sql veya document enum’udur; gerçek üründe client’ın database backend seçmesi gerekmez. Title 1–40 code point aralığında bir string, sort ise id veya title olur. Bu domain contract, parameterization’ın yerine geçmez. Contract hangi operation’ı kabul ettiğini; binding kabul edilen değerin query içindeki rolünü belirler.
SQL driver’a iki ayrı argüman gider
Artifact’te by-id ve by-title için iki önceden yazılmış SELECT bulunur. Her biri id ve title projection’ı, title equality ve visibility equality condition’ını içerir. Python sqlite3 execute çağrısına statement ve (title, public) tuple’ı ayrı verilir. Native check kendi :memory: database’ini açar, sıradan üç catalog row ekler ve O'Reilly için yalnız id=2 row’unu okur. İlk input kabulü query değildir; execute bitmeden result row hazır gösterilmez.
Python qmark binding’de sequence uzunluğu placeholder sayısına uymalıdır. Named placeholder için mapping beklenir. Bunlar driver contract’ıdır; field validation veya resource authorization değildir. Buradaki iki sabit statement’ın value slot’ları aynı kalır. Driver’ın her internal prepare/cache adımı veya başka SQL engine’in dialect’i animasyonda tahmin edilmez. Kanıt, seçilmiş SQLite çağrısına ve gözlenen row listesine aittir.
Sort bir value slot değildir
Title değeri ile ORDER BY column seçimi aynı görev değildir. Bir bind slot’una title yazmak onu column identifier haline getirmez. Uygulama id ve title seçeneklerini kendi iki sabit statement’ına map eder; rating gibi tanınmayan bir sort query çalışmadan reddedilir. Bu örnekte arbitrary identifier, raw SQL fragment veya yön string’i kabul edilmez. Kullanıcının sort seçmesi, query dilini yazma yetkisi vermez.
Bu farkı bir formun görünüşünden çıkaramazsın. Text box’tan gelen title data olarak bağlanabilir; dropdown’dan gelen sort da server’da enum olarak doğrulanmalıdır. UI’da iki option olması server contract’ının kanıtı değildir. Sort tanınmıyorsa builder’ın seçeceği statement null, data owner için query count=0 olur; result view sonuç göstermez. Eksik intent ayrı bir NOT-COMPUTED durumudur; tanınmayan değer ile eksik bilgi aynı karar değildir.
Document filter da bir query dilinin parçasıdır
NoSQL etiketi interpretation boundary’yi ortadan kaldırmaz. Uygulama scalar title’ın type’ını doğruladıktan sonra kendi equality filter’ını kurar. Client’tan gelen object’i olduğu gibi filter diye kullanmak, uygulamanın query yapısını client’ın veri yapısıyla karıştırır. Bu derste sıradan {display: Tea} object’i title:string contract’ına uymaz ve herhangi bir document lookup yapılmadan reddedilir. Object’in grammar olarak parse olması title değeri olmasını sağlamaz.
Document branch’i Python’da dar bir literal matcher’dır: uygulamanın kurduğu title ve visibility alanları exact equality ile kendi seed documents’ını seçer, id veya title sırasına koyar, id/title alanlarını projekte eder. Bu matcher MongoDB server, BSON codec, cursor veya ODM değildir. MongoDB’nin find sonucu cursor’dır; örneğin hazır listesi onun bütün davranışlarını taklit etmez. Animasyonun local Data owner kutusu bu sınırı açık bırakır.
Doğru query, doğru erişim kararıyla birleşmeli
Binding query yapısını korur; hangi row’un hangi caller’a sunulabileceğini tek başına belirlemez. Bu catalog yalnız public visibility için oluşturulmuş sabit eğitim verisidir. Özel kayıtlar, tenant membership, servis account izinleri ve field-level disclosure gerçek uygulamada ayrı policy ister. Public scope condition uygulama tarafından seçilir; title alanının içinden yeni bir scope kararı türetilmez.
Kabul edilen query’nin boş row listesi döndürmesi de rejection değildir. Type/schema failure, unknown sort, driver failure ve accepted-but-no-match farklı sonuçlardır. Result view ancak tamamlanmış lookup ve projection’dan sonra değişir. Bu ayrım retry ve error handler tasarımına taşınır: query hiç yapılmadıysa bunu empty result gibi kaydetmek, uygulamanın gerçekte neyi doğruladığını gizler. Bu artifact yalnız SELECT/literal lookup yapar; mutation, network veya production authorization çalıştırmaz.
2. Red · Güven ve etki
Hareket olmadan bütün senaryoları oku
Field type
- Query intent profili okundu
Document backend title için scalar string bekler. wrong-type input title={display:Tea} içerir; bu ordinary object valid JSON olabilir ama kabul edilen title türü değildir.
- Caller intent
- Backend: document
- Typed query factory
- Intent validation pending
- Data-owner boundary
- Query not executed
- Value ve structure sorumluluğu ayrıldı
JSON’dan çıkan object doğrudan query filter’a kopyalanmaz. Application typed title’dan yeni equality filter oluşturur; accepted olmayan type bu factory’ye ulaşmaz.
- Caller intent
- Application selects structure
- Typed query factory
- Field-type mismatch
- Data-owner boundary
- Factory gate pending
- Intent gate reddi belirlendi
expected decision=REJECT ve reason=field-type’tır. Accepted filter veya statement hazırlanmaz; queries=0 tutulur.
- Caller intent
- Decision: REJECT
- Typed query factory
- Queries=0
- Data-owner boundary
- Rows=null
- Data owner’a dispatch yapılmadı
statementId=null ve filter=null’dır. Driver veya document matcher’ın input’u çalıştırıp sonra gizli result döndürdüğü şeklinde anlatılmaz.
- Caller intent
- No accepted query structure
- Typed query factory
- No data-owner call
- Data-owner boundary
- No result delivery
- Failure ile no-match ayrıldı
rows=null intent failure’dır. acceptedNoMatch için Bread araması ACCEPT, queries=1 ve rows=[] verir; boş sonuç gerçekten yapılmış read gerektirir.
- Caller intent
- Rejection: rows=null
- Typed query factory
- Accepted no-match: rows=[]
- Data-owner boundary
- Outcomes distinct
- Ret sınıfı yanlış genişletilmedi
Bu ordinary type/sort retleri boundary contract’ını gösterir. Executable injection, endpoint vulnerability veya actor permission failure sonucu değildir.
- Caller intent
- Contract rejection known
- Typed query factory
- No query execution
- Data-owner boundary
- Permission separate
Sort unknown
- Query intent profili okundu
SQL backend sort için yalnız id veya title seçer. unknown-sort input sort=rating içerir; client tercihi approved statement setine karşılaştırılır.
- Caller intent
- Backend: sql
- Typed query factory
- Intent validation pending
- Data-owner boundary
- Query not executed
- Value ve structure sorumluluğu ayrıldı
Sort tercihi identifier’ı value parameter’ına bağlamakla çözülmez. Application id/title enum’unu iki fixed statement’a eşler; rating için yeni SQL oluşturmaz.
- Caller intent
- Application selects structure
- Typed query factory
- Sort outside enum
- Data-owner boundary
- Factory gate pending
- Intent gate reddi belirlendi
expected decision=REJECT ve reason=unknown-sort’tur. Approved statement seçilmediği için queries=0 kalır; result empty list gibi sunulmaz.
- Caller intent
- Decision: REJECT
- Typed query factory
- Queries=0
- Data-owner boundary
- Rows=null
- Data owner’a dispatch yapılmadı
statementId=null ve filter=null’dır. Driver veya document matcher’ın input’u çalıştırıp sonra gizli result döndürdüğü şeklinde anlatılmaz.
- Caller intent
- No accepted query structure
- Typed query factory
- No data-owner call
- Data-owner boundary
- No result delivery
- Failure ile no-match ayrıldı
rows=null intent failure’dır. acceptedNoMatch için Bread araması ACCEPT, queries=1 ve rows=[] verir; boş sonuç gerçekten yapılmış read gerektirir.
- Caller intent
- Rejection: rows=null
- Typed query factory
- Accepted no-match: rows=[]
- Data-owner boundary
- Outcomes distinct
- Ret sınıfı yanlış genişletilmedi
Bu ordinary type/sort retleri boundary contract’ını gösterir. Executable injection, endpoint vulnerability veya actor permission failure sonucu değildir.
- Caller intent
- Contract rejection known
- Typed query factory
- No query execution
- Data-owner boundary
- Permission separate
VARSAYIM · SINIR · KONTROL
Review sorusu: değer ne zaman yapıya dönüştü?
Bir incelemede ilk soruyu input’un görünüşü yerine sorumluluklar üzerine kur: uygulama statement/filter’ı nerede seçiyor, caller hangi alanları etkileyebiliyor, driver’a tam olarak hangi typed values gidiyor? Sıradan O'Reilly title’ı, noktalama işaretinin business data olarak korunabildiğini gösterir. Bu bir saldırı string’i denemesi değildir. Örneğin sabit SELECT’i ve ayrı tuple’ı, query yapısının hangi dosyada uygulama tarafından belirlendiğini görünür kılar.
ORM kullanıldığı bilgisinden bütün call path’in güvenli olduğu sonucunu çıkarma. Model method’u, raw expression escape hatch’i ve sort/projection factory’si farklı kontratlar olabilir. Bu derste raw expression çalıştırılmaz; review hedefi uygulamanın onaylı factory’yi kullanıp kullanmadığıdır. İnceleme çıktısı için statement identifier, doğrulanan field türleri ve seçilen scope yeterlidir. Bütün input değerlerini log’a dökmek gereksiz disclosure oluşturabilir.
Parse edilmiş object ile kabul edilmiş filter ayrılır
Document branch’inde title yerine sıradan display object verilince geçerli JSON’dan uygulamanın beklediği türe geçiş durur. Data owner’a query iletilmez ve önceki row listesi yeni bir başarı gibi gösterilmez. Bu inert failure, parser acceptance ile operation acceptance arasındaki farkı öğretir. Query count=0 ve result null birlikte kanıttır; yalnız ekranda bir error mesajı olması yeterli değildir.
Boş sonuç için kabul edilmiş Tea match’inin gerçekten çalışıp çalışmadığına bakmak gerekir. Unknown sort rating aynı empty list sonucu ile temsil edilseydi contract failure kaybolurdu. Eksik kanıt da otomatik bir red veya izin kararına dönüştürülmez. Bu örneğin sınırlı check’leri gerçek endpoint keşfi, injection payload, auth bypass veya başka sistemde vulnerability reproduction içermez; bir boundary review’ün hangi olgulara dayanabileceğini gösterir.
3. Blue · Güvenli geliştirme ve savunma
Hareket olmadan bütün senaryoları oku
Value binding
- Normal public intent seçildi
Normal SQL input title=O'Reilly ve sort=id içerir. Noktalama title’ın business data’sıdır; query syntax seçmek için kullanılmaz.
- Intent/query observation
- Title: O'Reilly
- Factory/result comparison
- Sort: id
- Evidence conclusion
- Factory review pending
- Fixed statement kimliği eşleştirildi
sort=id, by-id statement’ını seçer. Statement title=? ve visibility=? kullanır; title ile public scope ayrı bound values olarak kalır.
- Intent/query observation
- Statement: by-id
- Factory/result comparison
- Values: O'Reilly / public
- Evidence conclusion
- Execution pending
- Beklenen query sonucu okundu
normal expected queries=1 ve rows=[{id:2,title:O'Reilly}] içerir. Bu positive outcome noktalamanın value olarak korunduğunu gösterir; bütün query path’lerini doğrulamaz.
- Intent/query observation
- Queries=1
- Factory/result comparison
- Row id=2
- Evidence conclusion
- Title preserved
- Response projection alanları ayrıldı
Profile projection yalnız id ve title’dır. Visibility public scope koşulu olarak kullanılır; response’a bütün stored field’ları kopyalamak zorunlu değildir.
- Intent/query observation
- Scope: public
- Factory/result comparison
- Projection: id/title
- Evidence conclusion
- No extra stored fields
- Document branch factory’si karşılaştırıldı
Document input title=Tea için uygulama {title:Tea,visibility:public} equality filter’ı kurar. Accepted string’den yeni filter oluşturmak, caller object’ini kopyalamaktan farklıdır.
- Intent/query observation
- SQL fixed statement
- Factory/result comparison
- Document fixed equality filter
- Evidence conclusion
- Factories explicit
- Binding permission’a çevrilmedi
Parameter binding value/structure sınırına yardım eder. Public fixture scope’u dışında tenant authorization, database account yetkisi veya production query timeout için ayrıca control gerekir.
- Intent/query observation
- Value boundary known
- Factory/result comparison
- Public scope fixed
- Evidence conclusion
- Authorization separate
No-match ve eksik
- Accepted no-match kaydı açıldı
acceptedNoMatch title=Bread için decision=ACCEPT ve queries=1 bildirir. rows=[] aramanın kabul edilip çalıştığı fakat eşleşme bulunmadığı sonuçtur.
- Intent/query observation
- Intent accepted
- Factory/result comparison
- Queries=1
- Evidence conclusion
- Rows=[]
- Missing input farklı tuple sayıldı
missing.input=null, decision=NOT-COMPUTED, queries=0 ve rows=null’dır. Arama yapılmadığı için bu kayıt Bread’in empty result’ı gibi yorumlanmaz.
- Intent/query observation
- Input=null
- Factory/result comparison
- Queries=0
- Evidence conclusion
- Rows=null
- Bilinen ret ile missing ayrıldı
wrong-type ve unknown-sort için REJECT, missing için NOT-COMPUTED vardır. Hepsi no-query olabilir ama hangi contract koşulunun değerlendirildiği farklıdır.
- Intent/query observation
- Known rejection distinct
- Factory/result comparison
- Missing intent unresolved
- Evidence conclusion
- No-query cause explicit
- Query count result ile bağlandı
Accepted match için queries=1 ve projected rows gerekir; no-match için aynı query count ile [] beklenir. Yalnız UI error veya empty view bu tuple’ı tamamlamaz.
- Intent/query observation
- Intent + query + rows
- Factory/result comparison
- UI alone insufficient
- Evidence conclusion
- Evidence tuple required
- Document sonucu sınırlı okundu
Tea equality filter’ı id=1 ve id=3 için iki projected row döndürür. Bu literal matcher sonucu gerçek MongoDB/ODM davranışı veya bütün filter operatörlerini gözlemez.
- Intent/query observation
- Document rows: 1, 3
- Factory/result comparison
- Literal matcher scope
- Evidence conclusion
- ODM runtime unobserved
- Teşhis için değerler gereksiz loglanmadı
Statement identifier, field türleri, scope ve outcome review için yeterli olabilir. Bütün input değerlerini loglamak permission veya query correctness kanıtını güçlendirmez ve gereksiz disclosure yaratabilir.
- Intent/query observation
- Bounded decision metadata
- Factory/result comparison
- No-match vs missing retained
- Evidence conclusion
- No excessive value log
UYGULAMA · GÜVENLİK KONTROLÜ · DOĞRULAMA
Query factory’yi küçük ve açık tut
Uygulamanın public catalog factory’si closed field set, scalar title ve sort enum’unu doğrular. Kabul edilen id/title seçimleri yalnız iki sabit SELECT’e bağlanır. Value’lar sqlite3’ye tuple olarak verilir; document branch’inde uygulamanın belirlediği yeni equality filter oluşturulur. Client object’i copy etmek tek başına validation değildir. Type ve allowed field kararı, query builder’ın output’undan önce tamamlanır.
Testler source shape’ı tekrar söylemekle kalmamalı: native SQLite’de sıradan noktalama işareti içeren title’ın gerçekten doğru row’u verdiğini, query sonrası seed row sayısının değişmediğini ve unknown sort’un execute sayısını artırmadığını ölç. Document matcher için yanlış type’ın lookup yapmadan dönmesini ve kabul edilen match’in yalnız projected fields vermesini karşılaştır. Bu ölçümler driver/framework değişirse tekrar değerlendirilir; bir SQLite sonucu bütün engine ve ODM’lere genellenmez.
Failure, scope ve evidence aynı kayıtta bulunmalı
Kabul edilebilir intent, seçilen statement/filter, query count ve projected result ayrı alanlar olarak tutulur. Rejection result null üretir; kabul edilmiş fakat eşleşmeyen arama [] üretir. Intent eksikse NOT-COMPUTED olur. Bu küçük ayrım incident review’de önemlidir: permission kararı, database connectivity failure ve gerçekten bulunamayan resource aynı kayıt altında görünmemelidir. Public visibility örneğin sabit scope’udur; tenant erişimi yaptığımız iddia edilmez.
Database account’ın yetkileri operation’ın gerektirdiği düzeyde tutulmalı; read-only catalog için admin privilege gerekçesi yoktur. Production’da authz, query timeout, row/page bound, error disclosure ve transaction policy ayrıca tasarlanır. Bu artifact bunları test etmiş gibi bir başarı işareti göstermez. Gözlenen native kanıt kendi memory database’i, sıradan başlangıç verisi, sabit statement binding ve dar literal matcher ile sınırlıdır; UI reduced motion’da da aynı kararları okunur sunar.
ŞİMDİ VAKAYA UYGULA
Accepted JSON ne zaman query olmadan durmalıdır?
Application closed intent ve sort enum’dan fixed SQL veya equality filter seçer. Harmless title values data kalır; ret, no-match ve missing input ayrı tuple’larla anlatılır.
Vakadaki cached representation’ı authoritative data owner’la karşılaştır. Stored value, revision, transaction ve cache copy için aynı completion sonucunu kullanma.
Bağlı vaka dosyasını aç ↗ÖRNEĞİ BİRLİKTE OKUYALIM
Atlas query contract ve public sonuç kaydı
Bir alan seç; hangi sonucu desteklediğini ve nerede yetersiz kaldığını incele.
Ham kaydı ve alan açıklamalarını oku
{
"profile": {
"allowedKeys": [
"backend",
"title",
"sort"
],
"backends": [
"sql",
"document"
],
"titleCodePoints": [
1,
40
],
"sortChoices": [
"id",
"title"
],
"scope": "public",
"projection": [
"id",
"title"
]
},
"seed": [
{
"id": 1,
"title": "Tea",
"visibility": "public"
},
{
"id": 2,
"title": "O'Reilly",
"visibility": "public"
},
{
"id": 3,
"title": "Tea",
"visibility": "public"
}
],
"statements": {
"by-id": "SELECT id, title FROM books WHERE title = ? AND visibility = ? ORDER BY id",
"by-title": "SELECT id, title FROM books WHERE title = ? AND visibility = ? ORDER BY title, id"
},
"inputs": {
"normal": {
"backend": "sql",
"title": "O'Reilly",
"sort": "id"
},
"document": {
"backend": "document",
"title": "Tea",
"sort": "id"
},
"wrong-type": {
"backend": "document",
"title": {
"display": "Tea"
},
"sort": "id"
},
"unknown-sort": {
"backend": "sql",
"title": "Tea",
"sort": "rating"
}
},
"expected": {
"normal": {
"decision": "ACCEPT",
"reason": "public-exact-match",
"queries": 1,
"statementId": "by-id",
"filter": null,
"rows": [
{
"id": 2,
"title": "O'Reilly"
}
]
},
"document": {
"decision": "ACCEPT",
"reason": "public-exact-match",
"queries": 1,
"statementId": null,
"filter": {
"title": "Tea",
"visibility": "public"
},
"rows": [
{
"id": 1,
"title": "Tea"
},
{
"id": 3,
"title": "Tea"
}
]
},
"wrong-type": {
"decision": "REJECT",
"reason": "field-type",
"queries": 0,
"statementId": null,
"filter": null,
"rows": null
},
"unknown-sort": {
"decision": "REJECT",
"reason": "unknown-sort",
"queries": 0,
"statementId": null,
"filter": null,
"rows": null
}
},
"missing": {
"input": null,
"decision": "NOT-COMPUTED",
"queries": 0,
"rows": null
},
"acceptedNoMatch": {
"title": "Bread",
"decision": "ACCEPT",
"queries": 1,
"rows": []
}
}- inputs
- Sıradan typed intent; client’ın yazdığı query syntax değildir.
- statements / filter
- Uygulamanın belirlediği yapı ve sabit public scope.
- queries
- Tamamlanan aramaların sayacı; reddedilen dalda0.
- rows
- Tamamlanan projection: sonuç yoksa null, kabul edilen aramada eşleşme yoksa [] olur.
Örneğin Python SQLite :memory: veritabanında değerleri bağlanan SELECT ve local Python literal-document matcher. MongoDB server/driver/cursor, network, ORM, rastgele query, exploit veya user authorization çalıştırılmaz.
İki yanlış kanı
Bind edilen her değer column veya sort seçebilir.
Value slot yapıyı seçmez; sort/identifier için uygulamanın onaylı mapping’i gerekir.
JSON object kullanan query kendiliğinden güvenlidir.
Field/type contract ve uygulamanın belirlediği filter gerekir; parsing authorization 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.
Document backend için title bir string değil, {display: Tea} object’i. Query çalışır mı?
- Hayır. field-type; queries=0 ve filter=null.
- Evet. Her JSON object otomatik database filter’ıdır.
Gerekçeli cevabı oku
Hayır. field-type; queries=0 ve filter=null. — Bu sözleşme title string’i ister. Input object’i query operator veya filter olarak doğrudan kullanılmaz.
O'Reilly başlığı neden SQL statement’ın source’u değil, eşleşecek data olarak kalıyor?
Dersten seçilen artifact alanları; öğretim örneği
- inputs.normal
- {"backend":"sql","title":"O'Reilly","sort":"id"}
- statements.by-id
- SELECT id, title FROM books WHERE title = ? AND visibility = ? ORDER BY id
- expected.normal
- {"decision":"ACCEPT","reason":"public-exact-match","queries":1,"statementId":"by-id","filter":null,"rows":[{"id":2,"title":"O'Reilly"}]}
- Başlıktaki apostrophe yeni statement structure oluşturur.
- Statement sabit; title placeholder’a data olarak bağlanır.
Gerekçeli cevabı oku
Statement sabit; title placeholder’a data olarak bağlanır. — by-id statement’ı title ve visibility değerlerini ? placeholder’larıyla alır. Sonuç public id=2 kaydıdır; başlık query grammar seçmez.
sort=rating için queries=0, acceptedNoMatch için queries=1 ve rows=[]. Neden bu iki boş sonuç aynı değildir? Query/data ayrımı authorization mı?
Gerekçeli cevabı oku
Unknown sort sözleşmenin id/title seçeneklerinde değildir; query gönderilmeden reddedilir ve rows=null kalır. Bread başlığı kabul edilir, query çalışır ve eşleşme bulunmadığı için rows=[] döner. Query structure server’ın sabit seçimi olmalıdır; parameterization object/tenant izni yerine geçmez. Bu profile yalnız public projection kullanır; document adapter sonucu gerçek MongoDB deployment testi değildir.
□ Ret ile başarılı no-match sonucunu ayırdım.
□ Parameterization’ı resource authorization saymadım.
Uygulama konsolunu aç · request / response / browser
Request, URL, cookie ve DOM örneklerini ayrıca aç
Kaynaklar ve kapsam
- OWASP — SQL Injection Prevention Cheat SheetDefense Option 1: Prepared Statements (with Parameterized Queries) · Defense Option 3: Allow-list Input Validation · Least Privilege
- Python — sqlite3How to use placeholders to bind values in SQL queries · sqlite3.connect; :memory: database
- OWASP — NoSQL Security Cheat SheetPrevent NoSQL Injection · Use Secure Driver / ODM Patterns · Authentication & Authorization
- MongoDB — Read DocumentsQuery Result Format; find returns a cursor