{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://jos.local/schemas/clan-consent-event.schema.json",
  "title": "CLAN ConsentEvent Schema",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "consent_event_id",
    "ts",
    "scope",
    "decision",
    "target",
    "confirmations",
    "quorum",
    "provenance",
    "versions"
  ],
  "properties": {
    "consent_event_id": {
      "type": "string",
      "minLength": 3,
      "maxLength": 128,
      "pattern": "^ce_[A-Za-z0-9_-]+$"
    },
    "ts": {
      "type": "integer",
      "minimum": 0
    },
    "scope": {
      "$ref": "#/$defs/scope"
    },
    "decision": {
      "$ref": "#/$defs/decision"
    },
    "target": {
      "$ref": "#/$defs/target"
    },
    "confirmations": {
      "type": "array",
      "minItems": 0,
      "maxItems": 256,
      "items": {
        "$ref": "#/$defs/confirmation"
      }
    },
    "quorum": {
      "$ref": "#/$defs/quorum"
    },
    "provenance": {
      "$ref": "#/$defs/event_provenance"
    },
    "versions": {
      "$ref": "#/$defs/versions"
    },
    "integrity": {
      "$ref": "#/$defs/integrity"
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "decision": {
            "properties": {
              "type": {
                "enum": [
                  "approve",
                  "reject"
                ]
              }
            },
            "required": [
              "type"
            ]
          }
        },
        "required": [
          "decision"
        ]
      },
      "then": {
        "properties": {
          "confirmations": {
            "minItems": 1
          }
        }
      }
    },
    {
      "if": {
        "properties": {
          "decision": {
            "properties": {
              "type": {
                "const": "revoke"
              }
            },
            "required": [
              "type"
            ]
          }
        },
        "required": [
          "decision"
        ]
      },
      "then": {
        "properties": {
          "confirmations": {
            "minItems": 1
          }
        }
      }
    }
  ],
  "$defs": {
    "nonEmptyString": {
      "type": "string",
      "minLength": 1
    },
    "unixTimeInt": {
      "type": "integer",
      "minimum": 0
    },
    "sha256Ref": {
      "type": "string",
      "pattern": "^(sha256:)?[A-Fa-f0-9]{12,64}$"
    },
    "visibilityLevel": {
      "type": "string",
      "enum": [
        "public",
        "interclan",
        "incircle",
        "soulsafe",
        "sacred"
      ]
    },
    "consentDecisionType": {
      "type": "string",
      "enum": [
        "approve",
        "reject",
        "revoke"
      ]
    },
    "targetType": {
      "type": "string",
      "enum": [
        "artifact",
        "policy",
        "bridge_request",
        "allocation",
        "core_change"
      ]
    },
    "operationType": {
      "type": "string",
      "enum": [
        "execute",
        "export",
        "grant_access",
        "change_visibility",
        "merge_offline",
        "publish",
        "transfer",
        "dao_action",
        "core_update"
      ]
    },
    "channelType": {
      "type": "string",
      "enum": [
        "ui",
        "api",
        "telegram",
        "matrix",
        "internal",
        "webhook",
        "bridge"
      ]
    },
    "confirmationMethod": {
      "type": "string",
      "enum": [
        "voice",
        "biometric",
        "key_signature",
        "in_person"
      ]
    },
    "scope": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "circle_id",
        "visibility_level"
      ],
      "properties": {
        "circle_id": {
          "allOf": [
            {
              "$ref": "#/$defs/nonEmptyString"
            },
            {
              "maxLength": 128
            }
          ]
        },
        "gate_level": {
          "type": "string",
          "maxLength": 64
        },
        "visibility_level": {
          "$ref": "#/$defs/visibilityLevel"
        }
      }
    },
    "decision": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "type"
      ],
      "properties": {
        "type": {
          "$ref": "#/$defs/consentDecisionType"
        },
        "reason": {
          "type": "string",
          "maxLength": 240
        },
        "expires_at": {
          "$ref": "#/$defs/unixTimeInt"
        }
      }
    },
    "target": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "target_type",
        "artifact_ids",
        "operation"
      ],
      "properties": {
        "target_type": {
          "$ref": "#/$defs/targetType"
        },
        "artifact_ids": {
          "type": "array",
          "minItems": 1,
          "maxItems": 512,
          "items": {
            "allOf": [
              {
                "$ref": "#/$defs/nonEmptyString"
              },
              {
                "maxLength": 128
              }
            ]
          }
        },
        "operation": {
          "$ref": "#/$defs/operationType"
        },
        "intent": {
          "type": "string",
          "maxLength": 200
        }
      }
    },
    "confirmation": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "actor",
        "method",
        "step_up",
        "ts"
      ],
      "properties": {
        "actor": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "type",
            "id"
          ],
          "properties": {
            "type": {
              "type": "string",
              "const": "human"
            },
            "id": {
              "allOf": [
                {
                  "$ref": "#/$defs/nonEmptyString"
                },
                {
                  "maxLength": 128
                }
              ]
            },
            "display": {
              "type": "string",
              "maxLength": 120
            }
          }
        },
        "method": {
          "$ref": "#/$defs/confirmationMethod"
        },
        "step_up": {
          "type": "boolean"
        },
        "proof_ref": {
          "type": "string",
          "maxLength": 256
        },
        "ts": {
          "$ref": "#/$defs/unixTimeInt"
        }
      }
    },
    "quorum": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "rule",
        "required",
        "present"
      ],
      "properties": {
        "rule": {
          "type": "string",
          "enum": [
            "unanimous",
            "majority",
            "custom"
          ]
        },
        "required": {
          "type": "integer",
          "minimum": 1,
          "maximum": 1024
        },
        "present": {
          "type": "integer",
          "minimum": 0,
          "maximum": 1024
        }
      }
    },
    "event_provenance": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "channel",
        "request_id",
        "input_hash"
      ],
      "properties": {
        "channel": {
          "$ref": "#/$defs/channelType"
        },
        "request_id": {
          "allOf": [
            {
              "$ref": "#/$defs/nonEmptyString"
            },
            {
              "maxLength": 128
            }
          ]
        },
        "input_hash": {
          "$ref": "#/$defs/sha256Ref"
        }
      }
    },
    "versions": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "constitution_version",
        "protocol_version"
      ],
      "properties": {
        "constitution_version": {
          "allOf": [
            {
              "$ref": "#/$defs/nonEmptyString"
            },
            {
              "maxLength": 128
            }
          ]
        },
        "protocol_version": {
          "allOf": [
            {
              "$ref": "#/$defs/nonEmptyString"
            },
            {
              "maxLength": 128
            }
          ]
        }
      }
    },
    "integrity": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "event_hash"
      ],
      "properties": {
        "event_hash": {
          "$ref": "#/$defs/sha256Ref"
        },
        "prev_hash": {
          "$ref": "#/$defs/sha256Ref"
        }
      }
    }
  }
}
