GET /api/b2b/v1/portal/assets/{*key} (B2bPublicCtx, public) — durable marka varlığı sunumu.
*keycurl -X GET "https://{slug}.b2b.blesyum.app/api/b2b/v1/portal/assets/<*key>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}3 uç · /api/b2b/v1/portal
İstek örnekleri ucun GERÇEK metodu ve yolundan üretilir. 3 ucun elle doğrulanmış gövde örneği henüz yok; o uçlarda iskelet gövdesizdir — uydurma bir alan yazmıyoruz.
*keycurl -X GET "https://{slug}.b2b.blesyum.app/api/b2b/v1/portal/assets/<*key>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}aşamasında (layout.tsx, Task 6) çağırdığı **tek** sözleşme ucu; dönen JSON `window.
bootstrapData olarak enjekte edilir. redact`: yanıt yalnız burada el ile kurulan sabit
alanları taşır (hiçbir geniş "settings"/config ağacı okunmaz) → sır (llm.*/api key/sealed
cred) sızma YÜZEYİ hiç YOK (CRM bootstrap'ının aksine, burada redaksiyon edilecek genel bir
ayar deposu zaten sorgulanmıyor).
- brand: portal-scoped (Task 2 branding::resolve_portal+get_published; host eşleşmezse
tenant'ın is_default portalına düşer, o da yoksa null). info_handler'ın kullandığı
blesyum_branding::get_published (tenant-level, ayrı tablo/kavram) İLE KARIŞTIRILMAMASI için
burada modül-yerel branding:: alias'ı (bkz. yukarıdaki use crate::branding;) kullanılır.
- settings.features.online_payment: b2b.payment_settings (tenant-RLS; satır yoksa false
— BF5 varsayılanıyla birebir aynı fail-closed davranış).
- user: anonim/InactiveDealer/NonMember → null (misafir görünümü — oturum "geçerli"
olsa bile çözülebilir bir principal karşılık gelmiyorsa sızdırılacak bir şey yok). Dealer/
Staff → {id, name, email, principal, permissions}. Dealer izinleri `rbac::
effective_dealer_permissions'tan; **Staff izinleri (2026-08-14) b2b.*` ile SINIRLI
olarak** [staff_b2b_permissions]'tan gelir. Eskiden Staff için boş dönüyordu ve
gerekçesi "admin yüzeyleri zaten require_permission ile korunuyor" idi — bu doğru ama
eksikti: kapı korunuyordu, **menü süzülemiyordu**, kısıtlı personel giremeyeceği yedi
bölümü de görüp tıklayınca duvara çarpıyordu. Liste bir YETKİ KAPISI DEĞİL, görünürlük
ipucudur; kapı yerinde duruyor.
curl -X GET "https://{slug}.b2b.blesyum.app/api/b2b/v1/portal/bootstrap" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}NOT: burada blesyum_branding::get_published (extern crate, **tenant-level**
core.tenant_branding, RLS'siz) çağrılır — [bootstrap_handler]'ın kullandığı modül-yerel
branding::get_published (**portal-level**, b2b.portal_brand, Task 2) İLE KARIŞTIRILMAMALI;
ikisi ayrı tablo/ayrı kavramdır (bkz. crate::branding modül dokümantasyonu).
curl -X GET "https://{slug}.b2b.blesyum.app/api/b2b/v1/portal/info" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}