{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://getzero.dev/contracts/zero.hl_data_plane.v1.schema.json",
  "title": "Hyperliquid Data-Plane Provenance v1",
  "description": "Provenance block attached to a ReplayFrame / EvidenceBundle so consumers can see (a) which Hyperliquid source the Runtime read from, (b) how fresh each cached signal was at decision time, and (c) whether the source agreed with the public HL API. Produced by zero/data_plane.py:data_plane_provenance(). The schema deliberately does not specify a single hash field for the data plane state — divergence detection is a follow-on contract.",
  "type": "object",
  "required": [
    "schema",
    "checked_at",
    "source",
    "fallback_used",
    "freshness_budgets_ms",
    "ages_ms",
    "public_api_divergence_status"
  ],
  "properties": {
    "schema": {
      "type": "string",
      "const": "zero.hl_data_plane.v1"
    },
    "checked_at": {
      "type": "string",
      "format": "date-time",
      "description": "ISO-8601 UTC timestamp when the provenance block was built."
    },
    "source": {
      "type": "object",
      "description": "The HL endpoint the Runtime actually read from.",
      "required": ["source_id", "kind", "network", "info_url", "exchange_url", "ws_url"],
      "properties": {
        "source_id": {
          "type": "string",
          "description": "Stable identifier for this endpoint. Defaults to 'zero-hl-primary' when no override env is set."
        },
        "kind": {
          "type": "string",
          "enum": [
            "public_hl_api",
            "foundation_nonvalidating_node",
            "self_hosted_node_api",
            "managed_private_endpoint"
          ],
          "description": "What category of endpoint this is. Public HL API is the default."
        },
        "network": {
          "type": "string",
          "enum": ["mainnet", "testnet"]
        },
        "info_url": {"type": "string", "format": "uri"},
        "exchange_url": {"type": "string", "format": "uri"},
        "ws_url": {"type": "string"}
      }
    },
    "fallback_used": {
      "type": "boolean",
      "description": "True when the Runtime served this decision off the fallback source."
    },
    "fallback_reason": {
      "type": ["string", "null"],
      "description": "Human-readable reason the fallback was used, or null when fallback_used is false."
    },
    "freshness_budgets_ms": {
      "type": "object",
      "description": "The max-age budgets in effect when this provenance was built. Operators tighten via ZERO_HL_MAX_*_AGE_MS env vars.",
      "required": ["account_state", "open_orders", "fills", "book"],
      "properties": {
        "account_state": {"type": "integer", "minimum": 0},
        "open_orders": {"type": "integer", "minimum": 0},
        "fills": {"type": "integer", "minimum": 0},
        "book": {"type": "integer", "minimum": 0}
      }
    },
    "ages_ms": {
      "type": "object",
      "description": "Observed age in milliseconds of each cached signal at decision time. null means 'age could not be determined from the input timestamp' — treat as 'unknown', which the live-signing path should refuse on.",
      "required": ["account_state", "open_orders", "fills", "book"],
      "properties": {
        "account_state": {"type": ["integer", "null"], "minimum": 0},
        "open_orders": {"type": ["integer", "null"], "minimum": 0},
        "fills": {"type": ["integer", "null"], "minimum": 0},
        "book": {"type": ["integer", "null"], "minimum": 0}
      }
    },
    "public_api_divergence_status": {
      "type": "string",
      "enum": ["match", "minor_drift", "major_drift", "unchecked"],
      "description": "Result of comparing the Runtime's source against the public HL API for the same fields. 'unchecked' is the v1 default; divergence detection lands in a follow-on PR."
    }
  }
}
