{
  "$defs": {
    "ApprovalBind": {
      "enum": [
        "desired",
        "plan"
      ],
      "type": "string"
    },
    "ApprovalMode": {
      "enum": [
        "auto",
        "manual"
      ],
      "type": "string"
    },
    "ApprovalPolicy": {
      "anyOf": [
        {
          "enum": [
            "auto",
            "manual"
          ],
          "type": "string"
        },
        {
          "description": "When a unit's executions need an invocation's approval.\n\nWritten as `auto` (the default), `manual` (short for\n`{mode: manual, bind: desired}`), or `{mode, bind, requireDigest}`.",
          "properties": {
            "bind": {
              "$ref": "#/$defs/ApprovalBind",
              "description": "What an approval authorizes: one execution of the `desired` document, or the changes a reviewed `plan` showed."
            },
            "mode": {
              "$ref": "#/$defs/ApprovalMode",
              "description": "`auto` executes without approval; `manual` waits for `--approve`."
            },
            "requireDigest": {
              "description": "Refuse approvals without a change digest, for `bind: plan`.",
              "type": "boolean"
            }
          },
          "required": [
            "mode",
            "bind"
          ],
          "type": "object"
        }
      ],
      "description": "`auto` (default), `manual` (short for {mode: manual, bind: desired}), or {mode, bind, requireDigest}."
    },
    "AttestationDeclaration": {
      "additionalProperties": false,
      "description": "One attestation a unit's receipts can carry.",
      "properties": {
        "from": {
          "anyOf": [
            {
              "$ref": "#/$defs/AttestationSource"
            },
            {
              "type": "null"
            }
          ],
          "description": "`external` for an attestation only `nyl attest` supplies; omitted for one the kind produces itself."
        },
        "name": {
          "description": "Attestation name, such as `healthy`.",
          "type": "string"
        }
      },
      "required": [
        "name"
      ],
      "type": "object"
    },
    "AttestationSource": {
      "enum": [
        "external"
      ],
      "type": "string"
    },
    "DeletionPolicy": {
      "description": "What happens to a unit's resources when it leaves the ownership set.",
      "oneOf": [
        {
          "const": "Teardown",
          "description": "Tear the resources down, after `--allow-teardown`.",
          "type": "string"
        },
        {
          "const": "Retain",
          "description": "Leave the resources in place.",
          "type": "string"
        }
      ]
    },
    "DependsOn": {
      "anyOf": [
        {
          "description": "A unit of the same environment.",
          "type": "string"
        },
        {
          "$ref": "#/$defs/DependsOnEntry",
          "description": "A unit, optionally of another declared environment, with required evidence."
        }
      ],
      "description": "A unit that must have a current receipt before this one runs: a name, or\nan entry naming another declared environment or stronger evidence."
    },
    "DependsOnEntry": {
      "additionalProperties": false,
      "properties": {
        "attestations": {
          "description": "The producer's attestations to require, instead of all it declares.",
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "environment": {
          "description": "Another declared environment; default this one.",
          "type": [
            "string",
            "null"
          ]
        },
        "evidence": {
          "anyOf": [
            {
              "$ref": "#/$defs/Evidence"
            },
            {
              "type": "null"
            }
          ],
          "description": "Required evidence: `published` (a current receipt, the default) or `attested`."
        },
        "unit": {
          "description": "The producing unit.",
          "type": "string"
        }
      },
      "required": [
        "unit"
      ],
      "type": "object"
    },
    "Duration": {
      "description": "A duration such as `90s`, `30m`, `1h30m`, or `7d`.",
      "examples": [
        "30m"
      ],
      "pattern": "^(?=.)([0-9]+d)?([0-9]+h)?([0-9]+m)?([0-9]+s)?$",
      "type": "string"
    },
    "EnvAdmission": {
      "additionalProperties": false,
      "description": "Variables admitted into a unit's tool environment. Values are never part\nof the execution key; only names are.",
      "properties": {
        "passthrough": {
          "description": "Names of runner environment variables copied as they are.",
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "secrets": {
          "additionalProperties": {
            "type": "string"
          },
          "description": "Variables read from the project's secrets provider, by variable name and secret key. An object or array secret is passed as compact JSON.",
          "type": "object"
        }
      },
      "type": "object"
    },
    "Evidence": {
      "description": "Evidence a consumer requires from its producer.",
      "oneOf": [
        {
          "const": "published",
          "description": "A current receipt.",
          "type": "string"
        },
        {
          "const": "attested",
          "description": "A current receipt whose required attestations pass.",
          "type": "string"
        }
      ]
    },
    "GitOpsResourceMetadata": {
      "additionalProperties": false,
      "description": "Metadata shared by local GitOps compiler resources.",
      "properties": {
        "labels": {
          "additionalProperties": {
            "type": "string"
          },
          "description": "Literal labels used for organization and target selection.",
          "type": "object"
        },
        "name": {
          "description": "Project-local identity, validated by the resource kind; remains static during discovery.",
          "type": "string"
        }
      },
      "required": [
        "name"
      ],
      "type": "object"
    },
    "GitSource": {
      "description": "A directory or file in a Git repository: this repository when no\nrepository is named, otherwise a remote one, optionally pinned to a commit.",
      "properties": {
        "commit": {
          "description": "Full 40-character lowercase commit ID that is read, refreshed by `nyl update source-locks`.",
          "type": [
            "string",
            "null"
          ]
        },
        "path": {
          "description": "Path in the repository. In this repository it follows the local path rule: relative to the directory containing `nyl.toml`, may begin with `..` segments, or starts with `/` to name a path from the Git worktree root, and never leaves the worktree. In a remote repository it is relative to the checkout root, with an optional leading `/`.",
          "type": [
            "string",
            "null"
          ]
        },
        "repository": {
          "anyOf": [
            {
              "$ref": "#/$defs/ReadGitRepository"
            },
            {
              "type": "null"
            }
          ],
          "description": "Inline repository coordinates to read from. Mutually exclusive with `repositoryRef`."
        },
        "repositoryRef": {
          "anyOf": [
            {
              "$ref": "#/$defs/LocalReference"
            },
            {
              "type": "null"
            }
          ],
          "description": "Project-local `gitops.nyl/v1` GitRepository to read from. Mutually exclusive with inline `repository`."
        },
        "revision": {
          "description": "Human-readable branch or tag that `nyl update source-locks` resolves.",
          "type": [
            "string",
            "null"
          ]
        }
      },
      "type": "object"
    },
    "ImageCache": {
      "additionalProperties": false,
      "description": "Buildx cache specifications.",
      "properties": {
        "from": {
          "default": [],
          "description": "Buildx cache import specifications passed as `--cache-from`.",
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "to": {
          "default": [],
          "description": "Buildx cache export specifications passed as `--cache-to`.",
          "items": {
            "type": "string"
          },
          "type": "array"
        }
      },
      "type": "object"
    },
    "ImageContext": {
      "anyOf": [
        {
          "$ref": "#/$defs/ImageReference"
        },
        {
          "$ref": "#/$defs/GitSource"
        }
      ],
      "description": "A directory source or an image reference for a named Buildx context."
    },
    "ImageReference": {
      "additionalProperties": false,
      "description": "An image context. Its reference can be supplied by a `fromUnit` artifact binding.",
      "properties": {
        "image": {
          "description": "A digest-pinned image reference or a `fromUnit` artifact binding."
        }
      },
      "required": [
        "image"
      ],
      "type": "object"
    },
    "InputType": {
      "description": "Declared input type. Every type is a subset of JSON Schema.",
      "oneOf": [
        {
          "const": "string",
          "description": "A JSON string.",
          "type": "string"
        },
        {
          "const": "integer",
          "description": "A JSON integer; numbers with a fractional part are rejected.",
          "type": "string"
        },
        {
          "const": "number",
          "description": "Any JSON number.",
          "type": "string"
        },
        {
          "const": "boolean",
          "description": "`true` or `false`.",
          "type": "string"
        },
        {
          "const": "object",
          "description": "A JSON object. Only the top-level type is checked.",
          "type": "string"
        },
        {
          "const": "array",
          "description": "A JSON array. Only the top-level type is checked.",
          "type": "string"
        }
      ]
    },
    "LocalReference": {
      "additionalProperties": false,
      "properties": {
        "name": {
          "description": "Project-local name of the referenced resource; its kind and API group are determined by the containing field.",
          "type": "string"
        }
      },
      "required": [
        "name"
      ],
      "type": "object"
    },
    "OciImageSpec": {
      "additionalProperties": false,
      "description": "Docker Buildx inputs. Every directory context is a separately pinned Git source.",
      "properties": {
        "approval": {
          "$ref": "#/$defs/ApprovalPolicy",
          "description": "Whether executions need an invocation's approval."
        },
        "attestations": {
          "description": "Attestations of the unit's receipts: names its kind produces itself, or entries with `from: external` that only `nyl attest` supplies.",
          "items": {
            "$ref": "#/$defs/AttestationDeclaration"
          },
          "type": "array"
        },
        "buildArgs": {
          "additionalProperties": true,
          "description": "Build arguments, with references resolved before execution. Values must resolve to scalars.",
          "type": "object"
        },
        "builder": {
          "description": "Runner's Buildx builder; excluded from the execution key.",
          "type": [
            "string",
            "null"
          ]
        },
        "cache": {
          "anyOf": [
            {
              "$ref": "#/$defs/ImageCache"
            },
            {
              "type": "null"
            }
          ],
          "description": "Buildx cache imports and exports; excluded from the execution key."
        },
        "context": {
          "$ref": "#/$defs/GitSource",
          "description": "Main build context, following the common Git source and local path rules."
        },
        "contexts": {
          "additionalProperties": {
            "$ref": "#/$defs/ImageContext"
          },
          "description": "Named directories or digest-pinned image references, passed with `--build-context`.",
          "type": "object"
        },
        "deletionPolicy": {
          "anyOf": [
            {
              "$ref": "#/$defs/DeletionPolicy"
            },
            {
              "type": "null"
            }
          ],
          "description": "What happens to the unit's resources when it leaves the ownership set. Default `Teardown` where the kind supports teardown, else `Retain`."
        },
        "dependsOn": {
          "description": "Units that must have a current receipt first, for ordering without a data reference.",
          "items": {
            "$ref": "#/$defs/DependsOn"
          },
          "type": "array"
        },
        "dockerfile": {
          "default": "Dockerfile",
          "description": "Dockerfile relative to the main context, default `Dockerfile`; cannot leave the context.",
          "type": "string"
        },
        "enabled": {
          "description": "Evaluated after rendering; `false` leaves the environment's ownership set, which deletes the unit under its `deletionPolicy`.",
          "type": "boolean"
        },
        "env": {
          "$ref": "#/$defs/EnvAdmission",
          "description": "Variables and secrets admitted into the unit's otherwise empty tool environment."
        },
        "outputs": {
          "additionalProperties": {
            "$ref": "#/$defs/OutputDeclaration"
          },
          "description": "Declared outputs, for kinds that let units declare them. Only declared outputs are recorded.",
          "type": "object"
        },
        "platforms": {
          "description": "Target platforms, such as `linux/amd64`. Omitted uses the builder's platform.",
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "registryAuth": {
          "additionalProperties": {
            "$ref": "#/$defs/RegistryAuth"
          },
          "description": "Registry host to username/password secret keys. Values never enter state or execution keys.",
          "type": "object"
        },
        "repository": {
          "description": "Registry repository without a tag or digest, such as `registry.example.com/team/web`.",
          "type": "string"
        },
        "tags": {
          "description": "Extra moving tags in this repository. Consumers use the immutable artifact reference.",
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "target": {
          "description": "Optional Dockerfile build stage.",
          "type": [
            "string",
            "null"
          ]
        },
        "timeout": {
          "anyOf": [
            {
              "$ref": "#/$defs/Duration"
            },
            {
              "type": "null"
            }
          ],
          "description": "Deadline for one execution, teardown, or verification, at most `7d`. Default per kind."
        }
      },
      "required": [
        "context",
        "repository"
      ],
      "type": "object"
    },
    "OutputDeclaration": {
      "additionalProperties": false,
      "description": "One declared output: a type from the Release input type set.",
      "properties": {
        "description": {
          "description": "Documentation, surfaced in inspection.",
          "type": [
            "string",
            "null"
          ]
        },
        "sensitive": {
          "description": "Validated but never persisted, and never referenceable.",
          "type": "boolean"
        },
        "type": {
          "$ref": "#/$defs/InputType",
          "description": "Value type: `string`, `integer`, `number`, `boolean`, `object`, or `array`."
        }
      },
      "required": [
        "type"
      ],
      "type": "object"
    },
    "ReadGitRepository": {
      "additionalProperties": false,
      "description": "Credential-free coordinates for a repository that is only read.",
      "properties": {
        "repoURL": {
          "description": "Git read URL. Source checkouts never publish to this repository.",
          "type": "string"
        }
      },
      "required": [
        "repoURL"
      ],
      "type": "object"
    },
    "RegistryAuth": {
      "additionalProperties": false,
      "description": "Secret keys for one registry; the runner never reads undeclared credentials.",
      "properties": {
        "passwordSecret": {
          "description": "Project secret key containing this registry's password or access token.",
          "type": "string"
        },
        "usernameSecret": {
          "description": "Project secret key containing this registry's username.",
          "type": "string"
        }
      },
      "required": [
        "usernameSecret",
        "passwordSecret"
      ],
      "type": "object"
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "description": "Builds and pushes an immutable container image with Docker Buildx.\n\nConsumers read the `image` ContainerImage artifact by digest. Registry\ncredentials come only from the declared `registryAuth` keys or `env`.",
  "examples": [
    {
      "apiVersion": "units.gitops.nyl/v1",
      "kind": "OciImage",
      "metadata": {
        "name": "workloads"
      },
      "spec": {
        "context": {
          "path": "services/web"
        },
        "platforms": [
          "linux/amd64"
        ],
        "repository": "registry.example.com/team/web"
      }
    }
  ],
  "properties": {
    "apiVersion": {
      "const": "units.gitops.nyl/v1",
      "description": "The built-in unit API version, `units.gitops.nyl/v1`.",
      "type": "string"
    },
    "kind": {
      "const": "OciImage",
      "description": "The unit kind, `OciImage`.",
      "type": "string"
    },
    "metadata": {
      "$ref": "#/$defs/GitOpsResourceMetadata",
      "description": "Literal unit name and labels used for environment selection."
    },
    "spec": {
      "$ref": "#/$defs/OciImageSpec",
      "description": "The build inputs, registry destination, and common unit policy."
    }
  },
  "required": [
    "apiVersion",
    "kind",
    "metadata",
    "spec"
  ],
  "title": "OciImage",
  "type": "object"
}
