Kısa özet — canlı geçişte bulunan 4 düzeltme: Bu sürüm, canlı geçiş sırasında 4 gerçek framework hatasının bulunmasıyla çıktı. Dört düzeltme de canlı yüklemesi sonrası ortaya çıktı. Kırıcı değişiklik yok: hiçbir imza, şema, izin veya metot imzası değişmedi; güvenlik sınırları (kök sınır fail-closed davranışı dahil) aynen duruyor. Her madde kendi birim testiyle önce kırmızı, sonra yeşil doğrulandı.
Fixed
-
Dış varlık vekili (asset proxy) beyaz listesi artık proje ayarından okunuyor (
AssetController). Dış CDN hedefleri (media/<base64>dalı) beyaz listede olmadığı için güvenlik gereği reddediliyor,Locationüretilmiyor ve istek 404 ile bitiyordu. Beyaz listenin tek kaynağı framework sabitiydi; motor genel kalsın diye sabit boş bir varsayılan olarak bırakıldı ve ikinci kaynak olarak aktif projenin ayarı (project-settings.proxy_allowed_hosts) okunmaya başlandı — host listesi framework'e değil, projenin kendi ayar dosyasına yazılır. Eşleşme kuralı değişmedi: tam host veya.son ek. Güvenlik kontrolleri gevşetilmedi: şema beyaz listesi (yalnızhttp/https), kontrol karakteri/CRLF ve ters bölü normalizasyonu aynen durur, reddedilen hedefLocationüretmez (fail-closed). Geçersiz ayar girdisi (dizi olmayan, şema/port/yol/boşluk/kontrol karakteri içeren eleman) sessizce yok sayılır; ayar okunamazsa liste boş kalır. -
Büyük/küçük harfe duyarlı yollar artık küçük harf 301'ine uğramıyor (
RedirectManager::forceLowercaseUrl()):/media/<base64>/<dosya>ve/fw-proxy/<upload|export>/<Dosya>gibi opak (base64) segment taşıyan yollar, istek öncesinde küçük harfe çevrilip 301 yazılıyordu; hedef çözülemediği için istek 404 ile bitiyordu (canlı: 301 → 404). Muafiyet listesi tek yerde, değişmez bir sabitte toplandı (LOWERCASE_EXEMPT_PREFIXES) ve ön ek sınırı denetimi eklendi:/mediamuafken ön ek-benzeri/media-arsivimuaf değildir; böylece normal sayfa yollarındaki SEO kanonik küçük harf davranışı korunur. -
ViewEngine::path('module', ...)artık hiçbir@import('module', ...)ça�Yrısını reddetmiyor (KRİTİK).path()içindekiarray_shift($args)ifadesi PHP'de REFERANSLA çalı�Ytı�Yı için$argsdizisini kalıcı olarak kısaltıyordu; bir sonraki satırda$baseArgs = $argszaten kısaltılmı�Y diziyi kopyaladı�Yı içinarray_shift($baseArgs)dosya yolunu "modül adı" sanıyordu. Böylece kök sınırı kontrolü (guardRoots) izin kökü olarak modülün K�-K�o yerine görünür bir dosya yolu alıyor ve her@import('module', ...)ça�Yrısı fail-closed reddediliyordu. Sonuç: HTTP 200 amaView::__toStringin yuttu�Yu içerik olarak[Render Error]gövdesi. Artık modül adı ve kalan yolpath()ba�Yında �-NCEDEN ayrılır,$argshiç kı�Ylanmaz (kısaltılmaz) ve ikimatchaynı de�Yerleri kullanır. Kök sınırı fail-closed KALIR:..ile kök dı�Yına çıkan yol reddedilir, kapsam daralmadı. Yan hata olarak tek/argümansız ça�Yrı,array_shiftin bo�Y dizidenulldöndürmesi nedeniylePaths::module(null)TipHatası fırlatıyordu; o da kapandı. Metot imzası DEĞİŞMEDİ. -
Yerel giri�Y noktası (
domains/<site>/index.php) PHP sürüm kapısını gerçekten açar (20 dosya). Sürüm kapısı blo�Yu, yolu$rbnKapsiAdayide�Yi�Ykenine yazıyor amais_file($rbnKapisiAdayi)ile kontrol ediyordu;is_file(null)falsedöndü�Yü içinPhpVersionGatehiç bulunamıyor ve sessizce devre dı�Yı kalıyordu (geli�Ytirme ortamında ayrıca her istek sayfayaWarning/Deprecatedmetni basıyordu). De�Yi�Yken adı 20 dosyada$rbnKapisiAdayiolarak düzeltildi; dosyaların kodlaması ve geri kalan içeri�Yi bayt-bayt de�Yi�Ymedi. Yerel PHP 8.3.35 ile kap geçer ve tüm yerel siteler 200 + temiz gövde verir.
Added
-
Sürümleme: proje sürümünün TEK kaynağı master veritabanı;
rbn version:checkverbn version:nextkomutları. Proje sahibi kararı (2026-10-05):APP_VERSIONprojenin sürümüdür ve proje sürümüproject-settings.php'den GELMEZ, hiçbir yerel dosyaya da yazılmaz — tek kaynak master DBprojects.versionkolonudur; değer açılışta proje veri önbelleğine yazılır (ProjectDataMapper→project_data('version')) ve her yer oradan okur.- Yeni
Core\Support\Bridges\Helpers\Library\ProjectVersionResolver: TEK çözücü. GeçerliA.B.Cdeğeri aynen döner; değer yoksa veya bozuksa (iki parçalı1.0, dört parça,vöneki,1.17.0gibi) standart başlangıç sürümüVersion::initial()(0.1.1) döner. Bozuk kayıt görüldüğündeLogThrottle::once()ile saatte bir uyarı yazılır. Sınıf durumsuz ve tamamen statiktir (newkullanılmaz); istisna fırlatmaz, karar değişmez. app_version(),SeoResolver(module-versionmeta),AuthHandler(siteVersion) veRbnAdminController(stats.app_version) aynı çözücüyü kullanır. Tekrar eden iki parçalı1.0varsayılanları kaldırıldı.PreBoot:define('APP_VERSION', '3.5.0')kalıntısı kaldırıldı. Zamanlama gerekçesi koddan okunarak yazıldı:detectEnvironment()orchestrate()içinde 0. adımda çalışır, proje veri önbelleği ise 0.5. adımda (ProjectDiscovery) dolar — yani eski noktadaprojects.versionokunamazdı. YeniPreBoot::defineAppVersion()initPaths()sonrasında çağrılır. Giriş noktasındaki elledefine('APP_VERSION', '1.17.0')satırı da kaldırıldı (1.17.0kural ihlaliydi: B basamağı 17 > 9).- Bileşen sürümleri üç parçalı ve
vön eki olmadan:FRAMEWORK_CLI_VERSION 2.3 → 2.3.0,SHIELD_VERSION v2.1 → 2.1.0,ADMIN_VERSION 1.2 → 1.2.0,AUTH_VERSION 2.2 → 2.2.0. Gösterim yerleri (PanelHandler,AuthHandler,sidebar.rbn.php,RbnClibaşlığı) sabitleri okuduğu için elle değiştirilmedi.FrameworkIdentity::FRAMEWORK_VERSION(0.9.1) değiştirilmedi. applicationssürüm kapısı (şema değiştirilmedi):MasterApplicationRepository::assertVersion()yazma sırasındaVersion::isValid()kontrolü yapar ve geçersiz değeriInvalidArgumentExceptionile açık hata olarak reddeder;MasterApplicationsService::versionGate()okuma sırasında geçersiz sürümlü kaydıgetByAppKey()içinnull,list()için listeden çıkar (saatte bir uyarı). Panel bozulmaz, "sessizce yanlış sürüm" durumu oluşmaz.rbn version:check— salt-okunur denetim; tablo + çıkış kodu (0temiz,1sapma).FRAMEWORK_VERSION, dört bileşen sürümü,CITATION.cff, CHANGELOGSon sürümbaşlığı ve master DB'deki proje/uygulama sürümlerini karşılaştırır.rbn version:next <project_key>— sürümüVersion::next()ile hesaplar; varsayılan kuru koşu,--applyile yazar (yazma yalnız repository üzerinden, Anayasa §8).- Veri geçişi: yeni
Core\Database\Migrations\Master\NormalizeProjectVersions(rbn master:migrate, yalnız elle). Önceprojects_version_backuptablosuna yedek alır, sonra tüm projeleri başlangıç sürümü0.1.1'e çeker; karar tek çözücüden (ProjectVersionResolver) gelir.down()yedekteki değerleri geri koyar, yedek tablo silinmez.projectsşeması değiştirilmedi (kolon tipi veDEFAULT '1.0'aynen durur); yerel ölçüm: 19 proje, hepsi1.0(geçersiz) → 19 satır0.1.1; geri alma denendi ve 19 satır1.0'a döndü.applicationstablosu bu migration'a dokunmaz. MasterProjectsServiceartık proje kaydında'version' => '1.0'yazmaz;Version::initial()yazar.
- Yeni
-
Marka varlıkları için TEK adlandırma kuralı ve tek çözücü (
Core\Support\Definitions\Render\AssetConvention). Kural: favicon =images/favicon-<project_key>.{svg,png,ico}, OpenGraph görseli =images/og-image-<project_key>.{png,jpg,webp}. Motor geneldir: framework'e proje/müşteri adı yazılmaz,<project_key>çalışma anında gelir (Anayusa §9). Aday listesi ve öncelik sırası artık tek yerde; dört kapı (SeoResolvermeta etiketleri,AssetControllersanal/project-assets/<ad>servisi,RedirectManager::selfHealingAssets(/favicon.ico→ gerçek dosya),SchemaResolver::resolveDefaultImage(JSON-LDimage)) aynı çözücüyü çağırır — yinelenen mantık yoktur. -
Sürümleme kuralı için standart sayaç yardımcısı (
Core\Support\Bridges\Helpers\Library\Version+ global fonksiyonlar). Proje sahibi kuralı (.agents/rules/versioning.md): biçimA.B.C, birinci basamak sınırsız (9 → 10, 11…), ikinci ve üçüncü basamak yalnız0…9(asla10), başlangıç0.1.1, geçerli desen^(0|[1-9][0-9]*)\.[0-9]\.[0-9]$. Sürüm artık elle sayı yazılarak değilnext()ile hesaplanır:0.1.1 → 0.1.2,0.7.9 → 0.8.0,0.9.9 → 1.0.0,9.9.9 → 10.0.0,99.9.9 → 100.0.0. Metotlar:isValid(),parse(),next(),compare(),initial(); geçersiz girdideInvalidArgumentException. Sınıf durumsuz ve tamamen statiktir (metot adları İngilizce, Anayasa §10);newkullanılmaz (§1) ve framework'e proje adı yazılmaz (§9). Global eşleyicilernext_version(),version_is_valid(),version_compare(),version_parse(),version_initial()yalnızca sınıfı çağırır — yinelenen mantık yoktur. 2000 adımlık zincirde hiçbir adım geçersiz sürüm üretmiyor ve çıktı kesin artıyor. Davranış değişikliği yoktur: mevcut hiçbir sürüm sabiti değiştirilmedi.
Fixed
-
og:imagemeta etiketi artık ölü adres üretmiyor. Ölçülen kök hata:SeoResolver::getVirtualResourceRaw()yalnızfavicon-*/logo-*çözüyordu veAssetControllersanal kaynak dalını yalnız.svguçlantısında açıyordu; raster og görseli fiziksel keşfe düşüyor, dosyaimages/altında olduğu için istekAsset not foundile bitiyordu. Altı sitede ölçüldü (og:image404/500 → sosyal paylaşım önizlemesi görselsiz). Artık sanalog-image-<key>.<png|jpg|webp>adı doğruContent-Typeile servis edilir (yol güvenliğiAssetConvention::resolveVirtualOgImage()içinde:.., mutlak yol, ters bölü ve kök dışına çıkış reddedilir —AssetController'un mevcut güvenlik sertliğiyle aynı). -
/favicon.icoyönlendirmesi artık var olmayan uzantıya gitmiyor.selfHealingAssetsfavicon hedefini her zaman.pngyazıyordu;favicon-<key>.svgolan projede/favicon.ico→ 301 →/images/favicon-<key>.png→ 404 ölçüldü. Hedef artık projenin gerçek favicon dosyasıdır (aynı çözücü), bulunamazsa framework'ün nötr varlığına gidilir. -
ogüzerinde iki kaynak/sapma kapandı.SchemaResolver::resolveDefaultImage()sabit/images/og-image.pngveproject-routemapog_imageanahtarını okuyordu (og_imageanahtarı projelerde yazılı değil, yalnızog-imageyazılı — hiç eşleşmediği için sabit ad kullanılıyordu);SchemaPresetde ikinci bir sabit yazıyordu. Artık üçü de aynı çözücüyü kullanır. -
Dosyası olmayan projede uydurma görsel adresi üretilmiyor. Projede kurala uyan (ve geriye uyum adı da) hiçbir og görseli yoksa
og:imagemeta etiketi hiç üretilmez ve JSON-LD'de"image":""yerine alan tamamen düşer (SchemaBuilder)./og-image.pngstandart yolu da uydurma adrese yönlenmez.
Deprecated
- Anahtarsız eski varlık adları (
images/favicon.png|.svg|.ico,images/og-image.png|.jpg|.webp) "kullanımdan kalma" adımındadır; canlıda çalıştıkları için "son geri dönüş" olarak korunmuştur. Yeni dosyalar için yalnız kural adı kullanılmalıdır. Sıra: kural adı → eski adlar (yalnız kural bulunamazsa). Aynı şekildeproject-routemap.phpiçindekifavicon,og-image/og_imageanahtarları tolere edilir ama artık öncelikli değildir; proje sahibi bu anahtarları routemap'ten silmek istiyor — bu görevde routemap dosyalarına dokunulmadı, kaldırma kararı proje sahibine aittir.
Changed
-
project-routemap.phpartık panel ön eki için TEK kaynak;project-settings.phpiçindekihas_route_mapvedashboard_prefixanahtarları motor tarafından artık OKUNMAZ. (Proje sahibi kararı 05.10.2026; kırıcı değil.) İki düzeltme:-
Config.php—has_route_mapkapısı KALDIRILDI.project-settings.phpyüklenirken, aktifproject_keyiçinproject-routemap.phpview_mapping[<key>]değerleri her zamanproject-settingsüstüne birleşir. Önceden birleştirme yalnızcahas_route_mapanahtarı doğruysa çalışıyordu; anahtar yoksaview_mappinghiç uygulanmıyordu — bu yüzden canlıdahas_route_mapyazılmayan projelerde (ornek-proje-1, ornek-proje-2) ayarların siteye özel kısımları hiç okunmuyordu. Birleştirmenin gövdesi,getRouteConfig($activeKey)çağrısı ve yazma sırası değiştirilmedi; yalnızca&& !empty(...['has_route_map'])koşulu kalktı. -
SystemGuardHandler— bakım modu panel ön ekiproject-settings'ten okunmuyor. Birincil kaynakproject_data('dashboard_prefix', '')=project-routemap.php→ProjectDataMapper::assemble()→ BootCache →project_data()yolu (bu yol zaten kapısızdı); kaynak boşsaRouteBlueprint::DASHBOARD_PREFIX(dashboard) devreye girer.Config::get('project-settings.dashboard_prefix')geriye uyum yedeği olarak silindi. Muafiyet listesi (RouteBlueprint::SYSTEM_ALLOWED_PATHS), S-1 yol ayrıştırma koruması ve S-2 boş-IP koruması aynen duruyor.
Geriye uyum (canlı dosyalar bozulmaz):
project-settings.phpiçindehas_route_mapveyadashboard_prefixkalsa bile motor çalışır; bu iki anahtar artık yalnızca YOK SAYILIR, hiçbir davranışı etkilemez. Yani canlı dosyaları silmek zorunlu değildir — silmek isteyenler temizlik için yapabilir. Kaldırılırsa panel ön eki routemap'te tanımlı olmalıdır; routemap'te yoksaRouteBlueprint::DASHBOARD_PREFIX(dashboard) uygulanır. -
Added
-
RbnCommon CSS motoru eksik siniflarla tamamlandi (gorsel degisiklik yok, yeni kural yok).
rbn-master.csskapanisindaki on eksiz (katman B) yardimci sinif katmani yarim birakilmis; motor Bootstrap'in islevlerinin tamamini kendivar(--rbn-*)token'lariyla sunmuyordu. Kapsanan isler: (1).rbn-empty-state— her liste/tablo/panel ekraninda yapisal olarak bulunabilen bos-durum blogu; "hic kayit yok" ve "filtre sonucu yok" icerik modlari ayni sinifla, farkli icerikle ayrilir. (2).rbn-drawer-right+.rbn-drawer-body/.rbn-drawer-title— sag ray 992px altinda gizlenir ve mevcut overlay drawer'a devreder; tetikleyici icin yeni bir toggle sinifi yazilmadi, mevcut.rbn-btn+[data-rbn-drawer]kullanilir. (3).rbn-card-media— yalniz yuzey + oran tanimlar (kenarlik yok, ust koseler yuvarlak, alt koseler 0); gorsel view'da gercek<img>olarak yazilir; oran 16/9 kilitlidir,-portrait(4/5) ve-square(1/1) varyantlari vardir;.rbn-card-subtitle/-text/-linkveobject-fit-*yardimcilari eklendi. (4) Yenicore/utilities.css(katman B): tek yonlu bosluk (pt/pb/ps/pe),mx/my, sifir resetleri, negatif bosluk,overflow-*,z-*,order-*, sizing,visually-hidden, tipografi,align-self-*, konum/kenar,gx/gy/row-gap/column-gap. (5) Form:.input-group/.input-group-text/-sm/-lgve.form-control-sm/lg,.form-select-sm/lg. (6) Renk ve sinir:roundedailesi,border-1..5ve kenar/sifir varyantlari,border-opacity-*,opacity-*, eksikbg-*/text-*renkleri. Uyum: sayi olcegi motorun mevcut olcegiyle birebir ayni tutuldu (p-3= 16px gibi), boylececlass="p-3 pt-5"tutarli calisir; tum degerler mevcutvar(--rbn-*)token'larindan okunur, yeni renk ve yeni token tanimlanmadi. Mevcut siniflarin hesaplanan stilleri dogrulandi: 22 temsilci sinifingetComputedStyleciktisi degismedi; duman testi REGRESYON=0, 6 yerel site 200, kabul kosusu KIRMIZI 0 / YESIL 125 / ELLE 7 / HATA 0. Framework surumu degistirilmedi. -
Proje veritabanı bilgisi artık
project-settings.phpiçinde İKİ profille durabilir:DB_PROFILES. Yeni çözücüProjectDbProfileResolver(Core/System/Config/Engine/Database/)DB_PROFILES.local/DB_PROFILES.productionbloklarından çalıştığı ortama göre birini seçer. Geriye uyumlu:DB_PROFILESyoksa eski düzDB_*anahtarları aynen çalışır (kırıcı değişiklik yok, mevcut canlı dosyaları etkilenmez). Dört okuyucu —DatabaseConfig::fromRaw(),DatabaseGuardProvider::loadCredentials(),ProjectDataMapper::buildProjectPdo()veProjectCleanupJob— artık tek çözücüyü kullanır; ikinci bir profil seçme kodu yazılmadı.Ortam kararı sunucunun kimliğine bakar, isteğe değil: ortam değişkeni
RBN_DB_PROFILE(local/production; başka değer "karar yok" sayılır) → framework kökündeki tamlocalhostyol segmenti. Çalışılan dizin (getcwd()), alan adı veREMOTE_ADDR/Hostbaşlığı bilerek kullanılmaz:is_local()bir tarayıcıya dönük yardımcıdır (istek kimliğine bakar) ve veritabanı seçimine temel yapılırsa aynı sunucuda istek kimliğine göre farklı veritabanlarına bağlanılırdı. Belirsizlik her zamanproductionsayılır (fail-closed).Fail-closed: seçilen profil yoksa, profil içinde zorunlu anahtar (
DB_HOST/DB_NAME/DB_USER/DB_PASS/DB_CHARSET) eksikse ya da bir değer__DOLDUR__yer tutucusuysa AÇIK hata verilir; motor diğer profile ya daroot/boş parolaya sessizce düşmez. Hata metni yalnızca anahtar/profil adı yazar, sır değeri yazmaz.RBN_DB_PROFILEortam değişkeniEnvKeys::RBN_DB_PROFILEolarak kayıtlıdır. -
Kiracı kapsamının istisnası artık modele taşındı:
BaseModel::$projectScopeIncludes.QueryModelTraitiçindecm_sys_ip_blockstablo adı sabiti gömülüydü; tek bir tablo için yazılmış istisna büyüdükçe ikinci bir tablo eklemek kabuğu düzenlemek olurdu. Artık istisna modelin kendi dosyasında beyan edilir (CmSysIpBlocksModel → ['GLOBAL']). Kural kabukta tek: varsayılan[], bildirilen dizi varsa kapsamproject_key IN (aktif, …istisnalar), yoksaproject_key = aktif. Kapsam süzgeci artık tablo adı ile nitelikli yazılır (z_settings.project_key); JOIN'li sorgularda iki tabloda daproject_keyvarsa MySQL 1052 "ambiguous" vermeden önce bu gerekliydi. -
Kapsamı açıkça daraltan kapı:
BaseModel::withProjectScope(?string $projectKey). Kapsamlı bir modelde ellewhere('project_key', X)yazmak ikinci kez süzgeç çalıştırır ve iki koşul birbirini yok ederdi. Yeni kapı kapsamı genişletmez, yalnızca istenen anahtara daraltır (fail-closed) ve klon döndürür (kaynak model değişmez). Metot imzaları değişmedi;withoutProjectScope()aynen çalışır. -
BaseModel::isProjectScoped()veBaseModel::resolveScopeProjectKey(). Çağıranlar (repository/service/provider) bir hedef modelin kapsamlı olup olmadığını sorgular; kapsamlıysawithProjectScope(), kapsamsızsa eski elle süzgeç yolu kullanılır. Bu ayrım sayesinde kapsamı kapalı modellerde hiçbir davranış değişmedi. -
Zorunlu token kasası migrasyonu artık depoda. UPGRADING 0.9.0 Adım 5'in her proje veritabanına kod dağıtımından önce uygulanmasını istediği
111-z_user_tokens.sqldosyası repoda bulunmuyordu; tabloyu kuran başka bir yol da yoktu. Dosyarbnframework/Core/Database/Migrations/111-z_user_tokens.sqlaltına eklendi:CREATE TABLE IF NOT EXISTS(eklemeli, tekrar çalıştırılabilir, mevcut tabloyu/satırı değiştirmez), InnoDB +utf8mb4_unicode_ci,purposealanıENUM('email_verification','password_recovery'),token_hashüzerindeUNIQUE uq_user_token_hash,idx_user_purpose_pending (user_id, purpose, used_at)veidx_expires_at. Kapsam dışıdır:asw_*tabloları, ortak (cm_*) şema ve master şeması (developers,ip_blocks) hiçbir şekilde etkilenmez. Depo kökündeki.gitignoreiçindeki*.sql(veritabanı dökümü) kuralı framework migrasyonlarını da yutuyordu; migrasyon dizinine yönelik dar bir istisna eklendi. -
Kapsamlı bağlantı yardımcısı:
ConnectionTrait::connectionScoped(string $name, callable $islem). Bağlantıyı geçici olarak başka bir adla çalıştırıp iş bitincefinallyile geri alan "kaydet/geri al" deseninin tek yazılışı eklendi. Mevcutconnection()imzası değişmedi; yalnız elde kodla birebir aynı davranan yeni bir yardımcı eklendi: geri almafinallyiçindedir (istisna olsa da aktif bağlantı eski haline döner), istisna yutulmaz, işin dönüş değeri aynen geçer, iç içe kullanılabilir. Master geçişi yapan yardımcı kendi elindeki elle deseni silip bu çağrıya devrediyor; metot silinmedi ve imzası korundu. Kırıcı değildir, şema değişikliği yoktur. -
RbnCommon CSS motoru iki pakete bolundu ve kalan 306 eksik islev motor dosyalarina tasindi.
rbn-master.cssTEK bir@importzinciridir veAssetBundles::STACK_MAPuzerinden her sayfaya gider; bu yuzden yeni islevleri mastera eklemek gzip butcesini patlatiyordu. Karar: **masterin kapanisi degistirilmedi, yeni siniflar istege bagli paketlere** konuldu.(1) Yeni paket
rbnExtended—optional/rbn-utilities-extended.css(312 secici) +optional/rbn-components-extended.css(153 secici). Bu paketSTACK_MAPicine GIRILMEDI: hicbir sayfaya otomatik yuklenmez, yalnizca proje/gorunum acikcaassets => ['rbnExtended'](ViewMap) veya$this->addAsset('rbnExtended')(Controller) dediginde yuklenir.AssetBuilderhic degistirilmedi —collect()zaten bundle adini styles listesine cozuyordu. Kapsanan isler:offset-*,row-cols-*,col-auto/col-{sm,md,lg,xl}-auto, duyarlid-*/flex-*/justify-*/items-*/order-*(sm·md·lg·xl·xxl),g-0,container-md/xl,rounded-sm/xl,shadow-xs/hover,fs-xxs,link-*,*-opacity-10/100,text-*-emphasis,.rbn-visible/.rbn-invisible/.rbn-visually-hiddenaliaslari,.is-valid/.was-validated/.rbn-form-feedback-; bilesenlerderbn-btn-{block,info,light,outline-dark,outline-info,outline-light,outline-secondary},rbn-alert-{dark,info,light,heading,link}, form on ekleri (rbn-form-control,-sm/-lg,-plaintext,-color,rbn-form-select,rbn-form-range,rbn-form-text,rbn-form-floating,rbn-input-group-{sm,lg}),rbn-dropdown-{start,end,text,toggle},rbn-modal-{backdrop,dialog,content,header,centered,scrollable},rbn-navbar,rbn-list-,rbn-breadcrumb,rbn-ratio{,-1x1,-16x9,-4x3},rbn-progress-track,rbn-spinner-{sm,grow},rbn-table-{borderless,row-active,responsive},rbn-display-1..6,rbn-tooltip,rbn-popover,rbn-toast-{header,body},rbn-carousel*`.(2)
core/rbn-auth.css—Resources/Views/RbnAuth/Layouts/auth_header.rbn.phpicindeki 12,5 KBlik view-ici<style>blogu (17rbn-auth-*sinifi, 29 hardcoded hex) motor dosyasina tasindi;rbn_core_authpaketi artik bu dosyayi da istiyor. **29 hex yerine mevcut--rbn-*tokenlari ve 20 yeni--rbn-auth-*saydamlik tonu** kullaniliyor. Diger framework viewlarina (Resources/Views/`) dokunulmadi.Uyum ve olcu:
rbn_masterpaketinin istedigi dosyalar birebir ayni kaldi,rbn-master.csskapanisi 19 dosya / 47 884 B gzip olarak DEGISMEDI (butce asimi yok). Yeni paketler ayri olculdu:rbn-auth.css2 682 B gzip,rbnExtended8 242 B gzip. Dogrulama: mapping JSONundaki 863 hedefin **863u de tanimli (once 306 eksikti), ters uyusmazlik 0; 107 yeni sinifgetComputedStyleile 375/768/1280de olculdu; 44 mevcut sinifin hesaplanan stili 132/132 ayni; login sayfasi 375/768/1280de once-sonra karsilastirmasi 26/26 ayni, PNG farki 0; 4 yerel site ana sayfa + iletisim DOM/computed-style/PNG karsilastirmasi fark 0 (ornek-site-1 ve ornek-proje-1'taki kucuk PNG farklari kod tabanli olmayan sayfa ici canli icerik; ayni kod tabaniyla iki kez calistirildiginde ayni farklar tekrar uretiliyor). Duman testi REGRESYON=0, 6 yerel site 200, kabul kosusu kotuylesmedi, birim testi yeni:fw_css_motor_2_bundle13/13 yesil. Framework surumu degistirilmedi.**
Changed
-
13 çok kiracılı modelde kiracı izolasyonu AÇILDI (KIRICI — model bazında ölçülerek). FW-ALTYAPI-1 H'de ölçülen ve tek tek taşınan modeller:
FaqsModel,PagesModel,FrontendMenusModel,SettingsModel,SidebarCategoriesModel,SidebarMenusModel,ContentCategoryModel,ContentDraftModel,CronLogsModel,RssSourceModel,RssBlacklistModel(framework) +AAProductModel(ornek-proje-5) +IcerikModel(rbncore) →protected bool $scoped = true.BaseModel::$scopedfalse olarak kaldı; 68 somut model kapsam dışı kalmaya devam ediyor. Ölçülen etki:ornek-kiracikiracısıornek-proje-3veritabanındanornek-proje-3'in SSS ve sayfa kayıtlarını görebiliyordu; kapsam sonrası göremiyor. Kapsamlı model artıkcreate()/update()ileproject_keydeğerini sunucu bağlamından yazar (B-20) ve okuma süzgecini otomatik uygular. Ayrıntı ve geri alım içinUPGRADING.md. -
project_keyyazma yolu artık'default'sentinelini ASLA yazmıyor. Ölçülen gerçek: yedi yerel veritabanındaki 74 kolondaproject_key='default'satırı yoktur; yani bu değer ne okumada işe yarar (her zaman 0 satır) ne yazmada (görünmez, sahipsiz satır). Bağlam çözülemediğinde (getActiveProjectKey()yedeğine düşüldüğünde) kapsamlı model artık hiçbirproject_keyyazmaz; çağıran bir değer verdiyse o korunur, vermediyse kolonNULLkalır (hiçbir kiracının kapsamına girmez — fail-closed). -
Kenar çubuğu önbellek anahtarı artık kiracıyı içeriyor.
SidebarProviderönbelleği"sidebar_{rol}"anahtarını kullanıyordu; anahtar tüm kiracılarda ortaktı, yani bir projenin paneli başka projenin kenar çubuğunu gösterebiliyordu. Artık"sidebar_{kiraci}_{rol}". -
Request::form()artık yalnız doğrulanmış alanları döndürür (KIRICI).form()öncearray_merge($this->all(), $doğrulanmış)ile tüm istek gövdesini döndürüyor, yani kural dizisinde olmayan alanlar da servise/modele geçebiliyordu; artık dönen dizi yalnız kural dizisinde tanımlı VE gönderilmiş alanları içerir.nullable/optionalkuralı olup gönderilmemiş alanlaranullyazılmaz (kolon olduğu gibi kalır). Geri açma anahtarısecurity.form_input_mode(off|log|enforce, varsayılanenforce; bozuk değer fail-closed olarakenforce'a düşer). Kuralsız yazma yolunun açık karşılığı yeni metotRequest::rawAll(): alan doğrulaması yapmaz amaform()ile aynı kalkan zincirini (method kontrolü, CSRF, Origin, bot, hız sınırı, dosya güvenliği) çalıştırır.filter()da kendiliğinden daraldı. Ayrıntılı etki listesi ve çağrı envanteri içinUPGRADING.md. -
Açık ham yol:
Request::rawAll(). Kural dizisi tanımlamadan yazan çağıranlar artıkform([])yerinerawAll($seçenekler)kullanır; metotRequestInterfacesözleşmesine de yazıldı. Güvenlik alanları (ör. parola tekrar doğrulaması)rawAll()'a taşınmaz; onlar kural dizisine (beyaz listeye) alınır. -
Bilinmeyen veritabanı bağlantı adı artık sessizce kabul edilmiyor (KIRICI). Bağlantı üretilirken tanımlı olmayan bir ad verilirse framework o adı sessizce
database_projectkümesine eşlemek yerine istisna fırlatır. Gerekçe: çok projeli (çok kiracılı) kurulumda sessizce eşleme, proje A'nın verisinin proje B'nin veritabanına yazılması demekti.database_project/database_master/database_commonve eskidefaultadı aynen çalışır; bağlantı adlarının listesi değişmedi.connection()veconnectionScoped()imzaları değişmedi. -
Veritabanı bağlantısı değiştirmek için TEK yazım. Bağlantı üretme isteyen tüm sorgu ve yazma yolları tek bir kapsam yardımcısı üzerinden gidiyor: iş bitince aktif bağlantı eski haline döner. Önce doğrudan global aktif bağlantıyı ayarlıyor ve geri almadan bırakıyordu; bir model sorgusu, kendisinden sonra gelen ham sorguların hangi veritabanına gideceğini belirleyebiliyordu. Yalnızca okuma yapan yardımcı çağrıları da artık hiçbir şeyi sabitlemiyor. Davranışları aynı, yan etkileri (kapsam dışı durum sızması) kapandı.
-
Durum yazımı için anlamı açık yeni adlar:
setStatus()vesetStatusById().toggleStatusadı iki katmanda iki farklı sözleşme taşıyordu (model/sağlayıcıda 2. parametre alan adı, serviste istenen değer) ve istenen değer sağlayıcı katmanına giderken düşüyordu. Yeni adlar bu sözleşmeyi tekilleştirir; eski ad silinmedi, imzası değişmedi,@deprecatedişaretlendi ve kullanımı saatlik günlüğe düşüyor. Panelde "durum değiştir" isteği artık istenen değeri yazıyor;nulldeğer verildiğinde eski "değiştir" anlamı birebir korunur. Ayrıntı içinUPGRADING.md.
Fixed
-
Bakım modu muafiyeti panel ön ekini yanlış kaynaktan okuyordu (
SystemGuardHandler). Panel ön eki iki ayrı yerden geliyordu: rotalar ve önbellek tek kaynaktan (Core/Config/project-routemap.php→view_mapping[<project_key>]→ProjectDataMapper→project_data(), bu yolda hiçbir kapı yok) okurken, bakım modu muafiyeti ikinci bir yerden (project-settings.dashboard_prefix) okuyordu. İkisi ayrıştığında bakım modunda panel yolu kilitlenir: rota/rbnaltındayken muafiyet/dashboard'a bakardı (veya tersi). Artık sıra tek: önceproject_data('dashboard_prefix')(tek kaynak), yoksaproject-settings.dashboard_prefix(geriye uyum yedeği korundu), hiçbiri yoksa framework sabiti. Yardımcıfunction_existsile korunur (CLI/erken boot). Güvenlik sınırları gevşetilmedi: sorgu parametresi içinde taşınan istisna metinleri, statik varlık istisnaları, sistem izinli yollar ve boş IP'nin VIP sayılmaması aynen durur; kırıcı değişiklik yoktur. -
UNIQUE (project_key, <slug>)varlığı yanlış ölçülüyordu (veri bütünlüğü). Ölçüm, indeksin varlığınıCOLUMN_NAME IN ('project_key', <slug>)filtresiyle soruyordu; üç kolonlu bir UNIQUE (ör.project_key, type, slug) indeksi de bu filtreyle iki satır döndürüp "iki kolonlu UNIQUE var" sanılıyordu. Sonuçta iki kolonlu UNIQUE hiçbir tabloya ekleniyordu.TenantKeyMigrationartık indeksin tüm kolonlarını okuyup listesini sırayla birebir karşılaştırıyor (kolon sayısı da); ekleyiciUNIQUE (project_key, <slug>)ekleyenapplyUnique()yalnız çakışma yoksa çalışıyor, çakışmalı tabloyuskipped_conflictdurumuyla atlayıp sayısını raporluyor. Kırıcı değildir; mevcut indekslere dokunmaz, yalnız eksik olanı ekler (revertUnique()yalnız kendi ürettiği ada sahip indeksi düşürür). -
GeoIP hata yolu sessizdi. Coğrafi konum sağlayıcısına ulaşılamadığında, yanıt beklenenden büyük geldiğinde ya da istisna oluştuğunda istek düşürülmeden ülke bilgisi atlanıyordu ama hiçbir kayıt bırakılmıyordu. Artık bu yollar kısaltılmış (15 dakikada bir tek) bir
warningkaydı yazıyor. Dönen değer değişmedi: yineBILINMEYEN_ULKE('XX'); hiçbir koşulda boş değer dönmez, istisna yeniden fırlatılmaz. Kayıt anahtarı yalnız hata sınıfını taşır; istemci IP'si veya başka bir değer kayda girmez. -
Kategori güncellemesinde ham alan yazılabiliyordu. İçerik kategorisi kaydederken, kayıt nesne döndürmediği durumda korumalı alanlar beyaz listeden geçirilmeden yazılıyordu. Artık aynı beyaz liste her iki yolda da uygulanıyor.
-
Tablosu olmayan modelde tablo adı isteyen sessiz hata. Böyle bir modelde tablo adı soran bir çağrı artık neden başarısız olduğunu yazan bir hata veriyor ve tablosuz modeller için ayrı bir okuma yolu öneriyor. Metot imzası değişmedi; zaten hata veren yolun hatası netleştirildi.
-
Kayıt adımını tanımlamayan sağlayıcılar sessizce atlanıyordu. Bu durum artık saatlik günlüğe bir satır olarak yazılıyor (sağlayıcı sınıf adıyla). İstisna fırlatılmıyor: hiçbir sağlayıcı çalışmaya devam eder, hiçbir istek düşmez.
Security
-
İstemci IP'si kaynağı:
X-Forwarded-For/CF-Connecting-IPbaşlıklarına bilinçli olarak GÜVENİLMEZ (fail-closed). Proxy veya Cloudflare arkasında IP tabanlı kontroller (allowed_origins, IP ban)REMOTE_ADDR'e bakar; güvenilir proxy modeli ayrı bir karardır. -
Çıkış için asıl yol artık
POST+ CSRF. Yeni rotaPOST /auth/logout(auth.logout) eklendi; CSRF belirteci zorunludur ve doğrulanamazsa istek reddedilir (fail-closed). EskiGET /logoutveGET /cikisyolları kaldırılmadı (meşru çıkış bağlantıları ve otomatik testler çalışmaya devam eder); her kullanımdasecuritykanalına yalnız gözlem amaçlı bir "eski çıkış yolu" sayacı düşer. Geriye uyumluGETyolunda çapraz site isteği (Sec-Fetch-Site: cross-siteya da başka alan adından gelenReferer) oturumu kapatmaz ve 403 döner. İstemci bu iki başlığı hiç göndermiyorsa (komut satırı araçları, eski istemciler) çıkış yine çalışır. Çıkış mantığının kendisi (kimlik eşleşmesi, master anahtar koruması) değişmedi. -
Başlatma aşamalarındaki sessiz atlamalar artık görünür. Çekirdek kayıt aşamasında çözülemeyen servis, kaydedilemeyen hata servisi, kaynak sınıfı bulunmayan ve hedef adı zaten kullanımda olan sınıf takma adı kayıtları artık günlüğe yazılıyor (saatte bir,
LogThrottlekapısından geçerek). Daha önce bu durumlar hiçbir iz bırakmadan geçiliyordu, teşhisi zorlaştırıyordu. İstek düşürülmez, istisna fırlatılmaz, yanıt ve akış değişmez — yalnız teşhis satırı eklenmiştir. Günlük satırları proje adı, anahtar, kullanıcı veya istek verisi içermez. -
Tarayıcı tarama tuzaklarında gerçek sayfa kaybı giderildi. Saldırgan tarama tuzağı listesinde
/admin,/test,/demo,/site,/ipgibi uygulama önekleri de vardı; bu adresler bir projede gerçek bir sayfaya karşılık geliyorsa istek kalıcı olarak ana sayfaya yönlendiriliyordu. Tuzak listesi değiştirilmedi; bunun yerine yalnız bu önekler için, istek gerçek bir rotaya eşleşiyorsa yönlendirme yapılmıyor. Gerçek rota yoksa, rota koleksiyonu boşsa veya bir hata oluşursa eski davranış aynen korunur (fail-closed): yani tuzak hiçbir projede zayıflatılmıyor, yalnız gerçek sayfalar kurtarılıyor. Diğer tüm tuzak kuralları (alt dizge eşleşmesi, eski yazı tipi,.php/.html/.htmuzantı taramaları) değişmedi.
Fixed
-
Yetkisiz form isteği artık düz metin yerine standart 403 sayfası gösteriyor.
FormRequest::failedAuthorization()önceden403 Forbidden - Unauthorized Requestmetnini doğrudan basıyordu; bilgi sızdırmıyordu ama kullanıcı framework'ün gerçek hata ekranını görmüyordu. Artık tek merkezden (shield()->forbidden()) diğer tüm 403 yollarıyla aynı kalkan sayfası basılıyor. Durum kodu yine 403'tür. Çok erken başlatma veya birim testi gibishield()yardımcısının olmadığı durumlar için eski 403 + sonlandırma davranışı yedek olarak korundu; istek hiçbir koşulda 200/boş dönmez. -
Çekirdek başlatma aşamalarının sırası ve bağımlılıkları kodda belgelendi. Altı aşamanın (oto yükleme → tanılama → veritabanı → servisler → oturum → yönlendirme) her biri için "hangi aşamaya bağımlı" gerekçesi yorum olarak yazıldı; sıra değişirse hangi adımın kırıldığı belge okunarak bulunabiliyor. Davranış değişmedi.
-
Sayfalama, liste ve yazma katmanı onarımları (çekirdek). (1) Sayfalayıcı artık ham $_GET / $_SERVER okumuyor: geçerli sayfa, arama metni ve sorgu parametreleri istek nesnesinden alınıyor; taban adres istek yolundan türetiliyor, bu yüzden komut satırında istek adresi tanımsız olsa da sayfalama istisna atmıyor. Sayfalama bağlantılarındaki adresler HTML kaçışından geçiriliyor (taban adresten gelen betik enjeksiyonu kapatıldı) ve sayfa numarası adres içinde yalnızca bir kez yazılıyor (sorgu içeren taban adreslerde oluşan çift "?" ve taşınan eski sayfa giderildi). (2) Durum aç/kapa ve model güncelleme çağrıları artık gerçek sonucu döndürüyor: var olmayan bir kayıt üzerinde çalışıldığında "başarılı" görünüp hiçbir şeyin değişmediği durum sona erdi. (3) İçerik listeleme yardımcısı, proje anahtarı çözümlenemediğinde tanımsız yardımcı çağırmak yerine güvenli bir geri düşüşe geçiyor; sorgu sonucu hem koleksiyon hem düz dizi biçiminde destekleniyor. (4) Ham kayıt ekleme yolu, kayıt oluşturma yoluyla aynı alan süzgecinden geçiyor: beyaz listesi tanımlayan bir modelde liste dışı alan artık yazılmıyor. Beyaz listesi tanımlamayan modellerde davranış değişmedi. (5) Yapılandırma okuma yolundaki "özyineleme" koruması ve hata yakalama artık sessizce yutmuyor; düşen anahtar ve istisna ayrıntısı sunucu günlüğüne yazılıyor, dönen değer ve istisna fırlatma davranışı değişmedi. (6) Denetleyici kurulumundaki boş hata yakalama blokları, çözümlenen ad, istisna sınıfı ve mesajı günlüğe yazıyor; servis/model çözülemezse denetleyicinin kurulmaya devam etme davranışı korunuyor. (7) İlişki tanımlayıcıları tek bir üretim noktasından geçiyor ve birincil anahtar, modelin genel erişimcisi üzerinden okunuyor; dönen değerler değişmedi. (8) Aynı işlemde kullanılan iki dev örneğin (depolama motoru, ana servis) test izolasyonu için sıfırlama çağrıları eklendi; çağrılmadıkları sürece mevcut tekil davranışı aynen sürüyor.
Changed
-
Tanılama günlükleri
LogThrottleile saatte bir. Yeni, tek yardımcı sınıfLogThrottle(Core/Support/Bridges/Helpers/Library/LogThrottle.php):LogThrottle::once(string $key, int $ttlSeconds = 3600): boolaynı anahtar için TTL içinde yalnız ilk çağrıyatruedöner, hiçbir koşulda istisna fırlatmaz. Depolama sırasıStorage/cache/log-throttle/<sha256>.throttle(flock, süreçler arası birincil kaynak) → APCu (yalnız dosya kullanılamıyorsa) → fail-closed (false: satır yazılmaz, istek bozulmaz, günlük şişmez). Anahtar yalnız kalem etiketi + sınıf adı taşır (değer/PII yok). Bağlanan "her istekte yazan, tanılama amaçlı" kalemler: B-92 DI uyarısı, YP-1MODEL_NOT_SCOPED,PROXY_DISCOVERY_SWALLOWED, F-10/F-14LOG_ONLY_SAYAC(sayacın değeri değişmedi; yalnız yazılan satır sınırlı). Gerçek hata/denetim kayıtları (ApiGuardmachine-api denetimi,BaseConfig,Database::connection,BaseControllercatch) ve mevcut kilidi olantoggleStatusCompatsayaçları dokunulmadı. Ölçülen etki (162 isteklik duman koşusu):nginx-error.log+596 → 0,MODEL_NOT_SCOPED2098 → 0,LOG_ONLY_SAYAC72 → 0; gerçek güvenlik olayı olanMASS_ASSIGNMENT_BLOCKkayıtları korunuyor. Test/ölçüm kapısı:RBN_LOG_THROTTLE=0(EnvKeys'te kayıtlı,Envüzerinden okunur). Görünürlük korunur — uyarı saatte bir yine yazılır;RBN_DEVkapısı değiştirilmedi. -
Katmanlar arası kaydetme imzası geriye uyumlu hâle getirildi. Kaydetme yolu servis katmanında iki zorunlu argüman isterken sağlayıcı katmanında tek argüman istiyordu; tek argümanlı çağrı istisna fırlatıyordu. Servis katmanındaki imza genişletildi: hem eski iki argümanlı hem tek argümanlı çağrılar çalışıyor, tek argüman dizi geldiğinde veri olarak yorumlanıyor (bir alt servis bu uyarlamayı zaten elle yazmıştı). Sağlayıcı katmanındaki imzalar değiştirilmedi. Durum aç/kapa yolunda servis katmanı, çağırdığı sağlayıcıya alan adını doğru konumda geçiriyor; önceden alan adı sessizce düşüyordu. Çağıranın verdiği durum değeri sağlayıcıda karşılıksız olduğunda bu durum artık sessizce yutulmuyor, sunucu günlüğüne yazılıyor.
-
Çekirdek proxy ve nitelik erişimi. Proxy üzerinden metot çağrıları artık verilen argümanları hedefe iletiyor (önceden argümanlar sessizce düşüyor ve hedefin kendi hatası maskeleniyordu); metot bulunamazsa eski davranış korunuyor. Nitelik sınıfları (#[Module], #[SubModule], #[Component]) framework servislerine erişebiliyor; çözümleme başarısız olduğunda istisna fırlatılmadan önceki davranış korunuyor ve ayrıntı günlüğe yazılıyor.
-
Orta/düşük şiddetli güvenlik sertleştirmeleri (üçüncü dilim, on altı madde; çekirdek, yönlendirme, form güvenliği, şablon ve hata ekranı). (1) URL güvenlik denetiminde yasaklı alan adı eşleşmesi artık yalnız ana makine adı üzerinde ve tam/son-ek/etiket olarak yapılıyor (yol ve sorgudaki rastlantısal metin eşleşmesi kalktı); DNS çözümü geçersiz adlarda yapılmıyor, süreç içinde önbelleğe alınıyor ve süreç başına sorgu sayısı sınırlı. (2) Çekirdek ön-uçuş (boot) hata sayfası üretimde ipucu ve ham istisna mesajını göstermiyor; ayrıntı sistem günlüğüne yazılıyor, yerel geliştirmede eskisi gibi. (3) Şablon verisi artık motorun yerel değişkenlerini (derlenmiş dosya yolu, düzen çözücü) ezemiyor: veri izole bir kapsamda açılıyor, ayrılmış adlarla çakışma günlüğe yazılıyor; ham PHP görünüm yolunda da mevcut değişkenler korunuyor. (4) Hata sayfaları üretimde framework ve kalkan sürüm numarasını göstermiyor (marka adı kalır). (5)
?rbn_diag=1dizin dökümü artık yalnız geliştirme ortamı kararına (RBN_DEV) bağlı. (6) PHP sürüm başlığı (X-Powered-By) kaldırılıyor;X-Content-Type-Options: nosniffveReferrer-Policyyoksa ekleniyor, proje kendi değerini koyduysa ezilmiyor (HSTS/CSP/X-Frame-Optionsbilerek eklenmedi: sunucu/proje kararı). (7) İçerik listesi önbellek anahtarı sıralama seçeneklerini de içeriyor (farklı sıralama aynı önbelleği döndürmüyor); yükseltmede içerik listesi önbelleği bir kez soğuk başlar. (8) Rota eşleştiricisi, özel düzenli ifade kümesi içeren parametre bloklarını (örneğin onaltılı anahtar + sabit miktarlı tekrar) artık doğru ayrıştırıyor; önceki iki aşamalı ayrıştırma bu bloğu bozuyor ve ilgili doğrulama ucu sürekli 404 dönüyordu. Ayıraç karakteri hem sabit yolda hem özel düzenli ifadede kaçışlanıyor; derlenemeyen bir desen hiçbir isteği eşleştirmeyen bir desene düşüyor. (9) Yönlendirme muafiyeti artık yolun herhangi bir yerinde alt dizge aramak yerine segmentin tam eşleşmesine bakıyor; böylece gerçek webhook/API uç noktaları korunurken, ad içeren meşru sayfalar 301 normalizasyonundan ve kanal adı (canonical host) zorlamasından muaf olmuyor. (10) Panel-kapalı projelerde giriş/kayıt/parola sıfırlama alt yolları da kapatılıyor (tam eşleşme ile alt yollar korumayı geçiriyordu); ön ek benzeri yollar kapsam dışı. (11) Rota hedefi çözümlenemediğinde üretilen hata mesajı üretimde sınıf ve metot adını taşımıyor; ayrıntı sistem günlüğüne yazılıyor. (12) Proje keşfi alan adı normalizasyonu artık yalnızca sondaki yerel geliştirme ekini (test/local) atıyor; önce metin içinde her yerde silindiği için alan adının ortasında bu ekleri içeren adlar bozulup yanlış projeye bağlanıyordu. Geçersiz alan adı artık boş değer dönüyor (kapalıya kapalı). (13) Oturum temizliği ve modül rota yüklemesi sessizce atlandığında artık günlük yazılıyor; istek düşürülmüyor, davranış değişmiyor. (14) İndirme başlığındaki dosya adı kaçışlanıyor (indirme başlığı için zaten var olan tek kaçış yardımcısı kullanılıyor; ikinci bir kaçış kodu oluşturulmadı). (15) Sanal varlık tanılama başlığına istek yolundan gelen ad ham basılıyordu; artık kontrol karakterleri ayıklanıyor ve yolun son segmentiyle sınırlandırılıyor. (16) 404 sayfasında yansıtılan komut çalıştırma açığı: sayfa başlığı mesajı istisna metnini kaçışlamadan yazıyordu ve istisna metni istek yolunu içeriyordu; böylece bir sayfa adresindeki istek, o sayfada etiket olarak geri yansıyordu. Hata ekranlarındaki tüm mesaj/ipucu/başlık değerleri artık HTML kaçışlanıyor; panik sayfasında daha önce uygulanan koruma kardeş ekranlara da yaygınlaştırıldı. -
IP güvenlik katmanı (Gatekeepers) sertleştirmesi. (1) WAF ihlalinde yazılan yasak kaydı artık 7 günlük ve global değil: süre mevcut aktif yasak sayısından türetilen kademeli bir cezadır (ilk ihlal 15 dakika, tekrarında 1 saat, sonrasında 24 saat) ve kayıt bulunulan projenin kapsamında yazılır — aynı NAT adresindeki diğer projeler etkilenmez. Bu, form katmanında daha önce uygulanan kademeli/proje kapsamlı cezayla aynı kuralı paylaşır. IP
enforcemodu bu değişiklikle açılmaz. (2) Saldırı imzası taraması yeniden düzenlendi: istek yolu (kaynak kimliğidir) artık yalnız dizin gezinme denemelerine karşı taranır; sorgu dizesi ve gövde kendi desen kümeleriyle taranır; meşru metin, Türkçe içerik ve URL parçalarında yanlış pozitif azaltıldı. Gerçek saldırı göstergelerinin tümü korunmuştur (birim testi: 53 meşru örneğin 53'ü de temiz, saldırı örneklerinin tamamı yakalanıyor). (3) Konum servisine gönderilen adres kümesi genişletildi: CGNAT (100.64.0.0/10), belirtilmemiş adresler, çok noktaya yayın/reserve IPv4 aralıkları ve IPv6 özel aralıkları artık üçüncü tarafa gönderilmiyor; belirtilmemiş adresler "Türkiye" sayılmıyor. (4) Proje ön bilgisi okunurken tüm tablo sütunları çekilmek yerine kullanılan sütunların açık listesi okunuyor; okuma sonucu uygulama bağlamına konduğu için lisans anahtarı artık bu satırla taşınmıyor. (5) Veritabanı koruma katmanı, kullanıcıya gösterilen hata metinlerine ham bağlantı/sorgu hatalarını yapıştırmıyor; kök neden yalnızca sunucu günlüğüne yazılıyor. İstisna sınıflandırması, hata türü ve kabul testleri değişmedi: bağlantı/tablo/yazma yetkisi hataları yine ön koşulu engelleyerek (fail-closed) karşılanır. -
Orta/düşük şiddetli güvenlik sertleştirmeleri (ikinci dilim, yedi madde). (1) Güvenlik ayarı önbellek anahtarı artık proje bazlı (
ShieldSettingsRepository::settingsCacheKey()); okuma ve silme aynı anahtarı kullanır, ayar yazımı kendi projesinin önbelleğini düşürür. (2) Honeypot denetimitrim((string) $v) !== ''ile yapılıyor ("0"değeri artık bot sayılır). (3) Log/geçici dizinler0777yerine0775ile oluşturuluyor (Windows'ta izin biti etkisizdir). (4) Giriş akışında var olmayan veya pasif hesap için de sabit maliyetli sahte parola doğrulaması yapılıyor (zamanlama ile kullanıcı sayımlama). (5) Oturum politikasının Host eşleştirmesi geçerli alan adı karakterleri dışındakileri eşleştirmiyor. (6) Kilit ekranında POST yalnız kilit açma uçlarına (auth/login,auth/authenticate) izinli; denetim yolda "login" geçen isteklerin geçtiği alt dizge listesinden önce yapılıyor. (7) Panel SQL konsolu yalnız geliştirici/süper yönetici/master geliştiriciye açık, çoklu ifadeyi reddediyor ve her çalıştırmayısecuritykanalına değersiz (metin/sayı maskeli, ilk 200 karakter) kaydediyor. -
Orta/düşük şiddetli güvenlik sertleştirmeleri (altı paket). (1) Origin/Referer denetimi bozuk URL'de artık hata (500) vermeden isteği reddediyor; joker alan adı eşleşmesi başa ve sona sabitlendi. (2) Üretimde hata/yol sızıntıları kapandı: iki repository'nin sistem günlüğüne ham veritabanı mesajı yazılmıyor (sınıf adı + kod; ayrıntı yalnız debug kanalında),
Viewrender hatası veExceptionHandlerçözüm ipucu yalnız yerel geliştirmede ayrıntı gösteriyor, indirme başlığındaki dosya adı (Content-Disposition) satır sonu/tırnak kaçışlı. (3) Dosya yüklemede çift uzantı için yerel geliştirme muafiyeti kaldırıldı; gömülü<?phptaraması 1 MB'a genişletildi. (4)SchemaBuilderkimlik kaçışı tek geçitte,convert()collation değeri doğrulanıyor. (5)custom_pathdosya yoluna girmeden önce doğrulanıyor (geçersizse "yapılandırma yok" yoluna düşer, istisna atmaz). (6) Çıkışta silinen çerezler oluşturulurken kullanılan bayraklarla gönderiliyor; başarılı girişte eski parola özeti sessizce yenileniyor (CryptoHelper::needsRehash()). -
CRUD girişi artık model beyaz listesine bağlı:
CrudControllerTrait::create()/update()ham istek gövdesini servis/modele aktarmıyor. Standart CRUD uçlarırequest->form([])çağırıyordu; kuralsız bu çağrı tüm istek alanlarını döndürür (CSRF/iç anahtarlar düşülmüş haliyle) ve veri doğrudan servise akıtılıyordu. Artık veri hedef modelin$fillablelistesine göre budanır. Geri uyumluluk kilidi korunur: hedef model çözülemiyorsa veya$fillabletanımlı değilse veri hiç değişmeden geçer — beyaz listesi olmayan modelin davranışı birebir aynıdır. Birincil anahtar (id) her zaman geçer. Düşürülen alanlarsecuritykanalına değer taşımadanCRUD_INPUT_FIELD_DROPPEDolarak loglanır. Altı modülün (ornek-proje-5, ornek-proje-3, ornek-proje-4, ornek-proje-6, ornek-proje-2, ornek-proje-1) 35 yazma modeli beyaz listeye bağlandı; listeler gerçek veritabanı şemasından ölçülmüştür ve panelin gerçekten gönderdiği alanların tamamını kapsar. -
Süzgeçten geçen yazma yolları da beyaz listeye bağlandı (
filterFillable()).model->query()->insert()/update()yollarıCrudModelTrait'ten geçmediği için toplu atama süzgeci kendiliğinden çalışmıyordu.MassAssignmentTrait::filterFillable()eklendi ve ornek-proje-6 (PbProgramRepository::saveProgram) ile ornek-proje-1 (OfisProperty/OfisCustomer/OfisContract/OfisPersonel/OfisCash/DsaPropertyRepository) repository'lerindeki bu tür yazma yollarında açıkça çağrıldı. Bayrak kapalıyken veya liste tanımsızsa veri yine dokunulmaz. -
RbnAdmin profil ekranı gerçek şemaya uyarıldı.
z_userstablosundafirstname/lastname/phone_numberkolonları yok; profil formu bu alanları gönderdiği için ekran "Unknown column" ile kırık kalıyordu (ve T4 sonrasıemailde düşüyordu —emailUsersModel::$guardediçindedir). Ekran teknamekolonuna göre düzeltildi;emailaçık bir yetkili yazıcıya taşındı (UserRepository::updateEmail()→authorizeFields(['email']),UserRepository::updateProfile()→UserManager::updateProfile()). -
UserSecurityRepository::saveSecurityData()createyolunda artık doğru dönüş değerini veriyor. MotorLAST_INSERT_ID()değerini döndürüyor;z_users_securitytablosundauser_idbirincil anahtar veAUTO_INCREMENTdeğil olduğu için değer0geliyor ve(bool) 0 = falseoluyordu — satır yazılıyordu ama çağrıya yanlış negatif dönüyordu. Artık satır yazıldıktan sonra doğrulanarak dönülüyor. -
masterProjectsrepository takma adı registry'ye eklendi.MasterProjectsServicekendi repository'sini suffix çözümlemesiyle istiyordu ama registry'de yalnızca noktalımaster.projectsanahtarı vardı; proje kaydı/lisans anahtarı üretimi bu yüzden diagnostic hatasıyla ölüydü. Aynı desen (masterLicence) zaten çözülmüştü. -
Scoped modellerde
project_keyher zaman sunucu bağlamından yazılır (kiracı izolasyonu). Kapsamlı modeldecreate()yalnızcaproject_keyboşsa aktif anahtarı yazıyordu; kullanıcı dolu bir değer gönderdiğinde o değer kabul ediliyordu.update()yolunda ise hiçbir işlem yapılmadığı için bir kayıtproject_keydeğiştirilerek başka bir kiracıya taşınabiliyordu. Artık her iki yolda daproject_keyaktif uygulama bağlamından yazılır ve istekteki değer yok sayılır. Bilerek başka bir kiracıya yazması gereken tek yer (güvenlik ayarlarınınGLOBALkaydı) artık açık ve loglananwriteAsProject()kaçış kapısından geçiyor. Kapsam dışı modellerin davranışı değişmedi. -
Toplu atama koruması: beş güvenlik modelinin korumalı alanları artık toplu atamayla yazılamaz (
security.mass_assignmentvarsayılan AÇIK).UsersModel(role,email,username),UserSecurityModel(user_id),MasterDevelopersModel(role,password),MasterProjectsModel(license_key,status) veMasterLicenceModel(status) modelleri artık$guardedtanımlıyor;create()/update()/save()bu alanları süzüyor. Bu alanlara yazması gereken her meşru çağıran yetkili yola taşındı: rol atamasıUserManager::setRole()(rol beyaz listesiyle), parolaUserRepository::updatePassword()(özet sunucuda üretilir), güvenlik kasasıUserSecurityRepository::saveSecurityData()(user_iddaima metot imzasından gelir), lisans durumuMasterLicenceRepository::create()/updateStatus()(beyaz listeli sabit), proje kimliğiMasterProjectsRepository::createProjectIdentity()/updateProjectIdentity(). Yetkili yolların ortak kapısıauthorizeFields()'tır: her çağrısecuritykanalına kayıt düşürür ve istekten gelen alan adını kabul etmez. Kapsam dışı modellerin ve$fillable/$guardedtanımlamayan 76 modelin davranışı değişmedi; geçici geri almasecurity.mass_assignment=falseile tek anahtardır. -
IP güvenlik katmanı döngü (loopback) adresleri için kademeli ceza/ban kaydı yazmaz; yerel geliştirme ve aynı sunucudan gelen istekler kendi kendini banlamaz. Form katmanındaki şüpheli-User-Agent kontrolü, yerel döngü adreslerinden gelen isteklerde de çalışıyor ve global IP ban tablosuna kayıt yazıyordu. Test ve duman trafiği ile aynı sunucudan gelen sağlık/planlanmış-görev istekleri bu yüzden kendi kendini banlıyordu: katman bugün yalnızca gözlem (
log_only) yaptığı için engellemiyor, ancak zorlama moduna geçildiğinde yerelden hiçbir giriş geçemezdi. Muafiyet yalnızca127.0.0.0/8,::1ve IPv4-eşlemeli karşılıkları için geçerlidir; RFC1918 özel ağlar, bağlantı-yerel ve tekil-yerel adresler muaf değildir, çünkü ofis iç ağı gerçek bir istemci olabilir. Döngü adresleri için gözlem günlüğü de yazılmaz — 48 saatlik yanlış-pozitif ölçümünün kendi test trafiğimizle bozulmasını önlüyor. Katmanın modu değiştirilmemiştir.enforcemoduna geçmeden önce eski ban kayıtlarının temizlenmesi önerilir. -
"Beni hatırla" token'ı artık süre sınırlı ve sunucu tarafında doğrulanıyor (30 gün). Token'ın içine imzalı bir bitiş zamanı gömülüyor; imza mevcut uygulama anahtarı yolundan (HMAC) üretiliyor, yeni bir sır tanımlanmıyor ve veritabanı şeması değişmiyor. Önceden süre yalnızca çerezin ömrüydü; sunucu tarafında "süre doldu mu" denetimi hiç yoktu. Reddedilen bir token için tarayıcıdaki çerez de düşürülüyor. Aynı akışta "beni hatırla" normal kullanıcılarda hiç çalışmıyordu: kullanıcı kaydı e-posta/kullanıcı adıyla aranıyordu, oysa elde olan sayısal kullanıcı kimliğiydi; bu yüzden oturum yalnızca master geliştirici hesaplarında yeniden kurulabiliyordu. Artık kullanıcı kimliğinden getiriliyor. Geçiş: bu sürümden önce üretilmiş süresiz tokenlar 30 gün boyunca kabul edilir, sonra kullanıcıdan yeniden giriş istenir (bkz.
UPGRADING.md). -
Çıkış artık yalnızca çıkış yapan kullanıcının kendi oturumunu kapatıyor. Çıkış akışı, master geliştirici olmayan bir kullanıcı çıktığında da onun numarasıyla eşleşen master geliştirici hesabının "beni hatırla" tokenını siliyordu; yani bir kullanıcının çıkışı başka bir kimliğin oturumunu düşürebiliyordu. Master tokenı artık yalnızca oturum gerçekten o master kimliğiyle açıldıysa temizleniyor. Kullanıcı kimliği her hâlükârda oturumdan okunuyor, istek verisinden değil.
-
Giriş akışı global (master) IP ban listesini artık izliyor — ama engellemiyor. Giriş öncesi ban denetimi yalnızca siteye özel listeye bakıyordu. Global liste de okunuyor, ancak bir kayıt bulunduğunda giriş durdurulmuyor, yalnızca denetim kaydına "would-block" notu düşüyor. Ölçüm bunun için yapıldı: global listede 505 aktif kayıt var ve tamamı yerel IP adresine ait; bağlansaydı tüm yerel sitelerin girişi kapanırdı. Ban kayıtlarının temizliği ayrı bir karardır.
-
QueryBuilder SQL enjeksiyon yüzeyi kapatıldı:
orderBy()yön beyaz listesi, sütun adı kaçışı,updateBatch()placeholder'ları. Sorgu kurucusunun dört ayrı yeri kullanıcı girdisini doğrulamadan SQL'e gömerdi.orderBy()yön parametresi artık yalnızASC/DESCkabul ediyor (başka her değer istisna fırlatır); sütun adlarındaki backtick'lerwrapColumn()içinde ikilenerek kaçılıyor, böylece tırnak kapatma girişimi SQL'i kıramıyor.updateBatch()kimlik değerlerini tırnak içine gömerek yazmak yerine adlandırılmış yer tutucuya geçirdi ve tam sayı olmayan kimliği kaynakta reddetti — katı olmayan sunucu ayarlarında sessizce yanlış satırın güncellenmesi artık mümkün değil.sum()/avg()de artık yalnızca düzsütunya datablo.sütunadı kabul ediyor. Mevcut geçerliorderBy/sum/avg/updateBatchçağrılarının SQL anlamı korunuyor. -
Çerez üreten yardımcılar (
cookie(),rbn_alert) artık HTTPS'teSecureveSameSitebayrağı taşır. Oturum çereziSecure/SameSite/HttpOnlytaşırken framework'ün geri kalan çerez üreticileri bayraksız kalmıştı:cookie()imzasındakibool $secure = falsevarsayılanı her çerezi bayraktan arındırıyordu,rbn_alertçerezi ise hiç bayrak taşımıyordu.Securekararı artık tek kaynaktan (RequestEnvironment::isHttpsRequest(), A0-4 ile aynı) gelir ve düz HTTP'deSecureüretilmez — yerel geliştirme akışı bozulmaz.cookie()imzası sona isteğe bağlıSameSiteparametresi kazanmıştır; konumsal argümanlı mevcut çağıranlar çalışmaya devam eder.rbn_alertçereğindeHttpOnlybilerek yoktur:rbnAlert.jsçereyidocument.cookieile okur,HttpOnlykonulsaydı uyarı gösterilemezdi. -
Yeni parola belirlemede minimum 8 karakter zorunlu (giriş etkilenmez). Parola politikasında taban bir minimum uzunluk yoktu:
CredentialHandler::validatePassword()yalnız yaygın parola kara listesi ve sıra/klavye deseni kontrolü yapıyordu, tek uzunluk kuralı ise form katmanında dağınıkmin:6idi — bu yüzden 6 karakterlik zayıf parola kayıt ve şifre sıfırlama akışlarından geçiyordu. Kural artık tek yerde tanımlı (PasswordValidations::MIN_PASSWORD_LENGTH) ve hem form doğrulaması hem iş kuralı bu sabite bağlı; boş veya yalnızca boşluktan oluşan parola da reddediliyor. Giriş (login) akışı değişmedi: girişte parola uzunluğu denetlenmiyor, mevcut kullanıcıların kısa parolaları geçerli kalıyor. -
E-posta alan adı doğrulaması artık canlı DNS'e bağlı değil. Alan adı, MX kaydı olup olmadığına bakmak için
checkdnsrr()ile canlı DNS sorgusuna gönderiliyordu; PHP bu çağrıya zaman aşımı veremediği için yanıt vermeyen bir çözümleyici isteği — yani kayıt/giriş formunun kritik yolu ile giden e-posta akışını — asılı bırakabiliyor, ayrıca DNS'e bağlı karar zamanlama yan kanalı oluşturuyordu. Karar artık yalnızca e-posta biçimi, alan adı yazımı ve kara listelerine dayanıyor (DNS çağrısı yok); gerçek teslimat denetimi kendi zaman aşımı olan SMTP katmanında yapılıyor. -
IP katmanı ön koşulları kapatıldı: beyaz liste bot kuralını da muaf tutuyor, form ihlali cezası proje kapsamlı, ajan uçları ban/WAF bloklamasından muaftır, WAF istek gövdesini de tarıyor. Dört ayrı düzeltme: (1)
IpGuardHandler::check()içindeip_whitelistdenetimibot_user_agentkuralından sonra geliyordu; yönetici tarafından açıkça eklenen (güvenilir) bir IPsitebotUser-Agent ile geldiğinde yine de engelleniyordu. Beyaz liste kontrolü bot kuralından önceye alındı; beyaz listedeki IP artıkbot_user_agentveip_blacklistkurallarından muaftır. WAF'tan muaf değildir: WAF bir IP itibarı kuralı değil, istek yüzeyi taramasıdır. (2)FormGuardHandler::applyGlobalBlock()kademeli cezayıproject_id = 0(global) olarak yazıyordu; ban denetimiglobal VEYA aktif projekapsamını taradığı için aynı NAT IP'sindeki tüm projeler tek bir form ihlaliyle susturuluyordu (kurban banlanıyordu). Ceza artık bulunulan projenin kapsamında yazılıyor; ban satırının şeması değişmedi (mevcutproject_idkolonu kullanılıyor), kademeli süreler (15 dk / 1 saat / 24 saat) velog_only/enforceayrımı aynen korunuyor. (3)/api/agent/*ve/api/telegram/webhookuçları kendi kimlik doğrulaması ve kendi hız sınırıyla gelen uçlardır; IP katmanı ban/WAF uyguladığında ajan susturuluyordu. Bu iki yol artık IP banı ve WAF bloklamasından muaftır (loglanan tek satır: "muaf: ajan uç"). Muafiyet yalnız bu iki yol grubundadır, IP'ye veya User-Agent'a güvenilmez; yol normalleştirmesi sorgu dizesi ve parçayı atar, kodu çözer,..////\içeren yollar ile büyük harfli yollar fail-closed olarak muaf sayılmaz. (4)IpGuardService::detectAttack()yalnızREQUEST_URI,QUERY_STRINGve$_POST'u tarıyordu;Content-Type: application/jsonile gelen gövde$_POST'a düşmediği için JSON taşıyan saldırılar WAF'a görünmüyordu.php://inputgövdesi de taranır: 64 KB byte sınırı (aşan gövde taranmaz), SQLi için yapısal kalıplar ve path traversal;<script>/javascript:/onerror=gibi XSS kalıpları gövdede uygulanmaz çünkü gövde meşru HTML/JS içeriği taşır (XSS'in asıl yeri form katmanındakiInjectionHandler::detectXss()'tir). 25 örneklik meşru JSON korpusu (panel kaydetme, HTML içerik, Türkçe metin, log satırları) ölçüldü ve hiçbiri engellenmiyor. Gövdefile_get_contents('php://input')ile okunduğu için akış tüketilmez ve controller'ınRequest::getJsonData()okuması bozulmaz. Katmanın modu değiştirilmedi: ölçüm amacıylalog_onlyolarak kalıyor,enforceayrı bir karardır.
Fixed
-
Doğrulama kurallarında
acceptedkuralı eklendi; karşılığı olmayan kural artık sessizce atlanmıyor.Validator::applyRule()eşleşen bir doğrulama metodu bulamayınca hiçbir iz bırakmadan geçiyordu: yazım hatalı ya da framework'te unutulmuş bir kural güvenlik kuralıymış gibi görünüyor, uygulanmıyordu. En görünür sonucu, KVKK açık rıza onay kutularının ('privacy' => 'accepted') sunucu tarafında hiç doğrulanmamasıydı. Artıkacceptedgerçek bir kural (kabul kümesi:on/yes/1/true/accepted; onaylanmayan kutu reddedilir) ve karşılığı olmayan her kuralerror_loguyarısı bırakıpValidator::unknownRules()ile gözlenebilir hâle geliyor. Tarama sonucu karşılığı bulunmayan diğer kurallar da uygulandı:string,array,in,same;nullable/optionalyalnızca tanınmış işaretleyici olarak kaydedildi (mevcut kurallar zaten boş değerde atladığı için davranış değişmedi). Bir canlı kullanımda kural adı yerine rol değeri yazıldığı için bilinmeyen kuralda işlem durdurulmuyor, uyarı verilip devam ediliyor. -
Çözülemeyen middleware'de rota çalıştırılmıyor (
Dispatcher). Bir rotanın middleware'i çözülemediğinde (yüklenmemiş yapılandırma, yanlış ad, silinmiş sınıf) koruma hiç uygulanmadan controller çağrılıyordu;Route::middleware('admin')yazan bir rota,adminçözülemezse yetkisiz kullanıcıyı doğrudan controller'a götürüyordu. Artık çözülemeyen middleware için istek hata ile düşürülüyor ve controller hiç çağrılmıyor. Framework ve projelerde kullanılan tüm middleware adları önceden tarandı ve hepsinin çözülebildiği görüldü; meşru rotaların davranışı değişmedi. -
XSS algılama kalıpları genişletildi.
detectXss()yalnızca iki kalıpla çalışıyordu; ölçülen saldırı vektörlerinin çoğu bu ağdan geçiyordu (scripting şemaları,data:text/htmlyükleri,object/embed/iframe/svgetiketleri,expression()vesrcdoc=). Kalıp kümesi bu vektörleri kapsayacak şekilde genişletildi ve formun tamamı tarandığı için serbest metinde geçen kelimeleri engellememeye özen gösterildi (şema kalıpları yalnızca bağlantı niteliği bağlamında ya da boşluksuz çağrı biçiminde aranıyor; olay nitelikleri yalnızca etiket içinde aranıyor). Ayrıca iç içe dizi gönderilen alanlar (örneğinalan[alt][]) daha önce hiç taranmıyordu; artık özyinelemeli taranıyor. -
checkPrefixGuard()yönlendirmesi güvenli-hedef süzgecinden geçiyor. Panel ön eki değiştiğinde üretilenLocationbaşlığı doğrudan$_SERVER['REQUEST_URI']yolundan kurulup doğrulamasız basılıyordu; bu,RedirectManageriçin eklenen güvenli-hedef kapısından geçen ikinci bir yönlendirme yoluydu. Hedef üretimi saf bir adıma taşındı ve çıktı mevcut güvenli-hedef süzgecinden (guvenliHedef()) geçirildi; yeni bir süzgeç yazılmadı. Güvenli hedef üretilemezse yönlendirme yapılmıyor, mevcut kendini-iyileştirme yolu devreye giriyor. Meşru ön ek yönlendirmesi aynı çalışıyor. -
having()artık var;orWhere()tek başına ve iki argümanla doğru çalışıyor.having()koşuluQueryBuilder'da hiçbir trait'te tanımlı değildi, ama alan taşınıyor ve derleyici kullanıyordu; model katmanındaki proxy bu metoda gittiği için çalışma anında hata veriyordu — metot eklendi ve değerleri bağlanmış yer tutucuya çeviriyor.orWhere()koşulu ilk sırada olduğundaWHERE OR ...biçiminde geçersiz SQL üretiyordu;ORöneki artık konuma göre konuyor (ilk koşulda yok).orWhere('sütun', $değer)iki argümanlı biçim dewhere()ile aynı kuralı uyguluyor (eşitlik); üç argümanlı biçim vewhere()zincirleri önceki anlamını koruyor. -
Giriş hız sınırı sayacı artık CSRF doğrulamasından sonra artar.
FormGuardHandlersayacı CSRF kontrolünden önce güncelliyordu; böylece token'ı olmayan, başka bir siteden gelen çapraz-site bir istek bile kurbanın hız sınırı sayacını tüketebiliyor, kurban doğru bilgileriyle giriş yapamıyordu. Artık "zaten bloklu mu?" kontrolü yerinde kalır, sayacı artıran adım CSRF doğrulamasından sonra çalışır. Geçerli token'lı başarısız giriş denemeleri sayılmaya devam eder; hız sınırının kendisi (5 istek / 900 sn) değişmedi ve zayıflamadı.
Changed
- F-08: Token taşımayan framework form'larına
@csrfeklendi (Backstage E-posta/Ayarlar/Sidebar modalları, Webhub Politika modalı, RbnAdmin kullanıcı rolü + Hostmailhub, RbnStudio Posts/News) ve panel başlığınacsrf-tokenmeta etiketi kondu; böylece CSRF zorunlu hale geldiğinde framework'ün kendi form ve AJAX akışları geçerli bir token taşır.rbnService.jsdeğişmedi: token'ı zaten otomatik ekliyordu, sadece kaynağı (meta[name="csrf-token"]) artık mevcut.
Added
-
Modellerde opsiyonel
$fillable/$guardeddesteği (security.mass_assignment, varsayılan AÇIK). Model bu iki özellikten birini tanımlıyorsacreate()/update()/save()veriyi bu listeye göre süzer ($fillable= beyaz liste,$guarded= kara liste; ikisi birlikte tanımlıysa$fillablebaskın). Tanımlamayan modelde hiçbir şey süzülmez — 81 modelin hiçbiri kırılmadan eklenebilir. Beş güvenlik modeli bu sürümde$guardedtanımı kazandı (bkz. Security). Anahtaroff/false/log_onlyyapılırsa motor tamamen kapanır. -
Korumalı alanlar için log-only izleme (
security.protected_field_log, varsayılan AÇIK). Toplu atamadarole,is_admin,password,password_hash,license_key,project_key,user_idalanlarından biri gelirsesecuritykanalına alan adı yazan bir uyarı düşer; değer yazılmaz (parola sızmaz). Yazma davranışı hiç değişmez — yalnız ölçüm.statusveis_activebilinçli olarak listede değildir (meşru çağıranları kırmamak için). Sayaç yeni tablo gerektirmez:Storage/logs/security/altındakiMASS_ASSIGNMENT_BLOCKsatırları sayılır. -
Database::transaction(callable): başarıda commit, hatada rollback ve istisna yeniden fırlatılır; iç içe çağrılar dış işleme katılır. Model katmanıTransactionModelTrait::transaction()üzerinden uçtan uca çalışır. -
S-1/S-2 birim testi:
E:\tmp\_araclar\fw-regresyon\birim\fw_system_guard_bypass.php(framework içineTests/açılmadı): sorgu parametresine gizlenmiş istisna metni, gerçek statik varlık yolları, boş/doluREMOTE_ADDR, boş beyaz liste kaydı, gerçek VIP/yerel VIP ve CLI yolu senaryoları. Handler yalnız birim seviyesinde, sahte girdilerle sınanır (bakım modu ayarına dokunulmaz, DB yazılmaz). Taban sürümde 7 kontrol kırmızı, düzeltmede yeşil. -
FW-INSTALLER-KALDIR-2: Birim testi
E:\tmp\_araclar\fw-regresyon\birim\fw_installer_kaldir.php(framework içineTests/açılmadı): Installer kalıntı taraması (CHANGELOG/UPGRADING tarihçesi hariç sıfır eşleşme),Installer/klasörü veInstallerStage.phpyokluğu, hayatta kalan üç sınıfın (KernelFactory,SystemHandlers,SystemLogicMapTrait)php -ltemizliği ve autoload ile çözülmesi, bypass'ın yerine yeni kısa yol yazılmadığının kanıtı (BaseStage::isInstallerBypass,BaseGuard::isInstallerBypass,GuardInterfaceimzası yok) ve ölü komut kayıtlarının temizliği. Taban sürümde kırmızı, bu dala geçince yeşil. -
FW-INSTALLER-KALDIR-2:
fw_r1_r2_gomulu_sir.phpR2'nin "installer view bulundu" varsayımı güncellendi: Installer kaldırıldığı için view dosyası yoktur ve gömülü parola imkânı da yoktur; dosya yeniden gelirse içerik taraması yine devreye girer. -
FW-TEK-SECRETS-DOSYASI-161: Birim testi
E:\tmp\_araclar\fw-regresyon\birim\fw_tek_secrets.php: tek dosya okuma (sahte dizinle), eksik alan → adı söyleyen anlamlı hata,CHANGE_ME/boş reddi, kalıntı taraması (koddamaster-secrets.php/cpanel-secrets.php/ gömülü DB adı / host / SMTP host / kullanıcı sabiti yok), şablonda gerçek değer 0,.gitignoresecrets.php'yi kapsıyor ve git tarafından takip edilmiyor. -
FW-TEK-SECRETS-DOSYASI-161:
secrets.example.phpşablonu HER alanı Türkçe yorumla açıklar ("buraya NE yaz, örnek NE"); en üstte 3 satırlık kullanım.Secrets/README.md10 satıra indirildi. -
FW-TEK-SECRETS-DOSYASI-161:
projects/*/Core/Config/project-settings.phpüst yorumlarındaki düz metinuser :/pass :/admin_pass :kalıntıları kaldırıldı (yalnız yorum satırları;returndizisine dokunulmadı, değerler hiçbir çıktıya yazılmadı). -
FW-ENV-KAYIT-160: Ortam değişkenleri / kill-switch'ler artık TEK kapıdan okunur.
Core/System/Config/Env.php(Env::string()/Env::flag()/Env::int()) tek okuyucudur; kaynak sırası$_ENV→$_SERVER→getenvve değerler tembel (bir kez çözülüp önbelleğe alınır). Ağaçtagetenv(geçişi yalnızEnv.phpiçinde kaldı (birim testi kalıntı taramasıyla doğrular). -
FW-ENV-KAYIT-160:
Core/System/Config/Definitions/EnvKeys.php— tümRBN_*/APP_*adlarının TEK kayıt listesi. Her satırtur(string/flag/int),varsayilan,gizli,aciklama,kullanan,onerilen_yeralanlarını taşır. Kayıtsız adEnv'den okunamaz (fail-closedRuntimeException): yazım hatası sessizce "ortam değişkeni yok" sayılmaz. Gizli işaretli adların değeri hata mesajına/loga asla yazılmaz. -
FW-ENV-KAYIT-160:
Core/System/Config/README.md— "Gizli =Secrets, Bayrak/ortam =Env+EnvKeys; yeni anahtar eklemek =EnvKeys'e bir satır" kuralı,EnvAPI'si ve kayıtlı ad tablosu. -
FW-ENV-KAYIT-160: Birim testi
E:\tmp\_araclar\fw-regresyon\birim\fw_env_kayit.php(24 kontrol, 6 küme): (A)getenv(kalıntı taraması, (B) kodda okunan herRBN_*/APP_*adının kayıt kapsamı, (C)Env::flagkapalı listesiShieldSettingsRepository::normalizeSwitch()ile birebir aynı ve 13 girdide aynı karar, (D) kayıtsız ad → fail-closed, (E) gizli ad sızdırmaz, (F) okuma davranışı (kaynak sırası, boş değer,int, tembellik).kabul-kosu.ps1bunu otomatik keşfeder (dokunulmadı). -
FW-SIRLAR-TEK-CIKIS-149: Sırlar tek çıkıştan okunur:
Secrets::masterDb(),::smtp(),::cpanel(),::api($ad),::section($ad),::appKey(). Yeni dış servis (ödeme/SMS) eklemek artık ikinci bir sır dosyası değil,secrets.phpiçindekiapibölümüne bir satır eklemektir. Sır dosyasınırequireeden başka yer yoktur (kalıntı taraması bunu doğrular). -
FW-SIRLAR-TEK-CIKIS-149: Bölümlü tek sır dosyası
Core/System/Config/Secrets/secrets.php(bölümler:master_db,smtp,cpanel,api, üst düzeyapp_key) ve gerçek değer içermeyen şablonusecrets.example.php. Geçiş isteğe bağlıdır:secrets.phpvarsa tek başına okunur; yoksa mevcutmaster-secrets.php+cpanel-secrets.phpçalışmaya devam eder (sıfır kesinti, sır rotasyonu yok). Yayın sırası ve geçiş tuzağı:.github/UPGRADING.md→ 0.9.0 Adım 7. -
Core/System/Config/Definitions/ConfigFile.php+ConfigFileLoadertrait'i: dosya teknikleri (bul → 0600 izin kontrolü →<?php/returnbiçim kontrolü →require→ dizi/anahtar doğrulama → tembel önbellek) tek yazımda toplandı;SecretsveConfigFileaynı mantığı paylaşır. Hata mesajlarında hiçbir sır değeri yazılmaz (yalnız dosya/bölüm/anahtar adı).Secrets.phpkomsu dosyarequireetmez; bootstrap'ta ve izole kopyada tek başına çalışır. -
Birim testi
E:\tmp\_araclar\fw-regresyon\birim\fw_sirlar_tek_cikis.php(41 kontrol): kalıntı taraması, şablonda gerçek değer 0, gerçek sır dosyalarının git'e takip edilmemesi (check-ignore+ls-files), bölümlü okuma, eski iki dosya geriye uyumu, öncelik kuralı, fail-closed (eksik dosya/bölüm/anahtar,CHANGE_ME, boş değer) ve hata mesajında sır sızdırmama ölçümleri — hepsi sahte dizinle. -
Core/System/Config/Secretsaltında fail-closed çalışan sır okuyucusu (Config/Secrets.php): master veritabanı ve master SMTP parolaları artık kaynak kodda değil, ayrı bir sır dosyasından okunur. Okuyucu dosyayı bulamazsa veya gerekli anahtarlardan biri eksikse hata fırlatır; boş değere sessizce düşmez. -
Core/System/Config/Secrets/master-secrets.example.php— gerçek değer içermeyen şablon (yer tutucu). Gerçek sır dosyası bu şablon kopyalanarak sunucuda oluşturulur. -
Core/System/Config/Secrets/README.md— sır dosyasının ne olduğu, nasıl oluşturulacağı, dosya izni ve "depoya girmez" kuralı. -
Core/System/Config/Definitions/DbProfiles/README.md— veritabanı kimlik profilleri klasörünün ne olduğu, hangi sınıf ne yapar, neden koruma katmanında değil, kim kullanır (klasör standardı: ne girer / ne girmez / nereye yazılır). -
.gitignorekuralı: gerçek sır dosyası sürüm takibine girmez; şablon ve açıklama dosyası girer. Yayın paketi gerçek sır dosyasını içermez. -
Yönlendirme doğrulaması:
redirect()artık yalnızca beyaz listedeki site içi hedeflere izin verir, liste proje taban adresi + proje grubunun kendi alan adlarından oluşur. Reddedilen hedefler site içi güvenli adrese düşer. -
Form korumasında kademeli ceza: kalıcı uzun süreli engelleme yerine ihlal sayısına göre artan süreli kademeler; yeni tablo/kolon eklenmedi.
-
IP güvenlik katmanı için
shield_ip_guard_modeçalışma modu ayarı (log_only/enforce; varsayılanlog_only) ve buna bağlıStorage/logs/ipguard/altınawould-blockkaydı. Mod ayarı tek yerde tutulur. -
Core/System/Config/Secrets/cpanel-secrets.example.php- gercek deger icermeyen sablon (yer tutucu). Gercek dosya bu sablon kopyalanarak sunucuda olusturulur ve depoya girmez. -
Kabul testi
E:\tmp\_araclar\fw-regresyon\kabul\B1-cpanel-sir-koddan-cikar.php(B1 kalemi): kaynak kodda gomulu cPanel kimlik bilgisi olmamasi, tek kapi kurali ve fail-closed davranisi. -
Tek kullanimlik, sureli e-posta dogrulama ve parola sifirlama token kasasi (
Core/Database/Models/Project/UserTokenModel.php+Core/Database/Repositories/Project/UserTokenRepository.php, tabloz_user_tokens). Ham token veritabaninda saklanmaz; yalnizca ozeti tutulur, kullanim aninda mumkun olmayan sekilde denetlenir ve her satiri kullanim/sure bilgisi tasir. Kayitproject.userTokengirdisiyle tek merkezden yapilir. Migrasyon:111-z_user_tokens.sql(koddan once calistirilir). -
Parola sifirlama formu gonderimine token alani eklendi; sifre yenileme sayfasi gecerli bir baglanti olmadan form gostermez.
-
Lisans kapısı doğrudan
licencestablosundan (FW-LICENCE-G): Ara katmanLicenceGatekaldırıldı;DatabaseGuardHandlerartık proje kimliğiyleMasterLicencesService::forSubject()üzerinden lisans kaydını okur. Metin tabanlı anahtar kontrolü (projects.license_keyiçinde serbest arama) kaldırıldı. Kural:tier=FREE+status=active+ süresi dolmamış kayıt kısıtsızdır; kayıt yok, okunamıyor veya servis hatası durumunda ücretsiz sayılmaz ve proje durum kontrolü uygulanır (fail-closed, hata günlüğe yazılır, anahtar değeri hiçbir yere yazılmaz).projects.license_keysütunu değişmedi. -
Merkezi lisans (PARÇA B — servis katmanı): Yeni
MasterLicencesService(karar katmanı;verify,issue,revoke,forSubject) veMasterApplicationsService(getByAppKey,list,register,setCurrentVersion) eklendi; ikisi de yalnız repository üzerinden çalışır, veritabanına doğrudan erişmez. Veri erişimiMasterLicenceRepository/MasterApplicationRepositorysözleşmelerine birebir uyar.Data/MasterLicenceConfig.phpyalnızca sabit tutar (metot içermez); lisans durumları, kademeler (FREE/LIFETIME/PRO), özne türleri, anahtar öneki ve fail-closed doğrulama sebepleri buradan gelir. Doğrulama fail-closed: bilinmeyen anahtar, dondurulmuş/iptal kayıt, süresi dolmuş kayıt ve depolama hatası geçersiz sonuç verir; anahtar üretimiRBN-XXXX-XXXX-XXXX-XXXXbiçiminde ve benzersizlik için en çok 5 denemede yapılır. -
Merkezi lisans (PARÇA A — tablolar + migration + repository): Master veritabanına
applicationsvelicencestabloları eklendi; TEK 3 tablo kuralı (proje + uygulama aynı sistem),application_licenses/application_releases/application_installations/application_audit_logyok.projectstablosundan hiçbir sütun kaldırılmadı. Yeni migration yolu:Core/Database/Migrations/Master/+MasterMigrationService(kayıt tablosumaster_migrations); asla otomatik çalışmaz, yalnız ellerbn master:migrate [--rollback]verbn master:migrate:status. Aynı migrationprojects.license_keydeğerlerinilicencestablosuna kopyalar (tier ön eki kuralı:RBN-LIFETIME-→LIFETIME,RBN-FREE-/FREE-OSS→FREE, diğer →PRO;suspendeddışındaki her durum →active; boş anahtar → satır yazılmaz, adet raporlanır). Sürüm ürüne aittir:projects.versionveapplications.current_versionkalır,licences'ta sürüm sütunu yoktur. Yeni veri katmanı:MasterLicenceModel/MasterApplicationModel+MasterLicenceRepository(findByKey,findForSubject,create,updateStatus,bindDevice,isKeyUnique,list) veMasterApplicationRepository(findByAppKey,list,create,updateVersion), registry alias'larımaster.licence/master.application. Yazım kuralı:Licence(İngilizce) her yerde — tablolicences, sütunlicence_key, sınıfMasterLicenceRepository. Anahtarlar veritabanında saklanır; ed25519/imza/anahtar klasörü kalıbı yok. -
Yazım düzeltmesi (proje sahibi kararı): Yazılım lisansı yazımı İngilizce
Licenceolarak tekilleştirildi.Core/Services/Gatekeepers/LicenseGate.php→LicenceGate.php(sınıfLicenseGate→LicenceGate,git mvile), değişken$licenseKey→$licenceKey. Davranış, ölçüt ve veritabanı sütun adı değişmedi:projects.license_keysütunu ve'license_key'dizi anahtarı/sorgu dizeleri AYNEN kalır. -
Kimlik/sürüm verisi TEK merkezde: RbnShield, RbnAdmin ve RbnAuth ad/sürüm/slogan bilgileri
Support/Definitions/System/FrameworkIdentityiçine toplandı (SHIELD_*,ADMIN_*,AUTH_*);ShieldMetadata/PanelIdentity/AuthIdentityiçindeki kopyaNAME/VERSION/SLOGAN/TITLEsabitleri kaldırıldı; okuyanlar (AuthHandler,PanelHandler,ModuleData,BaseExceptionProvider,SurvivalProvider) merkezden okur; görünümlerRbnSystemInfo::get(...)ile aynı kaynağa bağlı. -
Hosting verisi (proje sahibi düzeni):
Core/Services/Hosting/Data/CpanelData.phpartık yalnız SABİT taşır (DEFAULT_QUOTA,DESTINATIONS; metot yok); kimlik okumaCPanelProvideriçinde (host()), dışarıyaCPanelService::host()ile açılır (ayrı sınıf yok);Hosting/Modelskalktı. -
Config yapısı (proje sahibi düzeni):
Engine/Database/klasörü eklendi (DatabaseConfig,DbProfileResolver,SmtpProfileResolver);BaseDbDataKALDIRILDI;MasterDbData/CommonDbData/ProjectDbDataartık hiçbir sınıftan türemez (final class, yalnızpublic const);ProjectDataMapperprofil kontrolü açık listeyle yapılır.
Changed
-
FW-TEK-SECRETS-DOSYASI-161 (KIRICI): Sunucuda TEK dosya:
secrets.php(eski 3 adımın yerine).Core/System/Config/Secrets/secrets.phpTEK sır dosyasıdır; bölümleri düz ve hepsi opsiyonel değil zorunludur:master_db{host, port, name, user, pass},smtp{enabled, host, port, secure, user, pass, from_address, from_name},cpanel{host, user, token},app_key,api{hizmet => alanlar}. Eskimaster-secrets.php+cpanel-secrets.phpdosyaları, "geriye uyum" kipi veMASTER_DB_USER/MASTER_DB_PASS/APP_KEYortam değişkeni ile geçersiz kılma yolları TAMAMEN KALDIRILDI (üç yol yerine tek yol). Canlı sunucuda sır dosyası yoktur; operatörsecrets.example.php'ten kopyalar. Yayın sırası ve komutlar:.github/UPGRADING.md→ 0.9.0 Adım 8. -
FW-TEK-SECRETS-DOSYASI-161 (KIRICI):
MasterDbDataiçindeki gömülü bağlantı sabitleriDB_NAME,SMTP_ENABLED,SMTP_HOST,SMTP_PORT,SMTP_USER,EMAIL_FROM_ADDRESS,EMAIL_FROM_NAMEKALDIRILDI; hepsi artıkSecrets::masterDb()/Secrets::smtp()üzerinden metotla okunur (host(),port(),dbName(),user(),pass(),smtpEnabled(),smtpHost(),smtpPort(),smtpSecure(),smtpUser(),smtpPass(),emailFromAddress(),emailFromName()).MasterDbData::DB_NAMEkullanan çağıranlardbName()'a geçirildi (CronLogRepository,SystemHandlers,EmailConfigHandler). Proje veritabanı dokunulmadı: her proje kendiproject-settings.phpdosyasından okumaya devam eder. -
FW-TEK-SECRETS-DOSYASI-161: Fail-closed hata metni artık alan adını söyler ve değeri yazmaz:
secrets.php: master_db.user tanimli degil. Üç yönlendirme (klasör + iki eski dosya + "isteğe bağlı geçiş") satırı kaldırıldı. -
FW-CONFIG-YAPISI (güvenlik incelemesi): Ortak dosya tekniği
Secrets.php'tenEngine/'ye taşındı.Engine/ConfigFileGuard.php(izin tavanı 0600 +<?php/returnsızıntı kontrolü + operatör yol/ipucu üretimi) veEngine/ConfigFileLoader.php(bul →require→ dizi doğrula → anahtar doğrula → tembel önbellek) ayrı trait'ler oldu; ikincisi birincisiniuseeder.Secrets.phpbunları görelirequire_onceile yükler (otoloader henüz hazır olmayan kernel/bootstrap aşaması ve izole dizin kopyaları için zorunlu). Gece yazılmış Türkçe metot adları İngilizceye çevrildi:sablonYolu()→examplePath(),ipucu()→hint(),izinTavani()→permissionCeiling(),ilkReturnKonumu()→firstReturnPosition(),onbellekAnahtari()→cacheKey(). Davranış birebir aynıdır (aynı hata metinleri, aynı fail-closed davranışı, aynı önbellek). -
FW-CONFIG-YAPISI (güvenlik incelemesi):
Secrets.phpİNCE CEPHEYE bölündü (1009 → 249 satır). Sorumluluklar ayrıldı:Definitions/SecretsSchema.php(yalnızpublic const, metot yok — alan adları, izin tavanı 0600,CHANGE_MEişaretçisi, bölüm kuralları),Engine/SecretsLoader.php(yol çözümü + ham dosya okuma; TEK okuma kapısı),Engine/SecretsValidator.php(bölüm adı biçimi + "var ama okunamıyor" ayrımı),Engine/SecretsSections.php(bölüm okuma/doğrulama + düz anahtar haritaları),Engine/SecretsFlatApi.php(eski düz anahtar yüzeyiall()/get()/optional()/masterDbPass()/masterSmtpPass(); trait olarakSecretsüzerindeuseedildiği için imzalar korunur).Secrets::masterDb()/smtp()/cpanel()/api()/appKey()/section()imzaları değişmedi, çağıranlar kırılmaz. Hiçbir `Config/dosyası 250 satırı geçmiyor.** Gece yazılmış Türkçe kod adları (hepsi,ipucu,sablonYolu,izinTavani,ilkReturnKonumu,onbellekAnahtari,bolumAdiDogrula,okunabilirDogrula,ustDuzEkler,gevsekDuz,apiTum,ham`) İngilizceye çevrildi. Davranış birebir aynıdır — aynı fail-closed hata mesajları; hata metinlerinde hiçbir sır değeri yazılmaz. -
FW-ENV-KAYIT-160:
getenv(/$_ENV/$_SERVERile ortam değişkeni okuyan 11 noktaEnv'e taşındı (davranış korunarak):CryptoHelper::ortamDegiskeni(),BaseDbData::ortamDegiskeni()(MASTER_DB_*/COMMON_DB_*/DB_*),SystemGuardHandler::resolveFailClosed()(RBN_GUARD_FAILCLOSED),PreBoot::envOverrideRequested()(RBN_DEBUG/RBN_DEV),AiUsageManager+rbnCLI +DebugHelper(APP_ENV),MediaIngestService(RBN_UPLOADS_DIR,RBN_UPLOADS_URL_BASE), bir proje modülünün jeton/dizin okumaları (ilgili ortam değişkenleri veREDIRECT_önekli yedekleri artık kayıtlı ad; sonradan kaldırıldı, bkz.[0.9.4]), Telegram test router'ı (TG_SEND_DELAY_MS). -
FW-ENV-KAYIT-160 (fail-closed / kill-switch semantiği DEĞİŞMEDİ):
RBN_GUARD_FAILCLOSEDartıkEnv::flag($ad, true)ile okunur — tanımsız/boş →true(fail-closed),0|false|off|no|hayir→false; yorum yine TEK merkezden (normalizeSwitch) gelir, ikinci bir parser yazılmadı.RBN_DEBUG/RBN_DEVbilerekEnv::flagDEĞİL, kendi1|true|on|yes|developmentlistesiyle okunmaya devam eder: bu kapının varsayılanı KAPALI'dır,normalizeSwitch"belirsiz → AÇIK" dediği için kullanılsa hata ayıklama modu yazım hatasıyla açılırdı.RBN_ALLOW_LEGACY_SALTde eski 4-değerlik listesiyle korundu (geriye uyum). A0-2, A0-3, R1/R2 öncelik sıraları veSecretsbölümü ↔Envilişkisi değişmedi. -
FW-SIRLAR-TEK-CIKIS-149: Çağıranlar yeni çıkışlara taşındı —
MasterDbData::pass()→Secrets::masterDb()['pass'],::smtpPass()→Secrets::smtp()['pass'],CommonDbData::pass()master'a düşerkenSecrets::masterDb()['pass'],CpanelData::host()/user()/token()/credentials()→Secrets::section('cpanel'). Geriye uyum:all(),get(),masterDbPass(),masterSmtpPass(),optional(),cpanel(),cpanelHost(),cpanelUser(),cpanelToken()isimleri ve davranışları korundu;Secrets::cpanel()dizisinincpanel_host/cpanel_user/cpanel_tokenanahtarları değiştirilmedi (kabul testi bunu sabitler) — kanonik bölüm biçimisection('cpanel')üzerinden okunur. Ortam değişkeni önceliği (MASTER_DB_PASS,COMMON_DB_PASS) ve bağlantı şeması değişmedi. -
Entegrasyon (integ/fw-asama0): A0-8 (gömülü DB parola/kullanıcı sabitlerinin kaldırılması) ve A0-9 (
@importkök sınırı) kalemlerifeat/fw-a0-8-9-sirlar-viewimportdalından--no-ffile birleştirildi; yukarıdaki iki madde bu birleşimle geldi. Değişen PHP dosyalarındaphp -ltemiz,fw-regresyon/birimpaketi 8/8 yeşil. -
A0-9 / R-02:
ViewEngine::path()veViewEngine::compile()artık kök sınırı denetler:realpath()+..normalizasyonu sonrası çözülen yol, ilgili tipin kök dizini (proje / framework / public / modül / suite) dışına çıkıyorsaRuntimeExceptionile reddedilir.@importartıkViewEngine::import()üzerinden tek güvenli girişten geçer (ViewConfig).@import('../../../../evil.php')ile kök dışı dosyarequireedilemez. Kırıcı: geçersiz bir view yolu artık sessizce boş/yarım sayfa yerine kontrollü hata üretir. -
A0-8:
BaseDbData/CommonDbData/ProjectDbDataiçindeki gömülüPASSsabitleri veMasterDbData/CommonDbDataiçindekiUSERsabitleri kaldırıldı. Parolapass()(ortam değişkeni →Secrets::→ fail-closed), kullanıcı adıuser()(ortam değişkeni →Secrets::optional()→ en az ayarlanmış varsayılan) üzerinden tek çıkıştan okunur.Secrets::optional()opsiyonel kimlik anahtarları için eklendi (zorunlu sırlar fail-closed kalır). Bağlantı şeması (anahtar adları ve sırası) değişmedi. -
MasterDbDataartık gömülü parola sabitlerini taşımıyor; veritabanı ve SMTP parolalarını sır okuyucusundan alıyor. Bağlantı şeması (anahtar adları ve sırası) değişmedi; projelerin kendi*DbDatasınıfları sır dosyasına bağımlı değil, davranışları aynen korundu. -
IP güvenlik katmanı artık log-only modda çalışıyor: kararı üretir ve kaydeder, ancak hiçbir isteği engellemez.
enforcemodu ayrı bir yayın olarak etkinleştirilir; o zamana kadar kullanıcı etkilenmez. -
Kara liste/beyaz liste sorguları
group()yerine desteklenen iç içe koşul biçimini kullanıyor; hız sınırı ayarı okuması kayıtlı ayar deposu üzerinden yapılıyor. -
Mail yapılandırması master SMTP parolasını sabit yerine erişim metot üzerinden okuyor. Projenin kendi SMTP yapılandırması varsa master sırına başvurulmuyor (davranış değişmedi).
-
Kaynak kodda parola yazan yorum satırları kaldırıldı; sürüm takibinde çalışma ağacında gömülü sır eşleşmesi 0.
-
Dört veritabanı kimlik sınıfı (
BaseDbData,CommonDbData,MasterDbData,ProjectDbData)Core/Services/Gatekeepers/Models/→Core/System/Config/Definitions/DbProfiles/altına taşındı; ad alanlarıRbn\Framework\Core\System\Config\Definitions\DbProfilesoldu. Sınıf adları değişmedi, bağlantı şeması ve tüm sabitler aynen duruyor. Taşımanın nedeni mimari: bu sınıflar kimlik/yapılandırma verisidir (koruma mantığı değil) ve çekirdek katman onları üst katmandan çağırıyordu; bu bağımlılık yönü giderildi. -
cPanel kimlik bilgisi (sunucu, kullanici, API tokeni/parola) artik kaynak kodda sabit degil;
Core/System/Config/Secrets/cpanel-secrets.phpdosyasindan okunur.CpanelDataicindekiHOST/USER/TOKENsabitleri yerine ayni adlari tasiyanhost()/user()/token()erisim metotlari kullanilir. Sir dosyasi tembel (gecikmeli) yuklenir: bir cPanel islevi cagrilana kadar okunmaz, bu yuzden cPanel kullanmayan siteler bu dosyaya ihtiyac duymaz. -
cPanel baglantisini kuran
CPanelProviderkimlik bilgilerini acilista degil, ilk gercek kullanimda cozer. Sir dosyasi eksik veya eksik anahtar iceriyorsa cPanel islevi acik hata verir; sessizce yapilandirilamis sayilmaz.
Fixed
-
G-03: Syshub bakım modu anahtarı ve zorlayıcı katman artık aynı kuralla (
ShieldSettingsRepository::normalizeSwitch(), fail-closed) yorumlanır. Önceden panel=== 'on'ile, zorlayıcı katman normalizasyonla bakıyordu; aynı değer iki zıt karara dönüşüyordu. Bakım ayarı okuması/yazması tek doğruluk kaynağı olanShieldSettingsRepository'ye taşındı; yazma sonrası ayar önbelleği düşürülür. Zorlayıcı katmanın kararı değiştirilmedi. -
G-02: Bakım moduna beyaz liste IP'si ekleme ekranı çalışıyor: kayıt defterinde olmayan bir model takma adı çağrısı kaldırıldı (çağrı sessizce boş sonuç dönüyordu).
-
FW-DB-2 (D-01): Hazırlanmış ifade önbelleği anahtarı PDO nesne kimliğini içerir: bağlantı değişince eski bağlantının ifadesi kullanılmaz.
-
FW-DB-1 (D-02): QueryBuilder
increment()/decrement()artıkSQLSTATE[HY093]vermiyor. Sayaç miktarı konumsal?yerine adlandırılmış yer tutucu ile gider;SETveWHEREparametreleri adla eşleştiği için karışmıyor. Model katmanındaki atomik sayaçlar (view count, hit sayacı vb.) çalışır duruma geldi. -
FW-DB-1 (B-26): QueryBuilder
update()/updateAffected()WHERE'siz çağrıldığında hata verir.delete()ile aynı güvenlik sözleşmesi paylaşılır. Dönüş sözleşmesi korunur:update()her zamanbool truedöner (0 satırda da), etkilenen satır sayısıupdateAffected()ile alınır. -
Mevcut projeler lisans tablosuna LIFETIME olarak kopyalanır (önek tahmini kaldırıldı);
verify()expired/revoked/suspended durumunu tarihten bağımsız geçersiz sayar -
Veritabanı kimlik bilgisi okuma yolu, master sır dosyası yoksa sessizce boş değere düşmek yerine açık hata veriyor. (Bu, tüm sitelerin aynı anda devreye girmesini engelleyen "güvenli kapalı" davranıştır; doğrulandı.)
-
Sır dosyasındaki eksik anahtar, tip uyuşmazlığı ve okunamayan dosya durumları ayrı ayrı teşhis edilen hatalara dönüştür; "boş proje" gibi yanlış okuma üretmez.
-
IP güvenlik katmanının kullandığı ayar sağlayıcısı ve model adları kayıt defterine eklendi; bu katman artık okuma zincirini kurabiliyor. Daha önce hiçbir istekte etkin değildi.
-
IP katmanının kendi hata yakalama kolonu artık hatayı kayda geçiriyor; önceki sessiz davranış kaldırıldı.
-
robots.txtgerçek sayfa ön eklerini engellemiyor:/sayfasaldırı tarayıcı tuzağı listelerinden çıkarıldı, böylece yasal/içerik sayfaları arama motorlarına ve AdSense'e açık kalıyor. -
robots.txtsitemap adreslerini ve gizli yönetim yolunu içermez. -
Hız sınırı, geçersiz veya eylem adı dışı bir çağrıda sessizce devre dışı kalmıyor; kanalizasyon tek noktadan yürüyor.
-
Oturum çerezi bayrakları (oturum sabitleme karşı önlemi) artık istek başına yeniden üretiliyor.
-
Tarihçe (artık geçerli değil): Lisans kapısı bir ara dönemde ürün adı/ön eki beyaz listesine (
FREE-OSS/RBN-FREE-) dayanıyordu; bu yaklaşım kaldırıldı. Karar artıklicencestablosundaki kayda (tier+status+ süre) göre verilir. -
İstemci tarafı yönlendirme koruması (AJAX/JS) ve tek kademeli kaynak doğrulaması eklendi.
-
E-posta dogrulama ve parola sifirlama baglantilari artik tek kullanimlik ve sureli: dogrulama 24 saat, sifre sifirlama 60 dakika gecerli; kullanilmis, iptal edilmis veya suresi dolmus baglantilar yeniden kullanilamaz. Ayni kullanici icin uretilen yeni bir baglanti, o amactaki bekleyen baglantilari gecersiz kilar. Yeni bir baglanti uretildiginde eski baglantilar gecersiz sayilir; mevcut ve daha once dogrulanmis hesaplar etkilenmez.
-
Parola sifirlama isteginin sonucu, hesabin kayitli olup olmadigindan bagimsiz olarak ayni mesaji dondurur; boylece kullanici sayimina (enumeration) dayali bilgi sizmaz.
-
Sifre yenileme formu gonderimi artik kisisel bilgi koruma (CSRF) dogrulamasi ve hiz siniri uygular; hiz siniri eylem adi gecerli adim listesiyle eslesti, bu yuzden sinir gercekten devreye giriyor.
-
Sifre degisince o kullaniciya ait "beni hatirla" isareti gecersiz kilinir.
-
Dogrulama ve sifirlama baglantilari bos, hatali veya suresi dolmus ise kullaniciya acik hata gosterilir; hata sayfasi uretilmez.
-
B-2 — bilinmeyen hiz siniri eylemi 500 degil:
RateLimitValidations::getLimit()veRateLimitHandlertarafinda eylem adi tanim listesinde yoksa daha onceInvalidArgumentExceptionfirlatiliyordu; bu istisna framework hata sayfasina dustugu icin bilinmeyen bir eylem adi 500 uretiyordu. Artik tanimsiz eylem guvenli tavana (safe ceiling) normalize edilir;isBlocked()istisna atmaz ve limitsiz kalmaz. Geriye donuk yazim tutarliligi icinrecoveryvepassword_resetayni kanonik kovada sayilir (cift sayim olmaz). Geliştirici API (getLimit()) geçersiz argümanda fırlatmaya devam eder — çalışma zamanı yolu ile API yolu bilinçli olarak ayrıdır. -
B-3 — tek kullanimlik token mührü atomik:
UserTokenRepository::consume()istegi onceSELECTedip sonraUPDATEediyordu; eszamanli iki istek ayni tokeni iki kez gecebiliyordu. Artik kosulluUPDATEtek bir ifadeyle calisiyor veCrudTrait::updateAffected()eklenerek etkilenen satir sayisi (0/1) olculebiliyor. Kural: kosulsuz UPDATE yazmaz. Yarista ikinci istek 0 satir etkilendigi icin basarisiz olur. -
Y-4 — başı
/olmayan göreli redirect hedefleri mutlak yola çevriliyor:dashboard/x,sayfa/ekle,iletisimgibi göreli hedefler daha önce güvenli varsayılana (/) düşüyordu — kullanıcı sessizce ana sayfaya gidiyordu. Artık mutlak yola normalize ediliyor. Atlatma listesi korunuyor://,\,javascript:,@, CRLF, açık port içeren girdiler yine reddediliyor; beyaz listeye giren aynı-origin hedefler geçiyor. DüzeltmeRedirectTraitiçinde tek choke noktasında yapıldı —redirect()ve AJAX JSON yolu aynıguvenliHedef()süzgecinden geçiyor. -
B-5 — boş beyaz listede 301 yazılmıyor (kalıcı önbellek riski):
RedirectManager::redirect()beyaz liste boşken hedefi denetimden geçirmeden 301 yazıyordu; bu durumda yönlendirme kalıcı olarak istemci/ara katman önbelleğine alınıyordu ve sonradan düzeltilemiyordu. Artık boş beyaz listede kural uygulanabilirliği denetleniyor ve yanlış kabul edilmiş hedef yazılmıyor. -
B-10 — IP kill-switch yönü düzeltildi: IP koruma ayarı okunamıyordu; önceki yol "okuma hatası"yı "koruma kapalı" olarak yorumluyordu, yani ayar bozulduğunda koruma sessizce kapanıyordu (fail-open). Artık okunamayan ayar korumayı kapatmıyor; "kapalı" anlamına gelen degerler tek bir liste üzerinden belirleniyor, böylece listeye eklenmeyen her deger korumayı açar durumda kalıyor.
-
A0-6 — token/recovery akislarindaki 500 kapatildi (fail-closed + jenerik hata + 302):
Bundles/RbnSuite/RbnAuth/Services/RecoveryService.phpicinde veritabanina dokunan dort nokta (findByIdentity,reset,verify,peek,consume)try/catchile sarildi. Sema uyumsuzlugu / eksik kolon / erisim hatasi artik framework'un gelistirme hata sayfasina dusmuyor; kullanicinin gormesi mumkun olan jenerik mesaj donuyor vehandleResult302 yonlendirmesi yapiyor. Davranis degisikligi: kullanici var/yok bilgisi sizmaz (A-26), istek "gonderildi" gorunur, yalnizca token uretilmez. YakalanmayanThrowablesessizce yutulmaz — belirtilen hata mesaji (password_recovery/email_verification) kullaniciya gider. Kirici: token akislari sema hatasinda da eski hata sayfasi yerine yonlendirme donuyor. -
Lisans geçerlilik kuralı tek yerde toplandı: bozuk
expires_atdeğeri veNULLstatus/tieralanları artık kısıtlı veya geçersiz sayılır (fail-closed); daha önce tarih çözümlenemediğinde kayıt süresiz sayılabiliyordu. Eksik/bozuk kayıt ücretsiz (kısıtsız) sayılmaz, proje durum kontrolüne girer. -
licencestablosunda(subject_type, subject_id)UNIQUE: aynı özne için ikinci bir lisans satırı yazılması veritabanı düzeyinde engellenir; karar katmanının "hangi kayıt geçerli" sorusu tekilleşir. -
Rutin lisans kısıtlaması günlüğe yazılmaz: beklenen "kısıtlı" kararları log gürültüsü üretmiyor; yalnız anormal durumlar (kayıt yok, okunamıyor, şema hatası) günlüğe geçiyor.
Security
-
F-08: Developer/master-developer rolleri artık CSRF doğrulamasından muaf değildir; tüm roller token ile doğrulanır.
CsrfHandler::verify()içindeki "developer bypass" bloğu kaldırıldı veFormGuardHandler::audit()bu rollere verdiği diğer koruma muafiyetlerini (bot/orijin/user-agent/hız sınırı) korurken CSRF adımını artık atlamaz. Token üretimi, geçerlilik süresi ve diğer rollerin davranışı değişmedi; doğrulama fail-closed'dur (token yoksa/yanlışsa/süresi dolmuşsa istek reddedilir). Etki:developer,admin,superadminve master-developer oturumuyla açılan bir tarayıcı, artık kurbanın tarayıcısı üzerinden CSRF ile işlem yaptıramaz. -
FW-DB-1: Sorgu katmanındaki toplu yazma yolu kapatıldı: WHERE koşulu yazılmadan
update(),updateAffected(),increment()veyadecrement()çağrıldığında istek hata ile durur ve hiçbir satır değişmez. Böylece tek bir eksik koşul tablonun tamamını ya da tüm sayaçları yanlışlıkla değiştiremiyor. -
FW-INSTALLER-KALDIR-2: İstek adresi içeriğine bağlı olan ve bir alt dizgeye göre karar veren Installer bypass kaldırıldı; çekirdek tanılamalar (asset, bakım, izin, sistem, shield, veritabanı) artık yalnızca kendi gerçek koşullarında çalışır ve istisna durumunda kapatılan yönde davranır.
-
SystemGuardHandleristisna ve IP kuralları sıkılaştırıldı: (1) framework/proje statik varlık istisnası artık yalnız URL yolunun başına bakar (parse_url(..., PHP_URL_PATH)+ önek eşleşmesi,AssetDoctorile aynı kalıp); sorgu parametresi içine gizlenen bir istisna metni bakım modunu ve VIP kontrolünü atlamıyor. (2)REMOTE_ADDRboşsa istek artık VIP sayılmıyor — daha önce istek hiç reddedilmeden bakım ve VIP kontrolü atlanıyordu; boş IP fail-closed yönde ilerler (bakım açıkken engellenir, kapalıyken serbest kalır). Konsol/cron yolu (PHP_SAPI === 'cli', ör.master:migrate) eski davranışını korur. Kritik yol (/auth,/rbn-admin,/api, dashboard öneki) eşlemesi de ham adres yerine yola çevrildi. Davranış değişikliği yalnız daha kapalı yöndedir: gerçek statik varlık ve gerçek VIP istekleri değişmedi. -
Hata ayıklama modu ortam tespiti sertleştirildi; hata sayfasında hassas alanlar maskelendi
-
Kaynak koda gömülü veritabanı ve SMTP parolaları framework dışına çıkarıldı ve sır dosyasına taşındı (sır okuyucu fail-closed).
-
IP güvenlik katmanı okuma zinciri düzeltildi ve etkinleştirildi. Durum: log-only — ilk sürüm kararı üretip kaydeder, hiçbir isteği engellemez; gerçek engelleme ayrı bir ayrı yayın olarak etkinleştirilir.
-
Veritabanı parolası sabiti (
PASS) artık dışarıdan okunamaz: parolaya yalnızcapass()erişim metodu üzerinden ulaşılır. Daha önce alt sınıflar bu sabiti miras yoluyla sessizce boş değere düşürebiliyordu. -
Açık yönlendirme doğrulaması sertleştirildi (aynı-origin beyaz listesi, çoklu alan adı destekli). Durum: bekliyor — yamalar çalışma ağacında hazır ve testli, ancak sürüm takibine commit edilmedi; yayın öncesi commit + kabul testi zorunlu.
-
Form koruması kalıcı uzun engelleme yerine kademeli cezaya geçirildi (yanlış pozitif ve meşru kullanıcı kilitlenmesi riskini azaltır). Durum: bekliyor — commit edilmemiş.
-
Açık yönlendirme koruması medya/JS isteklerine de uygulanıyor; yönlendirme tek kademeli kaynak doğrulamasıyla sınırlandırıldı.
-
Tarihçe (artık geçerli değil): Lisans kapısının kapsam dışı paketleri geçirmemesi bir ara beyaz listeyle sağlanıyordu; bu yöntem kaldırıldı ve yerini tablo tabanlı geçerlilik kontrolüne bıraktı.
-
PermissionDoctorkullanılmayan zorunlu kod katmanı klasörlerini açmıyor; çalışma zamanı katmanları (Storage, public) korunarak her zaman açılıyor, mevcut klasörler silinmiyor. -
R1 — fail-closed şifreleme tuzu:
Core/Support/Bridges/Helpers/Library/CryptoHelper.phpiçindeki gömülü (sabit string) şifreleme tuzu kaldırıldı. Tuz artıkAPP_KEY→ENCRYPTION_KEY→ sır dosyasıapp_keysırasıyla okunur. YAYIN UYARISI: bu üçünden hiçbiri tanımlı değilse şifreleme artık sessizce zayıf anahtarla devam etmez,RuntimeExceptionfırlatır. Yayından önce her projede anahtarın tanımlı olduğunu doğrula. Geçici geriye-uyum kill-switch'iRBN_ALLOW_LEGACY_SALTveRBN_LEGACY_SALTortam değişkenleridir; ikisinden yalnız biri yetmez, kalıcı yapı değildir (ayrıntı: güvenlik incelemesi raporu). -
R2 — gömülü kurulum parolası kaldırıldı (tarihçe; bu yol artık yok): Installer, gömülü varsayılan yönetici parolasını içeren ekranıyla birlikte tamamen kaldırıldı (
FW-INSTALLER-KALDIR-2). Bu madde yalnızca o aracın neden kaldırıldığını anlatır; bugün geçerli bir kurulum parolası üretme adımı yoktur. -
B71-#4 doğrulama notu (kademeli ceza sayacı):
FormGuardHandler::kademeliCezaDakika()artık metin taramasıyla değil metot çalıştırılarak ölçüldü (5 senaryo, master DB, RFC5737 IP'leri, geçici kayıtlarfinallyile silindi): 4 dolmuş + 0 aktif → 15 dk, +1 aktif → 60 dk, +2 aktif → 1440 dk, 0 kayıt → 15 dk, 5 aktif → 1440 dk. "Kullanıcı 25 saat sonra yine 24 saat yasak alıyor" senaryosu artık mümkün değil. Bilinçli değiştirilmedi: sayaçmaster.ipBlocktablosunun tamamını sayar;blockIp()kaydıproject_id'li yazdığı için aynı IP'nin başka projedeki aktif kaydı da kademeyi yükseltir. "Global" ceza için muhtemelen doğru, ama bilinçli olarak değiştirilmedi. -
G-08 — GeoIP sağlayıcı seçimi: kapatıldı: ipwho.is (TLS).
GeoIPHandlerartık ücretsiz ve TLS destekleyenipwho.issağlayıcısına bağlanıyor; düz HTTP kalemi kapandı. Taban URLGEOIP_UC_NOKTAsabitine çıkarıldı:https://ipwho.is/{ip}?fields=success,message,country_code(eski düz-HTTPip-api.comyerine). JSON alan adı değişti: ip-api'nincountryCode'i değil, ipwho.is'incountry_codealanı okunuyor. Sertifika doğrulamasıverify_peer/verify_peer_nameaçık yazıldı ve kapatılması yasak (kapatılırsa G-08 düz-HTTP'ye sessizce geri döner); SNI için ayrıcaGEOIP_SUNUCU = 'ipwho.is'sabiti var. Korunan çerçeve:follow_location => 0(uç nokta yönlendirirse istemci sessizce düz HTTP'ye düşmez), 2 sn timeout, 30 günlük önbellek (ipwho.is kotası istemci IP başına 1000 istek/gün ile uyumlu),BILINMEYEN_ULKEsabiti ('XX') ve hata yolunda isteğin durdurulmaması (fail-closed değil — istek akışı devam eder, yalnız ülke bilgisi atlanır). G-08'in (a) ip-api PRO satın alma, (c) ülkeyi bilerekXXyapma seçenekleri uygulanmadı; seçilen yol (b) idi. Birim testi:fw-regresyon\birim\fw_geoip_ipwho.php(ağ isteği atmaz, 0 başarısız). Dış istek doğrulaması yapılmadı; karar sağlayıcının kendi dokümanına dayandırıldı. -
Sırlar tek çıkış + B-4 bütünleşti — entegrasyon kaydı:
feat/fw-sirlar-tek-cikis(90ed0c8 + 488965b)integ/fw-asama0dalınagit merge --no-ffile birleştirildi (7644202). Yalnız ortak dosya.github/CHANGELOG.mdidi ve git otomatik birleştirdi; elle çakışma çözümü gerekmedi. R1 ile uyum denetimi: R1CryptoHelperfail-closed (gömülü tuz yok) ve yeniSecrets::appKey()aynıoptional('app_key')yolunu kullanır ve ikisi de çözülemeyen anahtardaRuntimeExceptionfırlatır — ikisi birbirini zayıflatmaz. Doğrulama: değişen 17 PHP dosyasındaphp -ltemiz;fw-regresyon\birimpaketinin tamamı yeşil (13 dosya,fw_sirlar_tek_cikis.php41 kontrol 0 başarısız 0 atlandı;fw_sirlar_tek_cikisbirleşim öncesi 0/41 idi). -
Denetim bulgu düzeltmeleri (B-2 / B-3 / Y-4 / B-5 / B-10) birleştirildi:
feat/fw-denetim-bulgular-1(b135aef) vefeat/fw-denetim-bulgular-2(8d8b8da + eded702)integ/fw-asama0dalına--no-ffile çakışmasız birleştirildi (09ba3ee, 4e5af1d). Etkilenen dosyalar:CrudTrait,UserTokenRepository,RedirectTrait,RateLimitHandler,RateLimitValidations,ShieldSettingsRepository,RedirectManager,IpGuardHandler,SystemGuardHandler. Birim testleri:fw_banu_b2_b3_y4.phpvefw_banu_b5_b10.php— ikisi de yeşil (0 başarısız). Ayrıntılı gerekçeler Fixed bölümünde. Sırlar tek çıkış (feat/fw-sirlar-tek-cikis) o anda hazır olmadığı için bu birleşime alınmamıştı; aşağıdaki bütünleşik kaydı ile ayrı bir--no-ffbirleşimiyle (7644202) alındı vefw_sirlar_tek_cikisbirim testi yeşildir. -
Onarım planındaki ele alınmamış güvenlik kalemleri (fail-closed varsayılanlar, oturum sertleştirme, hız sınırı eylem eşlemesi, token doğrulaması, view yol geçişi kontrolü) bu sürümde kapsam dışıdır; ayrı yama görevlerinde ilerliyor. Bu dosya o kalemler için "bitti" anlamına gelmez. (Token dogrulama kalemi bu yamada kapandi; "hiz siniri eylem eslemesi" yalnizca bu kalemin kendi eylem adinda duzeltildi.)
-
B-4 —
Secrets::optional()artık güvenlik hatalarını yutmaz (fail-closed):optional()all()'in tüm hatalarınıcatch(\Throwable)ile yutuyordu; sır dosyası 0644 (fazla geniş izinli), bozuk biçimli, dizi döndürmeyen ya da okunamaz olduğundanulldönüyor ve çağıran (BaseDbData::pass(),Secrets::appKey()) kendi genel "çözülemedi" hatasını atıyordu — yani operator asıl sorunu (geniş izin / bozuk dosya) hiç görmüyor, sır dosyasını yeniden yazıyor ve sorun bitmiyordu (yanlış teşhis + sessiz düşüş). Artıkoptional()yalnız "sır/bölüm TANIMLI DEĞİL" durumununullile yutar; dosya düzeyindeki her sorun (okunamama / fazla geniş izin / biçim / dizi değil) açıkRuntimeExceptionfırlatır. İç yolgevsekDuz()all()ile aynı düz-anahtar haritasını üretir ama zorunlu bölüm doğrulaması uygulamaz (aksi haldeoptional('app_key'), dosyada tanımlı olan anahtarınullyapardı);okunabilirDogrula()dosya var ama okunamıyorsa "bulunamadı" değil açık "OKUNAMADI" güvenlik hatası verir (Linux 0600 reddi dâhil).CryptoHelper::sirDosyasindanAnahtar()'daki kendicatchde kaldırıldı: kaynak hata (izin/biçim) yukarı kaybolmaz. Geriye uyum korunur —optional()yalnız "tanımsız" durumundanulldöndüğü için mevcut çağıranlar bozulmaz; davranış değişikliği yalnız hata yutma katmanındadır. Doğrulama:fw_sirlar_tek_cikis.phpF1–F11 (opsiyonel yok →null, bozuk/okunamaz dosya → istisna, tanımlı → değer) 0 başarısız 0 atlandı. -
B-4 kırıcı etkisi (yayın öncesi okunmalı): sır dosyasının izni fazla geniş veya dosya bozuk olan kurulumlarda bu sürüm daha önce sessizce çalışan, artık açık hata veren akışlara dokunur. Bu kasıtlıdır (fail-closed), ama
chmod 600uygulanmamış kurulumlar yayın sonrası hata görecektir. Yükseltme adımı:UPGRADING.md0.9.0 Adım 7.
Removed
- FW-INSTALLER-KALDIR-2:
rbnframework/Installer/klasörünün tamamı kaldırıldı (kullanılmayan, üretici olmayan araç).InstallerStagesilindi veKernelFactoryboot hattından çıkarıldı;Installer\Services\InstallationServiceve beşInstaller\Handlers\*kaydıSystemLogicMapTraitsınıf/kayıt haritasından elle silindi. Autoload PSR-4Installer\girdisi,FolderMatrixINSTALLERgirdisi,FrameworkContext::installer()erişimcisi veRouteBlueprint::SYSTEM_ALLOWED_PATHSiçindeki web kurulum yolu kaldırıldı. Ölü konsol komutları (system:check,install:project,shield:sync)SystemHandlerskayıtlarından verbnmaster komut listesinden silindi. Yeni bir kurulum/kısa yol YAZILMADI: yeni projeler elle kurulur. - FW-CONFIG-YAPISI (güvenlik incelemesi): Boş
Core/System/Config/Definitions/ConfigFile.phpkabuğu kaldırıldı (yalnızConfigFileLoadertrait'iniuseediyordu, tek satır tanım dışında kullanıcısı yoktu). Sır OLMAYAN yapılandırma dosyaları için ortak giriş noktası artıkEngine/ConfigFileLoadertrait'idir;Definitions/yalnız sabit/şema sınıflarını barındırır (proje sahibi kuralı: "sabitler ayrı dosya, metotlar ayrı dosya"). - FW-TEK-SECRETS-DOSYASI-161:
Core/System/Config/Secrets/master-secrets.example.phpvecpanel-secrets.example.phpşablonları;rbnframework/.gitignoreiçindeki iki sır dosyası satırı;Secrets.phpiçindeki iki eski dosya sabiti ve tüm "geriye uyum" okuma yolu (eskiMasterDuz(),eskiCpanelDuz(),eskiBolum()). - B-02:
SessionSandboxStageiçindekidefined('RBN_INSTALL_REQUIRED')dalı kaldırıldı: sabit ağaçta hiçbir yerde tanımlı değil, yalnız burada okunuyordu. Bu dal, tanımlı olsaydı oturum aşamasını tamamen atlayacaktı; kaldırılınca oturum/çerez bayrakları her zaman uygulanır (daha kapalı yön). İlgili iki doküman satırı da güncellendi. Kanıt: kalıntı taraması 0 eşleşme,php -ltemiz, duman testiREGRESYON=0(çerez bayrağı senaryosu 18 sitede PASS). - B-03:
rbn-terminal.cssiçindeki.rbn-terminal-btn-install(+:hover) kuralları kaldırıldı: tek kullanıcısı, silinmiş Installer ekranıydı; ağaçta başka kullanım yok. - Kaynak kodundaki parola sabitleri ve parolaları yansıtan yorum satırları kaldırıldı.
- Gerçek sır dosyası sürüm takibinden ve yayın paketinden çıkarıldı.
- Alti haneli kodla dogrulama ekrani kaldirildi; parola sifirlama akisi tek bir guvenli baglanti uzerinden yuruyor. Eski (kod iceren) baglantilar gecersizdir.
-
Gelen makine API korumasi
ApiGuardicinde tek merkezde: beyan, anahtar kimligi, kapsam, hiz/govde siniri, denetim kaydi ve makine-okunur hata kodu.machine-apibeyani (MachineApiRegistry). "Hangi uc makine API'sidir?" sorusunun once uc bagimsiz cevabi vardi (isAgentEndpoint()sabit listesi,session-policy.phpyol onekleri, route middleware = yok). Artik tek beyan tablosu var; IP katmani once beyani sorar, olmezse eski sabit listeye duser (sabit liste SILINMEDI = geri uyum emnetyeti). Beyan ile IP muafiyeti ayri kararlardir (ip_exempt):/ws/agentbeyan edildi (session katmaniyla tutarsizlik kapandi), crew/worker uclari da beyan edildi ama muafiyetleri kapali — gozlem verisi toplanmadan WAF/ban kapsami daraltilmaz.RouteBlueprintaltina parametresizmachine-apialias'i eklendi.- Anahtar basina kimlik (
MachineApiKeyStore).external-apiayarina geri uyumlukeysbolumu:sha256:<hex>saklama, sabit zamanlihash_equalskarsilastirmasi (diziden!==cikarildi), kapsam (scopes), iptal (revoked_at), sure (expires_at), anahtar basina hiz siniri ve govde siniri. Duz metinapi_keydali acik kalir. ?token=log-only. Anahtar once basliktan okunur; sorgu/govde parametresi geri uyum icin okunmaya devam eder ama her kullanimda denetim kaydi + uyari dusurur (allow_query_token, varsayilantrue— reddetme YAPILMAZ).- Hata sozlesmesi. Yanitlara makine-okunur
codealani eklendi (UNAUTHORIZED,FORBIDDEN_SCOPE,IP_NOT_ALLOWED, ...). Mevcutmessagemetinleri degismedi; eski istemciler aynen calisir. - Hata mesajinda istemci IP'si yansitilmiyor. Once
Bu IP adresinden erisim izniniz yok: <ip>seklinde ic ag topolojisi sizdiriyordu. - Yeni korumalar log-only. Govde/icerik tipi siniri, anahtar basina hiz siniri ve
denetim kaydi
enforce=falseile baslar; hicbir istek dusurulmez, yalniz kayit duser. Denetim kaydi (machine-apikanali) anahtar degerini degilkey_id'yi yazar.
-
Ajan ucunun 401 yanitinda anahtari geri yansitilmasi kaldirildi. Go ajaninin
/api/agent/*ucu, kimlik dogrulanamayan isteklerde gonderdigi anahtari istemciye geri yansitiyordu; bu deger ajan loguna duz metin dusuyordu. Alan kaldirildi; 401 yanitindaki hata metni aynen korundu ve ajan tarafi Go testleriyle dogrulandi (alan yapisal olarak okunmuyor, yalniz maskeleniyordu). -
Crew gorev ucunde artik gercek bir govde boyut siniri var. Yorumda "govde JSON olmali, boyut sinirli" deniyordu ama kodda boyut siniri yoktu; beyan edilen govde boyutu 1 MB'yi asiyorsa istek reddediliyor ve govde hic okunmuyor.