{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://github.com/welkaim/ea-codex/schemas/v1/evidence-record.json",
  "title": "EvidenceRecord",
  "description": "Typed evidence: the actual output produced when a control ran. Distinct from ObservabilityProfile (which describes what to collect) and from FitnessFunction (which is the control itself): an EvidenceRecord is the recorded result of a single execution. The Codex chain Decision -> Specification -> Control -> Evidence requires Evidence as a typed link so that any decision can be traced to the controls that enforced it and the runs that produced its evidence. Introduced in Chapter 14.",
  "type": "object",
  "required": ["apiVersion", "kind", "metadata", "spec"],
  "properties": {
    "apiVersion": { "$ref": "_common.json#/$defs/apiVersion" },
    "kind": { "type": "string", "const": "EvidenceRecord" },
    "metadata": { "$ref": "_common.json#/$defs/metadata" },
    "spec": {
      "type": "object",
      "required": ["evidenceType", "result", "evaluatedObjectRefs", "controlRefs", "producedAt"],
      "properties": {
        "evidenceType": {
          "type": "string",
          "enum": ["conformance-run", "approval-record", "runtime-trace", "audit-evidence", "convergence-history", "pull-request-evidence"],
          "description": "Kind of evidence. conformance-run is a single CI or scheduled control execution; approval-record is a human approval action; runtime-trace is observed runtime behavior; audit-evidence is a regulator-facing extract; convergence-history is the result of a scenario-pack iteration; pull-request-evidence is the bundle attached to a PR merge."
        },
        "producer": {
          "type": "string",
          "description": "What produced the evidence (e.g., 'github-actions', 'opa-runtime', 'mlflow', 'human:approver-id')."
        },
        "runId": {
          "type": "string",
          "description": "Stable identifier of the run that produced the evidence. Used to deduplicate and to link to logs."
        },
        "producedAt": {
          "type": "string",
          "format": "date-time",
          "description": "Timestamp at which the evidence was produced. ISO 8601 / RFC 3339."
        },
        "result": {
          "type": "string",
          "description": "Outcome. Common values: 'pass', 'fail', 'pass-with-warnings', 'skipped', 'approved', 'rejected', 'completed'."
        },
        "evaluatedObjectRefs": {
          "type": "array",
          "minItems": 1,
          "description": "Identifiers of the artifacts the evidence applies to. The evidence proves something about each of these.",
          "items": { "$ref": "_common.json#/$defs/identifier" }
        },
        "controlRefs": {
          "type": "array",
          "minItems": 1,
          "description": "Identifiers of the FitnessFunction or RegoPackage artifacts that ran. Multiple entries when one run executed several controls.",
          "items": { "$ref": "_common.json#/$defs/identifier" }
        },
        "decisionRefs": {
          "type": "array",
          "description": "DecisionRecord identifiers the evidence supports. Optional; populated when the evidence is presented as proof that a decision remains respected.",
          "items": { "$ref": "_common.json#/$defs/identifier" }
        },
        "artifacts": {
          "type": "array",
          "description": "Locations of the actual evidence content. Each entry includes a URI and an integrity hash so that downstream consumers can verify the evidence has not been altered.",
          "items": {
            "type": "object",
            "required": ["uri"],
            "properties": {
              "uri": {
                "type": "string",
                "description": "URI of the artifact (S3 location, log stream, registry entry, etc.)."
              },
              "hash": {
                "type": "string",
                "description": "Integrity hash, conventionally 'sha256:<digest>' or 'sha512:<digest>'."
              },
              "mediaType": { "type": "string" }
            },
            "additionalProperties": true
          }
        },
        "exceptions": {
          "type": "object",
          "description": "If the evidence records an approved exception (rather than a clean pass), capture the approver and the sunset.",
          "properties": {
            "approvedBy": { "type": "string" },
            "approvedAt": { "type": "string", "format": "date-time" },
            "sunset": { "type": "string", "format": "date" },
            "rationale": { "type": "string" }
          },
          "additionalProperties": true
        },
        "retainUntil": {
          "type": "string",
          "format": "date",
          "description": "When the evidence may be deleted. Set per the FitnessFunction's evidence-retention policy (e.g., 7 years for regulated controls)."
        }
      },
      "additionalProperties": true
    }
  },
  "additionalProperties": false
}
