Schema: approval

{
  "$id": "https://australis.systems/schemas/htmx-ui-template-scaffold/approval.schema.json",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "additionalProperties": false,
  "description": "Target-side authorization bound to one exact scaffold plan digest. The document MUST name the plan_digest of an existing plan and one or more approved_paths. Reconcile and the validator refuse stale, partial, differently-ordered, or differently-digested plans. Asset sync approvals use the same document shape with approved_assets populated instead of approved_paths.",
  "properties": {
    "approved_assets": {
      "description": "Optional list of approved deployable corpus asset paths (relative paths under a recognized DEPLOYABLE_ASSET_PREFIX). Reconcile does not consume this field; assets sync consumes it. The two lists MUST NOT overlap when both are present.",
      "items": {
        "minLength": 1,
        "type": "string"
      },
      "type": "array",
      "uniqueItems": true
    },
    "approved_paths": {
      "description": "Target-relative paths the approval grants. Reconcile restricts itself to this exact set. Items MUST be unique.",
      "items": {
        "minLength": 1,
        "type": "string"
      },
      "minItems": 1,
      "type": "array",
      "uniqueItems": true
    },
    "document_status": {
      "const": "ACTIVE",
      "description": "Approval lifecycle marker. Reconcile refuses anything that is not ACTIVE.",
      "type": "string"
    },
    "plan_digest": {
      "description": "SHA-256 hex digest of the canonical plan this approval binds. Reconcile refuses to mutate unless the supplied plan computes to this exact digest.",
      "pattern": "^[a-f0-9]{64}$",
      "type": "string"
    },
    "schema_version": {
      "description": "Major-version-locked envelope. Documents with any value other than 1.0.0 MUST fail validation, which enforces the major-version-1 contract.",
      "enum": [
        "1.0.0"
      ],
      "type": "string"
    },
    "signature": {
      "description": "Optional detached signature over the canonical approval payload. Present only when an external signing step exists. Omit when the signature is out of scope.",
      "type": "string"
    },
    "target_state_digest": {
      "description": "Optional SHA-256 digest of approved target paths captured when the plan was reviewed. When present, reconcile refuses any concurrent target-state change before mutation.",
      "pattern": "^[a-f0-9]{64}$",
      "type": "string"
    }
  },
  "required": [
    "schema_version",
    "plan_digest",
    "approved_paths",
    "document_status"
  ],
  "title": "Approval Document",
  "type": "object"
}