01 — MİMARİ HARİTA
Bu belge hangi commit'e göre yazıldı:
d4af18d(dalfeat/fw-license-master)
Son doğrulama tarihi: 2026-10-05
Yayın tabanı: 0.9.7 = bu commit + sonrası; belge yalnız doğrulama anındaki kodu anlatır
Kapsam: Açılış zinciri, yönlendirme, render, kavramlar,Paths, ortam algısı
1. Tek cümlelik özet
RBN, çok kiracılı (multi-tenant) bir PHP uygulama çatısıdır: bir çekirdek
kodon altında birden çok bağımsız site çalışır; siteler master veritabanındaki
projects satırlarıyla tanımlanır, veri tabanları ve klasörleri birbirinden ayrıdır.
2. Açılış zinciri (HTTP)
2.1 Giriş noktası (index.php)
Her site kendi giriş noktasını taşır; framework paketinin parçası değildir
(.github/UPGRADING.md:815-826). Yerel çalışma örneği:
domains/customers/<site>/index.php:1.
Sıra:
- PHP sürüm kapısı,
vendor/autoload.php'den önce
(domains/customers/<site>/index.php:11).
Dosya yoludirname(__DIR__, 2|3|4) . '/rbnframework/Core/System/Kernel/Base/PhpVersionGate.php'
aranır; bulunamazsa kapı sessizce atlanır (bulunursaenforce()çağrılır). - Composer autoloader keşfi: iki aday yol sırayla denenir —
dirname(__DIR__, 2)(hosting) vedirname(__DIR__, 3)(yerel)
(domains/customers/<site>/index.php:27). Bulunamazsa HTTP 500 + ölüm (satır 40-43). Bootstrap::run(__DIR__, ['project_key' => '<project_key>'])
(domains/customers/<site>/index.php:48).
project_keyaçıkça verilir;publicPath=__DIR__(o sitenin kendi klasörü).
Neden
project_keyaçık veriliyor? Master'da birden çok satır aynıdomain
kalıbını taşıyabilir (*.test,*.localekleriProjectDiscoveryiçinde
preg_replace('/\.(test|local)$/', '', $host)ile son ek olarak atılır,
ProjectDiscovery.php:78). Anahtar vermek bu belirsizliği tamamen kaldırır.
2.2 Bootstrap::run()
Core/System/Kernel/Bootstrap.php:19:
PhpVersionGate::enforce()tekrar (Bootstrap.php:26) — savunma derinliği.configureErrorVisibility()(Bootstrap.php:97):RBN_DEVtanımlı değilse
sonuç KAPALI (fail-closed).display_errors0/1,log_errors1,
error_reporting(E_ALL).sendBaseSecurityHeaders()(Bootstrap.php:112):X-Powered-Bykaldırılır;
X-Content-Type-Options: nosniffveReferrer-Policy: strict-origin-when-cross-origin
yoksa eklenir (projeye ait başlıklar ezilmez). CLI'de ve
headers_sent()ise hiç çalışmaz. HSTS/CSP kasıtlı olarak yok —
sunucu/proje katmanındadır (Bootstrap.php:106).PreBoot::orchestrate()(Bootstrap.php:37).configureErrorVisibility()tekrar (Bootstrap.php:40) — artıkRBN_DEVbellidir.ob_start()→KernelFactory::create()→$kernel->boot()(Bootstrap.php:43).Route::run()(Bootstrap.php:48).$kernel->terminate()(Bootstrap.php:51).- Tüm gövde
catch (\Throwable)içinde:BootSentinel::dispatch($e)+
renderTerminalFailure($e)(Bootstrap.php:53).
En dar çıkış yolu renderTerminalFailure() (Bootstrap.php:68): hata
kimliği (4 bayt rastgele, HEX büyük harf) error_log()'a yazılır; RBN_DEV === true
ise yalnız mesaj basılır, aksi halde "Sistem şu an kullanılamıyor. Hata kimliği: …"
(Bootstrap.php:86). Dosya/satır üretimde ekrana hiç dökülmez.
2.3 PreBoot::orchestrate() — 0 … 4. adımlar
Core/System/Kernel/Base/PreBoot.php:406:
| # | Adım | Satır | Ne yapar |
|---|---|---|---|
| — | PhpVersionGate::enforce() |
412-413 | Sürüm kapısı (autoload sonrası savunma) |
| — | saat dilimi + locale | 419-420 | Europe/Istanbul, tr_TR.UTF-8 |
| 0 | detectEnvironment() |
423 | RBN_DEV, RBN_DEBUG, DEFAULT_LANGUAGE, APP_NAME, APP_URL sabitlerini tanımlar. APP_VERSION burada tanımlanmaz (PreBoot.php:356) |
| 0.5 | Proje keşfi | 426-435 | ProjectDiscovery::getProjectData($publicPath, $config['project_key']) → sonuç boş değilse Bootstrap::setAppContext('project_data', …) ve ('project_key', …); $config['project_key'] gerçek anahtarla güncellenir |
| 1 | initPaths() |
438 | Paths::init($projectPath, $publicPath) (§4) |
| 1.5 | defineAppVersion() |
444 | APP_VERSION = proje sürümü (bkz. 04-surumleme-ve-yayin.md) |
| 2 | registerSentinel() |
447 | BootSentinel::register() (elle require, Paths gerekiyor) |
| 2.5 | Watchdog |
450-451 | require .../Guards/Watchdog.php |
| 3 | initAutoloader() |
453 | Paths::frameworkRoot() . '/vendor/autoload.php'; yoksa ölüm (PreBoot.php:545) |
| 4 | handleFastAssets() |
456 | AssetDoctor::check() — statik varlıklar için bağımlılıksız hızlı yol |
PreBoot tek seferliktir: private static bool $initialized (PreBoot.php:20, 415-416).
Ortam kararı autoloader'dan önce verildiği için Config/Secrets.php elle require
edilir (PreBoot::appSettings(); secrets.php app bölümü, FW-096-D8).
2.4 detectEnvironment() — RBN_DEV nasıl belirlenir?
PreBoot.php:340. Güvenli varsayılan: ÜRETİM. Geliştirme kipi yalnız iki
kaynaktan açılır:
- Operatör kararı:
secrets.phpapp.debug/app.dev= PHPtrue
(PreBoot::operatorDebugRequested()). Değerboololmak zorundadır;'banal'
gibi metin şema tarafından varsayılana (false) düşürülür, kapı kapalı kalır.
app.environment'development'değilse (yazılmamışsa da) 2. madde hiç denenmez. - Yerel istek:
isTrustedLocalEnvironment($host, $addr)(PreBoot.php:317)
→ host normalizasyonu geçerli, istemci IP'siisLocalClientAddress()'tan geçer
(loopback + RFC1918 + link-local + ULA, IPv4-eşlemeli IPv6 dahil,
PreBoot.php:158) VE host ya beyaz listede
(localhost,127.0.0.1,[::1]—PreBoot.php:34) ya da TAM son ek.test
(str_ends_with,PreBoot.php:333).
Alt dize eşlemesi yoktur (stripos/str_contains kullanılmaz,
PreBoot.php:30): www.tester-attacker.com, evil.localhost.attacker.com,
example.tr.test.evil.com kapsam dışıdır.
X-Forwarded-For bilerek hiç okunmaz (PreBoot.php:153).
APP_URL = http:// + host (yerel) / https:// + host (PreBoot.php:363).
2.5 Kernel aşamaları (KernelFactory)
Core/System/Kernel/Base/KernelFactory.php:74. new Kernel(...) sonrası altı
aşama zincirlenir. Sıra ve bağımlılık gerekçeleri kodun docblock'ındadır
(KernelFactory.php:24):
| # | Aşama | Neye bağımlı | Ne yapar |
|---|---|---|---|
| 1 | Autoload |
— | Composer + proje PSR-4 kayıtları |
| 2 | ShieldSentinel |
1 | Zorunlu sağlık/güvenlik denetimi; başarısızsa erken çıkış |
| 3 | DatabaseGuardStage |
1, 2 | Ortam ve aktif proje DB üzerinden çözülür; proje veri önbelleği burada kesinleşir |
| 4 | ComponentRegistry |
1, 2, 3 | Exception servisi + sınıf alias'ları |
| 5 | SessionSandboxStage |
3, 4 | Oturum çerezi bayrakları, ömür, "proje kutusu" senkronu |
| 6 | Routing |
1-5 | Route::loadRoutes(), bakım modu ve ön-ek denetimi |
Özet (koddan, KernelFactory.php:66):
Autoload → Tanılama → Veritabanı → Servisler → Oturum → Yönlendirme.
Sıra kuralı: Yeni aşama eklenirse docblock'a "neye bağımlı" satırı da
eklenmelidir (KernelFactory.php:70).
Kernel::boot() (Core/System/Kernel/Kernel.php:58) aşamaları sırayla çalıştırır;
RBN_DEV açıksa süre ölçümü yapar (Kernel.php:62, 66, 70-73).
PreflightException yakalanır ve PreflightProvider::renderFatal(...) ile ekrana
basılıp exit edilir (Kernel.php:77). Diğer istisnalar yakalanmaz —
Bootstrap::run()'un catch bloğuna düşer.
3. Yönlendirme
3.1 Route::run() — RedirectManager ÖNCE, dispatch SONRA
BaseService::get()->manager('redirect')→ varsa->process()
(Route.php:238).REQUEST_URIyol parçası alınır,trim(..., '/')edilir; boş veyaindex.php
ise/olur (Route.php:243).self::dispatch($uri)(Route.php:249).
RedirectManager::process() Route::dispatch()'ten önce çalışır; bu sıralama
R-02 tuzak kontrolünün dayanağıdır — collectHoneypotRoutes() yorumu:
RedirectManager.php:498 ("Routing aşaması Route::loadRoutes()'i çoktan
bitirdiği için koleksiyon hazırdır").
3.2 RedirectManager — tek 301 kuralı
Core/Routes/RedirectManager.php:
process()(RedirectManager.php:105):- CLI'de tamamen atlanır (
satır 108-110). shouldBypassRedirect()doğruysa hiç kural çalışmaz (121-123,588-601):
yol segmentlerinden biri tam olarakapi,webhook,bot-sync,bot-data
ise (hasSegment(),616-619).- Kurular sırayla çalışır (
128-132), sonra tek karşılaştırma yapılır:
ilk URL ≠ son URL ise tekredirect()+exit(137-139).
- CLI'de tamamen atlanır (
- Kural sırası (
RedirectManager.php:45):
enforceCanonicalDomain,forceHttps,removeWww,removeTrailingSlash,
forceLowercaseUrl,redirectOldUrls,redirectHome,selfHealingAssets. - Güvenlik kapısı:
redirect()(663-681) önceguvenliYonlendirmeHedefi()
(156-167) üzerinden aynı-origin doğrulaması yapar; beyaz liste boşken ve hedef
isteğin kendi host'u ise hiçLocationyazılmaz,exitde olmaz (667-669,
642-658). Bu, tarayıcıda kalıcı 301 birikmesini (B-5) engeller.
3.3 RedirectManager vs Config önceliği
enforceCanonicalDomain() resmi alan adını Bootstrap::getAppContext('project_data')['domain']
alanından okur (RedirectManager.php:206); yoksa erken döner (209-211).
3.4 Rotaların yüklenmesi
Route::loadRoutes() (Route.php:255):
- Framework rotaları:
Paths::framework()->core('Routes/Mappings')altından
core.php,auth.php,web.phprequire_once(Route.php:260). - Proje rotaları:
Definition::get('route','FILES')['project']listesi
(Route.php:265). ListeRouteBlueprint::FILESsabitinde şu an boştur
(Core/Support/Definitions/Route/RouteBlueprint.php:57), yani bugün proje
rotaları otomatik yüklenmez; bir proje bu listeye dosya adı ekleyerek açar.
DosyalarPaths::project()->routes()altında, proje ad alanı
(Definition::get('namespace','PROJECT_PREFIX')) içinde gruplanır (Route.php:269).
3.5 Dispatch → Controller
Core/Routes/Engine/Dispatcher.php:24: önce middleware'ler (runMiddleware, 38),
sonra callController() (32).
- Middleware çözülemezse veya yetki reddi →
response()->redirect('/')
(Dispatcher.php:49); middleware koruma uygulamadan controller'a gitmek fail-OPEN
rotadır ve bu yol bilinçli olarak kapalıdır (Dispatcher.php:75). - Controller çözümü
ControllerResolver::resolve()(Dispatcher.php:157):
sırayla dener ve ilk bulan adı döner — modül, proje modül ortak hub,
proje çekirdeği vb. (ControllerResolver.php:18). Ad alanında\Controllers
yoksa otomatik enjekte edilir (ControllerResolver.php:63), sonuna
Controllersoneki eklenir (85). new $classburada yapılır (Dispatcher.php:162); §1 yasağı model/repository/
service içindir, yönlendirici bu tek istisnadır.- Dönüş değeri: controller
returnetmezsegetActiveView()denenir
(Dispatcher.php:165); çıktıechoedilir (170-172).
3.6 Panel ön eki (dashboard_prefix)
Sıra: project-routemap.php → BootCache → project_data('dashboard_prefix');
o da boşsa framework sabiti RouteBlueprint::DASHBOARD_PREFIX = dashboard
(RouteBlueprint.php:99). SystemGuardHandler artık project-settings dosyasından
dashboard_prefix okumaz (SystemGuardHandler.php:50).
RouteManager okurken project_data['dashboard_prefix']'i kullanır
(RouteManager.php:159, 192, 223, 295).
4. Paths — yol çözümleme
Core/System/Paths/Paths.php:
Paths::init(?string $project, ?string $public)(Paths.php:37):
ProjectContext+FrameworkContextkurar, ardından
Core/Support/Bridges/Helpers/rbn_helpers.phpdosyasınırequire_onceeder
(Paths.php:50) — global helper'lar burada tanımlanır, yaniPaths::init()
sonrasındaproject_data(),is_local(),app_version()kullanılabilir.
RBN_DEV açıkken?rbn_diagtanılama çıktısı basılır (Paths.php:55).workspace()(Paths.php:63):__DIR__yukarı doğru yürütülür, ilk
basename === 'rbnframework'bulunan dizin framework kökü, onun üstü
workspace olur. Bulunamazsa yedek:dirname(__DIR__,3)çerçeve,
dirname(...)workspace (Paths.php:79).frameworkRoot()(Paths.php:90),projectRoot()(107),
publicRoot()(109-122):project_data('public_path')doluysa
workspace + '/domains/' + public_pathgerçekten dizinse (is_dir) o kullanılır,
değilseinit()ile verilen yol (Paths.php:112).module(string $name, string $source = 'auto')(Paths.php:160):
ModuleDiscoveryDriver::resolveModuleContext()ile modül bağlamı, sonuç
süreç içi önbelleğe alınır.
Sıra önemli: PreBoot::initPaths() (adım 1) defineAppVersion()'dan (adım 1.5)
önce gelir; proje sürümü okunabilsin diye. Gerekçe PreBoot.php:356, 440-444.
5. Kavramlar: project_key, site, modül, proje klasörü
5.1 Veritabanı tanımı (master)
Master projects tablosu (db:schema projects --master ile ölçüldü):
id, project_group, project_key (UNIQUE), project_name, domain,
public_path, custom_path, status (enum('active','maintenance','suspended'),
varsayılan active), options (json), version, license_key, created_at,
updated_at.
5.2 Tek proje klasörü = birden çok site
custom_path = projects/ altındaki klasör; birden çok project_key aynı
custom_path'i paylaşabilir. Ölçülen örnekler:
project_key |
custom_path |
domain |
|---|---|---|
<anahtar-1> |
customers/<proje> |
site.example |
<anahtar-2> |
customers/<proje> |
alt.site.example |
<anahtar-3> |
customers/<proje> |
ofis.site.example |
Yani bir klasör birden çok siteyi barındırır; "site" burada bir proje kaydıdır
(ayrı DB kimliği, ayrı modül, ayrı panel ön eki olabilir).
5.3 public_path bir göreli yoldur
projects/<...> değil, domains/ altına göre yazılır; Paths::publicRoot() bunu
workspace + '/domains/' + public_path olarak birleştirir (Paths.php:115).
db:query ile ölçüldü: 19 kaydın 18'i domains/ öneksiz, 1'i domains/
önekiyle yazılmış → bu kayıt için is_dir() denetimi başarısız olur ve
publicRoot() init değerine düşer (bkz. ../acik-sorular.md).
5.4 Keşif önbelleği
ProjectDiscovery::getProjectData() (Stages/ProjectDiscovery.php:42):
- Anahtar verilmişse
project_keykolonuyla, verilmemişsedomainkolonuyla aranır. - Domain aramasında host tek merkezden normalleştirilir
(PreBoot::normalizeHost,ProjectDiscovery.php:73) ve yalnız sondaki
.test/.localatılır (preg_replace('/\.(test|local)$/','',$host),
ProjectDiscovery.php:78).str_replacekullanılmaz — alt dizge silme hatasının
düzeltmesidir (açıklamaProjectDiscovery.php:62). - Önbellek hit ise anında döner (
ProjectDiscovery.php:86);
miss ise tüm hydrationProjectDataMapper::build()'e devredilir
(ProjectDiscovery.php:92). - Grup listesi ayrıca
group_önekiyle önbelleğe yazılır
(ProjectDataMapper.php:141).
Önbellek nerede? BootCacheProvider::getCacheDir() →
Paths::workspace() . '/.cache' (Core/System/Storage/Providers/BootCacheProvider.php:20).
Dosya adı: .cache/<önek><değer>.json (BootCacheProvider.php:28).
| Önek | Sabit | Dosya biçimi |
|---|---|---|
project_ |
CacheConstants::DISCOVERY_PREFIX_PROJECT |
.cache/project_<project_key>.json |
domain_ |
CacheConstants::DISCOVERY_PREFIX_DOMAIN |
.cache/domain_<domain>.json |
group_ |
CacheConstants::DISCOVERY_PREFIX_GROUP |
.cache/group_<project_group>.json |
(Sabitler: Core/System/Storage/Constants/CacheConstants.php:37.)
Ne zaman yenilenir? Önbellek kalıcı dosyadır; TTL kavramı yoktur.
BootCacheProvider::clearProjectCache($projectKey) üç dosyayı birlikte siler
(BootCacheProvider.php:79: domain → group → project). Elle yenileme:
php rbn cache:clear (kök README.md:135).
5.5 Proje verisi nasıl birleşir?
ProjectDataMapper::build() (Core/System/Discovery/Engine/Cache/ProjectDataMapper.php:74):
- Master PDO:
SELECT * FROM projects WHERE <kolon> = ? AND status IN ('active','maintenance','suspended') LIMIT 1
(ProjectDataMapper.php:85). Satır yoksa[]döner (91-93). MASTER_QUERIESmatrisi çalışır (98) ve grup satırları çekilir
(project_group = ? OR project_key = ?,104-108).- Workspace çözülür,
custom_pathprojects/altına bağlanır (115-118). - Common PDO (
CommonDbData) →COMMON_QUERIES(121-123). - Proje PDO →
PROJECT_QUERIES(125-129); bağlantı kurulamazsa boş dizi. - Birleştirme
assemble()(192-…) ve BootCache'e yazma (137,141-145).
assemble() içinde, routemap'ten gelen iki alan özel işlenir
(ProjectDataMapper.php:202):
view_mapping[<project_key>]['dashboard_prefix']→project_data('dashboard_prefix')
(214,220-221).view_mapping[<project_key>]['admin_panel_disabled']→admin_panel_disabled
(215,219); panel kapalıysadashboard_prefixsilinir (354-359).
Ayrıca master settings satırları setting_key → setting_value haritasına
çevrilir (ProjectDataMapper.php:226) ve ek önbellek alanları bildirimsel
listedendir (EXTRA_CACHE_KEYS, ProjectDataMapper.php:58) — yeni alan = 1 satır.
5.6 Modül
Route::module() (Route.php:77); çözüm ModuleDiscoveryDriver üzerinden
Paths::module() (Paths.php:160). Modül adı routemap'te tanımlanır
(view_mapping[<key>]['module']), örn. <modul> → modül klasörü ve
ModuleData.php (rotalar, yetkiler, menüler tek merkezde; §5 kuralları).
Modül bulunamazsa ModuleDiscoveryDriver kaynak taramasına düşer; kodda
"yoksa ana sayfaya 301" gibi bir davranış RedirectManager'ın işidir, modül
çözümleyicinin değil (RedirectManager.php:379 tek segmentli yollar içindir).
6. Render zinciri
Dispatcher → controller → $this->render(...) →
RenderService::render($type, $params) (Core/Render/Services/RenderService.php:36):
- Bağlam hazırlığı:
$this->handler($type)->prepare(...)(RenderService.php:42,68-83).
Handler yoksa/istisna olursa sessizce$datadöner (80-82). - Provider çözümü; yoksa HTTP 500 (
45-48). - Özel durumlar:
asset→AssetService(52-54);seo/meta→SeoService(57-59). - Diğer →
$provider->render($view, $preparedData, $type)(62).
Renderreturneder,echoetmez (RenderService.php:50).
Şablon motoru Core/Render/ViewEngine.php:
- Derleme:
.rbn.php→ saf PHP →Paths::project()->storage('framework/views')
(ViewEngine.php:47). Dosya adı<project_key>_<md5(view yolu)>.php
(ViewEngine.php:140). Kaynak daha yeni değilse önbellek kullanılır (142-144). - Kök koruması: derlenecek görünüm her zaman proje veya framework kökünde
olmalıdır; ikinci savunma hattıguardRoots()'tır (ViewEngine.php:130). - Yönerge→PHP (
ViewEngine.php:212):@if/@elseif/@else/@endif,
@foreach/@endforeach,@for/@endfor, ve layout yönergeleri:
@extends('…')→$layout->setExtends(…),
@section('…')/@endsection/@yield('…')
(ViewEngine.php:229). Uygulama ek yönergeleri yapılandırmadan gelir
(ViewConfig::directives(),ViewEngine.php:236). - İfade sözdizimi (
ViewEngine.php:170):
{{ expr }}→htmlspecialchars((string)(expr ?? ""), ENT_QUOTES, "UTF-8")(182),
{!! expr !!}→ ham çıktı (191).
İkisi deTemplateExpressionGuard::assertSafe()'dan geçer (181,190;
Core/Render/Handlers/TemplateExpressionGuard.php:114). - Layout sarmalama: görünüm
includeCompiled()ile basılır, sonra
LayoutResolver::getExtends()dönen layout yenidenrender()edilir
(ViewEngine.php:77). Yani içerik bölümler (@section/@yield) ile taşınır,
$contentdeğişkeni ile değil (bkz.../acik-sorular.md). - Veri izolasyonu:
includeCompiled()ayrılmış adları (__rbnFile,__rbnData,
this,GLOBALS) siler ve günlüğe yazar (ViewEngine.php:112).
7. CLI yolu (rbn)
rbnframework/rbn (giriş noktası):
define('RBN_CLI', true)(rbn:9).PhpVersionGate::enforce()— autoload'dan önce (rbn:14-15).- Autoloader yoksa ölüm (
rbn:21-23). --project=<anahtar>ve--masterayrıştırılır (rbn:41-48).- Otomatik master modu:
list,system:cron,project:list,db:*,
cache:clear,logs:clear,tmp:clear,system:doctor,doctor,
version:check,version:next,master:migrate,master:migrate:status
--masterolmayı kendisi açar (rbn:52-77). - Yol çözümü (
rbn:80-111):--projectverilmişse proje verisi master'dan okunur; yoksa hata + çıkış 1
(rbn:86-91). Proje kökücustom_pathüzerinden kurulur (93-97).--projectyoksa: çalışma dizinipublicise o, değilse
<workspace>/tmpproje kökü ve framework dizini public olarak kullanılır
(rbn:99-107). Bu yüzden projesiz komutlardaPaths::project()->storage()
çalışma anında<workspace>/tmpaltında oluşur.
Paths::init()(rbn:111) →Autoload::boot()(rbn:114) →
rbn_helpers.phprequire(rbn:116) →rbncliservisininrun($argv)
çağrılır (rbn:117-121).- İstisna:
[CLI Error]+ log +secrets.phpapp.environment = 'development'ise kaynak satırı,
çıkış kodu 1 (rbn:124-138).
Komut listesi (ölçüldü, php rbn list):
cache:clear, db:info, db:query, db:schema, db:tables, doctor, list,
logs:clear, make:controller, make:migration, make:model, make:request,
master:migrate, master:migrate:status, migrate, migrate:rollback,
migrate:status, project:list, system:cron, system:doctor, tenant:apply,
tenant:audit, tenant:plan, tenant:revert, tmp:clear, version:check,
version:next. Sürüm satırı: CLI v2.3.0 (rbn list çıktısı;
FrameworkIdentity::FRAMEWORK_CLI_VERSION = '2.3.0').
Kısıt: CLI'da HTTP isteği yoktur; $this->request kullanılamaz.
Web controller sınıfları CLI'da doğrudan çalıştırılamaz
(.agents/rules/database-and-cli.md §6). Çok kiracı işlemlerde
$this->tenant->resolve() ile bağlam kesinleştirilir (aynı kural §6).
8. Ortam algısı: is_local() ↔ DB profili kararı
Bu ikisi bilinçli olarak farklıdır ve karıştırılmamalıdır.
is_local() |
DB profili (ProjectDbProfileResolver) |
|
|---|---|---|
| Kod | Core/Support/Bridges/Helpers/Global/system_helpers.php:57 |
Core/System/Config/Engine/Database/ProjectDbProfileResolver.php:99 |
| Soru | "Bu istek/oturum yerel mi?" | "Bu sunucu hangi DB profilini kullanacak?" |
| HTTP'de girdi | HTTP_HOST + REMOTE_ADDR → PreBoot::isTrustedLocalEnvironment() (system_helpers.php:64) |
HTTP_HOST/REMOTE_ADDR BİLEREK KULLANILMAZ |
| CLI'da girdi | DOCUMENT_ROOT, __DIR__, getcwd() içinde tam localhost segmenti (system_helpers.php:78) |
framework kökünün yolunda tam localhost segmenti (ProjectDbProfileResolver.php:205) |
| Karşılaştırma | sonuç bool, önbellekli (static $isLocal, system_helpers.php:59) |
local | production (fail-closed) |
| Tipik kullanım | robots.txt muafiyeti (RobotsResolver.php:19), IndexNow/e-posta atlama |
DB_PROFILES seçimi (ProjectDbProfileResolver.php:121) |
Neden farklı? Gerekçe kodun içinde yazılıdır
(ProjectDbProfileResolver.php:73): is_local() bir istemci tarafı yardımcısıdır
ve Host başlığı saldırgan kontrollüdür. Veritabanı seçimi böyle bir karara
bağlanırsa aynı sunucuda istek kimliğine göre farklı veritabanlarına bağlanılır —
yerelde dış ağdan gelen istek production seçer, üretimde local denenir.
Ölçüm kanıtı aynı yerde: REMOTE_ADDR doküman IP'si ile kabul harness'i 8 dosyada
hata üretti.
Karar sırası (ProjectDbProfileResolver.php:85, 99-107):
secrets.phpapp.db_profile= tamlocalya da tamproduction
(declaredProfile(),180-189). Başka değer (yerel,1, boş) karar yok sayılır, sıradakine geçilir. Ortam değişkeni okunmaz (FW-096-D8).- Framework kökünde tam
localhostyol segmenti →local. - Hiçbiri okunamazsa/belirsizlik →
production(fail-closed).
getcwd() ve alan adı bilerek kullanılmaz (cron'un çalışma dizini sunucuda
/root da olabilir; ProjectDbProfileResolver.php:92).
9. Güvenlik sınırları (burada tekrar etmeye değmez)
.github/SECURITY.md— bildirim kanalları, desteklenen sürümler, koordineli ifşa..github/KNOWN-LIMITATIONS.md— bilinçli olarak sıkılaştırılmamış tercihler.Core/System/Config/README.md— sır tek kapı kuralı (secrets.php; ortam değişkeni yok).Core/System/Kernel/Base/PreBoot.php—RBN_DEVfail-closed kapısı.Core/Render/Handlers/TemplateExpressionGuard.php— şablon ifadesi güvenliği.RedirectManagerguvenliHedef()zinciri —Locationbaşlığı güvenliği..agents/rules/core-architecture.md—newyasağı, Repository/Provider ayrımı,
§9 proje adı yasağı, §10 İngilizce metot adı.
10. Bilinmeyenler
Bu belgede kodda doğrulanamayan veya çelişen noktalar
../acik-sorular.md dosyasında listelidir. Özetle:
Core/System/Config/README.md:20-21Engine/Config/yolunu yazıyor; kodda bu
dosyalarEngine/Config/veEngine/Database/altında dağınık.MasterRbnHeartbeatsModel::$table = 'rbn_heartbeats', ancak master'da ölçülen tablo
adız_sys_heartbeats(veMasterDbData::REQUIRED_TABLESdaz_sys_heartbeats'i
sayıyor —MasterDbData.php:54).ModuleContext/ModuleDiscoveryDriverkaynak taramasının hangi dizinleri
taradığı bu belgede doğrulanmadı.