{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://thehiveryiq.com/.well-known/schemas/sls-metering-v1.json",
  "title": "SLS Metering Receipt, v1",
  "description": "Canonical schema for the Hive machine service metering receipt, canonical type sls.metering. The useful number here is not the total. It is the fraction of billed units carrying receipt bound evidence, and the size of the unbacked remainder. Every amount is an integer in minor currency units, never a float. does_not_prove: this receipt does not prove the work was performed to any standard, does not prove the customer accepted it, and does not settle payment.",
  "type": "object",
  "required": [
    "receipt_id",
    "payload_sha256",
    "sig_b64u",
    "key_id",
    "algorithm",
    "ts",
    "signed_body"
  ],
  "additionalProperties": false,
  "properties": {
    "receipt_id": { "type": "string", "pattern": "^r_sls\\.metering_[0-9]{10,}_[0-9a-f]{12}$" },
    "payload_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
    "sig_b64u": { "type": "string", "pattern": "^[A-Za-z0-9_-]{86}$" },
    "key_id": { "type": "string", "pattern": "^did:(hive|web|key):[A-Za-z0-9._:%-]+$" },
    "algorithm": { "type": "string", "const": "Ed25519" },
    "ts": { "type": "integer", "minimum": 1000000000 },
    "signed_body": {
      "type": "object",
      "required": [
        "receipt_type",
        "schema",
        "metering_id",
        "machine_commitment",
        "customer_commitment",
        "window_start",
        "window_end",
        "compiled_at",
        "service_unit",
        "metered",
        "evidence_coverage_ratio",
        "coverage_class",
        "rate",
        "amount_minor",
        "evidence_backed_amount_minor",
        "verdict",
        "salt_commitment",
        "boundary"
      ],
      "additionalProperties": false,
      "properties": {
        "receipt_type": { "type": "string", "const": "sls.metering" },
        "schema": { "type": "string", "const": "r1.0.0" },
        "metering_id": { "type": "string", "pattern": "^sm_[0-9a-f]{16,64}$" },
        "machine_commitment": {
          "type": "string",
          "description": "Salted HMAC over the machine serial. The serial itself never enters the receipt.",
          "pattern": "^[0-9a-f]{64}$"
        },
        "customer_commitment": {
          "type": "string",
          "description": "Salted HMAC over the customer account identifier, so who was billed stays private while staying checkable.",
          "pattern": "^[0-9a-f]{64}$"
        },
        "window_start": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,9})?Z$"
        },
        "window_end": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,9})?Z$"
        },
        "compiled_at": {
          "type": "string",
          "description": "When the bill was compiled. A bill compiled before the window closed cannot have metered the window, so this is checked against window_end rather than accepted.",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,9})?Z$"
        },
        "service_unit": {
          "type": "string",
          "enum": [
            "machine_hour",
            "task_completion",
            "pick",
            "kilometre_travelled",
            "pallet_moved",
            "inspection_pass"
          ]
        },
        "metered": {
          "type": "object",
          "description": "The billed count, how much of it carries receipt bound evidence, and the Merkle root over the per unit evidence leaves.",
          "required": [
            "billed_unit_count",
            "evidence_backed_unit_count",
            "unbacked_unit_count",
            "receipt_set_digest"
          ],
          "additionalProperties": false,
          "properties": {
            "billed_unit_count": { "type": "integer", "minimum": 0, "maximum": 10000000 },
            "evidence_backed_unit_count": {
              "type": "integer",
              "description": "Recomputed by the service from the per unit evidence leaves it was given, so the count and the digest cannot disagree.",
              "minimum": 0,
              "maximum": 10000000
            },
            "unbacked_unit_count": {
              "type": "integer",
              "description": "Recomputed by the service as billed_unit_count minus evidence_backed_unit_count.",
              "minimum": 0,
              "maximum": 10000000
            },
            "receipt_set_digest": {
              "type": "string",
              "description": "RFC 6962 Merkle root over the per unit evidence leaves in the order supplied, so the evidence set cannot be edited after signing.",
              "pattern": "^[0-9a-f]{64}$"
            }
          }
        },
        "evidence_coverage_ratio": {
          "type": "number",
          "description": "Recomputed by the service as evidence_backed_unit_count divided by billed_unit_count, rounded to exactly six decimal places. A window with no billed units carries a ratio of 0.",
          "minimum": 0,
          "maximum": 1
        },
        "coverage_class": {
          "type": "string",
          "description": "Recomputed by the service from the coverage ratio.",
          "enum": [
            "fully_evidence_backed",
            "majority_evidence_backed",
            "minority_evidence_backed",
            "not_evidence_backed"
          ]
        },
        "rate": {
          "type": "object",
          "description": "The per unit rate, in integer minor currency units. There are no floating point amounts anywhere in this receipt.",
          "required": ["unit_rate_minor", "currency", "rate_commitment"],
          "additionalProperties": false,
          "properties": {
            "unit_rate_minor": { "type": "integer", "minimum": 0, "maximum": 100000000 },
            "currency": { "type": "string", "pattern": "^[A-Z]{3}$" },
            "rate_commitment": { "type": "string", "pattern": "^[0-9a-f]{64}$" }
          }
        },
        "amount_minor": {
          "type": "integer",
          "description": "Recomputed by the service as billed_unit_count times unit_rate_minor, in minor currency units.",
          "minimum": 0
        },
        "evidence_backed_amount_minor": {
          "type": "integer",
          "description": "Recomputed by the service as evidence_backed_unit_count times unit_rate_minor, in minor currency units.",
          "minimum": 0
        },
        "settlement_binding": {
          "type": "object",
          "description": "Optional. What this bill was presented against. Binding a settlement reference is not settling it.",
          "required": ["settlement_class", "settlement_commitment"],
          "additionalProperties": false,
          "properties": {
            "settlement_class": {
              "type": "string",
              "enum": ["x402_offer", "invoice_reference", "none"]
            },
            "settlement_commitment": { "type": "string", "pattern": "^[0-9a-f]{64}$" }
          }
        },
        "verdict": {
          "type": "string",
          "description": "Recomputed by the service from the coverage class. The ceiling is metered_units_fully_evidence_backed. There is no verdict that says the money is owed.",
          "enum": [
            "metered_units_fully_evidence_backed",
            "metered_units_partially_evidence_backed",
            "metered_units_not_evidence_backed"
          ]
        },
        "salt_commitment": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
        "boundary": {
          "type": "string",
          "minLength": 1,
          "const": "This receipt records metered machine service units for a stated billing window, the per unit evidence that backs them, and the fraction of billed units carrying receipt bound evidence. It does not prove the work was performed to any standard, does not prove the customer accepted it, and does not settle payment."
        }
      }
    }
  }
}
