{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://travel.agenthaven.dev/contracts/schemas/scorecard.schema.json",
  "title": "Scorecard",
  "description": "What the verifier publishes after a run, signed by its anchored report key (compact JWS, typ scorecard+jwt, or detached) from the verifier's own domain, next to the evidence archive. Nine dimensions, one verdict each, evidence links INTO the archive rather than at live infrastructure, and the name of the person accountable for the word PROVED. The headline is \"n of 9 dimensions PROVED\"; there is no numeric score. Status: IMPLEMENTED by agent-verifier (architecture v0.2 §5.10; first run 2026-09-07, published signed at https://provedby.dev since 2026-09-11).",
  "type": "object",
  "required": ["run", "dimensions", "overall", "headline", "accountable", "freeze_manifest_sha256", "archive"],
  "properties": {
    "run": {
      "type": "object",
      "required": ["started_at", "ended_at", "domains", "correlation_ids"],
      "properties": {
        "started_at": { "type": "string", "format": "date-time" },
        "ended_at": { "type": "string", "format": "date-time" },
        "domains": { "type": "object", "required": ["seller", "buyer", "authority"], "properties": { "seller": { "type": "string" }, "buyer": { "type": "string" }, "authority": { "type": "string" }, "rogue": { "type": "string" } } },
        "correlation_ids": { "type": "array", "items": { "type": "string" }, "description": "The legitimate transactions of the run. Entries joined on signer plus these ids; refusals from unknown signers are noise (R-24)." },
        "expected_entries": { "type": "object", "description": "Per side, how many entries a clean run writes; an inflated chain shows up as an anomaly.", "additionalProperties": { "type": "integer" } },
        "instances": {
          "type": "object",
          "description": "The instance behind each chain the run read, as its own domain vouches for it (§2): the SPIFFE ID and the key thumbprint the entries are signed under. Null for a side the run did not resolve. On the page since 2026-09-12; before that the ids were only inside check details.",
          "properties": {
            "seller": { "$ref": "#/$defs/instance" },
            "buyer": { "$ref": "#/$defs/instance" },
            "authority": { "$ref": "#/$defs/instance" }
          }
        },
        "checkpoints": {
          "type": "object",
          "description": "Per side, the latest checkpoint the run verified against that side's chain and the receipt it carries (§5.10): what a reader can take to the witness's log. Null for a side that publishes none. On the page since 2026-09-12.",
          "additionalProperties": { "$ref": "#/$defs/checkpoint" }
        }
      }
    },
    "dimensions": {
      "type": "array",
      "minItems": 9,
      "maxItems": 9,
      "items": {
        "type": "object",
        "required": ["dimension", "mandatory", "verdict", "evidence"],
        "properties": {
          "dimension": { "type": "string", "enum": ["discovery", "publisher_control", "registered_identity", "instance", "mandate", "payment", "attribution", "revocation", "rogue"] },
          "mandatory": { "type": "boolean" },
          "verdict": { "type": "string", "enum": ["PROVED", "FAILED", "INCONCLUSIVE", "NOT_TESTED"] },
          "evidence": { "type": "array", "items": { "type": "string", "format": "uri", "description": "A link into the evidence archive, never at live infrastructure." } },
          "checks": { "type": "array", "items": { "type": "object", "required": ["name", "ok"], "properties": { "name": { "type": "string" }, "ok": { "type": "boolean" }, "detail": { "type": "string" }, "measured": { "type": "object", "description": "e.g. seconds_to_first_refusal for revocation, measured on the verifier's clock as an upper bound." } } } },
          "notes": { "type": "string" }
        }
      }
    },
    "overall": { "type": "string", "enum": ["PROVED", "FAILED", "INCONCLUSIVE"], "description": "Any mandatory FAILED gives FAILED; else any mandatory INCONCLUSIVE gives INCONCLUSIVE; else PROVED. INCONCLUSIVE never rounds up." },
    "headline": { "type": "string", "pattern": "^[0-9] of 9 dimensions PROVED$" },
    "accountable": { "type": "object", "required": ["name", "role"], "properties": { "name": { "type": "string" }, "role": { "type": "string" } } },
    "third_party_scores": { "type": "array", "description": "Opinions shown as opinions: GoDaddy's five-dimension vector and the like.", "items": { "type": "object", "required": ["source", "value"], "properties": { "source": { "type": "string" }, "value": {}, "evidence": { "type": "string", "format": "uri" } } } },
    "freeze_manifest_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
    "drift": { "type": "array", "items": { "type": "string" }, "description": "Every difference between the run and the freeze manifest, reported, never hidden." },
    "archive": { "type": "object", "required": ["uri", "sha256"], "properties": { "uri": { "type": "string", "format": "uri" }, "sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" } } },
    "other_sellers": { "type": "array", "description": "What the buyer bought from sellers other than the one the run verifies (since 2026-09-29), each read against that seller's own ledger: beside the verdict, never in it.", "items": { "type": "object", "required": ["host", "read", "ok", "transactions", "purchases", "detail"], "properties": { "host": { "type": "string" }, "ledger": { "type": "string", "format": "uri" }, "evidence": { "type": "string", "format": "uri" }, "read": { "type": "boolean" }, "ok": { "type": ["boolean", "null"] }, "transactions": { "type": "integer" }, "purchases": { "type": "array" }, "unknown_to_buyer": { "type": "array", "items": { "type": "string" } }, "detail": { "type": "string" } } } },
    "buyer_verification": { "type": ["object", "null"], "description": "What the buyer checked about this seller before it bought (since 2026-10-06), as its own ledger says (the latest counterparty.verified entry naming the seller): the buyer's word, counted, beside the verdict and never in it. The verifier's own findings on the same questions are the dimensions.", "required": ["host", "correlation_id", "checks", "passed", "not_published", "failed", "total", "headline", "detail"], "properties": { "host": { "type": "string" }, "correlation_id": { "type": "string" }, "at": { "type": ["string", "null"] }, "ok": { "type": ["boolean", "null"], "description": "The buyer's own verdict on the entry." }, "checks": { "type": "array", "items": { "type": "object", "required": ["name", "ok"], "properties": { "name": { "type": "string" }, "ok": { "type": ["boolean", "null"], "description": "null: not published by the seller (the buyer's SKIP)." }, "detail": { "type": "string" } } } }, "passed": { "type": "integer" }, "not_published": { "type": "integer" }, "failed": { "type": "integer" }, "total": { "type": "integer" }, "headline": { "type": "string", "description": "\"n of m checks passed\", with \", k not published\" and \", j failed\" when they are not zero." }, "in_run": { "type": "boolean", "description": "Whether the entry comes from one of this run's transactions, else from the ledger as a whole." }, "verified_in_run": { "type": "integer" }, "verified_ok_in_run": { "type": "integer" }, "evidence": { "type": "string", "format": "uri" }, "detail": { "type": "string" } } }
  },
  "$defs": {
    "instance": {
      "type": ["object", "null"],
      "required": ["spiffe_id", "kid"],
      "properties": {
        "spiffe_id": { "type": "string", "pattern": "^spiffe://" },
        "kid": { "type": "string", "description": "RFC 7638 thumbprint of the key the chain is signed under at its head (after a handover, the key that took over)." },
        "key_url": { "type": "string", "format": "uri", "description": "Where the domain publishes the key: the seller's spiffe-svid.json, the buyer's agent-keys.json, the authority's jwks.json." },
        "handovers": { "type": "array", "description": "Since 2026-09-17: the key handovers (F-10) the run accepted while verifying this side's chain, oldest first; absent when the chain never changed key.", "items": { "type": "object", "required": ["height", "from_kid", "to_kid", "chain_head", "entry_hash"], "properties": { "height": { "type": "integer", "minimum": 1, "description": "1-based position of the instance.started entry in the chain." }, "at": { "type": ["string", "null"] }, "from_kid": { "type": "string" }, "to_kid": { "type": "string" }, "chain_head": { "type": "string", "pattern": "^[0-9a-f]{64}$", "description": "The head the retired key left, which the entry chains onto." }, "entry_hash": { "type": "string", "pattern": "^[0-9a-f]{64}$" } } } }
      }
    },
    "checkpoint": {
      "type": ["object", "null"],
      "required": ["height", "head", "at", "sealed"],
      "properties": {
        "height": { "type": "integer", "minimum": 1 },
        "head": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
        "at": { "type": "string", "format": "date-time" },
        "sealed": { "type": "boolean", "description": "Whether a receipt that verifies under the witness key set cites this checkpoint." },
        "witness": { "type": ["string", "null"], "format": "uri" },
        "log_index": { "type": ["integer", "null"], "minimum": 0, "description": "The receipt's position in the witness's log." },
        "logged_at": { "type": ["string", "null"], "format": "date-time" },
        "emulator": { "type": "boolean", "description": "True when the receipt says so: the witness is the verifier-operated emulator, not a transparency service." },
        "external": {
          "type": ["object", "null"],
          "description": "The second receipt, when the keeper registered this head at a public transparency log it does not operate (external-witness.md) and the receipt verified here: the log, where the head sits in its tree, the log's signed time, and whether the receipt's tree is a prefix of the tree head the log served this run (consistency, RFC 6962). Null when the checkpoint carries none, or it did not verify (the problem is in the check's detail). Since 2026-09-13.",
          "required": ["log", "leaf_index", "tree_size", "consistent"],
          "properties": {
            "log": { "type": "string", "format": "uri" },
            "leaf_index": { "type": "integer", "minimum": 0 },
            "tree_size": { "type": "integer", "minimum": 1 },
            "iat": { "type": ["integer", "null"], "description": "The log's signed registration time (CWT iat in the receipt's protected header), seconds since the epoch." },
            "consistent": { "type": ["boolean", "null"], "description": "True when the log's consistency proof from the receipt's tree to the tree head fetched this run verified; false when it did not; null when the log could not be asked." },
            "sth_tree_size": { "type": ["integer", "null"], "description": "The tree size of the tree head this run fetched and verified under the log's key." },
            "in_log_now": { "type": ["boolean", "null"], "description": "Whether the log resolved this head by name at run time (GET /v1/inclusion/{head}) with a proof that verifies to the root it names; null when it could not be asked. Independent of the keeper's stored receipt." }
          }
        }
      }
    }
  }
}
