{
  "$defs": {
    "Admission": {
      "description": "Whether state-writing runs require a CI deployment admission.",
      "enum": [
        "off",
        "required"
      ],
      "type": "string"
    },
    "DriftRepair": {
      "description": "Whether reconcile repairs drift on its own.\n\nContract: [Drift](../../../../design/orchestration-core.md#drift).",
      "oneOf": [
        {
          "const": "converge",
          "description": "The next reconcile executes drifted units whose recovery policy is\n`converge` again; a drifted unit that is not safe to re-run awaits\napproval.",
          "type": "string"
        },
        {
          "const": "manual",
          "description": "Reconcile repairs no drift by itself: drifted units stay `drifted`\nuntil `nyl reconcile --unit <unit> --reapply --reason <text>`.",
          "type": "string"
        }
      ]
    },
    "EnvironmentSource": {
      "additionalProperties": false,
      "description": "The source commit of an environment's runs: a ref whose tip each run uses,\noptionally pinned to a commit that `nyl update source-locks` moves, or the\ncommit the newest promotion recorded.",
      "properties": {
        "commit": {
          "description": "Full 40-character lowercase commit ID that is read, refreshed by `nyl update source-locks`.",
          "type": [
            "string",
            "null"
          ]
        },
        "fromPromotion": {
          "anyOf": [
            {
              "$ref": "#/$defs/PromotedSource"
            },
            {
              "type": "null"
            }
          ],
          "description": "The source commit recorded by the newest promotion on a path; excludes the other fields."
        },
        "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"
    },
    "EnvironmentSpec": {
      "additionalProperties": false,
      "properties": {
        "admission": {
          "anyOf": [
            {
              "$ref": "#/$defs/Admission"
            },
            {
              "type": "null"
            }
          ],
          "description": "CI deployment admission: `required` makes state-writing runs use the source of the current admission. Omitted, the group's, else `off`."
        },
        "allowUnprotectedSource": {
          "description": "Whether runs may use source commits outside `protectedRefs`. Omitted, the group's, else `false`.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "attestations": {
          "description": "Environment-wide attestations, recorded with `nyl attest` for the environment's current state.",
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "driftRepair": {
          "anyOf": [
            {
              "$ref": "#/$defs/DriftRepair"
            },
            {
              "type": "null"
            }
          ],
          "description": "Whether `reconcile` repairs drift by itself: `converge` executes units whose latest drift observation is `drifted` again (units not safe to re-run await approval); `manual` leaves them `drifted` until `--reapply`. Omitted, the group's, else `converge`."
        },
        "protectedRefs": {
          "description": "Refs that pinned commits and run source commits must be reachable from. Omitted, the group's, else each repository's default branch.",
          "items": {
            "type": "string"
          },
          "type": [
            "array",
            "null"
          ]
        },
        "source": {
          "anyOf": [
            {
              "$ref": "#/$defs/EnvironmentSource"
            },
            {
              "type": "null"
            }
          ],
          "description": "The source commit runs use. Omitted, the commit of the worktree a run starts from."
        },
        "state": {
          "$ref": "#/$defs/EnvironmentState",
          "default": {},
          "description": "Where the environment's state lives."
        },
        "unitSelector": {
          "$ref": "#/$defs/LabelSelector",
          "default": {},
          "description": "Matches literal unit `metadata.labels` across all unit kinds. An empty selector selects every unit."
        },
        "values": {
          "additionalProperties": true,
          "description": "Values unit templates see as `values`, merged recursively over the values of the EnvironmentGroup selecting this environment.",
          "type": "object"
        }
      },
      "type": "object"
    },
    "EnvironmentState": {
      "additionalProperties": false,
      "description": "The location of an environment's state: a repository and the refs within it.",
      "properties": {
        "admissionRef": {
          "description": "Ref of the deployment admission record. Default the desired ref.",
          "type": [
            "string",
            "null"
          ]
        },
        "coordinationRefPrefix": {
          "description": "Prefix, ending in `/`, of the leases, runs, and signals refs. Default `refs/nyl/`.",
          "type": [
            "string",
            "null"
          ]
        },
        "desiredRef": {
          "description": "Ref of the desired state. A short name is a branch. Default `nyl/<environment>/desired`.",
          "type": [
            "string",
            "null"
          ]
        },
        "observedRef": {
          "description": "Ref of the observed state; may equal `desiredRef`. Default `nyl/<environment>/observed`.",
          "type": [
            "string",
            "null"
          ]
        },
        "path": {
          "description": "Directory of the environment's state within its refs, so several environments can share one ref. Default the root.",
          "type": "string"
        },
        "repository": {
          "anyOf": [
            {
              "$ref": "#/$defs/InlineGitRepository"
            },
            {
              "type": "null"
            }
          ],
          "description": "Inline repository coordinates holding the state. Mutually exclusive with `repositoryRef`."
        },
        "repositoryRef": {
          "anyOf": [
            {
              "$ref": "#/$defs/LocalReference"
            },
            {
              "type": "null"
            }
          ],
          "description": "GitRepository holding the state, read through its `repoURL` and written through its `publishURL`. Mutually exclusive with `repository`. Omitted with `repository`: the group's, else the checkout's `origin`, else the local repository."
        }
      },
      "type": "object"
    },
    "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"
    },
    "InlineGitRepository": {
      "additionalProperties": false,
      "properties": {
        "publishURL": {
          "description": "Optional Git write URL. Publication uses `repoURL` when omitted.",
          "type": [
            "string",
            "null"
          ]
        },
        "repoURL": {
          "description": "Credential-free Git read URL used by renderers and generated Applications.",
          "type": "string"
        }
      },
      "required": [
        "repoURL"
      ],
      "type": "object"
    },
    "LabelSelector": {
      "additionalProperties": false,
      "properties": {
        "matchLabels": {
          "additionalProperties": {
            "type": "string"
          },
          "description": "Exact label matches, combined with AND. An empty map selects every ApplicationGroup.",
          "type": "object"
        }
      },
      "type": "object"
    },
    "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"
    },
    "PromotedSource": {
      "additionalProperties": false,
      "description": "A source that promotion paths supply.",
      "properties": {
        "path": {
          "description": "The PromotionPath that supplies the source. Mutually exclusive with `paths`.",
          "type": [
            "string",
            "null"
          ]
        },
        "paths": {
          "description": "Several PromotionPaths; the newest record on any of them wins. Mutually exclusive with `path`.",
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "promoted": {
          "description": "The record `nyl promote` writes here with `record: source`, never by hand."
        },
        "record": {
          "description": "Where the PromotionRecord lives: `state` (default) or `source`.",
          "type": [
            "string",
            "null"
          ]
        }
      },
      "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"
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "additionalProperties": false,
  "description": "A named place that units are reconciled into, with its own state.\n\nAn Environment selects units by their literal labels and gives their\ntemplates its `values`. The selected, enabled units are its ownership set:\na unit that leaves the set is deleted under its deletion policy.\n\n## When needed\n\nTo reconcile units with `nyl reconcile -e <environment>`.\n\n## If omitted\n\nNo orchestration happens; rendering and publication work as before.",
  "examples": [
    {
      "apiVersion": "gitops.nyl/v1",
      "kind": "Environment",
      "metadata": {
        "name": "production"
      },
      "spec": {
        "protectedRefs": [
          "main"
        ],
        "state": {
          "repositoryRef": {
            "name": "deploy"
          }
        },
        "unitSelector": {
          "matchLabels": {
            "stage": "production"
          }
        },
        "values": {
          "target": "production"
        }
      }
    }
  ],
  "properties": {
    "apiVersion": {
      "const": "gitops.nyl/v1",
      "description": "API group and version defining this resource.",
      "type": "string"
    },
    "kind": {
      "const": "Environment",
      "description": "Resource kind within the API group.",
      "type": "string"
    },
    "metadata": {
      "$ref": "#/$defs/GitOpsResourceMetadata",
      "description": "Resource identity and metadata."
    },
    "spec": {
      "$ref": "#/$defs/EnvironmentSpec",
      "default": {
        "state": {},
        "unitSelector": {}
      },
      "description": "Configuration for this resource."
    }
  },
  "required": [
    "apiVersion",
    "kind",
    "metadata"
  ],
  "title": "Environment",
  "type": "object"
}
