{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://thehiveryiq.com/.well-known/schemas/meter-witness-v1.json",
  "title": "Meter Witness Receipt, v1",
  "description": "Canonical schema for the Hive meter witness receipt, canonical type meter.witness. The instrument answers whether a reported quantity of energy came out of a specific calibrated physical meter or was typed in downstream. A calibration authority signs a calibration manifest committing to a salted meter identity commitment, the device public key, the firmware hash, a calibration coefficients commitment, and a validity interval. The meter secure element signs each interval record over the interval bounds, a commitment to the cumulative register reading, event flags, a verifier supplied freshness nonce commitment established before the record was signed, the calibration manifest envelope digest, and the previous record hash. A collector batches interval records into an RFC 6962 Merkle tree and publishes the batch root inside this receipt. The verifier rederives the interval energy from the cumulative register delta, the record hash, the previous hash chain, and the batch inclusion path, and refuses a reported quantity that does not equal the register delta.",
  "type": "object",
  "required": [
    "receipt_id",
    "payload_sha256",
    "sig_b64u",
    "key_id",
    "algorithm",
    "ts",
    "signed_body"
  ],
  "additionalProperties": false,
  "properties": {
    "receipt_id": {
      "type": "string",
      "pattern": "^r_meter[.]witness_[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",
        "witness_id",
        "meter",
        "calibration",
        "freshness",
        "metering",
        "records",
        "batch",
        "dispute",
        "boundary"
      ],
      "additionalProperties": false,
      "properties": {
        "receipt_type": {
          "type": "string",
          "const": "meter.witness"
        },
        "schema": {
          "type": "string",
          "const": "r1.0.0"
        },
        "witness_id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256,
          "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$"
        },
        "meter": {
          "type": "object",
          "required": [
            "salt_commitment",
            "meter_commitment",
            "device_key_commitment",
            "firmware_commitment"
          ],
          "additionalProperties": false,
          "properties": {
            "salt_commitment": {
              "type": "string",
              "pattern": "^[0-9a-f]{64}$"
            },
            "meter_commitment": {
              "type": "string",
              "pattern": "^[0-9a-f]{64}$"
            },
            "device_key_commitment": {
              "type": "string",
              "pattern": "^[0-9a-f]{64}$"
            },
            "firmware_commitment": {
              "type": "string",
              "pattern": "^[0-9a-f]{64}$"
            }
          }
        },
        "calibration": {
          "type": "object",
          "required": [
            "manifest_id",
            "coefficients_commitment",
            "validity",
            "drift_allowance_seconds",
            "chain_index",
            "prior_manifest_envelope_sha256",
            "manifest_receipt"
          ],
          "additionalProperties": false,
          "properties": {
            "manifest_id": {
              "type": "string",
              "minLength": 1,
              "maxLength": 256,
              "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$"
            },
            "coefficients_commitment": {
              "type": "string",
              "pattern": "^[0-9a-f]{64}$"
            },
            "validity": {
              "type": "object",
              "required": [
                "begins",
                "ends"
              ],
              "additionalProperties": false,
              "properties": {
                "begins": {
                  "type": "object",
                  "required": [
                    "utc",
                    "drift_seconds"
                  ],
                  "additionalProperties": false,
                  "properties": {
                    "utc": {
                      "type": "string",
                      "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}([.][0-9]{1,9})?Z$"
                    },
                    "drift_seconds": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 86400
                    }
                  }
                },
                "ends": {
                  "type": "object",
                  "required": [
                    "utc",
                    "drift_seconds"
                  ],
                  "additionalProperties": false,
                  "properties": {
                    "utc": {
                      "type": "string",
                      "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}([.][0-9]{1,9})?Z$"
                    },
                    "drift_seconds": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 86400
                    }
                  }
                }
              }
            },
            "drift_allowance_seconds": {
              "type": "integer",
              "minimum": 0,
              "maximum": 86400
            },
            "chain_index": {
              "type": "integer",
              "minimum": 0,
              "maximum": 999999
            },
            "prior_manifest_envelope_sha256": {
              "type": "string",
              "pattern": "^[0-9a-f]{64}$"
            },
            "manifest_receipt": {
              "type": "object",
              "required": [
                "receipt_id",
                "receipt_type",
                "envelope_sha256",
                "issuance_instant"
              ],
              "additionalProperties": false,
              "properties": {
                "receipt_id": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 256
                },
                "receipt_type": {
                  "type": "string",
                  "const": "meter.calibration"
                },
                "envelope_sha256": {
                  "type": "string",
                  "pattern": "^[0-9a-f]{64}$"
                },
                "issuance_instant": {
                  "type": "object",
                  "required": [
                    "utc",
                    "drift_seconds"
                  ],
                  "additionalProperties": false,
                  "properties": {
                    "utc": {
                      "type": "string",
                      "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}([.][0-9]{1,9})?Z$"
                    },
                    "drift_seconds": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 86400
                    }
                  }
                }
              }
            }
          }
        },
        "freshness": {
          "type": "object",
          "required": [
            "challenge_id",
            "nonce_commitment",
            "committed_at"
          ],
          "additionalProperties": false,
          "properties": {
            "challenge_id": {
              "type": "string",
              "minLength": 1,
              "maxLength": 256,
              "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$"
            },
            "nonce_commitment": {
              "type": "string",
              "pattern": "^[0-9a-f]{64}$"
            },
            "committed_at": {
              "type": "object",
              "required": [
                "utc",
                "drift_seconds"
              ],
              "additionalProperties": false,
              "properties": {
                "utc": {
                  "type": "string",
                  "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}([.][0-9]{1,9})?Z$"
                },
                "drift_seconds": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 86400
                }
              }
            }
          }
        },
        "metering": {
          "type": "object",
          "required": [
            "energy_unit",
            "nominal_interval_seconds",
            "duration_tolerance_seconds"
          ],
          "additionalProperties": false,
          "properties": {
            "energy_unit": {
              "type": "string",
              "const": "milliwatt_hour"
            },
            "nominal_interval_seconds": {
              "type": "integer",
              "minimum": 1,
              "maximum": 86400
            },
            "duration_tolerance_seconds": {
              "type": "integer",
              "minimum": 0,
              "maximum": 3600
            }
          }
        },
        "records": {
          "type": "array",
          "minItems": 2,
          "maxItems": 64,
          "items": {
            "type": "object",
            "required": [
              "record_index",
              "opens",
              "closes",
              "signed_at",
              "register_commitment",
              "reported_energy_milliwatt_hours",
              "event_flags",
              "previous_record_hash",
              "record_hash",
              "device_signature_b64u",
              "batch_leaf_index",
              "batch_inclusion_path"
            ],
            "additionalProperties": false,
            "properties": {
              "record_index": {
                "type": "integer",
                "minimum": 0,
                "maximum": 999999999999
              },
              "opens": {
                "type": "object",
                "required": [
                  "utc",
                  "drift_seconds"
                ],
                "additionalProperties": false,
                "properties": {
                  "utc": {
                    "type": "string",
                    "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}([.][0-9]{1,9})?Z$"
                  },
                  "drift_seconds": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 86400
                  }
                }
              },
              "closes": {
                "type": "object",
                "required": [
                  "utc",
                  "drift_seconds"
                ],
                "additionalProperties": false,
                "properties": {
                  "utc": {
                    "type": "string",
                    "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}([.][0-9]{1,9})?Z$"
                  },
                  "drift_seconds": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 86400
                  }
                }
              },
              "signed_at": {
                "type": "object",
                "required": [
                  "utc",
                  "drift_seconds"
                ],
                "additionalProperties": false,
                "properties": {
                  "utc": {
                    "type": "string",
                    "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}([.][0-9]{1,9})?Z$"
                  },
                  "drift_seconds": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 86400
                  }
                }
              },
              "register_commitment": {
                "type": "string",
                "pattern": "^[0-9a-f]{64}$"
              },
              "reported_energy_milliwatt_hours": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1000000000000
              },
              "event_flags": {
                "type": "array",
                "minItems": 0,
                "maxItems": 8,
                "items": {
                  "type": "string",
                  "enum": [
                    "cover_opened",
                    "reverse_flow",
                    "magnetic_field",
                    "terminal_tamper",
                    "clock_fault",
                    "register_reset",
                    "power_quality",
                    "firmware_changed"
                  ]
                }
              },
              "previous_record_hash": {
                "type": "string",
                "pattern": "^[0-9a-f]{64}$"
              },
              "record_hash": {
                "type": "string",
                "pattern": "^[0-9a-f]{64}$"
              },
              "device_signature_b64u": {
                "type": "string",
                "pattern": "^[A-Za-z0-9_-]{86}$"
              },
              "batch_leaf_index": {
                "type": "integer",
                "minimum": 0,
                "maximum": 999999999
              },
              "batch_inclusion_path": {
                "type": "array",
                "minItems": 0,
                "maxItems": 40,
                "items": {
                  "type": "string",
                  "pattern": "^[0-9a-f]{64}$"
                }
              }
            }
          }
        },
        "batch": {
          "type": "object",
          "required": [
            "batch_root",
            "tree_size"
          ],
          "additionalProperties": false,
          "properties": {
            "batch_root": {
              "type": "string",
              "pattern": "^[0-9a-f]{64}$"
            },
            "tree_size": {
              "type": "integer",
              "minimum": 1,
              "maximum": 999999999
            }
          }
        },
        "dispute": {
          "type": "object",
          "required": [
            "disputed_record_index",
            "query_class"
          ],
          "additionalProperties": false,
          "properties": {
            "disputed_record_index": {
              "type": "integer",
              "minimum": 0,
              "maximum": 999999999999
            },
            "query_class": {
              "type": "string",
              "enum": [
                "single_interval_dispute"
              ]
            }
          }
        },
        "boundary": {
          "type": "string",
          "const": "This receipt attests only that a calibration manifest signed by a named calibration authority, a set of interval records signed by the meter secure element whose public key that manifest names, a freshness nonce commitment established before those records were signed, and a collector batch root satisfy the stated deterministic metering procedure over the named intervals. A valid result means only that the reported interval energy equals the disclosed cumulative register delta, that each record hash, previous hash link, and batch inclusion path recompute, and that the manifest validity interval contains the interval bounds under the declared drift allowance. It does not establish that the meter measured the physical world correctly, that no physical tampering occurred without raising an event flag, that the firmware named by the manifest was honest when it was manufactured, or that the calibration authority signed a truthful manifest. It does not establish ownership of the site, the identity of the consumer, the source of the energy, or entitlement to any certificate, credit, payment, or settlement. This receipt decides no contractual, statutory, regulatory, evidentiary, or legal consequence, allocates no risk, fault, responsibility, liability, loss, or remedy, and authorizes no action, payment, sanction, denial, or remedy."
        }
      }
    }
  }
}
