// Signed JSON between two services: the payload made canonical (RFC 8785) before it is hashed or signed, so
// re-spacing or reordering on the way does not break the signature.
//
//   quillo run json_canonical.qwe      then open http://localhost:8080/canonical

use "json_canonical.qwer"

let SECRET = env("PARTNER_SECRET") ?? "partner-shared-secret"

// The RFC's own example, read as text and made canonical.
route GET /canonical = respond(200, jcs_canonical_text(read_file("json_canonical_sample.json")?)?, { "content-type": "application/json" })

// Keys ordered as JavaScript orders them (UTF-16), the RFC's sorting example.
route GET /order = jcs_canonical_text("{\"\\u20ac\": \"Euro\", \"\\r\": \"CR\", \"\\ufb33\": \"Hebrew\", \"1\": \"One\", \"\\ud83d\\ude00\": \"Smiley\", \"\\u0080\": \"Control\", \"\\u00f6\": \"Latin\"}")?

// A partner's webhook: the same order sent spaced and reordered still checks.
route GET /signed {
    let order = { id: "A-1042", total: 15.3, lines: [{ sku: "TEA-01", qty: 2 }], paid: true }
    let sig = jcs_hmac(order, SECRET)?
    let received = json.parse("{ \"paid\": true, \"lines\": [ { \"qty\": 2, \"sku\": \"TEA-01\" } ], \"total\": 15.30, \"id\": \"A-1042\" }")
    {
        canonical: jcs_canonical(order)?,
        signature: sig,
        received_checks: jcs_hmac_verify(received, SECRET, sig)?,
        tampered_checks: jcs_hmac_verify(merge(received, { total: 1.53 }), SECRET, sig)?,
        same: jcs_same("{\"a\": 1.0, \"b\": [1E2]}", "{\"b\":[100],\"a\":1}")?,
        sha256: jcs_sha256(order)?,
    }
}
