{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://scrty.net/schemas/crds/0.1/crds.schema.json",
  "title": "SCRTY:CRDS — Common Risk Definition Set",
  "description": "Canonical, machine-readable representation of a cyber risk. A CRDS document is either a BaseCard (globally true facts, shareable) or an OrgOverlay (org-specific context, private, stacked on a BaseCard at render time). Org data is never baked into a BaseCard. This schema is published under CC BY 4.0: https://creativecommons.org/licenses/by/4.0/",
  "oneOf": [
    { "$ref": "#/$defs/BaseCard" },
    { "$ref": "#/$defs/OrgOverlay" }
  ],
  "$defs": {

    "BaseCard": {
      "type": "object",
      "required": [
        "crds_version", "kind", "id", "revision", "title", "summary",
        "severity", "exploitation", "recommended_action", "confidence",
        "provenance", "references", "issued_at"
      ],
      "additionalProperties": false,
      "properties": {
        "crds_version": { "const": "0.1", "description": "The version of this schema the document follows." },
        "kind": { "const": "base", "description": "Marks the document as a BaseCard." },

        "id": {
          "type": "string",
          "description": "Immutable card identity. Never changes across revisions ('reprints'). Overlays reference this.",
          "pattern": "^crds:[a-z0-9][a-z0-9._-]+$",
          "examples": ["crds:cve-2021-44228", "crds:pt-2026-0042-acme"]
        },
        "revision": {
          "type": "integer",
          "minimum": 1,
          "description": "Monotonic revision ('errata/reprint'). New facts, e.g. a CISA KEV listing, bump the revision. Overlays re-stack onto the latest revision automatically unless pinned."
        },
        "supersedes": {
          "type": "integer",
          "description": "Optional: previous revision this one replaces."
        },

        "retired": {
          "type": "boolean",
          "default": false,
          "description": "The CVE has left CISA KEV. The card stays: it is never deleted for that reason."
        },

        "subtitle": {
          "type": "string",
          "maxLength": 60,
          "description": "One line that tells this card apart from others sharing its name."
        },

        "cvss_vendor": {
          "type": "object",
          "required": ["score", "version", "source", "as_of"],
          "additionalProperties": false,
          "description": "The score the vendor or CNA published, shown beside the NVD score in `cvss`. Set by the pipeline from a curated list.",
          "properties": {
            "score": { "type": "number", "minimum": 0, "maximum": 10 },
            "version": { "type": "string" },
            "source": { "type": "string", "format": "uri", "pattern": "^https?://" },
            "as_of": { "type": "string", "format": "date" }
          }
        },

        "aliases": {
          "type": "array",
          "uniqueItems": true,
          "items": { "type": "string", "minLength": 1, "maxLength": 60 },
          "description": "Other names the flaw goes by. Set by the pipeline from a curated list."
        },

        "affected": {
          "type": "array",
          "uniqueItems": true,
          "items": { "type": "string", "minLength": 1, "maxLength": 80 },
          "description": "Products and runtimes the flaw reaches. Set by the pipeline from a curated list."
        },

        "title": { "type": "string", "maxLength": 80, "description": "Card name. Short, recognizable. 'Log4Shell — Log4j JNDI RCE'." },
        "summary": { "type": "string", "maxLength": 280, "description": "What is it, in one breath. Plain language, no acronym soup." },

        "source_type": {
          "type": "string",
          "enum": ["cve", "vendor_advisory", "threat_intel", "pentest_finding", "scanner_finding", "incident", "other"],
          "description": "What kind of input this card was normalized from."
        },

        "severity": {
          "type": "string",
          "enum": ["critical", "high", "medium", "low", "info"],
          "description": "Card frame color. Normalized judgment, not raw CVSS."
        },
        "cvss": {
          "description": "The score recorded by NVD.",
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "score": { "type": "number", "minimum": 0, "maximum": 10 },
            "vector": { "type": "string" },
            "version": { "type": "string", "examples": ["3.1", "4.0"] }
          }
        },
        "epss": {
          "type": "number", "minimum": 0, "maximum": 1,
          "description": "Exploit Prediction Scoring System probability, if known."
        },

        "exploitation": {
          "description": "What is known about attacks on this flaw.",
          "type": "object",
          "required": ["known_exploited", "exploit_available", "attack_complexity"],
          "additionalProperties": false,
          "properties": {
            "known_exploited": { "type": "boolean", "description": "Exploitation observed in the wild (e.g. CISA KEV). Foil treatment." },
            "exploit_available": { "type": "boolean", "description": "Public PoC or weaponized exploit exists." },
            "exploit_override": {
              "type": "object",
              "required": ["source", "as_of"],
              "additionalProperties": false,
              "description": "Present when exploit_available comes from a curated source because NVD's reference tags do not record it.",
              "properties": {
                "source": { "type": "string", "format": "uri", "pattern": "^https?://" },
                "as_of": { "type": "string", "format": "date" },
                "note": { "type": "string", "maxLength": 200 }
              }
            },
            "attack_complexity": { "type": "string", "enum": ["low", "medium", "high"] },
            "kev_added": { "type": "string", "format": "date", "description": "Date CISA listed the CVE in the Known Exploited Vulnerabilities catalog." },
            "kev_due": { "type": "string", "format": "date", "description": "Remediation due date CISA set for the listing." },
            "prerequisites": { "type": "string", "maxLength": 200, "description": "What an attacker needs. 'Network access to the service' / 'Valid low-priv account'." }
          }
        },

        "remediation": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "patch_available": { "type": "boolean" },
            "workaround_available": { "type": "boolean" },
            "fixed_in": { "type": "array", "items": { "type": "string" }, "description": "Fixed versions, e.g. ['log4j >= 2.17.1']." }
          },
          "description": "Global remediation facts only. Effort estimates are org-specific and live in the overlay."
        },

        "mitre_attack": {
          "type": "array",
          "items": { "type": "string", "pattern": "^T[0-9]{4}(\\.[0-9]{3})?$" },
          "description": "ATT&CK technique IDs. The card's 'type line'."
        },
        "kill_chain": {
          "description": "The attack stage the flaw belongs to.",
          "type": "string",
          "enum": ["reconnaissance", "resource_development", "initial_access", "execution", "persistence", "privilege_escalation", "defense_evasion", "credential_access", "discovery", "lateral_movement", "collection", "command_and_control", "exfiltration", "impact"]
        },

        "recommended_action": {
          "type": "string", "maxLength": 200,
          "description": "The one sentence at the bottom of the card. Imperative. 'Patch immediately.'"
        },

        "confidence": {
          "type": "string", "enum": ["high", "medium", "low"],
          "description": "Overall confidence in the card as a whole."
        },
        "provenance": {
          "type": "array",
          "minItems": 1,
          "description": "Auditability: which source supports which fields. Every AI-extracted fact must be traceable.",
          "items": {
            "type": "object",
            "required": ["fields", "source", "retrieved_at"],
            "additionalProperties": false,
            "properties": {
              "fields": { "type": "array", "items": { "type": "string" }, "description": "JSON pointers or field names this source supports, e.g. ['exploitation.known_exploited']." },
              "source": { "type": "string", "pattern": "^https?://", "description": "URL of the source." },
              "retrieved_at": { "type": "string", "format": "date-time" },
              "confidence": { "type": "string", "enum": ["high", "medium", "low"] },
              "extractor": { "type": "string", "description": "'human' or the model/pipeline id that extracted the fact." }
            }
          }
        },

        "references": {
          "description": "Where a reader can check the card.",
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "object",
            "required": ["type", "url"],
            "additionalProperties": false,
            "properties": {
              "type": { "type": "string", "enum": ["cve", "vendor_advisory", "cisa", "exploit", "writeup", "other"] },
              "url": { "type": "string", "format": "uri", "pattern": "^https?://" },
              "label": { "type": "string" }
            }
          }
        },

        "published_at": { "type": "string", "format": "date-time", "description": "When the CVE record was published, per NVD. Not when the card was made." },
        "issued_at": { "type": "string", "format": "date-time", "description": "When this revision of the card was written." },
        "tags": { "type": "array", "items": { "type": "string" }, "description": "Free-form labels." }
      }
    },

    "OrgOverlay": {
      "type": "object",
      "required": ["crds_version", "kind", "overlay_id", "base_ref", "status", "updated_at"],
      "additionalProperties": false,
      "description": "Org-private context stacked on a BaseCard. Separate document, separate lifecycle, merged only at render time.",
      "properties": {
        "crds_version": { "const": "0.1", "description": "The version of this schema the document follows." },
        "kind": { "const": "overlay", "description": "Marks the document as an OrgOverlay." },

        "overlay_id": { "type": "string", "pattern": "^crds-ovl:[a-z0-9][a-z0-9._-]+$", "description": "Identity of the overlay." },
        "base_ref": {
          "description": "The BaseCard this overlay stacks on.",
          "type": "object",
          "required": ["id"],
          "additionalProperties": false,
          "properties": {
            "id": { "type": "string", "description": "Immutable id of the BaseCard this stacks on." },
            "pinned_revision": { "type": "integer", "description": "Optional: pin to a specific base revision. Default: always latest ('re-stack on reprint')." }
          }
        },

        "org": { "type": "string", "description": "Owning organization identifier. Overlays never leave the org boundary." },
        "status": { "type": "string", "enum": ["new", "triaged", "in_progress", "mitigated", "resolved", "accepted", "false_positive"], "description": "Where the organization is with this card." },
        "priority": { "type": "string", "enum": ["p0", "p1", "p2", "p3"], "description": "Org's own play order — may differ from base severity." },

        "affected_assets": {
          "description": "What this organization runs that the flaw reaches.",
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "count": { "type": "integer", "minimum": 0 },
            "internet_facing": { "type": "integer", "minimum": 0 },
            "asset_refs": { "type": "array", "items": { "type": "string" }, "description": "IDs in the org's CMDB/inventory." }
          }
        },

        "business_impact": { "type": "string", "maxLength": 280, "description": "Impact in this org's terms. 'Customer portal takeover; regulatory exposure.'" },
        "owner": { "type": "string", "description": "Team or person holding the card." },
        "remediation_estimate": { "type": "string", "description": "ISO 8601 duration, e.g. 'PT2H', 'P3D'." },
        "due_date": { "type": "string", "format": "date", "description": "When this organization means to have it done." },
        "exceptions": { "type": "string", "maxLength": 500, "description": "Risk acceptance rationale, if status is 'accepted'." },
        "notes": { "type": "string", "description": "Free text." },

        "updated_at": { "type": "string", "format": "date-time", "description": "When the overlay last changed." },
        "updated_by": { "type": "string", "description": "Who changed it last." }
      }
    }
  }
}
