{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://hushspec.dev/schemas/hushspec-evaluator-test.v0.schema.json",
  "$comment": "Frozen 0.x lineage. This file is retained for documents that declare a 0.x hushspec version and is not edited after HushSpec 1.0.0; the current schema is the .v1. file with the same name (spec/versioning.md).",
  "title": "HushSpec Evaluator Fixture v0",
  "description": "Schema for versioned evaluator fixtures used by the HushSpec reference evaluator and conformance testkit.",
  "type": "object",
  "required": [
    "hushspec_test",
    "description",
    "policy",
    "cases"
  ],
  "additionalProperties": false,
  "properties": {
    "hushspec_test": {
      "type": "string",
      "enum": [
        "0.1.0",
        "0.2.0"
      ],
      "description": "Fixture format version. 0.2.0 adds per-case `controls` and `tags` and the `expect.rule_trace` / `expect.receipt` assertions; a fixture that uses any of them declares 0.2.0."
    },
    "description": {
      "type": "string",
      "minLength": 1
    },
    "policy": {
      "type": "object",
      "required": [
        "hushspec"
      ],
      "description": "Embedded HushSpec document. Full policy validation is performed separately by the SDK.",
      "additionalProperties": true
    },
    "cases": {
      "type": "array",
      "minItems": 1,
      "items": {
        "$ref": "#/$defs/EvaluationCase"
      }
    }
  },
  "$defs": {
    "EvaluationCase": {
      "type": "object",
      "required": [
        "description",
        "action",
        "expect"
      ],
      "additionalProperties": false,
      "properties": {
        "description": {
          "type": "string",
          "minLength": 1
        },
        "action": {
          "$ref": "#/$defs/Action"
        },
        "context": {
          "$ref": "#/$defs/RuntimeContext"
        },
        "controls": {
          "type": "array",
          "description": "The controls this case proves (test-as-evidence). Reported by `h2h test --format junit` as `<property>` entries and by `--format json` per case.",
          "items": {
            "$ref": "#/$defs/ControlRef"
          }
        },
        "tags": {
          "type": "array",
          "description": "Free-form labels for selecting or grouping cases (for example `deny`, `phi`, `smoke`).",
          "items": {
            "type": "string",
            "minLength": 1
          }
        },
        "expect": {
          "$ref": "#/$defs/ExpectedResult"
        }
      }
    },
    "RuntimeContext": {
      "type": "object",
      "additionalProperties": false,
      "description": "Runtime context supplied to `when` conditions (core spec 3.13).",
      "properties": {
        "user": {
          "type": "object",
          "additionalProperties": true
        },
        "environment": {
          "type": "string"
        },
        "deployment": {
          "type": "object",
          "additionalProperties": true
        },
        "agent": {
          "type": "object",
          "additionalProperties": true
        },
        "session": {
          "type": "object",
          "additionalProperties": true
        },
        "request": {
          "type": "object",
          "additionalProperties": true
        },
        "custom": {
          "type": "object",
          "additionalProperties": true
        },
        "current_time": {
          "type": "string",
          "description": "RFC 3339 timestamp used instead of the engine clock (deterministic testing)."
        },
        "counters": {
          "type": "object",
          "additionalProperties": {
            "type": "integer",
            "minimum": 0
          },
          "description": "Engine-maintained counters consulted by `rate` conditions (core spec 3.13)."
        }
      }
    },
    "Action": {
      "type": "object",
      "required": [
        "type"
      ],
      "additionalProperties": false,
      "properties": {
        "type": {
          "type": "string",
          "minLength": 1,
          "description": "Action type (core spec 5). Any string is accepted so that unknown-type vectors can assert the fail-closed deny; reference types are file_read, file_write, patch_apply, shell_command, tool_call, egress, computer_use, input_inject, browser_action, code_exec, custom."
        },
        "target": {
          "type": "string"
        },
        "content": {
          "type": "string"
        },
        "args_size": {
          "type": "integer",
          "minimum": 0
        },
        "origin": {
          "$ref": "#/$defs/Origin"
        },
        "posture": {
          "$ref": "#/$defs/PostureInput"
        },
        "url": {
          "type": "string",
          "description": "browser_action: navigation destination (core spec 3.11)."
        },
        "network": {
          "type": "boolean",
          "description": "code_exec: whether the call requests network access (core spec 3.12)."
        },
        "timeout_ms": {
          "type": "integer",
          "minimum": 0,
          "description": "code_exec: requested execution time in milliseconds (core spec 3.12)."
        }
      }
    },
    "Origin": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "provider": {
          "type": "string"
        },
        "tenant_id": {
          "type": "string"
        },
        "space_id": {
          "type": "string"
        },
        "space_type": {
          "type": "string"
        },
        "visibility": {
          "type": "string"
        },
        "external_participants": {
          "type": "boolean"
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "sensitivity": {
          "type": "string"
        },
        "actor_role": {
          "type": "string"
        }
      }
    },
    "PostureInput": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "current": {
          "type": "string"
        },
        "signal": {
          "type": "string"
        }
      }
    },
    "ExpectedResult": {
      "type": "object",
      "required": [
        "decision"
      ],
      "additionalProperties": false,
      "properties": {
        "decision": {
          "type": "string",
          "enum": [
            "allow",
            "warn",
            "deny"
          ]
        },
        "matched_rule": {
          "type": "string"
        },
        "reason": {
          "type": "string"
        },
        "origin_profile": {
          "type": "string"
        },
        "posture": {
          "$ref": "#/$defs/PostureResult"
        },
        "rule_trace": {
          "type": "array",
          "description": "The recorded rule trace (receipt spec 4.3), compared in order and in full: the actual trace must have exactly this many entries, and each entry must match the members declared here.",
          "items": {
            "$ref": "#/$defs/RuleTraceExpectation"
          }
        },
        "receipt": {
          "type": "object",
          "description": "A partial format 0.2 receipt. Every member present here must equal the corresponding member of the receipt produced under the fixed inputs of fixtures/receipts/expected/README.md; members absent here are not compared. Nested objects are compared member-wise (a partial nested object matches); arrays are compared in full. `actor`, `timestamp` and `receipt_id` are ignored even when present, because they are inputs rather than outcomes.",
          "minProperties": 1,
          "additionalProperties": true
        }
      }
    },
    "ControlRef": {
      "type": "object",
      "description": "A control this case is evidence for. `framework` is an id from spec/registries/frameworks.yaml.",
      "required": [
        "framework",
        "control_id"
      ],
      "additionalProperties": false,
      "properties": {
        "framework": {
          "type": "string",
          "minLength": 1
        },
        "control_id": {
          "type": "string",
          "minLength": 1
        }
      }
    },
    "RuleTraceExpectation": {
      "type": "object",
      "description": "One expected rule-trace entry. `rule_block` uses the closed ids of the receipt schema; `rule_path` is compared only when present.",
      "required": [
        "rule_block",
        "outcome"
      ],
      "additionalProperties": false,
      "properties": {
        "rule_block": {
          "type": "string",
          "minLength": 1
        },
        "outcome": {
          "type": "string",
          "enum": [
            "allow",
            "warn",
            "deny",
            "skip"
          ]
        },
        "rule_path": {
          "type": "string",
          "minLength": 1
        }
      }
    },
    "PostureResult": {
      "type": "object",
      "required": [
        "current",
        "next"
      ],
      "additionalProperties": false,
      "properties": {
        "current": {
          "type": "string"
        },
        "next": {
          "type": "string"
        }
      }
    }
  }
}
