# Yasal sayfa motoru — şirket/yasal ayarlar, şablonlar, çerez envanteri > **Kaynak:** `Core/Support/Definitions/Legal/` (3 sınıf) · `Core/Services/System/LegalService.php` · `Core/Services/System/Handlers/LegalSchemaHandler.php` · `Core/Services/Console/Handlers/LegalHandlers.php` · `Resources/Views/RbnCommon/Legal/*.legal.html` (9 şablon) > **Ölçüt:** `docs/yasal/*` (kvkk-web-sitesi-gereksinimleri, gizlilik-politikasi-ve-iletisim-sayfalari, eticaret-mesafeli-satis). Hukuki yorum yapılmaz; şablon metinleri §7. ## 1. İlke Yasal sayfa bir **veritabanı satırı değildir**. Proje yalnız **veri** verir (şirket, iletişim, sosyal ayarlar; entegrasyonları); sayfanın metni framework şablonundan gelir, yer tutucular ayardan dolar. Projede yasal metin, yasal sayfa satırı ya da `page()` metodu bulunmaz: `z_app_pages` tablosu framework'te YOKTUR (kapı `G-yasal-07`, `G-yasal-10`). | Parça | Görev | |---|---| | `LegalPages` | **Tek kayıt defteri:** sayfalar (`PAGES`: slug → başlık, özet, açılma koşulu, sıra), yer tutucu → ayar anahtarı bağı (`PLACEHOLDERS`), kimlik listesi (`IDENTITY`), eski/kısa adresler (`ALIASES`) | | `LegalTemplate` | Şablon motoru (saf, katı): doldurur ve doğrular | | `CookieInventory` | Sitenin kurduğu çerezlerin **tek kayıt defteri** | | `LegalService` (`service('legal')`) | Projenin yayındaki yasal sayfaları (`pages()`), tek sayfa (`page($slug)`), yetenekler (`capabilities()`), bağlantı verisi (`link($slug)`, `links()`: slug, başlık, `path`, `url`; sayfa yayında değilse `null`). Görünümde `legal_link($slug)` / `legal_links()`; adresi tek yerde `LegalPages::path()` yazar. Proje slug'ı ham yazmaz, `/sayfa/...` adresi üretmez (kapı `G-yasal-07`) | | `LegalSchemaHandler` + `rbn legal:install` | Kaldırılan ayar satırlarını ve statik yasal sayfa tablosunu siler; ayar satırı EKLEMEZ | ## 2. Ayar şeması (veritabanında, projeden bağımsız tek şema) Anahtarlar `SettingsConfig::DEFAULT_SETTINGS` içindedir. Mevcut anahtarlar **yeniden kullanılır**, ikinci kopya açılmaz. | Yer tutucu | Grup / anahtar | Not | |---|---|---| | `company_name` | `company` / `company-name` | marka / görünen ad | | `company_legal_name` (Unvan) | `company` / `company-legal-name` | hukuki unvan; satışlı sitede dolu olmalı. `company-name` marka/görünen addır: ikisi ayrı alandır, biri ötekine yedek olmaz (yasal sayfada "Unvan" = `company-legal-name`) | | `company_owner_name` (Site Sahibi) | `company` / `company-owner-name` | **isteğe bağlı, açık karar (FRW-30):** yalnız GERÇEK KİŞİNİN sitesi için sahibin adı soyadı. Dolu ise `{{company_identity}}` listesinde ilk satır "Site Sahibi: " basılır (künye, KVKK/gizlilik veri sorumlusu, çerez, telif, kullanım koşulları aynı listeyi kullanır); `Unvan` yalnız `company-legal-name` doluysa ayrı satır olarak yazılır. Boşsa hiçbir şey değişmez. Şirket/kişi ayrımı VERGİ/MERSİS alanlarının boşluğundan TAHMİN EDİLMEZ (Rbnbilisim gibi unvanlı ama vergi alanı boş siteler yanlış sınıflanırdı); kişi sitesi bu ayarı bilerek doldurur. DB'de satır yalnız doluysa vardır | | `company_hosting_provider` (Yer Sağlayıcı), `company_hosting_url` | `company` / `company-hosting-provider`, `company-hosting-url` | **isteğe bağlı (FRW-31):** sitenin barındırıldığı hosting firmasının adı ve (isteğe bağlı) https adresi. YALNIZ `kunye` şablonunda `

Yer Sağlayıcı: {{company_hosting_provider}}

` satırı olarak basılır (kimlik listesine ve öteki sayfalara girmez); ad boşsa satır etiketiyle birlikte hiç basılmaz, adres tek başına satır açmaz. Adres geçerli bir `https://` ise ad `target="_blank" rel="nofollow noopener noreferrer"` bağlantı olur (`LinkRel::UNWANTED`: ödenen firmaya bağlantı değeri/yönlendiren bilgisi aktarılmaz; `http`, `javascript:`, şemasız adres bağlantı olmaz). `contact_info()` yalnız doluysa `hosting_provider` / `hosting_url` taşır. DB'de satır yalnız doluysa vardır | | `company_trade_name` | `company` / `company-trade-name` | **isteğe bağlı** (kurulum eklemez) | | `company_tax_office`, `company_tax_number` | `company` / `company-tax-office`, `company-tax-number` | **isteğe bağlı** (kurulum eklemez) | | `company_mersis_number` | `company` / `company-mersis-number` | **isteğe bağlı** (kurulum eklemez) | | `company_trade_registry_number` | `company` / `company-trade-registry-number` | **isteğe bağlı** (kurulum eklemez) | | `company_kep_address` | `company` / `company-kep-address` | **isteğe bağlı** (kurulum eklemez) | | `contact_email`, `contact_address`, `contact_phone` | `contact` / `contact-email`, `contact-adress`, `contact-phone` | mevcut; satışlı sitede dolu olmalı; telefon `format_phone()` ile basılır (`contact-adress` yazımı tarihsel, bkz. `acik-sorular.md` §1.13) | | (adres parçaları ve ikinci hat) | `contact` / `contact-landline`, `contact-locality`, `contact-region`, `contact-postal-code` | isteğe bağlı; yapısal veri (`PostalAddress`) ve sabit hat bunlardan okunur; koordinat `company` / `company-map-location` | | `social_facebook`, `social_twitter`, `social_instagram` | `social` / `facebook`, `twitter`, `instagram` | mevcut | | `{{website}}` (Web Adresi) | ayar DEĞİL | sitenin kendi adresi (`url()`, canonical ile aynı kaynak); hiçbir sitede boş basılmaz, yerelde `.test` adresi gelir | | `company_payment_methods`, `company_payment_provider` | `company` / `company-payment-methods`, `company-payment-provider` | isteğe bağlı; teslimat, mesafeli satış, KVKK aktarım, gizlilik (ödeme güvenliği) | | `company_delivery_time`, `company_shipping_cost`, `company_delivery_regions` | `company` / `company-delivery-time`, `company-shipping-cost`, `company-delivery-regions` | isteğe bağlı; teslimat ve mesafeli satış | | `company_return_carrier` | `company` / `company-return-carrier` | isteğe bağlı; iptal-iade (iade için belirlenen taşıyıcı) | **İsteğe bağlı şirket alanları (`LegalPages::OPTIONAL`).** Ticari unvan, vergi dairesi, vergi no, MERSİS no, ticaret sicil no ve KEP adresi her şirkette yoktur (şahıs firmasında MERSİS, ticaret sicil ve KEP bulunmaz). Veritabanında VARSA yasal sayfada yazılır, YOKSA satırın tamamı (etiket dahil) yazılmaz; şablon değişmez, veri karar verir. Alanlar ayar panelinde (`SettingsConfig`) tanımlı kalır, panelden ya da `rbn settings:set` ile girilir; tablo kuralı: [İletişim-Bilgisi §4](Iletisim-Bilgisi.md). `rbn legal:install --project=` (`--apply` yoksa plan): **hiçbir ayar satırı EKLEMEZ**: ayar tablosunda bir satır yalnız DOLU değer varken vardır, eksik anahtar yasal motor için boş değerdir (şema `SettingsConfig` yalnız panelde girilebilecek alanları tanımlar). Kurulum sonunda satışlı sitede unvan/adres/telefon/e-posta boşsa kırmızı uyarı verir. Aynı komut framework'ün kaldırdığı ayar satırlarını (`company-sells-online`, `contact-website`, `whatsapp`) siler ve `z_app_pages` tablosunu, varsa, DROP eder (planda satır sayısı yazar; `--apply` öncesi tablonun dökümünü al). Çalışma zamanında "anahtar var mı" dalı yoktur: eksik anahtar boş değer okunur (zorunlu satış alanları ayrıca denetlenir). Panelde kapatılmış (`is_active = 0`) ayar halka açık sitede gizli sayılır (boş değer: satırı yazılmaz). **Satışlı sitede zorunlu alanlar.** Site satış yapıyorsa (`LegalService::sellsOnline()`) unvan (`company-legal-name`), adres, telefon ve e-posta DOLU olmalıdır (`LegalPages::REQUIRED_FOR_SALES`; mesafeli satış ön bilgilendirmesi). Biri boşsa yasal sayfa sessizce boş basmaz: `LegalService` `RuntimeException` verir ve `rbn legal:install` kırmızı uyarı yazar. Satışsız sitede bu alanlar da yoksa satırı basılmaz. ## 3. Şablon sözdizimi Dosya: `Resources/Views/RbnCommon/Legal/.legal.html`. | Söz | Anlam | |---|---| | `{{company_legal_name}}` | ayar değeri (HTML kaçışlı). **Satır kuralı:** ayar yer tutuculu bir şablon SATIRI, yer tutucunun değeri boşsa satırın tamamı (etiket dahil) basılmaz (`

MERSİS No: {{company_mersis_number}}

` → hiçbir şey). Bu yüzden ayar yer tutucusu etiketiyle birlikte kendi satırında durur (`

Etiket: {{x}}

`); kapı `G-iletisim-06` | | `{{company_identity}}` | `LegalPages::IDENTITY` sırasıyla yalnız DOLU alanların etiketi + değeri; boş alanın satırı yoktur. Telefon `format_phone()` biçimindedir. Web Adresi hesaplanır, her zaman dolu | | `{{identity_fields}}` / `{{request_channels}}` | `{{company_identity}}` ile AYNI dolu-alan kararından (`LegalService::filledIdentity`) türeyen Türkçe liste ("adı/unvanı, vergi dairesi ve açık adresi"; `LegalPages::IDENTITY_PHRASES` / `REQUEST_CHANNELS`). Kimlik listesini işaret eden cümle bunu kullanır (mesafeli satış "1. Satıcı", KVKK talep kanalı): **bilgi listesi cümleleri dinamiktir, sayfada basılmayan bilgi vaat edilmez**; şablona "MERSİS/vergi no/KEP" gibi sabit alan adı yazılmaz. `request_channels` hiç dolu kanal yoksa `web adresi` der | | `{{cookie_table}}` | çerez envanterinden üretilen tablo (§5) | | `{{year}}` | yıl | | `{{website}}` | sitenin kendi adresi (kaçışlı) | | `{{social_links}}` | sitenin sosyal hesapları (`contact_info()['socials']`; başlık `Sosyal Hesaplar` dahil, hesap yoksa boş metin) | | `{{#sales}}…{{/sales}}` | bölüm yalnız yetenek doğruysa vardır (`sales`, `analytics`, `ads`, `consent_banner`, `news`, `copyright_notice`) | Bilinmeyen yer tutucu, bilinmeyen bölüm, kapanmamış bölüm ve artık `{{` **hata verir** (`InvalidArgumentException`); kapı `G-yasal-01/-04` hiçbir şablonun böyle gönderilmemesini sağlar. ## 4. Sayfalar ve açılma koşulu | Slug | Koşul | |---|---| | `gizlilik-politikasi`, `kvkk-aydinlatma-metni`, `cerez-politikasi`, `kullanim-kosullari` | her proje | | `mesafeli-satis-sozlesmesi`, `iptal-ve-iade-kosullari`, `teslimat-ve-kargo` | site çevrimiçi satış yapıyorsa (`LegalService::sellsOnline()`, aşağıda) | | `kunye` | route-map `content` altında `news` yazı türü varsa (`content.news.model`; internet haber yayını) ve site noindex değilse | | `telif-hakki-bildirimi` | route-map `content` altında herhangi bir yazı türü (`content..model`) varsa, site satış YAPMIYORSA ve noindex değilse | **Satış kararı (tek kaynak): `LegalService::sellsOnline()`.** Site, framework'ün bir ödeme sağlayıcısının (`LegalPages::PAYMENT_PROVIDERS`, bugün `shopier`) projede ETKİN anahtarı varsa satış yapıyordur: anahtar ödeme bağlantısı açmanın şartıdır, yani entegrasyon verisi bayraktır; elle ayar ve yedek dal yoktur. Mesafeli satış / iptal-iade / teslimat sayfaları, gizlilik politikasının "Ödeme Güvenliği" bölümü, sitemap, footer bağlantıları ve `legal_links()` bu tek karardan gelir. Yeni bir ödeme sağlayıcısı `ApiKeysRegistry::MAP`'e girince `PAYMENT_PROVIDERS` listesine eklenir. **Künye ve telif sayfasının açılma kararı (FRW-30).** Yeni ayar yoktur; mevcut üç bilgiden türer: route-map `content..model` (yazı türü bildirimi; `factory:published-at` da aynı bildirimi okur), `sellsOnline()` ve noindex kararı (`CrawlerProvider::isSiteNoindex()`, ConsentProvider ile aynı tek yorumlayıcı). `news` = `content.news` türü var; `copyright_notice` = herhangi bir yazı türü var VE satış yok. Noindex sitede yazı türü yok sayılır, iki sayfa da yoktur. Satış yapan sitede (Antalya Arıtma: `content.blog` var ama ödeme sağlayıcı anahtarı da var) telif sayfası kurulmaz; yazı türü hiç olmayan sitede (Uniqa) iki sayfa da yoktur. Künye yalnız haber yayınında açılır: docs `yasal/kunye-tanitici-bilgi.md` tablosuna göre yalnız-içerik sitesinde künye zorunluluğu kaynaktan çıkmaz (DOĞRULANMADI); satış yapan sitede kimlik bloğu zaten mesafeli satış sözleşmesi ve kullanım koşullarındadır. **Zorunlu alan kapısı.** `LegalPages::REQUIRED_BY_PAGE`: `kunye` ve `telif-hakki-bildirimi` `contact-email` boşken basılmaz (`RuntimeException`, satış kapısı `REQUIRED_FOR_SALES` ile aynı desen); telif sayfası başvurunun gideceği adres olmadan yayınlanmaz. Haber künyesinin diğer kalemleri (`LegalPages::NEWS_IMPRINT_FIELDS`) sayfada yalnız doluysa yazılır; `rbn legal:install` boş olanları RAPORLAR (hata değil), çünkü bir sitenin "internet haber sitesi" sayılma koşulu docs'ta DOĞRULANMADI. Yer sağlayıcı adı/adresi için ayar eklenmedi (§9). Yetenekler (`LegalService::capabilities()`): `sales` `sellsOnline()`'dan; `analytics`, `ads` ve `consent_banner` `ConsentProvider::decision()` sonucundan gelir (tek kaynak, ayrıntı `kavramlar/06-riza-kapisi.md`): ayar dolu VE site noindex değilse açık; noindex sitede üçü de kapalıdır. Gizlilik şablonunda reklam/ölçüm bölümleri `{{#ads}}`, `{{#analytics}}` ile yalnız ilgili entegrasyon varsa çıkar. **Adres ve sitemap.** `/sayfa/{slug}` rotasını framework kaydeder (`Mappings/web.php`) ve TEK metot basar: `FrontendBaseController::legalPage($slug)`. Slug yasal kayıt defterinde değilse ya da site için kapalıysa (satışsız sitede satış sayfası) gerçek 404 verilir (yönlendirme yok). Projenin `page` görünümü yalnız çerçevedir (`$legalPage`, boş `$faqs`); projede `page()` metodu ve rotası YAZILMAZ. Routemap `robots.noindex => true` olan alt sitede (kişisel kullanım) bu rota ve SSS rotası KAYDEDİLMEZ: o sitede yasal sayfa ve SSS yoktur (404), modülün `HomeController` taşıması gerekmez. `CrawlerProvider::getActivePages()` / `getActivePagesCount()` yasal sayfaları kayıt defterinden listeler; yasal sayfalara `modified_at` yoktur, bu yüzden sitemap `lastmod` yazmaz (tarih uydurulmaz, `docs/google-arama/tarih-kurallari.md`). Eski/kısa adresler (`/kvkk`, `/iade` …) `LegalPages::ALIASES` ile `/sayfa/` adresine yönlenir (`RedirectManager`); `RouteBlueprint::LEGAL_ALIASES` kaldırıldı. ## 5. Çerez envanteri (sözleşme) `CookieInventory::ENTRIES`: `name`, `category` (`necessary|analytics|ads`), `party` (`first|third`), `purpose`, `duration_days`/`duration_text`, `requires` (`null|consent_banner|analytics|ads`). Çerez politikası şablonu `{{cookie_table}}` ile tabloyu **bu defterden** üretir: politika yalnız gerçekten kurulan çerezleri sayar. - Oturum çerezi adı `session_name()` değeridir (`@session`). - `rbn_consent`: ad `ConsentProvider::COOKIE` sabitine envanterden gelir; ömür (180 gün) bant betiğindeki değerle aynı olmak zorundadır (kapı `G-yasal-05`). - Üçüncü taraf çerezlerde (ölçüm, reklam) sağlayıcının çerez adı/ömrü docs'ta **yoktur**: tablo adı/ömrü uydurmaz, "sağlayıcı belirler" yazar (DOĞRULANMADI). - Yeni bir bileşen çerez kuruyorsa önce envantere girer; adı/ömrü envanterden okur. **Tablo görünümü (FRW-21).** `cookieTable()` çıktısı standart `rbn-table rbn-table-readable rbn-table-striped rbn-table-stack` tablosudur (stil `Resources/Assets/RbnCommon/css/components/rbnTable.css`): çerez adı ``, kategori/taraf `rbn-badge` + Remix Icon 4.2.0 ikonu (`LegalService::COOKIE_CATEGORY_BADGES` / `COOKIE_PARTY_BADGES`), her gövde hücresinde `data-label` (başlıkla aynı metin; ≤ 1024 px kart düzeni etiketi bundan okur, yatay kaydırma yok). Yeni yasal tablo gerekirse aynı sınıflar ve `data-label` kuralı kullanılır; ham `` 200 + sitemap + `lastmod` yok · `-07` projede yasal metin/satır yok · `-08` slug/takma ad tek yerde. Künye + telif + şema: `g_kunye_telif_sema.php` (`G-kt-01…06`). ## 7. Şablon metinleri (FRW-17) Her şablonun iç metni `docs/yasal/*` maddelerine göre yazılır; hukuki yorum yapılmaz, docs'ta olmayan hukuki iddia eklenmez. Zorunlu unsurlar kapı `G-unsur-01…08` ile denetlenir (`E:\AgentSpace\.agentspace\araclar w-regresyon\birim\g_yasal_unsurlar.php`). | Şablon | Unsurlar (docs kaynağı) | |---|---| | `kvkk-aydinlatma-metni` | Kanun m.10 beş kalem (kimlik, amaç, aktarım, toplama yöntemi + hukuki sebep, m.11 hakları), başvuru yolu (m.13), Kurula şikâyet (m.14); toplama/amaç/aktarım satırları entegrasyona göre (`consent_banner`, `sales`, `analytics`, `ads`) | | `gizlilik-politikasi` | veri sorumlusu, toplanan veri, çerez, veri güvenliği (m.12/1); `{{#ads}}` AdSense dört madde, `{{#analytics}}` Google Analytics açıklaması, `{{#sales}}` ödeme güvenliği | | `cerez-politikasi` | `{{cookie_table}}` (envanter), tercih yönetimi (`consent_banner`) | | `kullanim-kosullari` | hizmet sağlayıcı kimliği, diğer yasal sayfalara yönlendirme (satış varsa satış sayfaları); sözleşmeyle çelişen cümle yok | | `mesafeli-satis-sozlesmesi` | Yönetmelik m.5 ön bilgi kalemleri, teyit (m.7), onay (m.8), cayma, şikâyet, hakem heyeti/arabulucu | | `iptal-ve-iade-kosullari` | cayma 14 gün (m.9-10), istisna listesi (m.15), bildirim yolu (m.11), iade taşıyıcısı ve masrafı (m.12/5, m.13), geri ödeme: malın iade taşıyıcısına tesliminden 14 gün (m.12) | | `teslimat-ve-kargo` | teslim süresi, bölge/kısıt, nakliye masrafı, ödeme araçları (ayar yer tutucuları) | | `kunye` | `docs/yasal/kunye-tanitici-bilgi.md`: kimlik listesi (`{{company_identity}}`: yalnız dolu alanlar), site adı, sosyal hesaplar (`{{social_links}}`), diğer yasal sayfalara bağlantılar, telif sayfası açıksa bağlantısı. Kanun madde numarası ve "zorunludur" hükmü YAZILMAZ | | `telif-hakki-bildirimi` | `docs/yasal/telif-bildirimi-icerik-kaldirma.md`: adı "Telif Hakkı Bildirimi" (DMCA adı geçmez), başvuru adresi ayardan (`contact-email`; varsa `contact-adress`), başvuruda beklenen bilgiler ("beklenir" dili; zorunlu liste olduğu DOĞRULANMADI), süreç (süre vaadi YOK), KVKK bağlantısı. 5846/5651 madde numarası YAZILMAZ. **Avukat onayı olmadan canlıya çıkmaz** | ## 8. Ödeme adımı: ön bilgilendirme / mesafeli satış onayı (WPRJ-38) **Kaynak:** `docs/yasal/eticaret-mesafeli-satis.md` (Yönetmelik m.5/6/7/8, 6563 m.4). Satış yapan site, ödeme yükümlülüğü doğmadan hemen önce temel nitelikleri, fiyatı ve cayma şartlarını gösterir, alıcının ön bilgileri edindiğini teyit etmesini sağlar ve düğmenin yanında siparişin ödeme yükümlülüğü anlamına geldiğini yazar. Ön bilgilendirmenin yapıldığını ispat yükü satıcıdadır: onay sunucuda kayda geçer. | Parça | Görev | |---|---| | `SalesConsentService` (`service('salesConsent')`) | `block()`: görünüm parçasının verisi (alan adı `sales_terms_accepted`, `mesafeli-satis-sozlesmesi` ve `iptal-ve-iade-kosullari` bağlantıları, cayma özeti, ödeme yükümlülüğü cümlesi); satışsız projede `null`. `confirm($input, $subjectRef, $amount)`: **sunucu kapısı**; alan `"1"` değilse başarısız (`"on"`, `"true"`, boş, yok: hepsi ret), satışsız projede başarısız, kayıt yazılamazsa başarısız (kayıt yoksa ödeme adımı yok) | | `sales_consent()` yardımcısı | `service('salesConsent')->block()` | | `Resources/Views/RbnCommon/Components/sales_consent.rbn.php` | Ortak görünüm parçası: cayma özeti, onay kutusu (`.rbn-form-check`, `required` yalnız kolaylıktır), iki yasal bağlantı, ödeme yükümlülüğü cümlesi. `sales_consent()` boşsa **hiçbir şey basmaz**. Stil `components/rbnSalesConsent.css` (yazı 1rem = 16 px altına inmez, yalnız token) | | `SalesConsentLogModel` / `SalesConsentLogRepository` / tablo `z_log_sales_consents` | Ekleyici kayıt: `subject_ref` (projenin kendi ürün/sipariş kimliği), `amount`, `terms_pages`, `terms_hash` (onaylanan sayfaların o anki yayın metninin SHA-256 özeti), `created_at`. **IP, kullanıcı aracısı, hesap ve alıcı verisi yoktur** (`z_log_consents` ile aynı veri azaltma politikası) | | `rbn sales-consent:install --project= [--apply]` | Tabloyu kurar (yalnız satış yapan projede gerekir; tablo yoksa onay kaydedilemez ve ödeme adımı geçilemez) | | `response()->redirectExternal($url, $izinliHostlar, 303)` | Onaydan sonra ödeme sağlayıcısına geçiş: yalnız https, çağıranın adıyla verdiği tam host; aksi `/` | | Hız sınırı `checkout_confirm` | `RateLimitValidations::LIMITS`: saat başına 20 | **Satış kararı** değişmedi: `LegalService::sellsOnline()` (etkin ödeme sağlayıcı anahtarı). Ayrı bir ayar, anahtar veya açma-kapama yoktur; satışsız projede parça boştur ve `confirm()` ret döner. **Projenin işi (yalnız yerleşim ve akış):** ödeme formu `POST` olur (`@csrf`), parça `@import('framework', 'Resources/Views/RbnCommon/Components/sales_consent.rbn.php')` ile düğmenin hemen üstüne konur, denetleyici `service('salesConsent')->confirm(...)` çağırır ve **yalnız başarıdan sonra** sağlayıcıya geçer. Sağlayıcı adresi onay doğrulanmadan sayfa kaynağına hiçbir biçimde yazılmaz (düz bağlantı onayı atlatır). Örnek: Antalya `CheckoutController::confirm()` (`POST /odeme/onay`). **Teyit sırası (kısa):** ürün sayfası → `/odeme` (özet, tutar, cayma özeti, onay kutusu, ödeme yükümlülüğü cümlesi) → onay → sağlayıcı sayfası. **Kapılar:** `E:\AgentSpace\.agentspace\araclar\fw-regresyon\birim\g_satis_onayi.php` (`G-satis-01…09`): parçalar ve kayıt defteri · onaysız/geçersiz/CSRF'siz POST ödemeye geçmez ve kayıt düşmez · onaylı POST 303 ile geçer ve tam bir kayıt düşer · sayfa kaynağında sağlayıcı adresi yok · yasal bağlantılar 200 · satışsızda kutu/rota yok · `redirectExternal` ret listesi · projede yasal metin/onay mantığı yok · CSS 16 px. ## 9. Açık konular - Haber künyesinin "yer sağlayıcı adı ve adresi" kalemi (docs `kunye-tanitici-bilgi.md` madde 5) için ayar eklenmedi: kalemin bir siteye uygulanması "internet haber sitesi" sayılmaya bağlı ve o koşul DOĞRULANMADI. - Telif sayfası içerik kaldırma sürecinin işleyişini (talep kaydı, bildirim, karşı başvuru) yazmaz; süreler docs'ta DOĞRULANMADI. - Tüketici hakem heyeti başvuru yeri/parasal sınır ve KVKK m.5 işleme şartı bent numaraları docs'ta yoktur; şablonlarda yazılmadı (avukat onayı). - Çerez politikası, bandın görünümü değişirse ('Çerez Tercihlerinizi Yönetme' bölümü) birlikte güncellenir. - Ödeme adımında **vergiler dahil toplam fiyat** ve **nakliye/teslim masrafı** gösterimi (Yönetmelik m.6, 6563 m.4) projenin sipariş özetindedir; Antalya'da `company-shipping-cost`/`company-delivery-time` ayarları DB'de yoktur, KDV bilgisi ürün verisinde ayrı alan değildir: DOĞRULANMADI (iş sahibine bildirildi, uydurulmadı). - Satın almanın Shopier'de tamamlanması nedeniyle ön bilgilendirmeyi kimin yaptığı sözleşme akışında hükme bağlanmadı (`eticaret-mesafeli-satis.md` Uygulama talimatı 11); bu sayfa onayı **sitede** alır ve kaydeder, Shopier tarafındaki onay ayrıdır. - IP adresinin onay kaydına yazılıp yazılmayacağı docs'ta hükme bağlanmadı; kayıt `z_log_consents` politikasıyla IP'siz tutuldu (karar: veri azaltma). - Siparişin alındığının e-postayla teyidi (6563 m.4) Shopier'de ve projede bu işin kapsamı dışındadır.