feat(api): gömülebilir katalog widget'ı (Faz 2 POC)

- GET /widget/loader.js: müşterinin yapıştırdığı tek script — iframe kurar,
  postMessage köprüsü (yükseklik + sase:partClick/sase:decoded olayları),
  parça tıklamasını data-part-click-url şablonuna ({code},{brand}) yönlendirir,
  window.saseWidget.onPartClick/onDecode callback'leri; CORP cross-origin
  (helmet same-origin varsayılanı müşteri sitesinde script'i bloklardı)
- GET /widget?key=sase_pk_...: iframe shell — vanilla JS katalog uygulaması
  (VIN formu, çok-aday seçimi, kategori grid + breadcrumb, parça tablosu,
  şema görseli, açık/koyu tema). Domain kilidi = anahtarın metadata.domains
  listesinden üretilen frame-ancestors CSP'si (tarayıcı zorlar); publishable
  olmayan anahtar 403; X-Frame-Options bu cevapta kaldırılır
- internal-admin: publishable:true + domains[] ile sase_pk_ anahtar üretimi
- api.sase.tr kısa yolu: /widget* → /api/widget*

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-03 17:50:29 +03:00
parent acadd84e4a
commit ae61ac055e
5 changed files with 480 additions and 5 deletions

View File

@@ -5,6 +5,7 @@ import { PModule } from "../integrations/p/p.module";
import { VehiclesModule } from "../vehicles/vehicles.module";
import { PublicApiQuotaService } from "./public-api-quota.service";
import { PublicApiController } from "./public-api.controller";
import { WidgetController } from "./widget.controller";
/**
* Müşteri entegrasyonlarına açık Public API (/api/v1). Kimlik better-auth
@@ -12,7 +13,7 @@ import { PublicApiController } from "./public-api.controller";
*/
@Module({
imports: [VehiclesModule, CategoriesModule, PModule],
controllers: [PublicApiController],
controllers: [PublicApiController, WidgetController],
providers: [ApiKeyGuard, PublicApiQuotaService],
})
export class PublicApiModule {}