Yayın Türü: Teknik İnceleme (Whitepaper) & Mimari Yol Haritası (RFC)
Sürüm: v1.2.0
Hedef Kitle: Kıdemli PHP Geliştiricileri, Sistem Mimarları, Açık Kaynak Geliştiricileri ve Yapay Zeka Ajanları
Yazar / Kurucu: Ali Çömez (slaweally)
Teknoloji Yığını: PHP 8.4+, Symfony 7.4 LTS, Doctrine ORM, AssetMapper, Tailwind CSS Standalone Binary
Giriş: Teori, Pratik ve "Tekerleği Yeniden İcat Etme" Sancısı
Modern web ekosisteminde yeni bir projeye başlarken geliştiriciler kendilerini her zaman iki ucu keskin bir bıçağın üzerinde bulurlar. Bir yanda, hazır eklenti ve tema sistemleriyle donatılmış ancak hantal veritabanı şemaları, teknik borç dağları ve güvenlik zaafiyetleriyle boğuşan klasik CMS'ler (WordPress, Drupal) vardır. Diğer yanda ise her şeye sıfırdan başlamayı gerektiren, her projede auth, ACL, dosya yönetimi ve admin paneli gibi temel bileşenleri sıfırdan yazarak zaman kaybettiren saf modern framework'ler (Symfony, Laravel) bulunur.
Sıfırdan kendi MVC yapısını yazmak kulağa romantik gelse de günümüz standartlarında rasyonel değildir. Bir framework sadece yönlendirme (routing) ve kontrolcülerden ibaret değildir; güvenlik (CSRF, XSS, SQLi engelleme), Dependency Injection (DI) Container yönetimi ve HTTP katmanı gibi devasa bir "görünmez buzdağı" barındırır.
İşte CPalius, bu iki dünya arasındaki köprüyü kurmak; geliştiriciyi tekerleği yeniden icat etme sancısından kurtarırken ona dünya standartlarında, optimize, güvenli ve genişletilebilir bir altyapı sunmak amacıyla doğdu. Bu döküman, CPalius'un en temiz skeleton kurulumundan, "çökmeyen" bir işletim sistemi mimarisine; ardından bir CMS'ten "Kurumsal Uygulama Framework'üne" uzanan teknik yolculuğunun en ince ayrıntısına kadar dökümüdür.
1. Bölüm: "Pristine Root" ve Klasör Mimarisi
Standart bir Symfony projesinde üçüncü parti paketler ve tarifler (recipes) yüklendikçe projenin ana dizini (root) dosya ve klasör çöplüğüne döner. Geliştiricinin kendi yazdığı kodlar ile framework'ün sistem dosyaları birbirine karışır. CPalius, projenin ilk gününde bu karmaşaya savaş açtı ve "Pristine Root" (Tertemiz Ana Dizin) politikasını benimsedi.
Ana dizinde sadece neyin nerede olduğunu gösteren 4 temel klasör, .env dosyası ve composer.json kalacak şekilde tüm mimariyi izole ettik.
Klasör Hiyerarşisi
CPalius/ (Ana Dizin)
|
|-- cp-core/ # === KERNEL & SYSTEM SPACE ===
| |-- bin/ # Konsol komut araci (bin/console)
| |-- config/ # Core konfigurasyonlari (bundles, packages, routes)
| |-- migrations/ # Cekirdek veritabani goc dosyalari (Git'e tabi)
| |-- src/ # Cekirdek PHP siniflari (App\ namespace)
| `-- var/ # Cache, log ve SQLite dosyalari (yazma alani)
|
|-- cp-includes/ # === DEPENDENCIES SPACE ===
| `-- vendor/ # Composer paketleri (Symfony ve kutuphaneler)
|
|-- cp-content/ # === USER & DEVELOPER SPACE ===
| |-- config/ # Config Sync alani (YAML olarak tasinan altyapi)
| |-- modules/ # Bagimsiz moduller/eklentiler (Modules\ namespace)
| |-- themes/ # Kullanici arayuz temalari
| `-- translations/ # Global arayuz cevirileri (tr, en)
|
|-- public/ # === WEB ROOT === (Disariya acik tek klasor)
| |-- index.php # Front Controller (Tek giris kapisi)
| `-- assets/ # Derlenmis/Semlink edilmis frontend varliklari
|
|-- .env # Ortam yapilandirmalari
`-- composer.json # CPalius ozel yol eslemeleri
Symfony Flex'in İç Mekanizmalarını Bükmek
Bu yapıyı kurabilmek için Symfony Flex ve Composer'ın yapılandırma yeteneklerini en uç sınırlarına kadar zorladık. composer.json dosyasını Flex'e kendi klasör yapımızı dikte edecek şekilde yapılandırdık: vendor-dir, bin-dir ve extra bloğu altındaki parametreler (config-dir, src-dir, var-dir, public-dir ve runtime project_dir / dotenv_path).
Teknik Not: Sadece config.vendor-dir değiştirmek yetersizdir. Symfony Flex'in içindeki komutlar (cache:clear, assets:install), yolları hesaplarken composer'ın standart konfigürasyonlarından değil, extra bloğu altındaki parametrelerden beslenir. Bu parametreler eklenmediğinde sistem derleme aşamasında çöküyordu. Bu sayede tüm Flex tariflerinin doğrudan cp-core altına kurulmasını garanti altına aldık.
2. Bölüm: "Core Never Dies" (Çökmeyen Çekirdek) Mimarisi
Bir CMF geliştirirken en büyük kabus, kullanıcı alanından (cp-content/modules) gelebilecek kötü yazılmış veya bozuk kodların tüm sistemi kilitlemesidir. PHP'de gerçek bir işletim sistemi seviyesinde "sandbox" olmadığı için, CPalius çok kademeli bir Aktif Savunma ve Karantina Hattı geliştirmiştir.
1. Savunma Hattı: Tavuk-Yumurta Probleminin Çözümü (bundles.php)
Symfony boot edilirken ilk olarak config/bundles.php dosyası okunur. Bu aşamada henüz veritabanı bağlantısı, servis konteyneri veya autoloader tam olarak ayağa kalkmamıştır. Modüllerin aktiflik durumunu doğrudan veritabanından okumaya çalışırsak, sistem daha boot edilemeden kilitlenir.
Çözüm: Bir modül aktif veya pasif edildiğinde CPalius, cp-core/config/active_modules.php adında statik, PHP opcache dostu bir dizi dosyası üretir. bundles.php sadece bu dosyayı okur; çekirdek bundle'lar her zaman yüklüdür ve her modül sınıfı yalnızca class_exists() başarılıysa eklenir.
2. Savunma Hattı: Çalışma Zamanı İzolasyonu (Kernel::boot Override)
Sınıfın fiziksel olarak var olması (class_exists), o modülün kodunun hatasız çalıştığı anlamına gelmez. Modülün kendi boot() metodu içinde fırlatacağı bir TypeError veya RuntimeException tüm sistemi çökertebilir. Bunu engellemek için Kernel::boot() override edilerek modül seviyesindeki tüm boot süreçleri try/catch (\Throwable) zırhıyla kuşatıldı; hatalı modül karantina günlüğüne yazılır, çekirdek çalışmaya devam eder.
3. Savunma Hattı: Compile-Time Kilitlenme Koruması & Dry-Run
Eklentideki bir services.yaml dosyasında geçersiz bir YAML sözdizimi varsa veya yanlış bir DI tanımı yapıldıysa, Symfony container'ı derlenemez. Bu durumda sistem çöker ve terminalden cp:module:deactivate komutunu bile çalıştıramayız.
Çözüm: Modül aktivasyonuna izole bir Dry-Run kontrolü entegre edildi. Modül sınıfı geçici olarak yazılır, symfony/process ile tamamen izole bir alt süreç başlatılır ve sırasıyla cache:clear --no-warmup → lint:yaml → lint:container koşturulur. Sıfır dışı bir exit code'da ana süreç finally bloğunda dosyayı geri getirir, aktivasyonu iptal eder ve modülü kalıcı karantinaya alır. Dosya asla bozuk haliyle kaydedilmez.
4. Savunma Hattı: İzole Route Yükleyicisi
Standart Symfony'de bir modülün routes.yaml dosyasındaki bir syntax hatası, rota yükleme anında tüm sistemi çökertir. SafeModuleRouteLoader her modülün rotalarını izole bir try/catch bloğunda yükler; hatalı modül atlanır, sistemin geri kalanı tamamen ayakta kalır.
3. Bölüm: Hibrit Veri Modeli ve Yüksek Performanslı Flat Index Sistemi
İçerik yönetiminde iki klasik yaklaşım da sorunludur:
- EAV (Entity-Attribute-Value) Modeli (Drupal): Her yeni alan için yeni bir veritabanı tablosu açılır. 15 özel alanı olan bir sayfayı çekmek için 15 JOIN sorgusu atılır; veritabanı kilitlenir.
- Postmeta/Serialized Modeli (WordPress): Tüm özel alanlar tek bir meta tablosunda satır satır tutulur. Filtreleme ve sıralama yapmak tam bir performans felaketidir.
CPalius Hibrit Veri Modeli: Sık sorgulanan, filtrelenen ve indekslenen temel alanları (ID, Başlık, Slug, Tür, Durum, Dil, Tarihler) gerçek veritabanı sütunları olarak tutuyoruz. İçeriğin kendisine ait tüm dinamik, esnek ve her projede değişebilecek alanları (Gövde metni, öne çıkan görsel, galeri alanları, SEO verileri) ise tek bir SQL json sütununda (data) saklıyoruz.
SQLite, MySQL ve Postgres Uyumluluğunda İndeksleme Çıkmazı
Dinamik JSON verilerini veritabanı düzeyinde sorgulamak isterseniz, SQLite, MySQL ve Postgres arasında tamamen farklı SQL sözdizimleri kullanmanız gerekir. Ayrıca generated columns üzerinde indeks oluşturmak Doctrine ORM şema araçlarıyla son derece kırılgandır; Doctrine her şema güncellemesinde bu indeksleri silmeye çalışır.
Çözüm: NodeFieldIndex ve Dinamik İndeksleme Motoru
CPalius bu sorunu bir Flat Field Index tablosu ve bir Doctrine Event Listener ile çözer. Bağımsız bir indeks tablosu, sorgulanacak dinamik alanlar için tip-uygun kolonlar (value_string, value_int, value_decimal, value_datetime) taşır; her biri field_name üzerinden bileşik indekslidir.
Geliştiricinin belirlediği QueryableFieldsRegistry yapılandırmasına göre, bir Node kaydedildiğinde veya güncellendiğinde NodeIndexListener otomatik olarak JSON data sütununu parse eder, eski indeksleri temizler ve postPersist / postUpdate anında idempotent şekilde yardımcı tabloya yazar.
Artık hangi veritabanı motoru kullanılırsa kullanılsın, JSON verileri NodeRepository::findByIndexedField() (type, locale, fieldName, value, valueColumn, operator) ile tek bir standart SQL/DQL sorgusuyla ışık hızında sorgulanabilir.
4. Bölüm: Çok Dilli Yapı ve Kompozit Benzersizlik Kısıtları
Çok dilli (i18n) yapı projelere sonradan eklendiğinde tüm veri modelini çökertir. CPalius, çoklu dili ilk günden çekirdeğin hücrelerine işlemiştir.
Kompozit Unique Constraints (Benzersizlik Güvencesi)
Çok dilli bir yapıda, klasik unique: true kısıtlamaları sistemi kilitler. Örneğin, Türkçe /tr/hakkimizda ile İngilizce /en/hakkimizda sayfalarının aynı anda var olabilmesi gerekir. Global tek bir slug unique kısıtlaması bunu engeller.
CPalius Çözümü: Veritabanı şemamızda kompozit benzersizlik kısıtları kullandık:
- Yönlendirme Benzersizliği: Aynı slug sadece aynı dilde unique olmalıdır:
UNIQUE(slug, locale). - Çeviri Grubu Benzersizliği: Aynı çeviri grubunda aynı dilden sadece bir adet içerik bulunabilir:
UNIQUE(translation_group_id, locale).
Aynı güvence, UNIQUE(translation_group_id, locale) ile dört entity'ye daha (categories, tags, menu_items, forum_sections) taşınmıştır; böylece "bir çeviri grubunda her dilden en fazla bir kayıt" kuralını eşzamanlı isteklerde bile veritabanının kendisi zorlar.
Operatör arayüz katalogları
AACP ve Studio kromu cp-content/translations altındaki ICU YAML'e ve her modülün Resources/translations dizinine bağlıdır. Kenar çubuğu etiketleri ve #[CpAdminMenu] öznitelikleri çeviri anahtarı kullanır. Sabit kodlanmış Türkçe (veya İngilizce) operatör metinleri PHP, Twig kromu veya JavaScript içinde yaşamaz.
5. Bölüm: "CMS"ten "Uygulama Framework'üne" Geçiş
CPalius sadece bir içerik yönetim sistemi (CMS) değildir; arkasında Oto Galeri, Turizm Acentası, Personel Yönetimi veya CRM/ERP sistemlerinin çalışabileceği esnek bir uygulama platformudur. Bu dönüşümü sağlamak için iki sınıf varlık tanımladık:
| Özellik | Content Entities (Node) | Business Records (Resource) |
|---|---|---|
| Kavramsal Karşılık | Sayfa, Yazı, İlan Vitrini, Blog | Araç, Fatura, Rezervasyon, Personel |
| Özellikleri | Slug var, çoklu dil var, yayın durumu var, SEO var. | Slug yok, dil yok, yayın yok, durum makinesi (workflow) var. |
| Ortak Payda | Aynı Yetenek (Capability) modeli, aynı Twig bileşenleri, aynı CLI yönetimi, aynı Config Sync. | |
#[CpResource] Devrimi
Geliştiricinin iş süreçlerini kodlamasını saniyeler seviyesine indirmek için özel bir PHP Attribute yapısı tasarladık. Tek bir anotasyon ile veritabanındaki ham bir Doctrine sınıfını platformun tüm güçleriyle birleştiriyoruz:
#[CpResource(
name: 'vehicle',
module: 'oto-galeri',
capabilities: ['create', 'edit', 'delete', 'view'],
auditable: true,
multiTenant: true,
workflow: 'vehicle_lifecycle'
)]
#[ORM\Entity]
class Vehicle
{
private ?int $id = null;
private ?string $plate = null;
private ?string $brand = null;
private ?int $price = 0; // Kurus bazinda saklanir (Float asla!)
}
Bu tek nitelik (#[CpResource]) sayesinde:
- Rol ve yetenek matrisine (
vehicle.create,vehicle.editvb.) dinamik yetenekler otomatik kaydolur. - Otomatik CRUD formları ve liste ekranları bu tanıma göre dinamik olarak türetilir.
- SaaS projeleri için çoklu kiracı (
multiTenant: true) izolasyonu arka planda otomatik uygulanır. - Entity üzerinde yapılan tüm değişiklikler anlık olarak sürüm geçmişine (audit log) kaydedilir.
İçerik platformu: alanlar, revizyonlar, workflow ve satır bazlı erişim
Hibrit veri modeli hikâyenin yarısıdır. CPalius bunun etrafına, bir tabloyu uygulamaya çeviren sözleşmeleri kurdu: özel alanlar, revizyonlar, editöryel durum makinesi, görüntüleme modları, metin biçimleri ve satır bazlı izinler. Her biri, kendi kategorisinin lideri olan sistemdeki belirli bir zaafa karşı tasarlandı.
Field API
Alan tipleri, widget'lar, formatter'lar ve alan başına ayarlar; FieldableInterface uygulayan her entity'ye takılabilir — bugün Node ve User, yarın #[CpEntityType] taşıyan her şey. Değerler entity'nin JSON kolonunda durur; sorgulanan alanlar için ayrı bir düz indeks tablosu vardır. Entity referansları satır satır değil toplu çözülür.
Kaçınılan tuzak WordPress'in postmeta'sı ve klasik EAV tablosudur: ikisi de "fiyatı 100'den büyük her yazıyı ver" sorgusunu bir join fırtınasına çevirir. Düz indeks, sorgulanabilir altkümeyi gerçek kolonlarda tutar; gerisi JSON'da kalır ve okunana kadar hiçbir maliyeti olmaz.
API'nin de uyduğu görüntüleme modları
Drupal'ın Manage Display'i olgun referanstır ve yapısal tek bir zaafı vardır: yalnızca temaya aittir. Bir "teaser" tanımlarsınız, JSON:API çıktısı onu görmezden gelir — şekli iki kez yazarsınız ve ikisi zamanla ayrışır. CPalius'ta tek bir EntityDisplayRegistry hem Twig oluşturucuyu hem API serileştiricisini besler; bir görüntüleme modu bir kere tanımlanır ve ikisinde de tutarlıdır. Bir test bu özelliği tutar.
Revizyon, moderasyon ve workflow
Moderasyon durumu, yayın durumundan ayrı bir kolondur; çünkü "incelemede" ile "yayında değil" farklı olgulardır ve tek alan bunları birbirine karıştırır. Altındaki workflow motoru, herhangi bir özne üzerinde çalışan ve YAML'da tanımlanan düz bir durum makinesidir: yerler, geçişler ve geçiş başına isteğe bağlı bir yetenek. İçerik moderasyonu onun tanımı değil, ilk tüketicisidir — yerleri teklif → onaylı → faturalı olan bir kurulum aynı motoru ve aynı ekranları kullanır.
Metin biçimleri: yalnız çıkışta değil, girişte de filtre
Drupal'ın Filter API'si referanstır ve yalnız çıktıda filtreler; bu da veritabanını temizlenmemiş işaretleme deposu olarak bırakır. Bir filtreyi kapatın, eski işaretleme canlanır. CPalius kayıtta allowlist, çıktıda dönüşüm uygular. Bir deny-list — script, style, form, kayıtta iframe — Full HTML dahil hiçbir biçim tarafından geçersiz kılınamaz. Yetki yazma anında yeniden kontrol edilir; full_html yetkisini kaybetmiş bir kullanıcının POST'u güvenilmez, reddedilir. Markdown, işlemeden önce ham HTML'i kaçırır.
Yeniden inşa gerektirmeyen satır bazlı erişim
Drupal'ın node access grant'leri referans uygulamadır ve bilinen dört maliyeti vardır: sıradan izinlerin yanında ikinci bir zihinsel model olan realm/gid yapısı; mantık her değiştiğinde gereken, atlandığında sessizce yanlış sonuç veren pahalı bir yeniden inşa; çekirdekte yalnız node desteği; ve verilen iznin gerçekten var olduğunu doğrulayan bir mekanizmanın olmaması.
CPalius dördüne de cevap verir. Grant'ler her şeyle aynı yetenek ad alanında ifade edilir, ikinci bir model yoktur. Her grant yazıldığı an bağımsız olarak doğrudur — unutulacak bir yeniden inşa yoktur. Entity tipi bir dizedir, dolayısıyla her #[CpEntityType] katılır. Bilinmeyen bir yetenek saklanmaz, reddedilir; bir yazım hatası sessizce "hiçbir şey" veremez. Sorgu tarafında satır başına kontrole değil, tek bir EXISTS alt sorgusuna derlenir.
Dürüst eksik: tek bir kaydı tek bir kullanıcıyla paylaşmak için tarayıcı arayüzü yok. Drupal çekirdeğinde de yok.
6. Bölüm: Güvenlik ve Performans Anayasası
Güvenlik ve performans, projenin son aşamasında "üzerine eklenen" birer cila değildir; sistemin en temel yapı taşlarıdır.
1. Yetenek Tabanlı Erişim Kontrolü (CBAC)
Standart Symfony ROLE_ADMIN veya ROLE_USER yaklaşımları hantaldır ve sonradan genişletilemez. CPalius'ta kodun hiçbir yerinde rol ismi kontrol edilmez; her zaman dinamik olarak üretilen yetenekler denyAccessUnlessGranted('system.module.manage') ile kontrol edilir.
- Roller = Config (YAML): Rol tanımları ve yetenek matrisleri
cp-content/config/sync/altında YAML dosyalarında tutulur ve Git ile taşınır. - Kullanıcılar = Content (DB): Gerçek kullanıcı kayıtları veritabanında kalır, asla dışa aktarılmaz.
2. SaaS Veri Sızıntısı Koruması (Automatic Tenant SQLFilter)
Çok kiracılı sistemlerde en büyük güvenlik açığı, yazılımcının bir sorgunun sonuna WHERE tenant_id = ? yazmayı unutmasıdır. CPalius'ta bu ihtimal platform seviyesinde yok edilmiştir: bir Doctrine SQLFilter, multi-tenant işaretli entity'ler için tenant kısıtını her sorguya enjekte eder.
3. N+1 Sorgu Muhafızı (Dev-Mode N+1 Guard)
Veritabanı şişmelerinin ve yavaşlıklarının en yaygın sebebi olan N+1 sorgu hatalarını engellemek için sadece dev ortamında tetiklenen bir Doctrine DBAL middleware'i devrededir. Tek bir HTTP isteğinde aynı tabloya atılan sorgu sayısı belirlenen limiti aşarsa, doğrudan MaxQueriesExceededException fırlatılır. Geliştirici bu hatayı lokalde çözmeden kodu canlıya alamaz. Zincir DBAL katmanında gerçektir: QueryCounterConnection, Driver, Statement ve TableParser.
4. Voter-to-SQL Dönüşümü
Liste ekranları her satır için PHP voter çalıştırmamalıdır (bu, yetkilendirmenin N+1'idir). QueryScopeApplier, çağıranın .own / .any yeteneklerini sorgu veritabanına gitmeden önce Doctrine WHERE koşuluna çevirir.
5. Zero-Trust Payload ve Çekirdek XSS Sterilizasyonu
Dışarıdan gelen HTTP gövdeleri sıkı DTO'lara map edilir ve denetleyicilere ulaşmadan doğrulanır. Veritabanına gidecek zengin metin RichTextSanitizer ile sterilize edilir (Manifesto Law 5.3). SchemaOrgBuilder aynı hibrit JSON'dan JSON-LD (BlogPosting, WebPage) üretir.
6. İyimser Eşzamanlılık
Yüksek yazma yolları tablo kilidi yerine optimistic locking kullanır; eşzamanlı mutasyonlar deadlock tiyatrosu olmadan izole edilir. Config (roller, yetenekler) Git'teki YAML'de kalır; kullanıcılar veritabanında kalır — Symfony TreeBuilder ile Drupal tarzı config sync.
7. Bölüm: Platform Genişletilebilirliği — API, Hook, Cron, Plugin
İlk whitepaper taslağından bu yana çekirdeğe dört genişletme omurgası indi. Her biri aynı Core Never Dies zırhını taşır: çöken bir eklenti karantinaya alınır; çekirdek ayakta kalır.
Kriptografik REST API Gateway
Tek bir /api/{path} joker rotası, derleme zamanında ApiRegistrationPass ile #[CpApi] işaretli servis metotlarına bağlanır. Kimlik doğrulama X-CP-API-KEY header'ı, SHA-256 hash ve zamanlama-güvenli hash_equals() ile yapılır. Fail-closed: geçersiz anahtar hedef metoda asla ulaşmaz. Her uç kendi try/catch'inde çalışır; çöken bir metot gateway'i 500'e düşüremez.
Çift kulvarlı izole Hook motoru
Cotonti tarzı Hooks/{hook_point}.php dosyaları bağlı bir Closure içinde çalışır; $this sızıntısı olmaz. Symfony tarzı #[CpHook] servisleri HookRegistrationPass ile toplanır. Fırlatan hook karantina günlüğüne yazılır; sayfa yine render edilir.
Birleşik hibrit Cron motoru
CronManager üç kaynağı tek listede birleştirir: cp_cron_jobs satırları, #[CpCronJob] metotları ve Hooks/cron.{job}.php dosyaları. Görevler izole alt süreçlerde çalışır ve CronCommandWhitelist ile yalnızca cp:* komutlarını çalıştırabilir. Operatörler /aacp/cron üzerinden izler ve “Şimdi çalıştır” der.
Modülden bağımsız Plugin katmanı
PluginInterface işaretli servisler PluginRegistry tarafından toplanır; aktiflik PluginToggleRepository'dedir. Bir modül, kendisini kapatmadan opsiyonel widget'ları açıp kapatabilir.
Lazy ayarlar
#[CpSetting] anahtarları SettingsRegistry üzerinden talep edilince yüklenir — boot'ta her anahtarı dökmez, sorulunca tek sorgu atar.
WordPress tarzı modül paketleri
Birinci parti bir modül Resources/config/importmap.php ve contributions.yaml taşıyabilir. ModulePackageContract disk düzenini doğrular; operatörler AACP'den ZIP yükleyebilir. Ana sayfa kipleri, portal akış blokları, şema türleri ve hesap giriş-sonrası iniş noktası contribution kataloğunda ilan edilir — çekirdek forum_index veya blog_index'i sabit kodlamaz.
Migrate: bir kurulumu başka bir CMS'ten taşımak
Kimse verisini taşıyamadığı bir framework'e geçmez. CPalius göç motorunu çekirdekte, yabancı sistem okuyucularını modülde taşır — çekirdek CPalius yazar, modül başkasının şemasını okur. Beş kaynak sistem tek motor üstünde koşar: dosyadan WordPress; doğrudan veritabanından XenForo, MyBB ve Joomla; ve CSV.
Referans uygulamanın zaaflarına karşı tasarım
Drupal'ın Migrate API'si aşılması gereken standarttır ve dört maliyeti vardır. Kuru çalıştırma yoktur — ne yapacağını, yaptırarak öğrenirsiniz. Bir migration, yazım hataları koşumun ortasında patlayan tipsiz dizelerden oluşan bir YAML eklenti çorbasıdır. Çekirdek tek başına koşamaz; contrib bir araç gerekir ve çekirdek arayüzü yalnız Drupal'dan Drupal'a çalışır. Geri alma da id haritasının kaydettiği kadar iyidir.
CPalius dördünü de tersine çevirir. Kuru çalıştırma varsayılandır ve gerçeğiyle aynı sayaçları üretir; --apply bilinçli bir eylemdir. Dönüşümler düz PHP'dir; IDE tamamlar, statik çözümleyici denetler. Koşucu çekirdektedir. Geri alma kesindir, çünkü haritayı koşucunun kendisi, hedefe yazma başarılı olduktan sonra yazar — öncesinde değil, migration da değil.
Dört garanti
- Idempotent.
(migration_id, source_id)üzerindeki tekil anahtar garantinin kendisidir — iki koşum çakıştığında bir satırın iki kez aktarılmasını kayıt tutma değil, veritabanı durdurur. Değişmemiş satır atlanır, değişmiş satır yerinde güncellenir. - Satır başına izolasyon. Bozuk tek kayıt yalnız kendisi düşer; komşuları aktarılır.
- Bildirime göre sıra. Bağımlılıklar topolojik çözülür; döngü ya da tanınmayan bağımlılık sessizce atlanmaz, reddedilir.
- Akışlı. WordPress okuyucusu export'u
XMLReaderile gezer; WordPress'in kendi içe aktarıcısı tüm dosyayı belleğe alır. Veritabanı kaynakları keyset ile sayfalanır, böylece koşum sırasında büyüyen bir tablo atlanan sayfaya yol açamaz.
Şemaların asıl öğrettiği
İlginç iş asla boru hattı değildir, kaynaktır. MyBB kategorileri ve forumları tek tabloda, tek bir karakterle ayırarak tutar; bir bağlantı ise linkto değeri olan bir forumdur — tip kolonuna güvenmek, birinin bağlantısını boş bir bölümle değiştirirdi. closed kolonu moved|tid tutabilir, dolayısıyla "1" ile karşılaştırmak taşınmış bir konuyu açık okur. Joomla tablo ön ekini kurulumda rastgeleleştirir, id = 1 kategorisi bir kategori değil nested-set çapasıdır ve makale gövdesi, birleştirilmezse her uzun makalenin sessizce kırpılmasına yol açan iki kolona bölünmüştür.
Bunlar kaydediliyor, çünkü koşan bir içe aktarma ile doğru bir içe aktarma arasındaki fark bunlardır.
Kanıtın sınırı
Sürücüler belgelenmiş şemalardan yazıldı ve onlara uygun kurulmuş fixture'lara karşı test edildi. Bu, eşlemeyi kanıtlar. Her gerçek kurulumla uyumu kanıtlamaz — sürüm farkları, eklenti kolonları ve on yıllık bir forumun biriktirdiği tuhaflıklar gerçektir. Gerçek bir veritabanına karşı ilk koşum hâlâ gerçek bir testtir; kuru çalıştırmanın varsayılan olmasının ve hataların kaynak satır id'siyle raporlanmasının sebebi tam olarak budur.
8. Bölüm: AACP Komuta Masası, Studio ve Kurtarma
Orijinal yol haritasında vaat edilen Safe Mode / Kurtarma Konsolu artık üretim kodudur. AACP süs bir admin teması değil, sistem yönetim merkezidir.
Kurtarma Konsolu (/aacp/recovery)
Rota security.yaml'da bilinçli olarak PUBLIC_ACCESS'tir. Yetki, .env'deki AACP_RECOVERY_TOKEN ile zamanlama-güvenli hash_equals()'tir. Hiç Doctrine sorgusu çalıştırmaz; veritabanı yokken de ayaktadır. Boş token kapıyı kilitler (fail-safe).
Canlı komuta masası (/aacp)
Dashboard /aacp/system/metrics'i poll eder: PHP sürümü, load, istek süresi, bellek, OPcache hit oranı, veritabanı telemetrisi, kuyruk, cron son çalışma, modül karantinası. Cache Rebuild ve OPcache flush tek tık, CSRF korumalıdır. İçerik KPI'ları Studio /admin'dedir, AACP'de değil — AACP operasyon, Studio editoryal komuta masasıdır.
Studio dashboard
Her ilk parti modül bir StudioDashboardStatsProvider sunar (Blog, Forum, Medya, Menü, Roadmap, SEO). Studio Drupal tarzı bir komuta masasıdır: sayılar, kısayollar ve ana sayfa portal düzeni (blok sırası, portal.{locale}.yaml içinde çift dilli metin).
Karantina, lokalizasyon, performans backend'leri
/aacp/quarantine, module_quarantine.log'un salt-okunur görünümüdür. TranslationManager çekirdek ve modül ICU YAML'ini atomik .tmp + rename() ile yazar. Performans ekranı Redis, Memcached, Varnish, Nginx PageSpeed ve CPalius Origin Cache'i test eder; “aktif” bayrağı yalnızca başarılı probe'dan sonra konur — sahte yeşil toggle yoktur. /aacp/backup Yedek Yönetimi masasıdır (system.backup.manage yeteneği): veritabanı dökümü, dosya ZIP'i veya tam arşiv; indirme ve silme dahildir.
Bir kurulumu işletmek: güncelleme, teşhis, kuyruklar ve loglar
Bir sistemin ömrünün büyük kısmı kurulduktan sonra geçer. Aşağıdakiler o yarıyı ele alan sözleşmelerdir.
cp:update — sıralı ve devam ettirilebilir tek boru hattı
Önce bekleyen migration'lar, sonra çekirdek güncelleme kancaları, sonra her modülün kendi yükseltme adımı, sonra yapılandırma içe aktarımı, sonra cache yeniden inşası. Drupal'ın update.php'si ve WordPress'in wp core update-db'si şema kısmını yapar ama veri düzeltmelerini ayrı bir mekanizmaya bırakır. Burada bir güncelleme kancası, defteri olan tipli bir arayüzdür ve sürümle etiketlidir; birkaç sürüm atlansa bile yayın sırasıyla uygulanır.
Devam ettirilebilirlik sonradan eklenmedi, tasarımın kendisinde: defter kaydı kanca döndükten sonra yazılır, böylece yarıda kesilen bir kanca "yapıldı" sanılmak yerine tekrar çalışır. Bozuk bir defter boş okunur, asla "hepsi bitti" olarak değil. Patlayan bir kanca komşularını durdurmaz; boru hattını yalnızca migration hatası durdurur. --dry-run hiçbir şeye dokunmadan tüm planı raporlar — üretimde önce onu koşarsınız.
Kapattığı boşluk sıradan ve pahalıydı: manifest sürümü ilerleyen bir modül, yükseltme adımını yalnızca elle kapatılıp açıldığında çalıştırıyordu — ve operatörün hangi modüllerin buna ihtiyacı olduğunu bilmesinin bir yolu yoktu.
cp:doctor ve cp:debug
CPalius kendini büyük ölçüde attribute'larla keşfeder — #[CpHook], #[CpCronJob], #[CpResource], #[CpEntityType], #[CpFieldType]. Bu, bir modüle çok az törenle çok geniş erişim kazandırır ve tek bir maliyeti vardır: bir kanca noktasındaki yazım hatası bir hata değil, sessizliktir. cp:debug, "benimki kaydoldu mu?" sorusunu breakpoint koymadan cevaplar; cp:doctor ise "bu kurulum, kendi kodunun beklediği durumda mı?" sorusunu.
İkisi de salt okunurdur, ikisi de CI için JSON üretir ve cp:doctor'un bir hata eşiği vardır — geçersiz bir eşik, kapıyı sessizce kapatmak yerine reddedilir.
Ayrı ayrı raporlanan iki kuyruk
Mail ve bildirimler Symfony Messenger üstünde koşar; bu da yerel yeniden deneme ve hata taşıyıcıları getirir. Webhook'lar platformun kendi AsyncJob tablosunda kalır; SSRF koruması ve imza yolu orada zaten olgundur. Yönetim ekranı ikisini ayrı sayılar olarak raporlar ve hiçbirini tarif etmeyecek tek bir toplamda birleştirmez.
Kaydettiği şeyden sağ çıkan loglar
Uygulama logları, mail logları ve güvenlik telemetrisi tek tablo değil, üç tablodur. Denetim kayıtları entity farklarını tutar; telemetri güvenlik olaylarını; watchdog uygulama arızalarını. Bunları tek tabloya sıkıştırmak her birini kötüleştirirdi. Log işleyicisi tamponlu, istek sonunda boşaltılan ve asla istisna fırlatmayan bir yapıdır — tarif ettiği isteği düşürebilen bir logger, yükümlülüktür.
9. Bölüm: Origin HTML Cache ve Performans Envanteri
CPalius Origin Cache, Redis, Varnish veya CDN gerektirmeyen birinci parti bir HTML önbelleğidir. Bu backend'lerin yanında durur; sade paylaşımlı hostingde de çalışır.
İsabet nasıl servis edilir
Açık/kapalı durumu public/page-cache/ altındaki disk sentinel'idir. public/.htaccess içindeki Apache rewrite, sorgu dizesi ve oturum çerezi (PHPSESSID, REMEMBERME) olmayan anonim GET isteklerinde page-cache/{path}/index.html dosyasını servis eder. PHP yazmayı ve sorgu-dizesi varyantlarını OriginCacheWriter / OriginCacheReader ile okumayı sürdürür.
Ne saklanır
HTML isteğe bağlı minify edilir. Bağlı CSS/JS kopyalanıp minify edilebilir; görseller WebP türevi olarak üretilebilir. İsteğe bağlı HTML kalkanı işaretlemeyi yeniden yazar. TTL, hariç tutulan yollar (/aacp, /admin, /login, API'ler, profiler), minify, asset/görsel sıkıştırma ve kalkan performance.cpalius.* ayarlarıdır. Cron cpalius.origin_cache.purge süresi dolan dosyaları 15 dakikada bir siler. Cache Rebuild origin HTML'i de temizler.
Geçersiz kılma
OriginCachePurger Blog yazı/kategori/etiket yazımlarında (zamanlanmış yayın dahil), Forum konu mutasyonlarında, Roadmap kayıt kaydında ve Menü kaydında çalışır — editoryal değişiklik diskte bayat HTML bırakmaz.
AACP Performans paneli
Dashboard'daki Performans bölümü, PHP sürecinin görebileceği her backend'in envanterini çıkarır:
- Origin Cache: HTML sayfa adedi, disk baytı, son yollar (boyut ve zaman).
- Redis:
DBSIZE(anahtar sayısı) veINFO memory(used_memory). - Memcached:
curr_itemsvebytes(daemon cevaplıyorsa hit sayısı). - OPcache: önbellekteki script'ler, kullanılan bellek, hit oranı.
- Varnish / PageSpeed: açık/kapalı ve TTL / son probe. Nesne sayıları host'ta
varnishstatveya PageSpeed admin ister; PHP bu sayıları uydurmaz.
Probe'lar izole edilir ve birkaç saniye önbelleğe alınır; takılan bir Redis dashboard'u 500'e düşüremez.
10. Bölüm: Yedek Yönetimi
Felaket kurtarma üçüncü parti bir eklenti değil, birinci parti bir AACP masasındır. system.backup.manage yeteneği /aacp/backup yolunu korur. Admin rolü bunu * ile miras alır; editörler menüyü görmez.
Üç arşiv türü
- Veritabanı: Doctrine DBAL üzerinden PHP ile yazılan gzip SQL dökümü.
mysqldumpgerekmez; Windows'ta Laragon, Linux hosting ile aynı şekilde çalışır. - Dosyalar: tüm CPalius ağacının ZIP'i;
cp-includes/vendorve tümpublic/dizini (yüklemeler, derlenmiş asset'ler, temalar, front controller) dahildir. Dışarıda: her.env*dosyası,.git,node_modules, Symfony cache, Tailwind derleme önbelleği, oturumlar, Origin Cache HTML vecp-core/var/backups/altındaki iç içe arşivler. - Tam: aynı arşivin içine
database.sql.gzeklenmiş dosya ZIP'i.
Arşiv adları cpalius-{db|files|full}-YYYYMMDD-HHMMSS.{sql.gz|zip} biçimindedir ve cp-core/var/backups/ altında durur (zaten gitignore). İndirme /aacp/backup/archive/{stem} kullanır (URL'de .sql.gz / .zip yoktur) ki nginx statik-dosya location'ı isteği kesmesin; Content-Disposition yine gerçek dosya adını gönderir. Silme CSRF korumalıdır. Path traversal dosya adı allowlist'i ile reddedilir. CLI cp:backup:create cron whitelist'indedir; operatörler web zaman aşımı olmadan döküm zamanlayabilir.
v1 tarayıcıdan canlı ağacı üzerine yazmaz. Geri yükleme önce staging'dir: dosyaları taze bir kurulumun yanına açın, SQL'i veritabanının bir kopyasına uygulayın, sonra yer değiştirin. Geri yüklemeyi tek tık AACP düğmesinin arkasına koymak Core Never Dies'ı ihlal eder.
11. Bölüm: Güvenlik Telemetrisi ve IP Denetimi
AACP, kamu sitesini karanlık-kalıp bir izleyiciye çevirmeden istek telemetrisi tutar. Ana anahtar telemetry.security_enabled'dır ve varsayılanı kapalıdır.
Ziyaretçi modu (varsayılan)
Dashboard sayfa görüntüleme, benzersiz IP, popüler yollar ve trafik grafiği gösterir. Tehdit akışı yoktur, Ban IP yoktur. Pazarlama sitesini, operatörün yüzüne bir WAF konsolu yapıştırmadan barındırmak için uygundur.
Güvenlik modu
Açıldığında kernel.terminate üzerindeki TelemetrySubscriber, cp_system_telemetry_logs'a satır yazar: IP, kullanıcı, metot, URI, user-agent, şiddet, olay türü, tehdit skoru ve JSON ayrıntı. ThreatAnalyzer SQLi, XSS, tarayıcı, path traversal ve giriş gürültüsünü skorlar. Canlı akış JSON poll eder; ayrıntı modalı satırı açar; Ban IP yalnızca critical / threat şiddette sunulur.
IP ban
IpBanService cp_banned_ips'e yazar. BannedIpSubscriber yasaklı istemciyi yığının geri kalanı bütçe harcamadan reddeder. Bir cron görevi eski telemetri satırlarını siler; tablo sınırsız büyüyemez.
12. Bölüm: İlk Parti Modüller, Medya Pipeline ve Deep-Localization
Blog, Medya, Menü, Forum, Roadmap, Pages ve SEO referans modülleridir: API, Hook, Cron, Plugin, Settings, contribution kataloğu ve Studio istatistiklerini üçüncü parti bir modülün kullanması gereken şekilde kullanırlar.
Blog Node::type = post üzerindedir; kategori, etiket, zamanlanmış yayın (PublishScheduledPostsTask), GET /api/blog/posts, sidebar hook ve Schema.org BlogPosting. Pages Node::type = page üzerindedir; alan grupları fg- slug kullanır ve kamu rotası /{_locale}/{slug} adresindeki page_show'dur. Menü WordPress tarzı sürükle-bıraktır; öğeler node'a gevşek referans verir (sert FK yok) ki soft-delete dürüst kalsın. Roadmap yerli bir akıştır; portala ilişkili blog ve forum etkinliğini de çekebilir. SEO sitemap kaynakları ve JSON-LD üretir.
Forum motoru
Hiyerarşik panolar Node ağacını yeniden kullanır; önekler, CSRF korumalı rapor/moderasyon kuyruğu, rütbe/rozet ve 20/80 postbit (Altın Oran) CMF'in geri kalanıyla aynı yetenek modelinde çalışır.
Medya pipeline (Manifesto Law 3.3)
Asset Node'dan bağımsızdır. Flysystem depolama ve sha256 dedup. ImageProcessor (GD) crop veya fit türevlerini public/uploads/cache/ altına yazar; cp_thumb bir Asset, id, depolama anahtarı veya /uploads/... URL kabul eder. Başarısız türev orijinal URL'i döner (fail-soft). Kaynak değişince purge() tüm boyutları siler.
Deep-localization
Her satır kendi dilinde yaşar ve kardeşlerine translation_group_id UUID'si ile bağlanır; kural UNIQUE(translation_group_id, locale) ile zorlanır (kategoriler, etiketler, menü öğeleri, forum bölümleri dahil). LocaleSwitchService karşı URL'i üretir; kardeş yoksa o dilin ana sayfasına düşer — asla 404. AACP'de locale öneki yoktur; panel dili cp_locale çerezidir. Çeviri dosyaları atomik yazılır (.tmp + işletim sistemi rename()).
Çekirdek arayüzde Zero Node.js
Admin ve geliştirici kromu AssetMapper + Tailwind standalone binary kullanır. Bu yüzeyler için Node.js derlemesi yoktur. Kamu tema CSS'i yine statik bir tema varlığı olabilir.
Bu belgedeki iddialar nasıl doğrulanıyor
Yukarıdaki her mimari iddia, onu doğru tutan kapı kadar değerlidir. CPalius her değişiklikte aşağıdakileri koşar; yapı uyarmaz, düşer.
- PHPStan seviye 6 — çekirdek, modüller ve testler; takip edilen bir baseline ile. Hatalar bastırılmaz, düzeltilir; bir baseline girdisi eşleşmeyi bıraktığında silinir — ölü kodun fark edilme yolu budur.
- İki test paketi. Birim testleri veritabanısız koşar; entegrasyon testleri gerçek bir çekirdeği gerçek bir MySQL şemasına karşı ayağa kaldırır ve testler arasında şemayı eşlemeye değil veritabanına bakarak sıfırlar — paketin kararsızlığının kökü tam olarak bu ayrımdı.
- Modüller için üçüncü bir paket, böylece bir modülün davranışı bağımlı olduğu çekirdekle aynı koşumda kanıtlanır.
- Statik lint kapıları: container (dev ve prod), YAML, Twig ve kod stili.
cp:doctoryalnız destek aracı değil, bir yapı adımı: bekleyen migration'lar, karantinadaki modüller, rollerde olup hiç kayıtlı olmayan yetenekler, kataloglar arası çeviri anahtarı eşliği, ortam yanlış yapılandırması, güvenlik duruşu ve çalışmamış güncelleme kancaları.
Bir şey kaçtığı için var olan iki kapı
Çeviri kontrolü satır sayısını değil anahtar kümesini karşılaştırır. Satır sayısı aynı olan iki katalog farklı anahtarlar taşıyabilir ve eksik olan, üretimde ham bir tanımlayıcı olarak ekrana basılır.
cp:doctor soyut olarak tasarlanmadı, bir olaydan sonra yazıldı. Beş migration birkaç geliştirme oturumu boyunca uygulanmadan durdu ve hiçbir şey yüksek sesle bozulmadı; çünkü o tablolara ihtiyaç duyan özellikler sessizce bozulacak şekilde yazılmıştı. Tek belirti, güvenlik telemetrisinin hiçbir yere yazmamasıydı. Bu yüzden uygulanmamış bir migration YÜKSEK olarak derecelendirilir: tehlike başarısız olması değil, olmamasıdır.
Bir teşhis aracı, teşhis ettiği kurulumdan sağ çıkmalıdır. Bir kontrol patlarsa koşu devam eder ve istisna bir bulguya dönüşür. İlk gerçek problemde ölen bir doktor, tam ihtiyaç duyulduğu anda işe yaramaz.
Kıyas: CPalius'un Drupal, TYPO3, WordPress ve ProcessWire karşısındaki yeri
Bir framework sıfatlarla değil kanıtla seçilir. Bu bölüm, projenin en sık kıyaslandığı dört sisteme karşı tuttuğu skor kartıdır ve düzeltilmeden yayımlanır — CPalius'un geride olduğu satırlar ve henüz hiç ölçülmemiş olan tek satır dahil.
Ölçek. D yok · C ilkel/parça · B kısmi · A olgun · A+ sınıfının en iyisi · A++ alanın önünde.
Sütunlar. CP CPalius · DR Drupal 10/11 · T3 TYPO3 v13 · WP WordPress 6.x · PW ProcessWire 3.x.
| # | Yetenek alanı | CP | DR | T3 | WP | PW |
|---|---|---|---|---|---|---|
| 1 | Çökmeyen çekirdek / modül izolasyonu | A+ | B | B | C | B |
| 2 | Güvenlik-varsayılan (CBAC, tenant, N+1 guard, XSS) | A++ | A | A | C | A |
| 3 | Hibrit veri modeli + flat index | A | B | B | C | A |
| 4 | Entity API (tek fieldable/revision/i18n/access sözleşmesi) | B | A+ | B | C | A |
| 5 | Field API (tip + widget + formatter + ayar) | B | A+ | A | C | A |
| 6 | Sorgu API (EntityQuery / Selector) | B | A | B | B | A+ |
| 7 | Satır-bazlı erişim (grant + query alter) | A+ | A+ | B | C | B |
| 8 | Taksonomi (fieldable vocabulary + term) | A++ | A+ | A | A | A |
| 9 | Revizyon + moderasyon + workflow | B | A+ | A | B | C |
| 10 | Tipli entity yaşam döngüsü olayları | A+ | A | B | C | A |
| 12 | Görüntüleme modları | A | A+ | A | A | C |
| 13 | Cache API (tag/context) + reverse-proxy purge | A++ | A+ | A | C | B |
| 14 | Origin / tam-sayfa HTML cache (çekirdekte) | A | A | A | D | B |
| 15 | Text format + filtre hattı (rol bazlı) | A+ | A+ | B | B | B |
| 16 | Token + desen-bazlı path alias | A+ | A+ | A | B | B |
| 17 | Config management (kod olarak config) | A | A+ | B | D | B |
| 18 | Çoklu dil — içerik + arayüz | A | A+ | A+ | C | A |
| 19 | Medya boru hattı + responsive image + oEmbed | B | A | A | A | A |
| 20 | Async kuyruk + bildirim primitifi | A++ | B | B | B | C |
| 21 | Multisite / domain / organizasyon | C | A | A+ | A | B |
| 22 | REST / JSON:API / headless auth | B | A+ | B | A | B |
| 23 | Hook / eklenti ergonomisi | B | A | B | A+ | A |
| 24 | Cron / zamanlanmış görevler | A | A | A | C | B |
| 25 | Modül paketleme + lifecycle + tek-tık kurulum | A | A | A | A+ | B |
| 26 | Migrate / CMS-ten CMS-e veri taşıma | A+ | A+ | B | B | C |
| 27 | Admin UI + kurtarma konsolu | A+ | A | A | A | A |
| 28 | Güvenlik telemetri + IP ban (çekirdekte) | A | C | C | C | C |
| 29 | Yedekleme (çekirdekte) | A | C | C | C | C |
| 30 | DX: maker + doctor + test kit + geliştirici dokümanı | A | A | B | B | B |
| 31 | Sürüm politikası + BC garantisi + LTS | D | A+ | A+ | A++ | A |
| 32 | Kurulum deneyimi (beş dakika kuralı) | B | B | C | A++ | A |
| 33 | Dokümantasyon | C | A+ | A+ | A+ | A+ |
| 34 | CI / otomatik kalite kapısı | A | A+ | A | B | B |
| 35 | Paket ekosistemi + dağıtım kanalı | D | A+ | A | A++ | B |
| 36 | Güvenlik açığı bildirim süreci + CVE | B | A++ | A+ | A | B |
| 37 | Performans kanıtı (benchmark) | D | B | B | C | A |
| 38 | Erişilebilirlik (WCAG) — admin UI | ? | A+ | A | A | C |
| 39 | Gözlemlenebilirlik (log / metrik / health) | A | A | A | C | B |
| 40 | DB taşınabilirliği | C | A+ | A | C | C |
11 numara bilinçli olarak yok. Eskiden "Views / kodsuz listeleme" yazıyordu ve yeniden numaralandırmak yerine kaldırıldı: site kurucu bir arayüz web sitelerine hizmet eder, bu çekirdeğin var olduğu CRM, ERP ve panel kurulumlarına değil. Numaralandırmadaki boşluk, görünür bırakılmış bir karardır.
CPalius'un önde olduğu yerler
- Çökmeyen çekirdek (satır 1). Dört savunma hattı — statik
active_modules.php, modül boot'unu sarantry/catchkalkanı, etkinleştirme öncesi kuru çalıştırma lint'i ve bozuk modüle rağmen ayakta kalan rota yükleyici. Hatalı modül karantinaya alınır; Drupal'da aynı durum beyaz ekrandır. - Güvenlik-varsayılan (satır 2). Bilinmeyeni reddeden yetenek tabanlı erişim, tenant SQL filtresi, geliştirmede N+1 tripwire'ı, voter'dan SQL'e kapsamlama, nonce'lu CSP, engelleyen WAF, CIDR ve süreli IP yasakları, akış ve kaba kuvvet savunması, HIBP parola politikası, çekirdekte TOTP iki faktör, şifreli ayar sırları ve puanlı
cp:security:audit. Drupal'da bunların her biri ayrı bir contrib modül; WordPress'te birkaçı ücretli eklenti. Hiçbirinde tek bir ekran ve tek bir duruş puanı yok. - Taksonomi, cache tag'leri, async kuyruk (satır 8, 13, 20). Cache geçersizleştirme bir yeniden inşa adımı gerektirmez: bir entity kaydedilince tipli yaşam döngüsü olayı yayılır ve tag indeksi kendini temizler. Drupal'ın karşılığı olgun ama erişim sistemi, atlandığında sessizce yanlış sonuç veren bir rebuild adımıyla ünlüdür.
- Yedekleme, telemetri, kurtarma konsolu (satır 27–29). Hepsi çekirdekte ve
/aacp/recoveryveritabanı olmadan çalışır — tam da veritabanının kendisi bozukken ihtiyaç duyduğunuz ekran.
CPalius'un geride olduğu yerler, açıkça
- Sürüm politikası ve paket ekosistemi (satır 31, 35 — ikisi de D). Semantik sürüm sözü, geriye dönük uyumluluk belgesi ve modül deposu yok. Güncelleme makinesi var (
cp:update); etrafındaki politika yok. - Dokümantasyon (satır 33 — C). README ve SECURITY.md var. Geliştirici el kitabı yok. Karttaki en düşük not budur ve bir gözden kaçma değil, bitmemiş iştir.
- Performans kanıtı (satır 37 — D). Mimari hız için kurulmuş ve yayımlanmış tek bir ölçüm yok. Bir tane çıkana kadar iddia bir argümandır, ölçüm değil.
- Veritabanı taşınabilirliği (satır 40 — C). Her migration ham MySQL DDL'i. ORM katmanı taşınabilir, kurulum değil.
- Erişilebilirlik (satır 38 — ölçülmedi). Yönetim arayüzü WCAG'a karşı hiç denetlenmedi. Bunu "bilinmiyor" diye raporlamak, bir not uydurmaktan daha yararlıdır.
13. Bölüm: Gelecek Yol Haritası ve Teknik İstişare (RFC)
CPalius'un çekirdek güvenlik, performans ve mimari omurgası tamamlanmıştır. Bu whitepaper'ın ilk taslağından bu yana teslim edilenler: AACP Safe Mode / Kurtarma Konsolu, izole Hook sistemi, birleşik Cron motoru, REST API Gateway, dördüncü savunma hattı (SafeModuleRouteLoader), anlık görsel pipeline'ı (cp_thumb), #[CpResource] audit log, Studio dashboard istatistikleri, CPalius Origin Cache, AACP performans envanteri, isteğe bağlı güvenlik telemetrisi (IP ban dahil), WordPress tarzı modül paketleri ve contribution kataloğu (ana sayfa, portal, şema, hesap inişi), Pages modülü, operatör arayüz katalog bağlama ve AACP Yedek Yönetimi (cp:backup:create).
Sıradaki geliştirme sprintlerinde aşağıdaki sistemleri inşa edeceğiz:
- Workflow & State Machine: Fatura, araç, rezervasyon gibi iş kayıtlarının geçiş süreçlerini (
draft → preparation → sold) YAML tanımlarıyla yöneten ve her geçişi otomatik audit log'a ve bildirim kuyruğuna bağlayan mekanizma.CpResource::$workflowalanı zaten deklare edilmiştir. - Messenger Async Kuyruk: Gerçek bir transport (Doctrine/Redis) bağlayarak e-posta ve bildirim işlemlerini asenkron kuyruğa taşımak.
symfony/messengerkurulu ve AACP masasında görünür; henüz aktif transport bağlı değildir.
Soru ve Görüşleriniz (Topluluk İstişaresi)
Bu mimariyi daha da kusursuzlaştırmak için siz değerli geliştiricilerden şu konularda geri bildirim bekliyoruz:
- Flat Field Index Modeli: SQLite, MySQL ve Postgres uyumluluğu için tasarladığımız bu model sizce devasa veri hacimlerinde nasıl bir performans gösterir? İndeks tablosunun partition edilmesi gerekir mi?
- Config Sync Yaklaşımı: Drupal'ın config sync sistemini Symfony'nin TreeBuilder yapısıyla taklit etme fikrimiz hakkındaki düşünceleriniz nelerdir?
- Zero Node.js Israrı: Geliştirici ve admin panelinde AssetMapper + Standalone Tailwind kullanma kararımız, gelecekte çok karmaşık frontend bileşenleri yazarken bizi kısıtlar mı?
Fikirlerinizi, eleştirilerinizi ve mimari önerilerinizi heyecanla bekliyoruz. CPalius, topluluğun gücüyle en sağlam uygulama framework'üne dönüşecek.