{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://intentius.io/sql-yodeler/schemas/v1/apply.schema.json",
  "title": "yodel apply <env> --json",
  "description": "Version 1. On a project with migrations, the status (status.schema.json) with mode \"versioned\" and what apply did; with --execute (the migrations Op's Apply step) or --wave-apply (a wave job's apply), what the step applied; with --wave-plan, the wave plan it wrote; on a project without migrations, the declarative outcome with chant's plan. Within a version, fields are only added; a reader ignores fields it does not know.",
  "oneOf": [
    {
      "$ref": "#/$defs/versioned"
    },
    {
      "$ref": "#/$defs/execute"
    },
    {
      "$ref": "#/$defs/wavePlan"
    },
    {
      "$ref": "#/$defs/declarative"
    }
  ],
  "$defs": {
    "lock": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "kind",
        "where"
      ],
      "properties": {
        "kind": {
          "enum": [
            "keeper",
            "local",
            "advisory"
          ]
        },
        "where": {
          "type": "string"
        },
        "notice": {
          "type": "string"
        },
        "waited": {
          "description": "The run waited for another apply's lock (--lock-wait): for how long, who held it when the run first found it held, and where.",
          "type": "object",
          "additionalProperties": false,
          "required": [
            "ms",
            "heldBy",
            "where"
          ],
          "properties": {
            "ms": {
              "type": "integer"
            },
            "heldBy": {
              "type": "string"
            },
            "where": {
              "type": "string"
            }
          }
        }
      }
    },
    "versioned": {
      "type": "object",
      "$ref": "status.schema.json#/$defs/report",
      "required": [
        "mode",
        "status"
      ],
      "unevaluatedProperties": false,
      "properties": {
        "mode": {
          "const": "versioned"
        },
        "status": {
          "description": "planned (--plan, something pending), unchanged, refused, denied (a policy rule denies the plan, with no override), stood-down (--stand-down: a newer commit's apply applies this environment, so this one applied nothing), gated (waiting at the Op's gate for a person's approval), failed, applied.",
          "enum": [
            "planned",
            "unchanged",
            "refused",
            "denied",
            "stood-down",
            "gated",
            "failed",
            "applied"
          ]
        },
        "stoodDown": {
          "description": "stood-down: why, in one line.",
          "type": "string"
        },
        "preChecks": {
          "description": "The first pending migration's checks, when one failed before the gate.",
          "type": "object",
          "additionalProperties": false,
          "required": [
            "migration",
            "checks"
          ],
          "properties": {
            "migration": {
              "type": "string"
            },
            "checks": {
              "type": "array",
              "items": {
                "$ref": "common.schema.json#/$defs/checkOutcome"
              }
            }
          }
        },
        "policy": {
          "description": "denied: each policy rule's outcome.",
          "$ref": "common.schema.json#/$defs/policy"
        },
        "op": {
          "type": "string"
        },
        "gate": {
          "type": "string"
        },
        "approve": {
          "description": "gated: the command a person runs to approve. An agent prints it and never runs it.",
          "type": "string"
        },
        "chantApprove": { "description": "chant's own command for the same approval (chant approve <op> <gate> --plan <digest>), for scripts; a person runs approve.", "type": "string" },
        "gatePlanDigest": {
          "type": "string"
        },
        "moved": {
          "description": "gated: the gate's newest approval does not hold, and what moved since it.",
          "type": "object",
          "additionalProperties": false,
          "required": [
            "approved",
            "by",
            "at",
            "confirmed",
            "changes"
          ],
          "properties": {
            "approved": {
              "type": "string"
            },
            "by": {
              "type": "string"
            },
            "at": {
              "type": "string"
            },
            "confirmed": {
              "type": "boolean"
            },
            "changes": {
              "$ref": "plan.schema.json#/$defs/moved"
            },
            "askedAgain": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "at"
              ],
              "properties": {
                "at": {
                  "type": "string"
                },
                "digest": {
                  "type": "string"
                }
              }
            }
          }
        },
        "exitCode": {
          "description": "failed: yodel apply's exit code, the Apply step's own when it had one.",
          "type": "integer"
        },
        "chantExitCode": {
          "description": "failed: chant run's exit code.",
          "type": "integer"
        },
        "appliedNow": {
          "description": "applied: the migrations this run applied.",
          "$ref": "common.schema.json#/$defs/stringList"
        }
      }
    },
    "execute": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "environment",
        "status",
        "planDigest",
        "applied",
        "skipped",
        "lock"
      ],
      "properties": {
        "environment": {
          "type": "string"
        },
        "status": {
          "description": "applied, or stood-down (--stand-down: a newer commit came while the step waited for the lock, and it applied nothing).",
          "enum": [
            "applied",
            "stood-down"
          ]
        },
        "stoodDown": {
          "description": "stood-down: why, in one line.",
          "type": "string"
        },
        "planDigest": {
          "description": "The digest the gate approved.",
          "type": "string"
        },
        "applied": {
          "$ref": "common.schema.json#/$defs/stringList"
        },
        "skipped": {
          "description": "Statements not sent because an earlier run had already succeeded with them.",
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "statement"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "statement": {
                "type": "integer"
              }
            }
          }
        },
        "lock": {
          "$ref": "#/$defs/lock"
        },
        "wavePlanDigest": {
          "description": "--wave-apply: the wave plan digest chant's wave decision named.",
          "type": "string"
        }
      }
    },
    "declarative": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "environment",
        "dialect",
        "op",
        "status",
        "plan"
      ],
      "properties": {
        "environment": {
          "type": "string"
        },
        "dialect": {
          "$ref": "common.schema.json#/$defs/dialect"
        },
        "server": {
          "$ref": "common.schema.json#/$defs/server"
        },
        "op": {
          "description": "The ApplyOp.",
          "type": "string"
        },
        "status": {
          "enum": [
            "refused",
            "unchanged",
            "gated",
            "failed",
            "incomplete",
            "applied"
          ]
        },
        "gate": {
          "type": "string"
        },
        "approve": {
          "description": "gated: the command a person runs to approve. An agent prints it and never runs it.",
          "type": "string"
        },
        "chantApprove": { "description": "chant's own command for the same approval (chant approve <op> <gate> --plan <digest>), for scripts; a person runs approve.", "type": "string" },
        "planDigest": {
          "type": "string"
        },
        "exitCode": {
          "description": "failed: chant run's exit code.",
          "type": "integer"
        },
        "plan": {
          "description": "The plan before the run.",
          "$ref": "plan.schema.json#/$defs/declarative"
        },
        "remaining": {
          "description": "incomplete: the plan after the Op completed.",
          "$ref": "plan.schema.json#/$defs/declarative"
        }
      }
    },
    "wavePlan": {
      "description": "--wave-plan: the plan file chant run wave reads, as written.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "planDigest",
        "destructive",
        "empty",
        "environment",
        "migrations",
        "gate",
        "base",
        "pending",
        "destructiveSteps",
        "requires"
      ],
      "properties": {
        "planDigest": {
          "description": "The wave plan digest: over the migrations' digest, the gate policy at the base commit and whether a pending step is destructive.",
          "type": "string"
        },
        "destructive": {
          "type": "boolean"
        },
        "empty": {
          "description": "Nothing is pending.",
          "type": "boolean"
        },
        "environment": {
          "type": "string"
        },
        "migrations": {
          "description": "The migrations' plan digest, as yodel apply --digest prints it.",
          "type": "string"
        },
        "gate": {
          "enum": [
            "always",
            "on-destructive",
            "never"
          ]
        },
        "base": {
          "description": "The base commit the gate was read at.",
          "type": "string"
        },
        "pending": {
          "$ref": "common.schema.json#/$defs/stringList"
        },
        "destructiveSteps": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/destructiveStep"
          }
        },
        "requires": {
          "description": "Each environment this one requires, and the pending migrations its history records applied; part of the plan digest.",
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "env",
              "applied"
            ],
            "properties": {
              "env": {
                "type": "string"
              },
              "applied": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "id",
                    "checksum"
                  ],
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "checksum": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "destructiveStep": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "migration",
        "step",
        "what",
        "why"
      ],
      "properties": {
        "migration": {
          "type": "string"
        },
        "step": {
          "type": "integer"
        },
        "what": {
          "type": "string"
        },
        "why": {
          "description": "The lint rules that class it (destructive, pg-rewrite, pg-lock, pg-access, ch-mutation, ch-rebuild, ch-access), or op-step, manual-step.",
          "type": "string"
        }
      }
    }
  }
}
