{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://github.com/AndrewAltimit/swarmchasing/blob/main/schemas/sc-incident-v1.json",
  "title": "SC-Incident v1",
  "description": "A published swarmchasing incident as one JSON document (docs/specs/incident-v1.md): what its public notice carries, in fields other groups can read. Public profile only: it never carries what a notice withholds (SC-FM 11.4). Host names are plain for machines; anything that shows them to a person defangs them.",
  "type": "object",
  "additionalProperties": false,
  "required": ["spec", "id", "title", "status", "published", "updated", "method", "rules_version", "affected", "updates"],
  "properties": {
    "spec": { "const": "SC-Incident v1" },
    "id": {
      "type": "string",
      "pattern": "^[a-z0-9][a-z0-9-]{0,63}$",
      "description": "The notice id: lower-case letters, digits and hyphens, at most 64 characters, not starting with a hyphen."
    },
    "title": { "type": "string", "minLength": 1 },
    "url": { "type": "string", "format": "uri", "pattern": "^https://", "description": "The published notice." },
    "status": { "enum": ["active", "contained", "historical"] },
    "retracted": { "type": "boolean", "default": false },
    "published": { "$ref": "#/$defs/date" },
    "updated": { "$ref": "#/$defs/date" },
    "sector": {
      "enum": ["government", "health", "education", "research", "finance", "energy", "water", "telecom", "transport", "technology", "media", "nonprofit", "retail", "manufacturing", "other"]
    },
    "method": { "type": "string", "pattern": "^SC-FM [0-9]+\\.[0-9]+$", "description": "The Field Manual version followed, e.g. SC-FM 1.1." },
    "departures": { "type": "array", "items": { "type": "string" }, "description": "Manual sections not followed, each with what was done instead." },
    "rules_version": { "type": "string", "minLength": 1 },
    "toolkit": { "type": "string" },
    "affected": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["host", "state"],
        "properties": {
          "host": { "type": "string", "pattern": "^[a-z0-9.-]+$" },
          "state": { "enum": ["compromised", "targeted", "historical"] },
          "single_source": { "type": "boolean", "description": "Every record on this endpoint came from a source anyone can submit a URL to (SC-FM 10.9)." }
        }
      }
    },
    "attribution": {
      "type": "array",
      "description": "Claims a public notice may carry: developers through the naming gate, providers as notified parties, and hosts. Harness and model-family candidates are never here (SC-FM 7.8).",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["party", "layer", "evidence", "label", "tag"],
        "properties": {
          "party": { "type": "string", "minLength": 1 },
          "layer": { "enum": ["developer", "host"] },
          "named_as": { "enum": ["developer", "notified", "host"], "description": "How the notice names the party: as developer (through the gate), as the party notified (below it), or as a host." },
          "evidence": { "enum": ["self_id", "hosting_asn", "shared_identifiers", "provider_infrastructure", "provider_confirmed"] },
          "label": { "enum": ["Confirmed", "Suspected", "Possible", "Unattributed"] },
          "tag": { "enum": ["Observed", "Documented", "Inference", "Conclusion"] },
          "likelihood": { "$ref": "#/$defs/likelihood" }
        },
        "allOf": [
          { "if": { "properties": { "label": { "const": "Unattributed" } } }, "then": { "not": { "required": ["likelihood"] } } },
          { "if": { "properties": { "label": { "const": "Possible" } } }, "then": { "properties": { "likelihood": { "enum": ["almost no chance", "very unlikely", "unlikely", "roughly even chance", "likely"] } } } },
          { "if": { "properties": { "label": { "const": "Suspected" } } }, "then": { "properties": { "likelihood": { "not": { "const": "almost certain" } } } } }
        ]
      }
    },
    "tier": { "enum": ["significant", "suggestive", "noise"], "description": "The strongest cluster tier in the incident." },
    "tactics": {
      "type": "array",
      "uniqueItems": true,
      "items": { "enum": ["T1", "T2", "T3", "T4", "T5", "T6", "T7", "T8", "T9"] },
      "description": "SC-T tactics in order of first appearance. T8 and T9 only as the reviewer's findings."
    },
    "scope": {
      "type": "object",
      "additionalProperties": false,
      "required": ["finding"],
      "properties": {
        "finding": { "enum": ["in_scope", "scope_exceeded", "not_assessable"] },
        "tests": { "type": "array", "uniqueItems": true, "items": { "enum": ["S1", "S2", "S3", "S4", "S5", "S6", "S7"] }, "description": "The scope tests that failed (SC-FM 15.3)." }
      }
    },
    "agent_grade": {
      "type": "object",
      "additionalProperties": false,
      "required": ["level", "measurement"],
      "description": "Only with a held-out measurement of the grade (SC-FM 7.10).",
      "properties": {
        "level": { "enum": ["L0", "L1", "L2", "L3", "L4", "L5"] },
        "measurement": { "type": "string", "minLength": 1, "description": "Where the grade's held-out measurement is published." }
      }
    },
    "groupings": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["id", "kind"],
        "properties": {
          "id": { "type": "string", "pattern": "^(fleet-[0-9]+|SCF-[0-9]+)$" },
          "kind": { "enum": ["fleet", "swarm"] },
          "aliases": { "type": "array", "items": { "type": "string" } },
          "interaction": { "type": "array", "items": { "enum": ["shared_sink", "handoff", "synchronized_start", "role_sequence", "disjoint_partition", "dispatch_star"] } }
        },
        "if": { "properties": { "kind": { "const": "swarm" } } },
        "then": { "required": ["interaction"], "properties": { "interaction": { "minItems": 1 } } }
      }
    },
    "timeline": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["first_seen", "last_seen", "timestamp_kind"],
        "properties": {
          "first_seen": { "type": "string", "format": "date-time" },
          "last_seen": { "type": "string", "format": "date-time" },
          "timestamp_kind": { "enum": ["request", "submit", "capture", "unknown", "mixed"] },
          "records": { "type": "integer", "minimum": 1 }
        }
      }
    },
    "withheld": {
      "type": "array",
      "uniqueItems": true,
      "items": { "enum": ["channels", "secrets", "compromised_details", "personal_data", "operator_logs", "restricted_source_content", "unclassified"] },
      "description": "Categories the notice withholds (SC-FM 11.4)."
    },
    "records": {
      "type": "array",
      "items": { "type": "string", "format": "uri", "pattern": "^https://" },
      "description": "Links to the public records, never their content."
    },
    "updates": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["date", "kind", "text"],
        "properties": {
          "date": { "$ref": "#/$defs/date" },
          "kind": { "enum": ["published", "update", "status", "correction", "reply", "retraction"] },
          "from": { "type": "string" },
          "text": { "type": "string" }
        },
        "if": { "properties": { "kind": { "const": "reply" } } },
        "then": { "required": ["from"] }
      }
    }
  },
  "$defs": {
    "date": { "type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" },
    "likelihood": {
      "enum": ["almost no chance", "very unlikely", "unlikely", "roughly even chance", "likely", "very likely", "almost certain"]
    }
  }
}
