{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://github.com/welkaim/ea-codex/schemas/v1/decision-record.json",
  "title": "DecisionRecord",
  "description": "Typed architectural decision with explicit provenance. Captures the choice forced by an internal or external trigger and binds it to dependent kinds (ArchitecturePrinciple, TechnologyStandard, ArchitectureChangePacket, AgentContract). Introduced in Chapter 14. The provenance fields under spec.trigger distinguish externally-imposed decisions (vendor policy, regulator notice, ISO revision) from internal ones; externally-imposed decisions carry different review obligations and exception semantics. Every DecisionRecord must be expressible as one or more fitness functions; otherwise it is a memo, not a decision.",
  "type": "object",
  "required": ["apiVersion", "kind", "metadata", "spec"],
  "properties": {
    "apiVersion": { "$ref": "_common.json#/$defs/apiVersion" },
    "kind": { "type": "string", "const": "DecisionRecord" },
    "metadata": {
      "type": "object",
      "required": ["id", "title", "status", "date", "owner"],
      "properties": {
        "id": { "$ref": "_common.json#/$defs/identifier" },
        "title": {
          "type": "string",
          "minLength": 10,
          "description": "Human-readable title. May contain spaces and punctuation."
        },
        "status": { "$ref": "_common.json#/$defs/decisionStatus" },
        "date": {
          "type": "string",
          "format": "date",
          "description": "ISO-8601 date the decision was accepted or last updated."
        },
        "owner": {
          "type": "string",
          "description": "Single accountable role or group for the decision."
        },
        "version": { "$ref": "_common.json#/$defs/version" }
      },
      "additionalProperties": true
    },
    "spec": {
      "type": "object",
      "required": ["trigger", "context", "decision"],
      "properties": {
        "trigger": {
          "type": "object",
          "required": ["type", "source"],
          "description": "Provenance of the decision. Distinguishes externally-imposed events from internally-initiated ones. The provenance matters: an externally-imposed decision carries different review obligations and different exception semantics than an internal one.",
          "properties": {
            "type": {
              "type": "string",
              "enum": [
                "external-vendor-policy",
                "external-regulator-notice",
                "external-standard-revision",
                "internal-strategic",
                "internal-tactical",
                "incident-response",
                "exception-renewal"
              ]
            },
            "source": {
              "type": "string",
              "description": "Identifier of the trigger event (vendor policy reference, regulation citation, incident ticket)."
            },
            "supersedes": {
              "type": "string",
              "description": "Identifier of the prior, less formal predecessor this decision replaces (informal note, working-group memo, ad-hoc exception)."
            }
          },
          "additionalProperties": true
        },
        "context": {
          "type": "string",
          "minLength": 20,
          "description": "Narrative of the trigger and the architectural surface it touches."
        },
        "decision": {
          "type": "string",
          "minLength": 20,
          "description": "The choice itself, stated as a normative obligation. Allowed mechanisms named explicitly. Prohibited mechanisms named explicitly."
        },
        "relatedPrinciples": {
          "type": "array",
          "description": "ArchitecturePrinciple identifiers this decision instantiates or modifies.",
          "items": { "$ref": "_common.json#/$defs/identifier" }
        },
        "relatedStandards": {
          "type": "array",
          "description": "TechnologyStandard identifiers this decision points at or revises.",
          "items": { "$ref": "_common.json#/$defs/identifier" }
        },
        "relatedSpecs": {
          "type": "array",
          "description": "Specification identifiers (AgentContract, DataProductContract, SovereigntySpecification, etc.) constrained by this decision.",
          "items": { "type": "string" }
        },
        "affectedFactSheetTypes": {
          "type": "array",
          "description": "EA-tool fact-sheet types whose instances may be flagged by this decision's fitness functions.",
          "items": { "type": "string" }
        },
        "exceptions": {
          "type": "array",
          "description": "Time-boxed exceptions granted under this decision. Every exception names a sunset date and a risk owner.",
          "items": {
            "type": "object",
            "required": ["id", "sunsetDate", "riskOwner"],
            "properties": {
              "id": { "type": "string" },
              "scope": { "type": "string" },
              "rationale": { "type": "string" },
              "sunsetDate": {
                "type": "string",
                "format": "date"
              },
              "riskOwner": { "type": "string" }
            },
            "additionalProperties": true
          }
        },
        "doubleCheck": {
          "type": "object",
          "description": "The bridge from decision to running enterprise. A DecisionRecord that cannot be expressed as one or more fitness functions is a memo, not a decision.",
          "properties": {
            "fitnessFunctions": {
              "type": "array",
              "minItems": 1,
              "items": {
                "type": "object",
                "required": ["id", "rule", "check"],
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "Stable fitness-function identifier, e.g. FF-SAP-001."
                  },
                  "rule": {
                    "type": "string",
                    "description": "Plain-language or pseudo-formal statement of the rule. The executable form lives in the Rego package or scheduled scan named by check."
                  },
                  "check": {
                    "type": "string",
                    "description": "Where and how the rule is enforced (Rego package in CI, scheduled scan, EA-tool MCP query)."
                  }
                },
                "additionalProperties": true
              }
            },
            "scenarioPacks": {
              "type": "array",
              "items": { "type": "string" }
            }
          },
          "additionalProperties": true
        }
      },
      "additionalProperties": true
    }
  },
  "additionalProperties": false
}
