{
  "tentang": "Test vector tanda tangan Kayya API — kontrak integrasi tenant v2 (https://gitlab.com/sdk-marketplace-ui/sdk). Dihasilkan dari kode marketplace yang benar-benar menandatangani; jangan disunting tangan.",
  "cara_pakai": {
    "gateway": "Verifikasi masukan.header untuk request masukan.method ke masukan.path_diterima dengan masukan.secret, jam = masukan.sekarang, awalan yang dibuang proxy = masukan.prefix_yang_dibuang. Hasil wajib sama dengan harapan.sah; kalau tidak sah, alasannya harapan.alasan (header_kurang | timestamp | tanda_tangan | path — diperiksa berurutan).",
    "webhook": "Verifikasi masukan.header untuk raw body = UTF-8 dari masukan.body, dengan masukan.secret dan jam = masukan.sekarang. Alasan: header_kurang | timestamp | tanda_tangan.",
    "sync": "Tandatangani masukan.target dengan masukan.secret & masukan.timestamp; hasilnya wajib sama persis dengan harapan.signature."
  },
  "gateway": [
    {
      "nama": "sah: dasar",
      "catatan": "Panggilan GET biasa.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "pesan_kanonik": "v1:gateway\n1790000000\n5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f\nGET\n/v1/cuaca?kota=Denpasar\n0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\n3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\napi-cuaca\n2026-10-21T15:33:20+00:00",
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "method": "GET",
        "path_diterima": "/v1/cuaca?kota=Denpasar",
        "prefix_yang_dibuang": "",
        "sekarang": 1790000007,
        "header": {
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Request-Id": "5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f",
          "X-Marketplace-Target": "/v1/cuaca?kota=Denpasar",
          "X-Marketplace-Buyer-Id": "0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f",
          "X-Marketplace-Entitlement-Id": "3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8",
          "X-Marketplace-Produk": "api-cuaca",
          "X-Marketplace-Expires-At": "2026-10-21T15:33:20+00:00",
          "X-Marketplace-Signature": "sha256=68a380468e420cdcd56c42c5d2efa8bb536773b9faa7ad5f2eaf537901672b7a"
        }
      },
      "harapan": {
        "sah": true,
        "alasan": null
      }
    },
    {
      "nama": "sah: path berisi spasi, non-ASCII, dan + ter-encode — diterima mentah",
      "catatan": "Framework yang menyajikan path & query apa adanya (PHP REQUEST_URI, Express originalUrl, Starlette raw_path).",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "pesan_kanonik": "v1:gateway\n1790000000\n5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f\nGET\n/v1/kota%20denpasar/caf%C3%A9?to=%2B6281\n0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\n3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\napi-cuaca\n2026-10-21T15:33:20+00:00",
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "method": "GET",
        "path_diterima": "/v1/kota%20denpasar/caf%C3%A9?to=%2B6281",
        "prefix_yang_dibuang": "",
        "sekarang": 1790000007,
        "header": {
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Request-Id": "5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f",
          "X-Marketplace-Target": "/v1/kota%20denpasar/caf%C3%A9?to=%2B6281",
          "X-Marketplace-Buyer-Id": "0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f",
          "X-Marketplace-Entitlement-Id": "3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8",
          "X-Marketplace-Produk": "api-cuaca",
          "X-Marketplace-Expires-At": "2026-10-21T15:33:20+00:00",
          "X-Marketplace-Signature": "sha256=f7062edaf100073d8d83bd08ad9cb03b29d8f4ce0941b75cfe50a4cf1c9a3061"
        }
      },
      "harapan": {
        "sah": true,
        "alasan": null
      }
    },
    {
      "nama": "sah: framework menyajikan path yang sudah di-decode",
      "catatan": "Path ter-decode, query mentah (Django PATH_INFO, Starlette path). Kedua sisi di-decode sebelum dibandingkan — membandingkan byte mentah menolak panggilan sah.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "pesan_kanonik": "v1:gateway\n1790000000\n5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f\nGET\n/v1/kota%20denpasar/caf%C3%A9?to=%2B6281\n0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\n3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\napi-cuaca\n2026-10-21T15:33:20+00:00",
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "method": "GET",
        "path_diterima": "/v1/kota denpasar/café?to=%2B6281",
        "prefix_yang_dibuang": "",
        "sekarang": 1790000007,
        "header": {
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Request-Id": "5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f",
          "X-Marketplace-Target": "/v1/kota%20denpasar/caf%C3%A9?to=%2B6281",
          "X-Marketplace-Buyer-Id": "0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f",
          "X-Marketplace-Entitlement-Id": "3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8",
          "X-Marketplace-Produk": "api-cuaca",
          "X-Marketplace-Expires-At": "2026-10-21T15:33:20+00:00",
          "X-Marketplace-Signature": "sha256=f7062edaf100073d8d83bd08ad9cb03b29d8f4ce0941b75cfe50a4cf1c9a3061"
        }
      },
      "harapan": {
        "sah": true,
        "alasan": null
      }
    },
    {
      "nama": "sah: reverse proxy membuang awalan path",
      "catatan": "Proxy di depan server menerima /v1/cuaca lalu meneruskan /cuaca.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "pesan_kanonik": "v1:gateway\n1790000000\n5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f\nGET\n/v1/cuaca?kota=Denpasar\n0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\n3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\napi-cuaca\n2026-10-21T15:33:20+00:00",
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "method": "GET",
        "path_diterima": "/cuaca?kota=Denpasar",
        "prefix_yang_dibuang": "/v1",
        "sekarang": 1790000007,
        "header": {
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Request-Id": "5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f",
          "X-Marketplace-Target": "/v1/cuaca?kota=Denpasar",
          "X-Marketplace-Buyer-Id": "0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f",
          "X-Marketplace-Entitlement-Id": "3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8",
          "X-Marketplace-Produk": "api-cuaca",
          "X-Marketplace-Expires-At": "2026-10-21T15:33:20+00:00",
          "X-Marketplace-Signature": "sha256=68a380468e420cdcd56c42c5d2efa8bb536773b9faa7ad5f2eaf537901672b7a"
        }
      },
      "harapan": {
        "sah": true,
        "alasan": null
      }
    },
    {
      "nama": "sah: nama header huruf kecil (HTTP/2)",
      "catatan": "HTTP/2 mengirim seluruh nama header huruf kecil; pencarian header wajib tidak peka huruf besar/kecil.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "pesan_kanonik": "v1:gateway\n1790000000\n5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f\nGET\n/v1/cuaca?kota=Denpasar\n0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\n3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\napi-cuaca\n2026-10-21T15:33:20+00:00",
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "method": "GET",
        "path_diterima": "/v1/cuaca?kota=Denpasar",
        "prefix_yang_dibuang": "",
        "sekarang": 1790000007,
        "header": {
          "x-marketplace-timestamp": "1790000000",
          "x-marketplace-request-id": "5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f",
          "x-marketplace-target": "/v1/cuaca?kota=Denpasar",
          "x-marketplace-buyer-id": "0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f",
          "x-marketplace-entitlement-id": "3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8",
          "x-marketplace-produk": "api-cuaca",
          "x-marketplace-expires-at": "2026-10-21T15:33:20+00:00",
          "x-marketplace-signature": "sha256=68a380468e420cdcd56c42c5d2efa8bb536773b9faa7ad5f2eaf537901672b7a"
        }
      },
      "harapan": {
        "sah": true,
        "alasan": null
      }
    },
    {
      "nama": "sah: masa tenggang rotasi, server masih memakai secret lama",
      "catatan": "Selama 24 jam setelah secret diganti, header berisi dua tanda tangan (baru, lama). Cukup satu yang cocok.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-BARU-bukan-rahasia-9876543210",
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "pesan_kanonik": "v1:gateway\n1790000000\n5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f\nGET\n/v1/cuaca?kota=Denpasar\n0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\n3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\napi-cuaca\n2026-10-21T15:33:20+00:00",
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "method": "GET",
        "path_diterima": "/v1/cuaca?kota=Denpasar",
        "prefix_yang_dibuang": "",
        "sekarang": 1790000007,
        "header": {
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Request-Id": "5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f",
          "X-Marketplace-Target": "/v1/cuaca?kota=Denpasar",
          "X-Marketplace-Buyer-Id": "0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f",
          "X-Marketplace-Entitlement-Id": "3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8",
          "X-Marketplace-Produk": "api-cuaca",
          "X-Marketplace-Expires-At": "2026-10-21T15:33:20+00:00",
          "X-Marketplace-Signature": "sha256=cb07a12012c40511f076145a54be87e5194cdfbdc802ba9a5228bd7c89b4fb51,sha256=68a380468e420cdcd56c42c5d2efa8bb536773b9faa7ad5f2eaf537901672b7a"
        }
      },
      "harapan": {
        "sah": true,
        "alasan": null
      }
    },
    {
      "nama": "sah: masa tenggang rotasi, server sudah memakai secret baru",
      "catatan": "Server yang sigap memasang secret baru juga lolos.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-BARU-bukan-rahasia-9876543210",
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "pesan_kanonik": "v1:gateway\n1790000000\n5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f\nGET\n/v1/cuaca?kota=Denpasar\n0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\n3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\napi-cuaca\n2026-10-21T15:33:20+00:00",
      "masukan": {
        "secret": "whsec_vektor-uji-BARU-bukan-rahasia-9876543210",
        "method": "GET",
        "path_diterima": "/v1/cuaca?kota=Denpasar",
        "prefix_yang_dibuang": "",
        "sekarang": 1790000007,
        "header": {
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Request-Id": "5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f",
          "X-Marketplace-Target": "/v1/cuaca?kota=Denpasar",
          "X-Marketplace-Buyer-Id": "0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f",
          "X-Marketplace-Entitlement-Id": "3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8",
          "X-Marketplace-Produk": "api-cuaca",
          "X-Marketplace-Expires-At": "2026-10-21T15:33:20+00:00",
          "X-Marketplace-Signature": "sha256=cb07a12012c40511f076145a54be87e5194cdfbdc802ba9a5228bd7c89b4fb51,sha256=68a380468e420cdcd56c42c5d2efa8bb536773b9faa7ad5f2eaf537901672b7a"
        }
      },
      "harapan": {
        "sah": true,
        "alasan": null
      }
    },
    {
      "nama": "sah: spasi setelah koma di antara dua tanda tangan",
      "catatan": "Proxy boleh menormalkan daftar nilai header; tiap bagian di-trim sebelum dibandingkan.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-BARU-bukan-rahasia-9876543210",
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "pesan_kanonik": "v1:gateway\n1790000000\n5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f\nGET\n/v1/cuaca?kota=Denpasar\n0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\n3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\napi-cuaca\n2026-10-21T15:33:20+00:00",
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "method": "GET",
        "path_diterima": "/v1/cuaca?kota=Denpasar",
        "prefix_yang_dibuang": "",
        "sekarang": 1790000007,
        "header": {
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Request-Id": "5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f",
          "X-Marketplace-Target": "/v1/cuaca?kota=Denpasar",
          "X-Marketplace-Buyer-Id": "0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f",
          "X-Marketplace-Entitlement-Id": "3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8",
          "X-Marketplace-Produk": "api-cuaca",
          "X-Marketplace-Expires-At": "2026-10-21T15:33:20+00:00",
          "X-Marketplace-Signature": "sha256=cb07a12012c40511f076145a54be87e5194cdfbdc802ba9a5228bd7c89b4fb51, sha256=68a380468e420cdcd56c42c5d2efa8bb536773b9faa7ad5f2eaf537901672b7a"
        }
      },
      "harapan": {
        "sah": true,
        "alasan": null
      }
    },
    {
      "nama": "sah: expires_at sudah lewat",
      "catatan": "Keputusan akses milik gateway (Bagian 2.3) — mis. masa tenggang pembayaran. Server tenant TIDAK boleh menolak berdasarkan tanggal ini.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "pesan_kanonik": "v1:gateway\n1790000000\n5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f\nGET\n/v1/cuaca?kota=Denpasar\n0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\n3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\napi-cuaca\n2026-09-01T00:00:00+00:00",
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "method": "GET",
        "path_diterima": "/v1/cuaca?kota=Denpasar",
        "prefix_yang_dibuang": "",
        "sekarang": 1790000007,
        "header": {
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Request-Id": "5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f",
          "X-Marketplace-Target": "/v1/cuaca?kota=Denpasar",
          "X-Marketplace-Buyer-Id": "0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f",
          "X-Marketplace-Entitlement-Id": "3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8",
          "X-Marketplace-Produk": "api-cuaca",
          "X-Marketplace-Expires-At": "2026-09-01T00:00:00+00:00",
          "X-Marketplace-Signature": "sha256=72cfb4335695a6290b4e2d2815b8dbe546a558465d726e64cf1b9287a251ff33"
        }
      },
      "harapan": {
        "sah": true,
        "alasan": null
      }
    },
    {
      "nama": "sah: POST",
      "catatan": "Method ikut ditandatangani, huruf besar.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "pesan_kanonik": "v1:gateway\n1790000000\n5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f\nPOST\n/v1/pengamatan\n0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\n3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\napi-cuaca\n2026-10-21T15:33:20+00:00",
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "method": "POST",
        "path_diterima": "/v1/pengamatan",
        "prefix_yang_dibuang": "",
        "sekarang": 1790000007,
        "header": {
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Request-Id": "5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f",
          "X-Marketplace-Target": "/v1/pengamatan",
          "X-Marketplace-Buyer-Id": "0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f",
          "X-Marketplace-Entitlement-Id": "3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8",
          "X-Marketplace-Produk": "api-cuaca",
          "X-Marketplace-Expires-At": "2026-10-21T15:33:20+00:00",
          "X-Marketplace-Signature": "sha256=99d7e340062fe4fa523b6a22e6fa4ff11271b19ad38e06abfdcf3d96cb3d1c70"
        }
      },
      "harapan": {
        "sah": true,
        "alasan": null
      }
    },
    {
      "nama": "tidak sah: secret lain",
      "catatan": "Server memakai secret yang bukan milik tenant ini.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "pesan_kanonik": "v1:gateway\n1790000000\n5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f\nGET\n/v1/cuaca?kota=Denpasar\n0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\n3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\napi-cuaca\n2026-10-21T15:33:20+00:00",
      "masukan": {
        "secret": "whsec_vektor-uji-LAIN-bukan-rahasia-5555555555",
        "method": "GET",
        "path_diterima": "/v1/cuaca?kota=Denpasar",
        "prefix_yang_dibuang": "",
        "sekarang": 1790000007,
        "header": {
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Request-Id": "5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f",
          "X-Marketplace-Target": "/v1/cuaca?kota=Denpasar",
          "X-Marketplace-Buyer-Id": "0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f",
          "X-Marketplace-Entitlement-Id": "3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8",
          "X-Marketplace-Produk": "api-cuaca",
          "X-Marketplace-Expires-At": "2026-10-21T15:33:20+00:00",
          "X-Marketplace-Signature": "sha256=68a380468e420cdcd56c42c5d2efa8bb536773b9faa7ad5f2eaf537901672b7a"
        }
      },
      "harapan": {
        "sah": false,
        "alasan": "tanda_tangan"
      }
    },
    {
      "nama": "tidak sah: X-Marketplace-Buyer-Id diubah setelah ditandatangani",
      "catatan": "Pemalsuan identitas pemanggil — alasan utama tanda tangan ini ada.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "pesan_kanonik": "v1:gateway\n1790000000\n5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f\nGET\n/v1/cuaca?kota=Denpasar\n0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\n3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\napi-cuaca\n2026-10-21T15:33:20+00:00",
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "method": "GET",
        "path_diterima": "/v1/cuaca?kota=Denpasar",
        "prefix_yang_dibuang": "",
        "sekarang": 1790000007,
        "header": {
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Request-Id": "5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f",
          "X-Marketplace-Target": "/v1/cuaca?kota=Denpasar",
          "X-Marketplace-Buyer-Id": "buyer-palsu",
          "X-Marketplace-Entitlement-Id": "3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8",
          "X-Marketplace-Produk": "api-cuaca",
          "X-Marketplace-Expires-At": "2026-10-21T15:33:20+00:00",
          "X-Marketplace-Signature": "sha256=68a380468e420cdcd56c42c5d2efa8bb536773b9faa7ad5f2eaf537901672b7a"
        }
      },
      "harapan": {
        "sah": false,
        "alasan": "tanda_tangan"
      }
    },
    {
      "nama": "tidak sah: method berbeda dari yang ditandatangani",
      "catatan": "Tanda tangan untuk GET dipakai ulang untuk DELETE.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "pesan_kanonik": "v1:gateway\n1790000000\n5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f\nGET\n/v1/cuaca?kota=Denpasar\n0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\n3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\napi-cuaca\n2026-10-21T15:33:20+00:00",
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "method": "DELETE",
        "path_diterima": "/v1/cuaca?kota=Denpasar",
        "prefix_yang_dibuang": "",
        "sekarang": 1790000007,
        "header": {
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Request-Id": "5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f",
          "X-Marketplace-Target": "/v1/cuaca?kota=Denpasar",
          "X-Marketplace-Buyer-Id": "0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f",
          "X-Marketplace-Entitlement-Id": "3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8",
          "X-Marketplace-Produk": "api-cuaca",
          "X-Marketplace-Expires-At": "2026-10-21T15:33:20+00:00",
          "X-Marketplace-Signature": "sha256=68a380468e420cdcd56c42c5d2efa8bb536773b9faa7ad5f2eaf537901672b7a"
        }
      },
      "harapan": {
        "sah": false,
        "alasan": "tanda_tangan"
      }
    },
    {
      "nama": "tidak sah: path berbeda dari yang ditandatangani",
      "catatan": "Tanda tangan sah, tapi dipakai ulang untuk endpoint lain.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "pesan_kanonik": "v1:gateway\n1790000000\n5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f\nGET\n/v1/cuaca?kota=Denpasar\n0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\n3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\napi-cuaca\n2026-10-21T15:33:20+00:00",
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "method": "GET",
        "path_diterima": "/v1/hapus-semua",
        "prefix_yang_dibuang": "",
        "sekarang": 1790000007,
        "header": {
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Request-Id": "5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f",
          "X-Marketplace-Target": "/v1/cuaca?kota=Denpasar",
          "X-Marketplace-Buyer-Id": "0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f",
          "X-Marketplace-Entitlement-Id": "3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8",
          "X-Marketplace-Produk": "api-cuaca",
          "X-Marketplace-Expires-At": "2026-10-21T15:33:20+00:00",
          "X-Marketplace-Signature": "sha256=68a380468e420cdcd56c42c5d2efa8bb536773b9faa7ad5f2eaf537901672b7a"
        }
      },
      "harapan": {
        "sah": false,
        "alasan": "path"
      }
    },
    {
      "nama": "tidak sah: timestamp 301 detik di belakang jam server",
      "catatan": "Di luar toleransi 300 detik. Pesan galat sebaiknya menyebut kemungkinan jam server tidak sinkron (NTP).",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "pesan_kanonik": "v1:gateway\n1790000000\n5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f\nGET\n/v1/cuaca?kota=Denpasar\n0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\n3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\napi-cuaca\n2026-10-21T15:33:20+00:00",
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "method": "GET",
        "path_diterima": "/v1/cuaca?kota=Denpasar",
        "prefix_yang_dibuang": "",
        "sekarang": 1790000301,
        "header": {
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Request-Id": "5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f",
          "X-Marketplace-Target": "/v1/cuaca?kota=Denpasar",
          "X-Marketplace-Buyer-Id": "0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f",
          "X-Marketplace-Entitlement-Id": "3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8",
          "X-Marketplace-Produk": "api-cuaca",
          "X-Marketplace-Expires-At": "2026-10-21T15:33:20+00:00",
          "X-Marketplace-Signature": "sha256=68a380468e420cdcd56c42c5d2efa8bb536773b9faa7ad5f2eaf537901672b7a"
        }
      },
      "harapan": {
        "sah": false,
        "alasan": "timestamp"
      }
    },
    {
      "nama": "tidak sah: timestamp 301 detik di depan jam server",
      "catatan": "Toleransi berlaku ke dua arah.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "pesan_kanonik": "v1:gateway\n1790000000\n5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f\nGET\n/v1/cuaca?kota=Denpasar\n0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\n3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\napi-cuaca\n2026-10-21T15:33:20+00:00",
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "method": "GET",
        "path_diterima": "/v1/cuaca?kota=Denpasar",
        "prefix_yang_dibuang": "",
        "sekarang": 1789999699,
        "header": {
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Request-Id": "5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f",
          "X-Marketplace-Target": "/v1/cuaca?kota=Denpasar",
          "X-Marketplace-Buyer-Id": "0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f",
          "X-Marketplace-Entitlement-Id": "3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8",
          "X-Marketplace-Produk": "api-cuaca",
          "X-Marketplace-Expires-At": "2026-10-21T15:33:20+00:00",
          "X-Marketplace-Signature": "sha256=68a380468e420cdcd56c42c5d2efa8bb536773b9faa7ad5f2eaf537901672b7a"
        }
      },
      "harapan": {
        "sah": false,
        "alasan": "timestamp"
      }
    },
    {
      "nama": "tidak sah: header X-Marketplace-Target tidak ada",
      "catatan": "Header yang kurang ditolak sebelum menghitung apa pun.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "pesan_kanonik": "v1:gateway\n1790000000\n5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f\nGET\n/v1/cuaca?kota=Denpasar\n0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\n3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\napi-cuaca\n2026-10-21T15:33:20+00:00",
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "method": "GET",
        "path_diterima": "/v1/cuaca?kota=Denpasar",
        "prefix_yang_dibuang": "",
        "sekarang": 1790000007,
        "header": {
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Request-Id": "5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f",
          "X-Marketplace-Buyer-Id": "0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f",
          "X-Marketplace-Entitlement-Id": "3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8",
          "X-Marketplace-Produk": "api-cuaca",
          "X-Marketplace-Expires-At": "2026-10-21T15:33:20+00:00",
          "X-Marketplace-Signature": "sha256=68a380468e420cdcd56c42c5d2efa8bb536773b9faa7ad5f2eaf537901672b7a"
        }
      },
      "harapan": {
        "sah": false,
        "alasan": "header_kurang"
      }
    },
    {
      "nama": "tidak sah: header identitas tanpa tanda tangan",
      "catatan": "Panggilan langsung ke base URL oleh siapa pun yang menemukannya.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "pesan_kanonik": "v1:gateway\n1790000000\n5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f\nGET\n/v1/cuaca?kota=Denpasar\n0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\n3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\napi-cuaca\n2026-10-21T15:33:20+00:00",
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "method": "GET",
        "path_diterima": "/v1/cuaca?kota=Denpasar",
        "prefix_yang_dibuang": "",
        "sekarang": 1790000007,
        "header": {
          "X-Marketplace-Buyer-Id": "0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f",
          "X-Marketplace-Entitlement-Id": "3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8",
          "X-Marketplace-Produk": "api-cuaca",
          "X-Marketplace-Expires-At": "2026-10-21T15:33:20+00:00"
        }
      },
      "harapan": {
        "sah": false,
        "alasan": "header_kurang"
      }
    },
    {
      "nama": "tidak sah: secret dipakai tanpa awalan whsec_",
      "catatan": "Awalan adalah bagian dari nilai secret. Memotongnya adalah salah satu kesalahan integrasi tersering.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "pesan_kanonik": "v1:gateway\n1790000000\n5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f\nGET\n/v1/cuaca?kota=Denpasar\n0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\n3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\napi-cuaca\n2026-10-21T15:33:20+00:00",
      "masukan": {
        "secret": "vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "method": "GET",
        "path_diterima": "/v1/cuaca?kota=Denpasar",
        "prefix_yang_dibuang": "",
        "sekarang": 1790000007,
        "header": {
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Request-Id": "5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f",
          "X-Marketplace-Target": "/v1/cuaca?kota=Denpasar",
          "X-Marketplace-Buyer-Id": "0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f",
          "X-Marketplace-Entitlement-Id": "3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8",
          "X-Marketplace-Produk": "api-cuaca",
          "X-Marketplace-Expires-At": "2026-10-21T15:33:20+00:00",
          "X-Marketplace-Signature": "sha256=68a380468e420cdcd56c42c5d2efa8bb536773b9faa7ad5f2eaf537901672b7a"
        }
      },
      "harapan": {
        "sah": false,
        "alasan": "tanda_tangan"
      }
    },
    {
      "nama": "tidak sah: masa tenggang berakhir, server masih memakai secret lama",
      "catatan": "Setelah tenggang habis (atau diakhiri Owner), hanya secret baru yang menandatangani.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-BARU-bukan-rahasia-9876543210"
      ],
      "pesan_kanonik": "v1:gateway\n1790000000\n5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f\nGET\n/v1/cuaca?kota=Denpasar\n0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\n3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\napi-cuaca\n2026-10-21T15:33:20+00:00",
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "method": "GET",
        "path_diterima": "/v1/cuaca?kota=Denpasar",
        "prefix_yang_dibuang": "",
        "sekarang": 1790000007,
        "header": {
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Request-Id": "5f0c6b1e-2a9d-4c3b-8e7f-1a2b3c4d5e6f",
          "X-Marketplace-Target": "/v1/cuaca?kota=Denpasar",
          "X-Marketplace-Buyer-Id": "0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f",
          "X-Marketplace-Entitlement-Id": "3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8",
          "X-Marketplace-Produk": "api-cuaca",
          "X-Marketplace-Expires-At": "2026-10-21T15:33:20+00:00",
          "X-Marketplace-Signature": "sha256=cb07a12012c40511f076145a54be87e5194cdfbdc802ba9a5228bd7c89b4fb51"
        }
      },
      "harapan": {
        "sah": false,
        "alasan": "tanda_tangan"
      }
    }
  ],
  "webhook": [
    {
      "nama": "sah: entitlement.updated",
      "catatan": "Contoh payload Bagian 3.2.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "sekarang": 1790000007,
        "header": {
          "Content-Type": "application/json",
          "User-Agent": "KayyaAPI-Webhook/1.0",
          "X-Marketplace-Event": "entitlement.updated",
          "X-Marketplace-Delivery": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Signature": "sha256=f2561ad8e74b6bf2b36c342fad703593f36ea063334e33679525ea155bc7e640"
        },
        "body": "{\"event\":\"entitlement.updated\",\"entitlement_id\":\"3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\",\"buyer_id\":\"0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\",\"product_id\":\"7c1a9e33-4d2b-4f6a-8c0d-9e1f2a3b4c5d\",\"tenant_id\":\"4f1c2b8e-9a7d-4e3f-8b21-6c5d0e9a1f37\",\"durasi_bulan\":6,\"status\":\"active\",\"expires_at\":\"2027-03-21T15:33:20Z\",\"revoked_at\":null,\"limit_hit\":80000,\"updated_at\":\"2026-09-21T15:33:18.123456Z\"}"
      },
      "harapan": {
        "sah": true,
        "alasan": null
      }
    },
    {
      "nama": "sah: ping",
      "catatan": "Tombol Kirim uji & pemeriksaan berkala.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "sekarang": 1790000007,
        "header": {
          "Content-Type": "application/json",
          "User-Agent": "KayyaAPI-Webhook/1.0",
          "X-Marketplace-Event": "ping",
          "X-Marketplace-Delivery": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Signature": "sha256=97a19b7177323f00f6013fee58fc15b6502ea5e543d67037371bd877049bf917"
        },
        "body": "{\"event\":\"ping\",\"tenant_id\":\"4f1c2b8e-9a7d-4e3f-8b21-6c5d0e9a1f37\"}"
      },
      "harapan": {
        "sah": true,
        "alasan": null
      }
    },
    {
      "nama": "sah: body berisi karakter non-ASCII",
      "catatan": "Body dikirim UTF-8 tanpa escape \\u. Tanda tangan dihitung dari byte mentah — bukan dari string hasil decode lalu encode ulang dengan codec lain.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "sekarang": 1790000007,
        "header": {
          "Content-Type": "application/json",
          "User-Agent": "KayyaAPI-Webhook/1.0",
          "X-Marketplace-Event": "ping",
          "X-Marketplace-Delivery": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Signature": "sha256=fab6329c394d7596c5d4d5601eb0a71f976c588f6bec7fd91b6e6203fd5da92d"
        },
        "body": "{\"event\":\"ping\",\"tenant_id\":\"4f1c2b8e-9a7d-4e3f-8b21-6c5d0e9a1f37\",\"catatan\":\"Kopi ☕ di Denpasar — café Ümit\"}"
      },
      "harapan": {
        "sah": true,
        "alasan": null
      }
    },
    {
      "nama": "sah: nama header huruf kecil (HTTP/2)",
      "catatan": "Pencarian header wajib tidak peka huruf besar/kecil.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "sekarang": 1790000007,
        "header": {
          "content-type": "application/json",
          "user-agent": "KayyaAPI-Webhook/1.0",
          "x-marketplace-event": "entitlement.updated",
          "x-marketplace-delivery": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
          "x-marketplace-timestamp": "1790000000",
          "x-marketplace-signature": "sha256=f2561ad8e74b6bf2b36c342fad703593f36ea063334e33679525ea155bc7e640"
        },
        "body": "{\"event\":\"entitlement.updated\",\"entitlement_id\":\"3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\",\"buyer_id\":\"0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\",\"product_id\":\"7c1a9e33-4d2b-4f6a-8c0d-9e1f2a3b4c5d\",\"tenant_id\":\"4f1c2b8e-9a7d-4e3f-8b21-6c5d0e9a1f37\",\"durasi_bulan\":6,\"status\":\"active\",\"expires_at\":\"2027-03-21T15:33:20Z\",\"revoked_at\":null,\"limit_hit\":80000,\"updated_at\":\"2026-09-21T15:33:18.123456Z\"}"
      },
      "harapan": {
        "sah": true,
        "alasan": null
      }
    },
    {
      "nama": "sah: masa tenggang rotasi, server masih memakai secret lama",
      "catatan": "Dua tanda tangan dipisah koma; cukup satu yang cocok.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-BARU-bukan-rahasia-9876543210",
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "sekarang": 1790000007,
        "header": {
          "Content-Type": "application/json",
          "User-Agent": "KayyaAPI-Webhook/1.0",
          "X-Marketplace-Event": "entitlement.updated",
          "X-Marketplace-Delivery": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Signature": "sha256=376e52439ba548c39a6267e41ff0613496f8019f094ffc742474c4f6405c823e,sha256=f2561ad8e74b6bf2b36c342fad703593f36ea063334e33679525ea155bc7e640"
        },
        "body": "{\"event\":\"entitlement.updated\",\"entitlement_id\":\"3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\",\"buyer_id\":\"0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\",\"product_id\":\"7c1a9e33-4d2b-4f6a-8c0d-9e1f2a3b4c5d\",\"tenant_id\":\"4f1c2b8e-9a7d-4e3f-8b21-6c5d0e9a1f37\",\"durasi_bulan\":6,\"status\":\"active\",\"expires_at\":\"2027-03-21T15:33:20Z\",\"revoked_at\":null,\"limit_hit\":80000,\"updated_at\":\"2026-09-21T15:33:18.123456Z\"}"
      },
      "harapan": {
        "sah": true,
        "alasan": null
      }
    },
    {
      "nama": "tidak sah: satu byte body diubah",
      "catatan": "",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "sekarang": 1790000007,
        "header": {
          "Content-Type": "application/json",
          "User-Agent": "KayyaAPI-Webhook/1.0",
          "X-Marketplace-Event": "entitlement.updated",
          "X-Marketplace-Delivery": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Signature": "sha256=f2561ad8e74b6bf2b36c342fad703593f36ea063334e33679525ea155bc7e640"
        },
        "body": "{\"event\":\"entitlement.updated\",\"entitlement_id\":\"3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\",\"buyer_id\":\"0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\",\"product_id\":\"7c1a9e33-4d2b-4f6a-8c0d-9e1f2a3b4c5d\",\"tenant_id\":\"4f1c2b8e-9a7d-4e3f-8b21-6c5d0e9a1f37\",\"durasi_bulan\":7,\"status\":\"active\",\"expires_at\":\"2027-03-21T15:33:20Z\",\"revoked_at\":null,\"limit_hit\":80000,\"updated_at\":\"2026-09-21T15:33:18.123456Z\"}"
      },
      "harapan": {
        "sah": false,
        "alasan": "tanda_tangan"
      }
    },
    {
      "nama": "tidak sah: body di-serialize ulang",
      "catatan": "json.loads lalu json.dumps menyisipkan spasi — tanda tangan dihitung dari raw body SEBELUM body-parser framework bekerja.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "sekarang": 1790000007,
        "header": {
          "Content-Type": "application/json",
          "User-Agent": "KayyaAPI-Webhook/1.0",
          "X-Marketplace-Event": "entitlement.updated",
          "X-Marketplace-Delivery": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Signature": "sha256=f2561ad8e74b6bf2b36c342fad703593f36ea063334e33679525ea155bc7e640"
        },
        "body": "{\"event\": \"entitlement.updated\", \"entitlement_id\": \"3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\", \"buyer_id\": \"0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\", \"product_id\": \"7c1a9e33-4d2b-4f6a-8c0d-9e1f2a3b4c5d\", \"tenant_id\": \"4f1c2b8e-9a7d-4e3f-8b21-6c5d0e9a1f37\", \"durasi_bulan\": 6, \"status\": \"active\", \"expires_at\": \"2027-03-21T15:33:20Z\", \"revoked_at\": null, \"limit_hit\": 80000, \"updated_at\": \"2026-09-21T15:33:18.123456Z\"}"
      },
      "harapan": {
        "sah": false,
        "alasan": "tanda_tangan"
      }
    },
    {
      "nama": "tidak sah: timestamp 301 detik di belakang jam server",
      "catatan": "",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "sekarang": 1790000301,
        "header": {
          "Content-Type": "application/json",
          "User-Agent": "KayyaAPI-Webhook/1.0",
          "X-Marketplace-Event": "entitlement.updated",
          "X-Marketplace-Delivery": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Signature": "sha256=f2561ad8e74b6bf2b36c342fad703593f36ea063334e33679525ea155bc7e640"
        },
        "body": "{\"event\":\"entitlement.updated\",\"entitlement_id\":\"3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\",\"buyer_id\":\"0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\",\"product_id\":\"7c1a9e33-4d2b-4f6a-8c0d-9e1f2a3b4c5d\",\"tenant_id\":\"4f1c2b8e-9a7d-4e3f-8b21-6c5d0e9a1f37\",\"durasi_bulan\":6,\"status\":\"active\",\"expires_at\":\"2027-03-21T15:33:20Z\",\"revoked_at\":null,\"limit_hit\":80000,\"updated_at\":\"2026-09-21T15:33:18.123456Z\"}"
      },
      "harapan": {
        "sah": false,
        "alasan": "timestamp"
      }
    },
    {
      "nama": "tidak sah: timestamp diganti, tanda tangan lama dipakai ulang",
      "catatan": "Replay dengan timestamp segar — timestamp ikut ditandatangani.",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "sekarang": 1790000007,
        "header": {
          "Content-Type": "application/json",
          "User-Agent": "KayyaAPI-Webhook/1.0",
          "X-Marketplace-Event": "entitlement.updated",
          "X-Marketplace-Delivery": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
          "X-Marketplace-Timestamp": "1790000005",
          "X-Marketplace-Signature": "sha256=f2561ad8e74b6bf2b36c342fad703593f36ea063334e33679525ea155bc7e640"
        },
        "body": "{\"event\":\"entitlement.updated\",\"entitlement_id\":\"3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\",\"buyer_id\":\"0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\",\"product_id\":\"7c1a9e33-4d2b-4f6a-8c0d-9e1f2a3b4c5d\",\"tenant_id\":\"4f1c2b8e-9a7d-4e3f-8b21-6c5d0e9a1f37\",\"durasi_bulan\":6,\"status\":\"active\",\"expires_at\":\"2027-03-21T15:33:20Z\",\"revoked_at\":null,\"limit_hit\":80000,\"updated_at\":\"2026-09-21T15:33:18.123456Z\"}"
      },
      "harapan": {
        "sah": false,
        "alasan": "tanda_tangan"
      }
    },
    {
      "nama": "tidak sah: secret dipakai tanpa awalan whsec_",
      "catatan": "",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "masukan": {
        "secret": "vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "sekarang": 1790000007,
        "header": {
          "Content-Type": "application/json",
          "User-Agent": "KayyaAPI-Webhook/1.0",
          "X-Marketplace-Event": "entitlement.updated",
          "X-Marketplace-Delivery": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
          "X-Marketplace-Timestamp": "1790000000",
          "X-Marketplace-Signature": "sha256=f2561ad8e74b6bf2b36c342fad703593f36ea063334e33679525ea155bc7e640"
        },
        "body": "{\"event\":\"entitlement.updated\",\"entitlement_id\":\"3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\",\"buyer_id\":\"0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\",\"product_id\":\"7c1a9e33-4d2b-4f6a-8c0d-9e1f2a3b4c5d\",\"tenant_id\":\"4f1c2b8e-9a7d-4e3f-8b21-6c5d0e9a1f37\",\"durasi_bulan\":6,\"status\":\"active\",\"expires_at\":\"2027-03-21T15:33:20Z\",\"revoked_at\":null,\"limit_hit\":80000,\"updated_at\":\"2026-09-21T15:33:18.123456Z\"}"
      },
      "harapan": {
        "sah": false,
        "alasan": "tanda_tangan"
      }
    },
    {
      "nama": "tidak sah: header X-Marketplace-Signature tidak ada",
      "catatan": "",
      "secret_penanda_tangan": [
        "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789"
      ],
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "sekarang": 1790000007,
        "header": {
          "Content-Type": "application/json",
          "User-Agent": "KayyaAPI-Webhook/1.0",
          "X-Marketplace-Event": "entitlement.updated",
          "X-Marketplace-Delivery": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
          "X-Marketplace-Timestamp": "1790000000"
        },
        "body": "{\"event\":\"entitlement.updated\",\"entitlement_id\":\"3b7d5c11-8e2f-4a90-b1c2-d3e4f5a6b7c8\",\"buyer_id\":\"0f9c1e2a-7b3d-4c5e-9f10-2a3b4c5d6e7f\",\"product_id\":\"7c1a9e33-4d2b-4f6a-8c0d-9e1f2a3b4c5d\",\"tenant_id\":\"4f1c2b8e-9a7d-4e3f-8b21-6c5d0e9a1f37\",\"durasi_bulan\":6,\"status\":\"active\",\"expires_at\":\"2027-03-21T15:33:20Z\",\"revoked_at\":null,\"limit_hit\":80000,\"updated_at\":\"2026-09-21T15:33:18.123456Z\"}"
      },
      "harapan": {
        "sah": false,
        "alasan": "header_kurang"
      }
    }
  ],
  "sync": [
    {
      "nama": "halaman pertama tanpa since",
      "catatan": "Pemasangan pertama atau database lokal hilang: tarik semuanya.",
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "timestamp": "1790000000",
        "target": "/api/v1/provisioning/sync/"
      },
      "harapan": {
        "signature": "sha256=c69a31adb9a9e71891ba01aa10826e8fcd91d0f8f3886004dcb8d54e5da80887"
      }
    },
    {
      "nama": "since berzona Z",
      "catatan": "Nilai `sampai` putaran sebelumnya, di-encode sebagai parameter URL.",
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "timestamp": "1790000000",
        "target": "/api/v1/provisioning/sync/?since=2026-09-21T00%3A00%3A00Z"
      },
      "harapan": {
        "signature": "sha256=ccb1db8ecb54cd4db52e7e85ec9f15aba9ccaacc2e5dd3973e30c9fff3aa2c46"
      }
    },
    {
      "nama": "since berzona +00:00",
      "catatan": "Tanda + WAJIB di-encode %2B — tanpa itu server membacanya sebagai spasi dan menolak since-nya.",
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "timestamp": "1790000000",
        "target": "/api/v1/provisioning/sync/?since=2026-09-21T00%3A00%3A00.123456%2B00%3A00"
      },
      "harapan": {
        "signature": "sha256=e46f44961f813a7dfef8554628e9706dc85c1cffa2d9ac647bc456dd7f57a933"
      }
    },
    {
      "nama": "halaman berikutnya dengan kursor",
      "catatan": "Kursor dikirim apa adanya, tanpa since. Yang ditandatangani adalah target persis seperti yang dikirim.",
      "masukan": {
        "secret": "whsec_vektor-uji-UTAMA-bukan-rahasia-0123456789",
        "timestamp": "1790000000",
        "target": "/api/v1/provisioning/sync/?kursor=eyJuIjoiNGYxYzJiOGUiLCJ1IjoiMjAyNi0wOS0yMSJ9%3A1u2V3w%3AZm9vYmFyLWJhel9xdXV4"
      },
      "harapan": {
        "signature": "sha256=cd9ae5c9b537551741c23259fa3f56efe819ffcab0d71dada7590803f2dcbe3a"
      }
    }
  ]
}
