Paket Kapatma Gate’i — packet.close ✓ Canlı

Paket hesabı kapatılmadan önce sorulan before-action gate. table.close gibi TENANT-GENEL çalışır: SAHİPLİK ŞARTI YOKTUR — bu hook’u kaydeden her aktif eklenti, restoranın TÜM paket kapanışlarında (kendi oluşturmadığı paketler dahil) sorgulanır ve herhangi bir eklentinin deny’ı kapanışı engeller. allow/deny dönersiniz; deny → hesap kapanmaz, message personele gösterilir. transition YOKTUR. (Sahiplik kuralı yalnız packet.status.update için geçerlidir.)

← Hook'lar

Genel

Hook keypacket.close
Scopehooks:packet.close (consent-gated güçlü yetki)
SahiplikYOK — tenant-genel (table.close gibi); tüm paket kapanışlarında sorulur
Manifesthooks: [{ event, ui, timeoutMs, failMode, includeData }]
Hedefmanifest actionUrl (yoksa webhookUrl)
MethodPOST (senkron)
Rate limithook kovası (varsayılan 60/dk per-install)

Manifest hook config

{
  "event": "packet.close",
  "ui": { "kind": "none" },        // gate genelde UI'sız karar; form/iframe da desteklenir
  "timeoutMs": 5000,               // cevap bütçesi [1s,10s]; aşımda failMode uygulanır
  "failMode": "open",              // VARSAYILAN: open (timeout/hata → kapanışa izin ver + uyar)
  "includeData": true              // gövdeye paketin kanonik verisi gömülür (packets/get şekli)
}

failMode — dikkat

Varsayılan open: endpoint’iniz cevap veremezse hesap kapatma engellenmez (degraded uyarısıyla devam). "closed" seçebilirsiniz ama ciddi sorumluluk: sunucunuz düştüğünde restoranın o paketlerdeki hesap kapatması bloklanır.

enforce desteklenmez

enforce bu hook’ta DESTEKLENMEZ (yok sayılır): gate çekirdek işlemin (hesap kapatma) içinde çalışır, ayrı sert doğrulayıcı yok. deny sunucuda kapanışı engeller; bu yeterli garantidir.

Restomenum → eklenti (request body)

{
  "type": "hook",
  "event": "packet.close",
  "stage": "before",
  "tenantId": "<tenantId>",
  "target": { "type": "packet", "id": "<packetId>" },
  "data": {
    "packetId": "<packetId>", "docNo": 12,
    "customer": { "id": "c1", "name": "...", "phone": "..." },
    "orders": [ { "id": "...", "title": "...", "quantity": 1, "options": [], "lineTotal": 130 } ],
    "entegrasyon": "packet", "total": 130, "paid": 0, "totalDiscount": 0
  },
  "formData": { "<sizin-field-keyiniz>": "<personel-degeri>" },   // DİNAMİK: formunuzdaki key'ler; yalnız ui.kind form/iframe ise
  "actor": { "userId": "<uid>", "role": "staff" },
  "timeoutMs": 5000,
  "occurredAt": 1718000000000,
  "hookId": "hk_<uuid>"
}
AlanAçıklama
target.idPaket id’si. Veriyi packets/get?packetId= ile de çekebilirsiniz. (transition YOKTUR — bu hook kapanış öncesidir.)
dataYalnız includeData:true ise. packets/get ile birebir kanonik şekil; customer yalnız customers:read + PII consent ile, data yalnız orders:read ile.
formDataYalnız ui.kind form/iframe ise gelir. İçeriği DİNAMİKTİR: anahtarlar SİZİN formunuzda tanımladığınız field key’ler, değerler personelin girdiği değerlerdir (her eklentiye özel; sabit şema yok). ui.kind none ise hiç gelmez.
actorKapatmayı başlatan kullanıcı {userId, role} (manager/staff) — imzalı gövdede, güvenilir.
hookIdBu çağrının id’si (loglama/dedup).

Eklenti → Restomenum (response)

allow — kapanış devam
{ "decision": "allow", "message": "Hesap kapatılabilir." }
deny — engelle (message personele gösterilir)
{ "decision": "deny", "message": "Önce kurye teslimini onaylayın." }
  • decision: allow (kapanış devam) / deny (engelle; message personele gösterilir).
  • Geçersiz/boş cevap veya timeout → failMode uygulanır.
  • attach desteklenir (allowlist: invoiceNo / reference / note).

Hata mesajları (hook çağrısı)

messageAnlam
plugin.hook.targetNotFoundPaket bulunamadı.
plugin.hook.notRegisteredManifest’inizde bu hook yok.
plugin.scope.deniedhooks:packet.close onaylı değil.
plugin.hook.inactiveKurulum pasif (kill-switch / billing / connect).

Güvenlik

  • İmza: X-Restomenum-Signature: t=<sec>,v1=<HMAC_SHA256(webhookSecret,"<t>.<rawBody>")> (±5dk) — webhook/action ile aynı şema; type:"hook" ile ayırt edin.
  • TENANT-GENEL: tüm paket kapanışlarında sorulursunuz (sahiplik yok). Yalnız sizi ilgilendiren paketleri data ile ayırt edip gerisine allow dönün.
  • data/actor server-türevli (panel iddiası değil; panel yalnız kapanışı başlatır). deny sunucuda hesap kapanışını engeller (panel-işbirlikli).