{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "case-oracle.schema.json",
  "title": "Case result and oracle",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "schema_version",
    "run_id",
    "case_id",
    "route",
    "phase",
    "category",
    "request_fixture_id",
    "oracle_id",
    "observed",
    "observed_side_effects",
    "db_assertions",
    "sink_probes",
    "crash_seam",
    "lock_transport",
    "started_at",
    "ended_at",
    "verdict",
    "canonical_outcome_sha256",
    "trace_ref",
    "trace_sha256",
    "evidence_refs",
    "db_context"
  ],
  "properties": {
    "schema_version": {
      "const": "1.0.0"
    },
    "run_id": {
      "type": "string",
      "minLength": 1
    },
    "case_id": {
      "type": "string",
      "minLength": 1
    },
    "route": {
      "enum": [
        "/auth/register",
        "/auth/login",
        "/auth/logout",
        "/auth/session",
        "/auth/csrf",
        "/auth/refresh-csrf",
        "/auth/refresh",
        "/auth/password-reset/request",
        "/auth/password-reset/complete"
      ]
    },
    "phase": {
      "enum": [
        "options",
        "actual",
        "crash",
        "redaction",
        "browser"
      ]
    },
    "category": {
      "enum": [
        "success",
        "wrong-method",
        "origin-absent",
        "origin-null",
        "origin-malformed",
        "origin-disallowed",
        "content-type-missing",
        "content-type-unsupported",
        "json-malformed",
        "dto-invalid",
        "idempotency-missing",
        "idempotency-conflict",
        "auth-invalid",
        "csrf-invalid",
        "rate-limited",
        "dependency-failure",
        "options-success",
        "options-acr-method-absent",
        "options-acr-method-malformed",
        "options-acr-method-wrong",
        "options-acr-header-extra",
        "cookie-policy",
        "expiry",
        "replay",
        "logout-partition",
        "logout-overlap-consumed-inactive",
        "reset-non-enumeration",
        "two-tab-ordering",
        "bounded-contention",
        "connection-loss",
        "redaction-probe"
      ]
    },
    "request_fixture_id": {
      "type": "string",
      "minLength": 1
    },
    "oracle_id": {
      "type": "string",
      "minLength": 1
    },
    "observed": {
      "$ref": "#/$defs/outcome"
    },
    "observed_side_effects": {
      "$ref": "#/$defs/effects"
    },
    "db_assertions": {
      "type": "array",
      "uniqueItems": true,
      "items": {
        "type": "string",
        "minLength": 1
      },
      "minItems": 1
    },
    "sink_probes": {
      "type": "array",
      "uniqueItems": true,
      "items": {
        "type": "string",
        "minLength": 1
      },
      "minItems": 1
    },
    "crash_seam": {
      "type": [
        "string",
        "null"
      ]
    },
    "lock_transport": {
      "enum": [
        "web-locks",
        "not-applicable"
      ]
    },
    "started_at": {
      "type": "string",
      "format": "date-time"
    },
    "ended_at": {
      "type": "string",
      "format": "date-time"
    },
    "verdict": {
      "enum": [
        "PASS",
        "FAIL",
        "BLOCKED"
      ]
    },
    "blocked_reason": {
      "type": "string",
      "minLength": 1
    },
    "canonical_outcome_sha256": {
      "type": "string",
      "pattern": "^[0-9a-f]{64}$",
      "not": {
        "const": "0000000000000000000000000000000000000000000000000000000000000000"
      }
    },
    "trace_ref": {
      "type": "string",
      "minLength": 1
    },
    "trace_sha256": {
      "type": "string",
      "pattern": "^[0-9a-f]{64}$",
      "not": {
        "const": "0000000000000000000000000000000000000000000000000000000000000000"
      }
    },
    "evidence_refs": {
      "type": "array",
      "minItems": 1,
      "uniqueItems": true,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "path",
          "sha256"
        ],
        "properties": {
          "path": {
            "type": "string",
            "minLength": 1
          },
          "sha256": {
            "type": "string",
            "pattern": "^[0-9a-f]{64}$",
            "not": {
              "const": "0000000000000000000000000000000000000000000000000000000000000000"
            }
          }
        }
      }
    },
    "db_context": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "owner_id",
        "session_id",
        "family_id",
        "generation_before",
        "generation_after"
      ],
      "properties": {
        "owner_id": {
          "type": "string",
          "minLength": 1
        },
        "session_id": {
          "type": "string",
          "minLength": 1
        },
        "family_id": {
          "type": "string",
          "minLength": 1
        },
        "generation_before": {
          "type": "integer",
          "minimum": 0
        },
        "generation_after": {
          "type": "integer",
          "minimum": 0
        }
      }
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "verdict": {
            "const": "BLOCKED"
          }
        },
        "required": [
          "verdict"
        ]
      },
      "then": {
        "required": [
          "blocked_reason"
        ]
      }
    },
    {
      "if": {
        "properties": {
          "phase": {
            "const": "crash"
          }
        },
        "required": [
          "phase"
        ]
      },
      "then": {
        "properties": {
          "crash_seam": {
            "type": "string",
            "minLength": 1
          }
        }
      }
    }
  ],
  "$defs": {
    "effects": {
      "type": "object",
      "additionalProperties": {
        "type": "integer",
        "minimum": 0
      }
    },
    "outcome": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "status",
        "canonical_body_sha256",
        "headers_present",
        "headers_absent",
        "cookie_metadata",
        "retry_outcome",
        "reuse_outcome",
        "generation_outcome"
      ],
      "properties": {
        "status": {
          "type": "integer",
          "minimum": 100,
          "maximum": 599
        },
        "canonical_body_sha256": {
          "type": "string",
          "pattern": "^[0-9a-f]{64}$"
        },
        "headers_present": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          }
        },
        "headers_absent": {
          "type": "array",
          "uniqueItems": true,
          "items": {
            "type": "string",
            "pattern": "^[A-Za-z0-9-]+$"
          }
        },
        "cookie_metadata": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "name",
              "path",
              "secure",
              "http_only",
              "same_site",
              "operation"
            ],
            "properties": {
              "name": {
                "enum": [
                  "__Host-pdf2html_access",
                  "__Host-pdf2html_csrf",
                  "__Secure-pdf2html_refresh"
                ]
              },
              "path": {
                "enum": [
                  "/",
                  "/auth"
                ]
              },
              "secure": {
                "const": true
              },
              "http_only": {
                "type": "boolean"
              },
              "same_site": {
                "const": "Lax"
              },
              "operation": {
                "enum": [
                  "emit",
                  "clear"
                ]
              }
            }
          }
        },
        "retry_outcome": {
          "enum": [
            "not-applicable",
            "not-retried",
            "single-bounded-retry",
            "recovered-committed",
            "blocked-indeterminate"
          ]
        },
        "reuse_outcome": {
          "enum": [
            "not-applicable",
            "not-reuse",
            "current",
            "expired",
            "consumed-replay",
            "family-revoked"
          ]
        },
        "generation_outcome": {
          "enum": [
            "not-applicable",
            "advanced-once",
            "unchanged",
            "stale-suppressed",
            "cas-conflict"
          ]
        }
      }
    }
  }
}
