{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://twinethos.com/schemas/condition-v0.3.schema.json",
  "title": "Canonical Control Condition (v0.3)",
  "description": "P3. A first-class, versioned control condition — the normalized 'what must or must not be true in the code' that many authorities converge on. Rules point to a condition by id; convergence is COMPUTED from those pointers rather than hand-maintained free-text (fixing the fragile condition_key string). This registry is the primary moat: fix this one condition and satisfy specific portions of these authorities, subject to applicability differences.",
  "type": "object",
  "required": [
    "condition_id",
    "schema_version",
    "condition_version",
    "title",
    "control_objective",
    "required_or_prohibited_state"
  ],
  "additionalProperties": false,
  "properties": {
    "condition_id": {
      "type": "string",
      "pattern": "^cond\\.[a-z0-9]+(?:[._-][a-z0-9]+)*$",
      "description": "Stable id, namespaced with 'cond.', e.g. 'cond.protected-or-proxy-attribute-in-ai-decision'. Rules reference this. Never changes once published."
    },
    "schema_version": {
      "type": "string",
      "const": "0.3"
    },
    "condition_version": {
      "type": "string",
      "pattern": "^\\d+\\.\\d+\\.\\d+$",
      "description": "Semver of the condition definition (independent of any rule or detector version)."
    },
    "title": {
      "type": "string",
      "minLength": 4
    },
    "control_objective": {
      "type": "string",
      "description": "The outcome the condition secures, in plain terms, e.g. 'AI decisions about people must not be driven by protected traits or their proxies'."
    },
    "required_or_prohibited_state": {
      "type": "object",
      "required": [
        "mode",
        "statement"
      ],
      "additionalProperties": false,
      "properties": {
        "mode": {
          "type": "string",
          "enum": [
            "required",
            "prohibited"
          ],
          "description": "Whether the condition describes a state that MUST exist (required) or MUST NOT exist (prohibited)."
        },
        "statement": {
          "type": "string",
          "description": "The normalized state, e.g. 'no protected/proxy attribute reaches an LLM on a consequential-decision path without a redaction/allowlist control'."
        }
      }
    },
    "risk_addressed": {
      "type": "string",
      "description": "The harm this guards against, e.g. 'invisible discrimination in automated decisions'."
    },
    "required_evidence": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "What would prove the condition is satisfied, e.g. 'redaction applied on the prompt-construction path', 'feature allowlist constrains prompt inputs'."
    },
    "accepted_compensating_controls": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Alternative controls that satisfy the objective if the primary one is absent, e.g. 'documented lawful basis plus bias monitoring'."
    },
    "applicability_hints": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Applicability dimensions typically relevant to this condition (the authoritative applicability lives on each rule; this is guidance)."
    },
    "parent_condition": {
      "type": "string",
      "description": "Family condition this control belongs to (condition_kind=family). Used to compute family-level convergence across controls whose legal scope differs."
    },
    "narrower_conditions": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "More specific child conditions."
    },
    "review": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "authored_by": {
          "type": "string"
        },
        "reviewed_by": {
          "type": "string"
        },
        "review_status": {
          "type": "string",
          "enum": [
            "draft",
            "human_reviewed",
            "legal_reviewed",
            "published"
          ]
        },
        "reviewed_date": {
          "type": "string",
          "format": "date"
        }
      }
    },
    "condition_kind": {
      "type": "string",
      "enum": [
        "control",
        "family"
      ],
      "default": "control",
      "description": "control = a concrete code-detectable control state that rules reference via condition_ref. family = an abstract grouping of related controls (members point to it via parent_condition); rules never reference a family directly. Family-level convergence is computed across member controls."
    },
    "remediation": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "summary",
        "guard",
        "surfaces",
        "verify",
        "examples"
      ],
      "description": "v0.3.5 (DQ-1, D-10). The guard to add when an item on this control fails: an engineering control, never legal advice or a statement of compliance. Every rule that references the condition inherits it; a rule adds only its own jurisdiction-specific details (rule `remediation.specifics`). Validator E07 requires it on every control used by a binding-law rule or a recommended guardrail.",
      "properties": {
        "summary": {
          "type": "string",
          "minLength": 20,
          "maxLength": 200,
          "description": "One imperative sentence: the guard to add. Served as the compact checklist record's `fix`."
        },
        "guard": {
          "type": "string",
          "minLength": 80,
          "description": "What the control does, where in the code it belongs (route, handler, tool executor, prompt builder, config, data model, CI step), and what it blocks, records or shows."
        },
        "surfaces": {
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": {
            "type": "integer",
            "minimum": 1,
            "maximum": 15
          },
          "description": "Code surfaces where the guard lives, numbered as rule `detection_surfaces` (docs/TECHNICAL-OVERVIEW.md §4)."
        },
        "verify": {
          "type": "string",
          "minLength": 40,
          "description": "What reviewers look for: the observable evidence that the guard exists and takes effect (the detectors' safe path)."
        },
        "scope": {
          "type": "string",
          "enum": [
            "code",
            "organizational"
          ],
          "default": "code",
          "description": "code: the guard is in the repository. organizational: the guard is an artifact the organization keeps (assessment, management system, published framework, filed policy), matching detectors with evidence_scope organizational."
        },
        "examples": {
          "type": "array",
          "minItems": 1,
          "maxItems": 3,
          "items": {
            "$ref": "#/$defs/remediation_example"
          }
        }
      }
    }
  },
  "$defs": {
    "remediation_example": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "language",
        "before",
        "after"
      ],
      "properties": {
        "language": {
          "type": "string",
          "minLength": 1
        },
        "stack": {
          "type": "string",
          "description": "Short label for the stack the example is written for, e.g. 'Next.js + Vercel AI SDK'."
        },
        "before": {
          "type": "string",
          "minLength": 1
        },
        "after": {
          "type": "string",
          "minLength": 1
        }
      }
    }
  }
}
