{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Config",
  "description": "`deny_unknown_fields` rejects typos and unknown config fields at parse time (strict YAML unmarshalling).",
  "type": "object",
  "properties": {
    "after": {
      "description": "Hooks run after the release pipeline completes.",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/HooksConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "announce": {
      "description": "Announcement configuration (Slack, Discord, email, etc.).",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/AnnounceConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "appimages": {
      "description": "AppImage configurations. Each entry bundles a built Linux binary plus its desktop integration into a single self-contained `.AppImage` via linuxdeploy.",
      "default": [],
      "type": "array",
      "items": {
        "$ref": "#/definitions/AppImageConfig"
      }
    },
    "artifactories": {
      "description": "Artifactory upload configurations.",
      "default": null,
      "type": [
        "array",
        "null"
      ],
      "items": {
        "$ref": "#/definitions/ArtifactoryConfig"
      }
    },
    "attestations": {
      "description": "SLSA build-provenance / attestation configuration for binaries and archives. In the default `subjects` mode, anodizer writes a subjects manifest for `actions/attest-build-provenance`; in `emit` mode it generates and signs a self-contained in-toto SLSA provenance statement. When omitted (or `enabled: false`), the attestation stage is a no-op.",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/AttestationConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "aur_sources": {
      "description": "AUR source package publishing configurations (source-only PKGBUILD, not -bin).",
      "default": null,
      "type": [
        "array",
        "null"
      ],
      "items": {
        "$ref": "#/definitions/AurSourceConfig"
      }
    },
    "before": {
      "description": "Hooks run before the release pipeline starts.",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/HooksConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "before_publish": {
      "description": "Hooks run after build/archive/sign/sbom/checksum complete but immediately before the publish phase dispatches any publisher.\n\nUse cases: smoke-test artifacts against the staged dist tree, run external validators (antivirus, vulnerability scanners), stage external state, or abort the release before any publisher writes to a registry.\n\nA non-zero exit code from any hook aborts the release before publish runs. Hooks fire in declared order. Use `--skip=before-publish` to bypass.",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/HooksConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "binary_signs": {
      "description": "Binary-specific signing configs (same shape as `signs` but only for binary artifacts). The `artifacts` field on each entry is constrained at parse time to `binary` / `none` (or omitted) — a broader filter on `binary_signs` would silently match nothing because the loop only iterates Binary artifacts. Constraint lives in `deserialize_binary_signs`.",
      "default": [],
      "type": "array",
      "items": {
        "$ref": "#/definitions/SignConfig"
      }
    },
    "changelog": {
      "description": "Changelog generation configuration.",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/ChangelogConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "cloudsmiths": {
      "description": "CloudSmith publisher configurations.",
      "default": null,
      "type": [
        "array",
        "null"
      ],
      "items": {
        "$ref": "#/definitions/CloudSmithConfig"
      }
    },
    "crates": {
      "description": "List of crates in this project.",
      "default": [],
      "type": "array",
      "items": {
        "$ref": "#/definitions/CrateConfig"
      }
    },
    "defaults": {
      "description": "Default values applied to all crates unless overridden.",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/Defaults"
        },
        {
          "type": "null"
        }
      ]
    },
    "dist": {
      "description": "Output directory for build artifacts (default: ./dist).",
      "default": "./dist",
      "type": "string"
    },
    "docker_signs": {
      "description": "Docker image signing configurations.",
      "default": null,
      "type": [
        "array",
        "null"
      ],
      "items": {
        "$ref": "#/definitions/DockerSignConfig"
      }
    },
    "dockerhub": {
      "description": "DockerHub description sync configurations.",
      "default": null,
      "type": [
        "array",
        "null"
      ],
      "items": {
        "$ref": "#/definitions/DockerHubConfig"
      }
    },
    "env": {
      "description": "Environment variables available to all template expressions.\n\nList of `KEY=VALUE` strings: `env: [\"MY_VAR=hello\", \"DEPLOY_ENV=staging\"]`. Order is preserved so chained env applications (sign + sbom + notarize) see entries in declared order. Values are rendered through the template engine before being set, so expressions like `{{ Tag }}` or `{{ Date }}` are expanded.",
      "default": null,
      "type": [
        "array",
        "null"
      ],
      "items": {
        "type": "string"
      }
    },
    "env_files": {
      "description": "Environment file configuration. Accepts either: - A list of `.env` file paths: `[\".env\", \".release.env\"]` - A struct with token file paths: `{ github_token: \"~/.config/goreleaser/github_token\" }`",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/EnvFilesConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "force_token": {
      "description": "Force a specific token type for authentication. When set, overrides automatic token detection from environment variables.",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/ForceTokenKind"
        },
        {
          "type": "null"
        }
      ]
    },
    "gemfury": {
      "description": "GemFury (fury.io) deb/rpm/apk publishing configurations. Mirrors The `gemfury:` block. The legacy spelling `furies:` is accepted via serde alias; a one-time deprecation warning is emitted by [`warn_on_legacy_furies_alias`].",
      "default": null,
      "type": [
        "array",
        "null"
      ],
      "items": {
        "$ref": "#/definitions/GemFuryConfig"
      }
    },
    "git": {
      "description": "Git-level tag discovery and sorting settings.",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/GitConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "gitea_urls": {
      "description": "Custom Gitea API/download URLs for self-hosted Gitea installations.",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/GiteaUrlsConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "github_urls": {
      "description": "Custom GitHub API/upload/download URLs for GitHub Enterprise installations.",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/GitHubUrlsConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "gitlab_urls": {
      "description": "Custom GitLab API/download URLs for self-hosted GitLab installations.",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/GitLabUrlsConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "homebrew_casks": {
      "description": "Top-level Homebrew Cask configurations. `homebrew_casks` is a top-level array with its own repository, commit_author, directory, skip_upload, hooks, dependencies, conflicts, completions, manpages, structured uninstall/zap, etc.",
      "default": null,
      "type": [
        "array",
        "null"
      ],
      "items": {
        "$ref": "#/definitions/HomebrewCaskConfig"
      }
    },
    "includes": {
      "description": "Additional config files to merge into this config. Supports plain string paths, `from_file:` for structured file paths, and `from_url:` for fetching configs from URLs with optional headers.",
      "default": null,
      "type": [
        "array",
        "null"
      ],
      "items": {
        "$ref": "#/definitions/IncludeSpec"
      }
    },
    "makeselfs": {
      "description": "Makeself self-extracting archive configurations.",
      "default": [],
      "type": "array",
      "items": {
        "$ref": "#/definitions/MakeselfConfig"
      }
    },
    "mcp": {
      "description": "MCP (Model Context Protocol) server registry publishing configuration. When `name` is empty (the default), the publisher is skipped. The `mcp:` publisher block.",
      "default": {
        "name": null,
        "title": null,
        "description": null,
        "homepage": null,
        "packages": [],
        "transports": [],
        "skip": null,
        "repository": {
          "url": "",
          "source": "",
          "id": "",
          "subfolder": ""
        },
        "auth": {
          "type": "none"
        },
        "registry": null,
        "if": null,
        "retain_on_rollback": null
      },
      "allOf": [
        {
          "$ref": "#/definitions/McpConfig"
        }
      ]
    },
    "metadata": {
      "description": "Project metadata configuration (applied to metadata.json output files).",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/MetadataConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "milestones": {
      "description": "Milestone closing configurations.",
      "default": null,
      "type": [
        "array",
        "null"
      ],
      "items": {
        "$ref": "#/definitions/MilestoneConfig"
      }
    },
    "monorepo": {
      "description": "Monorepo configuration. When configured, tag discovery filters by tag_prefix and the working directory is scoped to dir.",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/MonorepoConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "nightly": {
      "description": "Nightly release configuration.",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/NightlyConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "notarize": {
      "description": "macOS code signing and notarization configuration.",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/NotarizeConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "npms": {
      "description": "NPM package registry publishing configurations. One entry per published package. In the default `optional-deps` mode anodizer emits npm's native per-platform packages (biome / git-cliff pattern); in `postinstall` mode it emits a download shim (the `npms:` parity).",
      "default": null,
      "type": [
        "array",
        "null"
      ],
      "items": {
        "$ref": "#/definitions/NpmConfig"
      }
    },
    "partial": {
      "description": "Partial/split build configuration for fan-out CI pipelines.",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/PartialConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "project_name": {
      "description": "Human-readable project name used in templates and release titles.",
      "default": "",
      "type": "string"
    },
    "publishers": {
      "description": "Generic artifact publisher configurations.",
      "default": null,
      "type": [
        "array",
        "null"
      ],
      "items": {
        "$ref": "#/definitions/PublisherConfig"
      }
    },
    "release": {
      "description": "GitHub release configuration shared by all crates.",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/ReleaseConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "report_sizes": {
      "description": "When true, log artifact file sizes after building.",
      "default": null,
      "type": [
        "boolean",
        "null"
      ]
    },
    "retry": {
      "description": "Top-level retry configuration applied to network-bound operations (announcers, git providers, HTTP uploads, docker pipes). When omitted, `RetryConfig::default()` is used (10 attempts, 10s base, 5m cap — the project-level retry policy).",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/RetryConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "sboms": {
      "description": "Software bill of materials (SBOM) generation configurations.",
      "default": [],
      "type": "array",
      "items": {
        "$ref": "#/definitions/SbomConfig"
      }
    },
    "schemastore": {
      "description": "SchemaStore publisher. Registers the project's JSON Schema(s) on SchemaStore at release time. When `schemas` is empty (the default), the publisher is skipped. The `schemastore:` publisher block.",
      "default": {
        "repository": null,
        "commit_author": null,
        "versioned": null,
        "skip": null,
        "if": null,
        "schemas": [],
        "retain_on_rollback": null
      },
      "allOf": [
        {
          "$ref": "#/definitions/SchemastoreConfig"
        }
      ]
    },
    "signs": {
      "description": "Signing configurations for binaries, archives, and checksums.",
      "default": [],
      "type": "array",
      "items": {
        "$ref": "#/definitions/SignConfig"
      }
    },
    "snapshot": {
      "description": "Snapshot release configuration (local/non-tag builds).",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/SnapshotConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "source": {
      "description": "Source archive configuration.",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/SourceConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "srpms": {
      "description": "Source RPM configuration. Renamed from `srpm:` (singular) for spelling parity with `Defaults.srpms` and the rest of the plural-name packaging fields. The `srpm:` spelling is still accepted via serde alias for back-compat.",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/SrpmConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "tag": {
      "description": "Automatic semantic version tagging configuration.",
      "default": null,
      "anyOf": [
        {
          "$ref": "#/definitions/TagConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "template_files": {
      "description": "Template files to render and include as release artifacts. File contents are processed through the template engine.",
      "default": null,
      "type": [
        "array",
        "null"
      ],
      "items": {
        "$ref": "#/definitions/TemplateFileConfig"
      }
    },
    "uploads": {
      "description": "Generic HTTP upload configurations.",
      "default": null,
      "type": [
        "array",
        "null"
      ],
      "items": {
        "$ref": "#/definitions/UploadConfig"
      }
    },
    "upx": {
      "description": "UPX binary compression configurations.",
      "default": [],
      "type": "array",
      "items": {
        "$ref": "#/definitions/UpxConfig"
      }
    },
    "variables": {
      "description": "Custom template variables accessible as `{{ Var.<key> }}` in templates. Provides a way to define reusable values, especially useful with config includes.\n\nStored as a `BTreeMap` so rendering iterates in deterministic (sorted) key order — without this guarantee, a value that references another variable (`b: \"{{ Var.a }}_v2\"`) could render before its dependency on a different process / host. The current resolver is single-pass (one render per value), so cross-variable references only resolve when the referenced key sorts earlier.",
      "default": null,
      "type": [
        "object",
        "null"
      ],
      "additionalProperties": {
        "type": "string"
      }
    },
    "verify_release": {
      "description": "Opt-in post-release verification gate. Runs LAST (after the release is created and every publisher has run) and REPORTS post-publish defects — missing assets, failed install smoke-tests, glibc-ceiling violations. Because it runs after the irreversible publish, a failure exits non-zero to flag CI but never undoes the release. Off unless `verify_release.enabled: true`.",
      "default": {
        "enabled": false,
        "assert_assets": true,
        "install_smoke": null
      },
      "allOf": [
        {
          "$ref": "#/definitions/VerifyReleaseConfig"
        }
      ]
    },
    "version": {
      "description": "Schema version. Currently supports 1 (implicit default) and 2.",
      "default": null,
      "type": [
        "integer",
        "null"
      ],
      "format": "uint32",
      "minimum": 0.0
    },
    "version_files": {
      "description": "Repo-committed files that embed the release version outside `Cargo.toml` (e.g. a Helm `Chart.yaml`, an install doc, a README badge), given as repo-root-relative path strings. At `tag` time each listed file has its occurrences of the old version rewritten to the new version — both the bare (`0.1.0`) and `v`-prefixed (`v0.1.0`) forms, word-boundary anchored — and is staged into the same bump commit as `Cargo.toml` / `Cargo.lock`, so these files never drift from the tag.\n\n```yaml version_files: - charts/cfgd/Chart.yaml - docs/installation.md ```",
      "default": null,
      "type": [
        "array",
        "null"
      ],
      "items": {
        "type": "string"
      }
    },
    "workspaces": {
      "description": "Independent workspace roots in a monorepo.",
      "default": null,
      "type": [
        "array",
        "null"
      ],
      "items": {
        "$ref": "#/definitions/WorkspaceConfig"
      }
    }
  },
  "additionalProperties": false,
  "definitions": {
    "Amd64Variant": {
      "description": "`x86_64` micro-architecture variant. A typed values. Used by [`AurSourceConfig::amd64_variant`] to constrain the `prepare:` / `build:` / `package:` template var surface to a known set — AUR source pkgs build from the upstream tarball so the value is template-only (no artifact filter) and a typo would render an invalid PKGBUILD silently.",
      "type": "string",
      "enum": [
        "v1",
        "v2",
        "v3",
        "v4"
      ]
    },
    "AnnounceConfig": {
      "type": "object",
      "properties": {
        "bluesky": {
          "description": "Bluesky announcement configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/BlueskyAnnounce"
            },
            {
              "type": "null"
            }
          ]
        },
        "discord": {
          "description": "Discord announcement configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/DiscordAnnounce"
            },
            {
              "type": "null"
            }
          ]
        },
        "discourse": {
          "description": "Discourse announcement configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/DiscourseAnnounce"
            },
            {
              "type": "null"
            }
          ]
        },
        "email": {
          "description": "Email announcement configuration. accepts the historical `smtp:` key as an alias because the field was renamed `smtp:` -> `email:` in v1.21+ and kept the alias for migration. Keeping the alias avoids forcing a re-yaml of legacy configs.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/EmailAnnounce"
            },
            {
              "type": "null"
            }
          ]
        },
        "gate_on": {
          "description": "Selects when AnnounceStage runs vs. skips based on the `PublishReport` written by PublishStage/BlobStage. Default is `required_publishers` (announce only if every required publisher succeeded). See [`AnnounceGate`] for the other variants.",
          "default": "required_publishers",
          "allOf": [
            {
              "$ref": "#/definitions/AnnounceGate"
            }
          ]
        },
        "if": {
          "description": "Template-conditional gate: when the rendered result is falsy (`\"false\"` / `\"0\"` / `\"no\"` / empty), the entire announce stage is skipped. Render failure hard-errors. The `announce.if:`. Distinct from `skip:` (always-skip predicate) — both surfaces are documented.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "linkedin": {
          "description": "LinkedIn announcement configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/LinkedInAnnounce"
            },
            {
              "type": "null"
            }
          ]
        },
        "mastodon": {
          "description": "Mastodon announcement configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/MastodonAnnounce"
            },
            {
              "type": "null"
            }
          ]
        },
        "mattermost": {
          "description": "Mattermost announcement configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/MattermostAnnounce"
            },
            {
              "type": "null"
            }
          ]
        },
        "opencollective": {
          "description": "OpenCollective announcement configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/OpenCollectiveAnnounce"
            },
            {
              "type": "null"
            }
          ]
        },
        "reddit": {
          "description": "Reddit announcement configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/RedditAnnounce"
            },
            {
              "type": "null"
            }
          ]
        },
        "skip": {
          "description": "Template-conditional skip: if rendered to \"true\", skip the entire announce stage.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "slack": {
          "description": "Slack announcement configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/SlackAnnounce"
            },
            {
              "type": "null"
            }
          ]
        },
        "teams": {
          "description": "Microsoft Teams announcement configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/TeamsAnnounce"
            },
            {
              "type": "null"
            }
          ]
        },
        "telegram": {
          "description": "Telegram announcement configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/TelegramAnnounce"
            },
            {
              "type": "null"
            }
          ]
        },
        "twitter": {
          "description": "Twitter/X announcement configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/TwitterAnnounce"
            },
            {
              "type": "null"
            }
          ]
        },
        "webhook": {
          "description": "Generic webhook announcement configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/WebhookConfig"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "AnnounceGate": {
      "description": "Announce-stage gate semantics.\n\nDecides whether [`AnnounceStage`] runs based on the `PublishReport` produced by `PublishStage` (and contributed to by `BlobStage`):\n\n- `required_publishers` (default): announce runs only if every `required: true` publisher across the run succeeded. - `all_publishers`: announce runs only if every configured publisher succeeded (Submitter gate failures count here too). - `none`: announce always runs.\n\n[`AnnounceStage`]: ../../stage-announce/struct.AnnounceStage.html",
      "type": "string",
      "enum": [
        "required_publishers",
        "all_publishers",
        "none"
      ]
    },
    "AppBundleConfig": {
      "type": "object",
      "properties": {
        "bundle": {
          "description": "Bundle identifier in reverse-DNS notation (e.g. `com.example.myapp`). Required.\n\nMust be set explicitly; there is no default. A missing value is caught at validation time with an actionable error message.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "extra_files": {
          "description": "Additional files to include in the bundle (src/dst/info objects or glob strings).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/ArchiveFileSpec"
          }
        },
        "icon": {
          "description": "Path to .icns icon file for the app bundle (supports templates).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "id": {
          "description": "Unique identifier for this app bundle config.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs to include. Empty means all builds.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional: skip this app bundle config if rendered result is \"false\" or empty. Render failure hard-errors (not silent-skip).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "min_os_version": {
          "description": "Minimum macOS version written to `LSMinimumSystemVersion` in `Info.plist`.\n\nDefaults to `\"10.13\"` when unset. Symmetry with `PkgConfig.min_os_version`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "mod_timestamp": {
          "description": "Output timestamp for reproducible builds.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "name": {
          "description": "Output .app bundle name (supports templates).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "replace": {
          "description": "Remove source archives from artifacts, keeping only the app bundle.\n\nAnodizer-additive: `replace:` on `app_bundles`.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "skip": {
          "description": "Skip this app bundle config. Accepts bool or template string.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "templated_extra_files": {
          "description": "Extra files whose contents are rendered through the template engine before inclusion. Unlike `extra_files` which copy as-is, template variables like `{{ Tag }}` are expanded. Conditional-skip gate.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/TemplatedExtraFile"
          }
        }
      },
      "additionalProperties": false
    },
    "AppImageConfig": {
      "description": "AppImage packaging configuration.\n\nDrives the [AppImage](https://appimage.org/) stage, which bundles a built Linux binary plus its desktop integration (a `.desktop` entry + icon) into a single self-contained, runnable `.AppImage` file via [`linuxdeploy`](https://github.com/linuxdeploy/linuxdeploy)'s `appimage` output plugin. One `.AppImage` is produced per matching Linux target so a multi-arch build yields distinct, non-colliding outputs.\n\nYAML: ```yaml appimages: - id: helix ids: [helix-bin] desktop: contrib/Helix.desktop icon: contrib/helix.png appdir_extra: - src: runtime/ dst: usr/lib/helix/runtime update_information: \"gh-releases-zsync|helix-editor|helix|latest|helix-*.AppImage.zsync\" runtime_harvest: command: \"{{ ArtifactPath }} --populate-runtime {{ HarvestDir }}\" dir: runtime/ ```",
      "type": "object",
      "properties": {
        "appdir_extra": {
          "description": "Extra files / directories copied into the AppDir before linuxdeploy runs (e.g. a harvested `runtime/` tree). Each entry's `dst` is interpreted relative to the AppDir root.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/AppImageExtra"
          }
        },
        "arch": {
          "description": "Target architecture filter. When omitted, every architecture in the build matrix produces its own `.AppImage`.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "desktop": {
          "description": "Path to the `.desktop` entry file (template). Required — linuxdeploy will not assemble an AppImage without a desktop file.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "extra_args": {
          "description": "Extra arguments appended to the linuxdeploy command line.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "filename": {
          "description": "Output filename template (default includes project, version, os, arch). The `.AppImage` extension is appended automatically when absent.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "icon": {
          "description": "Path to the application icon (template). Required.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "id": {
          "description": "Unique identifier for this AppImage config (default: \"default\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs filter: only bundle binaries whose `id` is in this list. When omitted, every Linux binary in the build matrix is eligible.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "name": {
          "description": "Application name passed to linuxdeploy via the `APP` env var and used as the AppDir basename. Defaults to the project name.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "os": {
          "description": "Target OS filter (default: [\"linux\"]). AppImage is a Linux-only format.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "runtime_harvest": {
          "description": "Runtime-asset harvest hook: run the freshly-built binary ONCE on the host to populate a directory, then bundle that directory into the AppDir. The harvested data is architecture-independent (grammars, themes, queries), so it is produced once on the host-native binary and reused for every target's AppImage.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/RuntimeHarvest"
            },
            {
              "type": "null"
            }
          ]
        },
        "skip": {
          "description": "Skip this config. Accepts bool or template string.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "update_information": {
          "description": "zsync delta-update metadata embedded in the AppImage, passed to linuxdeploy via the `UPDATE_INFORMATION` env var. When omitted, the AppImage carries no update information and `UPDATE_INFORMATION` is left unset (matching linuxdeploy's default).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "AppImageExtra": {
      "description": "A file or directory copied into the AppDir before linuxdeploy assembles the AppImage. Mirrors [`MakeselfFile`]'s `src` / `dst` shape.",
      "type": "object",
      "properties": {
        "dst": {
          "description": "Destination path inside the AppDir (relative to the AppDir root, e.g. `usr/lib/helix/runtime`).",
          "default": "",
          "type": "string"
        },
        "src": {
          "description": "Source path (file or directory, relative to project root). A trailing `/` is not required; directories are copied recursively.",
          "default": "",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "ArchiveConfig": {
      "type": "object",
      "properties": {
        "allow_different_binary_count": {
          "description": "Allow different binary counts across targets. Default false (warn on mismatch).",
          "type": [
            "boolean",
            "null"
          ]
        },
        "binaries": {
          "description": "Binary names to include (defaults to all binaries from matched builds).",
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "builds_info": {
          "description": "File permissions applied to binaries in archives.",
          "anyOf": [
            {
              "$ref": "#/definitions/FileInfo"
            },
            {
              "type": "null"
            }
          ]
        },
        "completions": {
          "description": "Turnkey shell-completion generation: auto-generate (or harvest, or copy) completion files and bundle them into every archive produced by this entry. See [`CompletionsConfig`] for the three generation modes.",
          "anyOf": [
            {
              "$ref": "#/definitions/CompletionsConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "files": {
          "description": "Extra files to include in the archive (glob patterns or detailed src/dst specs).",
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/ArchiveFileSpec"
          }
        },
        "format_overrides": {
          "description": "Per-OS format overrides for this archive config.",
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/FormatOverride"
          }
        },
        "formats": {
          "description": "Archive formats: tar.gz, tar.xz, tar.zst, tar, zip, gz, xz, or binary. `gz` and `xz` are single-file compressors — supplying multiple input files errors. Plural list; one archive per format is produced for each target.",
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "hooks": {
          "description": "Pre/post archive hooks (`before`/`after`).",
          "anyOf": [
            {
              "$ref": "#/definitions/ArchiveHooksConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "id": {
          "description": "Unique identifier for cross-referencing this archive from other configs. Defaults to `\"default\"` so a parse->serialise->reparse round-trip is stable (stored verbatim, not as an Option).",
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs filter: only include artifacts from builds whose `id` is in this list.",
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional gate: when the rendered result is falsy (`\"false\"` / `\"0\"` / `\"no\"` / empty), the archive entry is skipped entirely (no archives produced for this `id`). Render failure hard-errors. \"Filter artifacts with `if` statements\" is listed as a blanket promise — anodizer surfaces it explicitly to keep imported configs portable).",
          "type": [
            "string",
            "null"
          ]
        },
        "manpages": {
          "description": "Turnkey man-page generation: auto-generate (or harvest, or copy) man pages and bundle them into every archive produced by this entry. See [`ManpagesConfig`] for the three generation modes.",
          "anyOf": [
            {
              "$ref": "#/definitions/ManpagesConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "meta": {
          "description": "When true, create archive with no binaries (metadata-only).",
          "type": [
            "boolean",
            "null"
          ]
        },
        "name_template": {
          "description": "Archive filename template (supports templates, e.g., \"{{ ProjectName }}_{{ Version }}_{{ Os }}_{{ Arch }}\").",
          "type": [
            "string",
            "null"
          ]
        },
        "strip_binary_directory": {
          "description": "Strip binary parent directory in archive (place binaries at archive root).",
          "type": [
            "boolean",
            "null"
          ]
        },
        "templated_files": {
          "description": "Templated files scoped to this archive entry. Rendered per-archive (so each entry's `dst:` and contents see `.Os`, `.Arch`, `.Target`, `.Format`, etc.) and packed into the archive at the rendered `dst:` path. The `archives[].templated_files:` field.",
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/TemplateFileConfig"
          }
        },
        "wrap_in_directory": {
          "description": "When set, wrap archive contents in a top-level directory. Accepts `true` (use archive stem as directory name), `false` (no wrapping), or a string template for a custom directory name.",
          "anyOf": [
            {
              "$ref": "#/definitions/WrapInDirectory"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "ArchiveFileSpec": {
      "description": "Specifies a file to include in archives. Can be a simple glob string or a detailed object with src/dst/info fields for controlling archive placement and file metadata.\n\nNOTE: This is intentionally a separate type from [`ExtraFileSpec`] (used for checksum/release extra_files). `ArchiveFileSpec` needs `src`/`dst`/`info` fields for archive placement and file metadata (owner, group, mode, mtime), while `ExtraFileSpec` needs `glob`/`name_template` for checksumming and upload renaming. The fields and semantics are different enough that a unified type would be confusing.",
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "object",
          "required": [
            "src"
          ],
          "properties": {
            "dst": {
              "type": [
                "string",
                "null"
              ]
            },
            "info": {
              "anyOf": [
                {
                  "$ref": "#/definitions/FileInfo"
                },
                {
                  "type": "null"
                }
              ]
            },
            "src": {
              "type": "string"
            },
            "strip_parent": {
              "description": "When true, strip the parent directory from the file path in the archive.",
              "type": [
                "boolean",
                "null"
              ]
            }
          }
        }
      ]
    },
    "ArchiveHooksConfig": {
      "description": "Pre/post archive hook configuration.\n\nArchive hooks use `before`/`after`; build hooks use `pre`/`post`.",
      "type": "object",
      "properties": {
        "after": {
          "description": "Commands to run after the archive step.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/HookEntry"
          }
        },
        "before": {
          "description": "Commands to run before the archive step.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/HookEntry"
          }
        }
      },
      "additionalProperties": false
    },
    "ArtifactoryConfig": {
      "description": "Artifactory upload configuration. Uploads artifacts to JFrog Artifactory repositories.",
      "type": "object",
      "properties": {
        "checksum": {
          "description": "Include checksums in uploaded artifacts.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "checksum_header": {
          "description": "Header name used for checksum verification (e.g. `X-Checksum-Sha256`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "client_x509_cert": {
          "description": "Path to client X.509 certificate for mTLS authentication.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "client_x509_key": {
          "description": "Path to client X.509 private key for mTLS authentication.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "custom_artifact_name": {
          "description": "Use custom artifact naming instead of default.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "custom_headers": {
          "description": "Custom HTTP headers sent with each upload request.",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {
            "type": "string"
          }
        },
        "extra_files": {
          "description": "Extra files to upload alongside build artifacts.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/ExtraFileSpec"
          }
        },
        "extra_files_only": {
          "description": "When true, upload only extra_files (skip normal artifacts).",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "exts": {
          "description": "File extension filter: only upload artifacts matching these extensions.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "ids": {
          "description": "Build IDs filter: only upload artifacts from builds whose `id` is in this list.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional gate: when the rendered result is falsy (`\"false\"` / `\"0\"` / `\"no\"` / empty), the artifactory publisher is skipped. Render failure hard-errors. The `artifactories[].if:`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "meta": {
          "description": "Include metadata artifacts in uploaded artifacts.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "method": {
          "description": "HTTP method to use for uploads (default: \"PUT\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "mode": {
          "description": "Upload mode: \"archive\" (upload archives) or \"binary\" (upload binaries).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "name": {
          "description": "Human-readable name for this publisher (used in logs).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "overwrite": {
          "description": "Re-upload an artifact even when an identical one already exists at the target path (default: `false`).\n\nWith the default, a re-run that finds the same version's artifact already uploaded with a matching SHA-256 records an idempotent SKIP rather than re-PUTting it — so re-running a partially-failed release is safe. A path that already holds a *different* artifact for the same version still hard-errors (immutable-version drift) unless `overwrite` is set. With `overwrite: true`, every artifact is PUT unconditionally (Artifactory replaces the stored copy), restoring blind-overwrite behaviour for repos configured to allow it.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "password": {
          "description": "Artifactory password or API key (or env var reference).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "required": {
          "description": "Override whether this publisher failing should fail the overall release.\n\nDefault: `false` — a failure here is logged but does not abort the release. Set to `true` to fail the release on any error.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "retain_on_rollback": {
          "description": "When `true`, a triggered rollback leaves this publisher's work in place rather than attempting to undo it. Default `false`.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "signature": {
          "description": "Include signatures in uploaded artifacts.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "skip": {
          "description": "Template-conditional skip: if rendered result is `\"true\"`, skip this publisher.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "target": {
          "description": "Target URL template for uploads (supports template variables).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "trusted_certificates": {
          "description": "PEM-encoded trusted CA certificates for TLS verification. Appended to the system certificate pool.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "username": {
          "description": "Artifactory username for authentication.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "AttestationArtifactKind": {
      "description": "A selectable artifact KIND for attestation. Each variant maps to one or more concrete [`crate::artifact::ArtifactKind`] values at subject-collection time; together the variants cover the full release-uploadable surface so any artifact that lands on the release can be attested.",
      "oneOf": [
        {
          "description": "Packaged archives (`.tar.gz`, `.zip`, ...) and self-extracting archives.",
          "type": "string",
          "enum": [
            "archive"
          ]
        },
        {
          "description": "Raw uploadable binaries (uploaded as bare release assets).",
          "type": "string",
          "enum": [
            "binary"
          ]
        },
        {
          "description": "Checksum file(s) (`checksums.txt` and split sidecars).",
          "type": "string",
          "enum": [
            "checksum"
          ]
        },
        {
          "description": "Linux packages (`.deb` / `.rpm` / `.apk`) and source RPMs.",
          "type": "string",
          "enum": [
            "package"
          ]
        },
        {
          "description": "Source archives (`source:` tarball).",
          "type": "string",
          "enum": [
            "source"
          ]
        },
        {
          "description": "Generated SBOM documents.",
          "type": "string",
          "enum": [
            "sbom"
          ]
        },
        {
          "description": "OS installers: Windows MSI/NSIS, macOS DMG (disk image), and macOS PKG.",
          "type": "string",
          "enum": [
            "installer"
          ]
        }
      ]
    },
    "AttestationConfig": {
      "description": "SLSA build-provenance / attestation configuration for binaries and archives.\n\nTwo modes select how anodizer participates in attestation:\n\n- [`AttestationMode::Subjects`] (the default) emits a **subjects manifest** (`dist/attestation-subjects.json`) that `anodizer-action` feeds to GitHub's `actions/attest-build-provenance`. anodizer does NOT mint a GitHub-trusted attestation itself in this mode — the Action's OIDC identity does. This is the path fd / biome / gping use. - [`AttestationMode::Emit`] generates a self-contained in-toto v1 statement carrying an SLSA provenance v1 predicate over the selected artifacts, writes it as a release asset (`attestation.intoto.jsonl`), and lets the existing `signs:` stage sign it (keyed, not OIDC). This is for users who can't run the Action (the `--with-provenance` toggle).\n\nYAML: ```yaml attestations: enabled: true mode: subjects          # or: emit ; default = subjects artifacts: [archive, binary, checksum] ```",
      "type": "object",
      "properties": {
        "artifacts": {
          "description": "Which produced-artifact kinds to attest. Each entry selects a KIND (`archive`, `binary`, `checksum`); the concrete subject set (filenames + sha256) is DERIVED from the artifacts anodizer already produced.\n\nDefaults to `[archive, binary, checksum]` when omitted.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/AttestationArtifactKind"
          }
        },
        "enabled": {
          "description": "Enable attestation. When false (the default), the stage is a no-op.",
          "default": false,
          "type": "boolean"
        },
        "mode": {
          "description": "Participation mode: `subjects` (default) writes a manifest for `actions/attest-build-provenance`; `emit` generates and signs an in-toto SLSA provenance statement as a release asset.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/AttestationMode"
            },
            {
              "type": "null"
            }
          ]
        },
        "skip": {
          "description": "Skip the attestation stage. Accepts a bool or a template string.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "AttestationMode": {
      "description": "Attestation participation mode. See [`AttestationConfig`].",
      "oneOf": [
        {
          "description": "Emit a subjects manifest for `actions/attest-build-provenance` (OIDC).",
          "type": "string",
          "enum": [
            "subjects"
          ]
        },
        {
          "description": "Generate + sign a self-contained in-toto SLSA provenance statement.",
          "type": "string",
          "enum": [
            "emit"
          ]
        }
      ]
    },
    "AurConfig": {
      "type": "object",
      "properties": {
        "amd64_variant": {
          "description": "amd64 microarchitecture variant filter (e.g. \"v1\", \"v2\", \"v3\", \"v4\"). Only artifacts matching this variant are included. Default: \"v1\".",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "backup": {
          "description": "List of config files to preserve on upgrade (relative to `/`).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "commit_author": {
          "description": "Commit author with optional signing.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/CommitAuthorConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "commit_msg_template": {
          "description": "Custom commit message template. Default: \"Update to {{ version }}\".",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "conflicts": {
          "description": "Packages this PKGBUILD conflicts with.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "contributors": {
          "description": "Contributors listed in PKGBUILD comments.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "depends": {
          "description": "Runtime dependencies required by this package.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "description": {
          "description": "Short description of the package for PKGBUILD.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "directory": {
          "description": "Subdirectory in the git repo for committed files.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "git_ssh_command": {
          "description": "Custom SSH command for git operations.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "git_url": {
          "description": "AUR SSH git URL override. Defaults to `ssh://aur@aur.archlinux.org/<package>.git`, derived from the resolved package name; set this only for a non-standard endpoint.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "homepage": {
          "description": "Project homepage URL.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs filter: only include artifacts whose `id` is in this list.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional gate: when the rendered result is falsy (`\"false\"` / `\"0\"` / `\"no\"` / empty), the AUR publisher is skipped. Render failure hard-errors. The `aurs[].if:` conditional gate.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "install": {
          "description": "Content for a .install file (post-install/pre-remove scripts).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "license": {
          "description": "SPDX license identifier (e.g., \"MIT\", \"Apache-2.0\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "maintainers": {
          "description": "PKGBUILD maintainer entries (e.g., \"Name <email@example.com>\").",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "name": {
          "description": "Override the package name (default: crate name + \"-bin\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "optdepends": {
          "description": "Optional dependencies with descriptions (e.g., \"fzf: fuzzy finder support\").",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "package": {
          "description": "Custom PKGBUILD `package()` function body.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "private_key": {
          "description": "Path to SSH private key file.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "provides": {
          "description": "Packages this PKGBUILD provides (virtual package names).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "rel": {
          "description": "Package release number (default: \"1\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "replaces": {
          "description": "Packages this PKGBUILD replaces (for upgrade paths from old package names).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "required": {
          "description": "Override whether this publisher failing should fail the overall release.\n\nDefault: `false` — a failure here is logged but does not abort the release. Set to `true` to fail the release on any error.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "retain_on_rollback": {
          "description": "When `true`, a triggered rollback leaves this publisher's work in place rather than attempting to undo it. Default `false`.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "skip": {
          "description": "Skip this AUR config. Accepts bool or template string (e.g. `\"{{ if .IsSnapshot }}true{{ endif }}\"` for conditional skip). Accepts the legacy `disable:` spelling via serde alias for back-compat.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "skip_upload": {
          "description": "Skip publishing. `\"true\"` always skips; `\"auto\"` skips for prereleases. Accepts bool or template string.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "url_template": {
          "description": "Custom URL template for download URLs (overrides release URL).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "AurSourceConfig": {
      "type": "object",
      "properties": {
        "amd64_variant": {
          "description": "`x86_64` micro-architecture variant — `v1` (baseline), `v2`, `v3` (AVX2), or `v4`. Constrained to a typed enum because AUR source pkgs build from the upstream tarball (no binary artifacts to filter), so the value's only role is as the `Amd64` template var consumed by `prepare:` / `build:` / `package:` script bodies — typos must fail at parse time, not silently render an invalid string into the PKGBUILD. When unset, defaults to `v1` at template-render time.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/Amd64Variant"
            },
            {
              "type": "null"
            }
          ]
        },
        "arches": {
          "description": "Explicit architecture list (default: auto-detect from artifacts).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "backup": {
          "description": "Backup files to preserve on upgrade.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "build": {
          "description": "Custom `build()` function body for PKGBUILD.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "commit_author": {
          "description": "Commit author with optional signing.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/CommitAuthorConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "commit_msg_template": {
          "description": "Custom commit message template.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "conflicts": {
          "description": "Packages this PKGBUILD conflicts with.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "contributors": {
          "description": "Contributors listed in PKGBUILD comments.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "depends": {
          "description": "Runtime dependencies.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "description": {
          "description": "Short description of the package.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "directory": {
          "description": "Subdirectory in the git repo for committed files.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "git_ssh_command": {
          "description": "Custom SSH command for git operations.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "git_url": {
          "description": "AUR SSH git URL override. Defaults to `ssh://aur@aur.archlinux.org/<package>.git`, derived from the resolved package name; set this only for a non-standard endpoint.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "homepage": {
          "description": "Project homepage URL.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs filter.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional gate: when the rendered result is falsy (`\"false\"` / `\"0\"` / `\"no\"` / empty), the AUR source config is skipped. Render failure hard-errors. The `aur_sources[].if:`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "install": {
          "description": "Content for a .install file (post-install/pre-remove scripts).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "license": {
          "description": "SPDX license identifier.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "maintainers": {
          "description": "PKGBUILD maintainer entries.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "makedepends": {
          "description": "Build-time dependencies (source packages need these).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "name": {
          "description": "Override the package name (default: crate name, no -bin suffix).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "optdepends": {
          "description": "Optional dependencies.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "package": {
          "description": "Custom `package()` function body for PKGBUILD.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "prepare": {
          "description": "Custom `prepare()` function body for PKGBUILD.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "private_key": {
          "description": "Path to SSH private key file.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "provides": {
          "description": "Packages this PKGBUILD provides.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "rel": {
          "description": "Package release number (default: \"1\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "required": {
          "description": "Override whether this publisher failing should fail the overall release.\n\nDefault: `false` — a failure here is logged but does not abort the release. Set to `true` to fail the release on any error.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "retain_on_rollback": {
          "description": "When `true`, a triggered rollback leaves this publisher's work in place rather than attempting to undo it. Default `false`.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "skip": {
          "description": "Skip this config. Accepts the legacy `disable:` spelling via serde alias for back-compat.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "skip_upload": {
          "description": "Skip publishing. `\"true\"` always skips; `\"auto\"` skips for prereleases.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "url_template": {
          "description": "Custom URL template for download URLs.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "BeforePublishArtifactFilter": {
      "description": "Artifact-type filter for `before_publish[*].artifacts`.\n\nThe `before_publish[*].artifacts` enum (`checksum` / `source` / `package` / `installer` / `diskimage` / `archive` / `binary` / `sbom` / `image` / `all`). Maps each variant to a predicate over [`ArtifactKind`]:\n\n| Variant | Matched [`ArtifactKind`] values | |---|---| | `Checksum` | `Checksum` | | `Source` | `SourceArchive`, `SourcePkgBuild`, `SourceSrcInfo`, `SourceRpm` | | `Package` | `LinuxPackage`, `Snap`, `PublishableSnapcraft`, `Flatpak` | | `Installer` | `Installer`, `MacOsPackage` | | `DiskImage` | `DiskImage` | | `Archive` | `Archive`, `Makeself` | | `Binary` | `Binary`, `UploadableBinary`, `UniversalBinary` | | `Sbom` | `Sbom` | | `Image` | `DockerImage`, `DockerImageV2`, `PublishableDockerImage` (multi-arch `DockerManifest` excluded — covers individual images only) | | `All` | every kind |\n\nMapping notes: - `Source` includes RPM-source variants since all source-derived artifacts under one bucket. - `Installer` covers macOS `.pkg` (`MacOsPackage`) alongside Windows MSI/NSIS — \"installer\" is used without OS qualification. - `Image` deliberately excludes [`ArtifactKind::DockerManifest`] / [`ArtifactKind::DockerDigest`]; those are multi-arch index entries and don't correspond to a scannable image blob. The per-image hook semantics (the multi-arch manifest is published separately and isn't a vulnerability scan target).",
      "type": "string",
      "enum": [
        "checksum",
        "source",
        "package",
        "installer",
        "disk_image",
        "archive",
        "binary",
        "sbom",
        "image",
        "all"
      ]
    },
    "BinstallConfig": {
      "type": "object",
      "properties": {
        "bin_dir": {
          "description": "Directory within the archive where binaries are located.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "enabled": {
          "description": "When true, write `[package.metadata.binstall]` into the crate's Cargo.toml so `cargo binstall` can install prebuilt release archives.\n\n# Auto-derivation\n\nWith `enabled: true` and **no** `pkg_url` and **no** `overrides`, anodize fills in correct per-target metadata automatically: for every configured build target it emits an `overrides.<rust-triple>` whose `pkg_url` is the GitHub release download URL for that target's archive, with the asset name rendered through the *same* `archive.name_template` the archive stage uses (so the URL can never drift from the asset the release uploads) and the version positions expressed as cargo-binstall's own `{ version }` token. The matching `pkg_fmt` (`tar.gz`→`tgz`, `zip`→`zip`, …) is set per target.\n\n```yaml binstall: enabled: true   # nothing else required ```",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "overrides": {
          "description": "Per-target overrides keyed by Rust target triple (e.g. `x86_64-unknown-linux-gnu`). Each entry overrides `pkg_url`/`pkg_fmt`/`bin_dir` for the matching triple, emitted as a `[package.metadata.binstall.overrides.<triple>]` sub-table.\n\nYou rarely need to set this by hand: with `enabled: true` and no `pkg_url`/`overrides`, anodize auto-derives a correct per-target override for every build target (see [`enabled`](Self::enabled)). Supplying any override here (like supplying [`pkg_url`](Self::pkg_url)) **disables auto-derivation** and takes full manual control of the table.",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {
            "$ref": "#/definitions/BinstallOverride"
          }
        },
        "pkg_fmt": {
          "description": "Package format hint for cargo-binstall: tgz, tar.gz, tar.xz, zip, bin, etc.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "pkg_url": {
          "description": "Custom download URL template for cargo-binstall (supports templates).\n\nSetting this (or any [`overrides`](Self::overrides) entry) **disables auto-derivation** — anodize writes your value verbatim and computes nothing. Use it only when the auto-derived per-target URLs don't fit (manual values always win).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "BinstallOverride": {
      "type": "object",
      "properties": {
        "bin_dir": {
          "description": "Directory within the archive where binaries are located for this target triple.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "pkg_fmt": {
          "description": "Package format hint for this target triple: tgz, tar.gz, tar.xz, zip, bin, etc.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "pkg_url": {
          "description": "Custom download URL template for this target triple (supports templates). Lets you point cargo-binstall at a per-target asset name such as `myapp-{{ Version }}-linux-amd64.tar.gz`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "BlobConfig": {
      "type": "object",
      "properties": {
        "acl": {
          "description": "Canned ACL for uploaded objects. **S3**: one of `private` (default), `public-read`, `public-read-write`, `authenticated-read`, `aws-exec-read`, `bucket-owner-read`, `bucket-owner-full-control`. The accepted ACL set; AWS's `log-delivery-write` is intentionally omitted because it is only valid on `S3LogBucket` targets and would silently fail on a normal bucket. **GCS**: pass the camelCase predefined-ACL name (e.g. `publicRead`, `bucketOwnerFullControl`); not validated up-front, so a typo surfaces as a 400 from the GCS API at upload time.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "bucket": {
          "description": "Bucket or container name (supports templates).",
          "default": "",
          "type": "string"
        },
        "cache_control": {
          "description": "HTTP Cache-Control header values, joined with \", \" when uploading. Accepts a string (single value) or array of strings in YAML.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "content_disposition": {
          "description": "HTTP Content-Disposition header (supports templates). Default: `\"attachment;filename={{Filename}}\"`. Set to `\"-\"` to disable.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "directory": {
          "description": "Directory/folder within the bucket (supports templates). Default: `{{ ProjectName }}/{{ Tag }}`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "disable_ssl": {
          "description": "Disable SSL for the connection (S3 only, default: false).",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "endpoint": {
          "description": "Custom endpoint URL for S3-compatible storage (e.g. MinIO, R2, DO Spaces).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "extra_files": {
          "description": "Pre-existing files to upload (supports glob patterns).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/ExtraFileSpec"
          }
        },
        "extra_files_only": {
          "description": "Upload only extra files (skip artifacts).",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "id": {
          "description": "Unique identifier for this blob config.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs to include. Empty means all artifacts.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional gate: when the rendered result is falsy (`\"false\"` / `\"0\"` / `\"no\"` / empty), the blob config is skipped. Render failure hard-errors. The `blobs[].if:` conditional gate.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "include_meta": {
          "description": "Also upload metadata.json and artifacts.json.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "kms_key": {
          "description": "AWS KMS encryption key for server-side encryption (S3 only).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "parallelism": {
          "description": "Maximum number of parallel uploads for this blob config. Overrides the global `--parallelism` setting when set.",
          "default": null,
          "type": [
            "integer",
            "null"
          ],
          "format": "uint",
          "minimum": 0.0
        },
        "provider": {
          "description": "Cloud storage provider: s3, gcs (or gs), or azblob (or azure).",
          "default": "",
          "type": "string"
        },
        "region": {
          "description": "AWS region (S3 only).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "required": {
          "description": "When `true`, a failed blob upload counts as a required-publisher failure: trips the submitter gate (chocolatey/winget/snapcraft/aur don't run if blob failed) and surfaces in `report.required_failures()` so the CLI exits non-zero.\n\nDefault: `false`. Snapshot release pipelines typically don't require blobs; production pipelines that ship binaries via S3/GCS often do.\n\nWhen multiple blob configs exist, the blob stage records ONE aggregated `PublisherResult`: `required = true` if ANY config opted in. Same semantics as \"any required blob target failing should fail the release.\"",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "retain_on_rollback": {
          "description": "When `true`, a triggered rollback leaves this publisher's work in place rather than attempting to undo it. Default `false`.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "s3_force_path_style": {
          "description": "Enable path-style addressing for S3-compatible backends. Defaults to `true` when `endpoint` is set (MinIO, R2, DO Spaces need this), `false` otherwise (standard AWS virtual-hosted style).",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "skip": {
          "description": "Skip this blob config. Accepts bool or template string (e.g. `\"{{ if IsSnapshot }}true{{ endif }}\"` for conditional skip). Accepts the legacy `disable:` spelling via serde alias for back-compat.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "templated_extra_files": {
          "description": "Extra files whose contents are rendered through the template engine before upload. Unlike `extra_files` which copy as-is, template variables like `{{ Tag }}` are expanded.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/TemplatedExtraFile"
          }
        }
      },
      "additionalProperties": false
    },
    "BlueskyAnnounce": {
      "type": "object",
      "properties": {
        "enabled": {
          "description": "Enable Bluesky announcements (supports template expressions).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "message_template": {
          "description": "Message template for the post. Default: \"{{ ProjectName }} {{ Tag }} is out! Check it out at {{ ReleaseURL }}\"",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "pds_url": {
          "description": "Override the Bluesky PDS (Personal Data Server) URL. Defaults to `https://bsky.social`. Set this to point at a self-hosted PDS or alternative instance (e.g. `https://pds.example.com`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "username": {
          "description": "Bluesky handle/username (e.g. \"user.bsky.social\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "BuildConfig": {
      "type": "object",
      "properties": {
        "binary": {
          "description": "Binary name to build (must match a Cargo binary target in the crate).\n\nOptional so that `defaults.builds` (a path-mirrored template that applies to every crate) can omit `binary` — the per-crate `builds[]` entry supplies it. When the binary is absent at the per-crate level it falls back to the crate's `name` field.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "builder": {
          "description": "Builder to use for this entry. `cargo` (the default when omitted) runs `cargo build`. `prebuilt` skips compilation and imports a binary the operator already produced via the `prebuilt:` block.\n\nWhen `builder: prebuilt`, `targets:` MUST be set explicitly — no `defaults.targets` fallback — and the `prebuilt.path` template is rendered per target then stat()-ed before the import.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/BuilderKind"
            },
            {
              "type": "null"
            }
          ]
        },
        "command": {
          "description": "Override the cargo subcommand (default: auto-detected \"build\" or \"zigbuild\"). Enables e.g. `cargo auditable build` by setting `command: \"auditable build\"`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "copy_from": {
          "description": "Copy the binary from another build ID instead of building it.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "cross_tool": {
          "description": "Override the cross-compilation tool binary path (e.g., a custom `cross` wrapper). When set, this binary is used instead of cargo/cross/zigbuild.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "env": {
          "description": "Per-target environment variables keyed as {target: {KEY: VALUE}}.",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          }
        },
        "features": {
          "description": "Cargo features to enable for this build.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "flags": {
          "description": "Extra flags passed to cargo build, one per list entry (e.g., `[\"--release\", \"--locked\"]`).\n\nEach entry is template-rendered then passed verbatim as a single argv token — there is no `sh -c` step and no shell tokenization, so a rendered value containing spaces stays one argv entry (it is NOT re-split). Use one list entry per flag, including the flag and its value as separate entries (`[\"--target-dir\", \"/tmp/{{ Version }}\"]`) when the value itself may contain spaces.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "gobinary": {
          "description": "Accepted-but-ignored legacy key. anodizer always drives the cargo toolchain (or `cross` / `zigbuild`) directly, so there is no pluggable build binary to point at. The field is parsed only so that configs imported from a Go-style tool keep loading instead of hard-failing under `deny_unknown_fields`; its value is never read. Use `command:` to override the cargo subcommand instead.",
          "writeOnly": true,
          "type": [
            "string",
            "null"
          ]
        },
        "hooks": {
          "description": "Per-build hooks executed before and after compilation.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/BuildHooksConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "id": {
          "description": "Unique identifier for this build, used to reference it from archives and other configs.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ignore": {
          "description": "Exclude specific os/arch combinations from this build's target matrix. Falls back to `defaults.builds.ignore` when not set.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/BuildIgnore"
          }
        },
        "mod_timestamp": {
          "description": "Override the modification timestamp of built binaries for reproducible builds. Template string (e.g. `\"{{ CommitTimestamp }}\"`) or unix timestamp.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "no_default_features": {
          "description": "When true, pass --no-default-features to cargo build.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "no_unique_dist_dir": {
          "description": "When true (or template evaluating to \"true\"), place binaries in flat dist/ instead of dist/{target}/. Overrides the crate-level setting.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "overrides": {
          "description": "Per-target overrides for env, flags, and features for this build. Falls back to `defaults.builds.overrides` when not set.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/BuildOverride"
          }
        },
        "prebuilt": {
          "description": "Options for the `prebuilt` builder. Required when `builder: prebuilt`; ignored (with a config-load warning) otherwise.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/PrebuiltConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "reproducible": {
          "description": "When true, enable reproducible builds by stripping timestamps.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "skip": {
          "description": "When true (or template evaluating to \"true\"), skip this build entirely.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "targets": {
          "description": "Target triples to build for. When set, REPLACES `defaults.targets` for this build (override semantics — the per-build value wins outright, no concat). When `None`, this build inherits `defaults.targets` verbatim. Both `cli::commands::helpers:: collect_build_targets` and `stage-build` enforce this rule.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        }
      },
      "additionalProperties": false
    },
    "BuildHooksConfig": {
      "description": "Pre/post hook configuration shared across multiple stages. Despite the `Build` prefix in the name, this type is used by both the **build** stage (pre/post compilation hooks) and the **archive** stage (pre/post archiving hooks). The name is kept for backward compatibility with existing configs. **Not** to be confused with the top-level `HooksConfig` (which carries a flat `hooks: Vec<String>` list for `before`/`after` lifecycle hooks).",
      "type": "object",
      "properties": {
        "post": {
          "description": "Commands to run after the build step.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/HookEntry"
          }
        },
        "pre": {
          "description": "Commands to run before the build step.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/HookEntry"
          }
        }
      },
      "additionalProperties": false
    },
    "BuildIgnore": {
      "description": "Exclude a specific os/arch combination from the build matrix.",
      "type": "object",
      "required": [
        "arch",
        "os"
      ],
      "properties": {
        "arch": {
          "description": "Architecture to exclude (e.g., \"amd64\", \"arm64\", \"386\").",
          "type": "string"
        },
        "os": {
          "description": "Operating system to exclude (e.g., \"linux\", \"darwin\", \"windows\").",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "BuildOverride": {
      "description": "Override env, flags, or features for targets matching glob patterns.",
      "type": "object",
      "properties": {
        "env": {
          "description": "Extra environment variables to set for matching targets.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "features": {
          "description": "Extra features to enable for matching targets.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "flags": {
          "description": "Extra flags to append for matching targets, one per list entry.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "targets": {
          "description": "Glob patterns to match against target triples (e.g., `[\"x86_64-*\", \"*-linux-*\"]`).",
          "default": [],
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "additionalProperties": false
    },
    "BuilderKind": {
      "description": "Selects which builder a `builds[]` entry uses. `Cargo` (the default) runs `cargo build` and discovers the resulting binary under `target/<triple>/<profile>/`. `Prebuilt` skips compilation entirely and imports a binary the operator already placed on disk via the per-build `prebuilt:` block.",
      "oneOf": [
        {
          "description": "Build the binary by invoking `cargo build` (or `cross` / `zigbuild` per the `cross:` strategy). Default when no `builder:` is set.",
          "type": "string",
          "enum": [
            "cargo"
          ]
        },
        {
          "description": "Import a binary already staged on disk instead of compiling. Pairs with the `prebuilt:` block on the same build entry.",
          "type": "string",
          "enum": [
            "prebuilt"
          ]
        }
      ]
    },
    "CargoPublishConfig": {
      "description": "`cargo publish` flag surface.\n\nPresence under `publish:` opts the crate in; use `skip: true` (or a truthy template) to opt out. There is no `enabled` field — presence is the on-switch.\n\nFields intentionally omitted because anodizer owns them: - `--package` / `--workspace` / `--exclude`: the top-level `crates[]` axis owns crate selection. - `--dry-run`: pipeline-level CLI ergonomics (`anodizer release --dry-run`). - `-v` / `-q` / `--color`: CLI ergonomics, not config. - `--config` / `-Z`: cargo CLI escape hatches; out of scope.",
      "type": "object",
      "properties": {
        "all_features": {
          "description": "Activate every feature, including `default` (`--all-features`).",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "allow_dirty": {
          "description": "Allow publishing with an uncommitted working tree (`--allow-dirty`).",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "features": {
          "description": "Crate features to activate (`--features`).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "frozen": {
          "description": "Both `--locked` and `--offline` (`--frozen`).",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "if": {
          "description": "Template-conditional gate: when the rendered result is falsy (`\"false\"` / `\"0\"` / `\"no\"` / empty), the cargo publisher is skipped. Render failure hard-errors. Config key: the publisher's `if:`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "index": {
          "description": "Registry index URL (`--index`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "index_timeout": {
          "description": "Seconds to wait for the crates.io sparse index to publish a crate before its dependents are pushed (anodizer-original — no `cargo publish` equivalent).",
          "default": null,
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0.0
        },
        "jobs": {
          "description": "Number of parallel compile jobs for verification (`--jobs`).",
          "default": null,
          "type": [
            "integer",
            "null"
          ],
          "format": "uint32",
          "minimum": 0.0
        },
        "keep_going": {
          "description": "Continue on errors when verifying multiple crates (`--keep-going`).",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "locked": {
          "description": "Require an up-to-date `Cargo.lock` matching the resolver (`--locked`).",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "manifest_path": {
          "description": "Path to the crate's `Cargo.toml` (`--manifest-path`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "no_default_features": {
          "description": "Disable the `default` feature set (`--no-default-features`).",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "no_verify": {
          "description": "Skip the local `cargo build --release` verification step (`--no-verify`).",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "offline": {
          "description": "Require offline resolution; never hit the network (`--offline`).",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "registry": {
          "description": "Alternate registry name from `~/.cargo/config.toml` (`--registry`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "required": {
          "description": "Override whether this publisher failing should fail the overall release.\n\nDefault: `true` — a failure here aborts the release. Set to `false` to log failures but continue.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "retain_on_rollback": {
          "description": "When `true`, a triggered rollback leaves this publisher's work in place rather than attempting to undo it. Default `false`.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "skip": {
          "description": "Skip this publisher; supports template strings or bool. Truthy renders disable the publisher without removing the block.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "target": {
          "description": "Build target triple for the verification step (`--target`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "target_dir": {
          "description": "Override the cargo target directory (`--target-dir`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "wait_for_workspace_deps": {
          "description": "Pre-publish gate that polls crates.io for every workspace-internal dep of the crate being published, blocking until each is queryable at its expected version. Required for multi-tag-multi-crate workspaces (e.g. cfgd) where per-crate tags fire independent `Release.yml` runs that would otherwise race the sparse-index propagation.\n\nSingle-crate workspaces and lockstep-bumped monorepos (anodizer itself) leave this off — there is no inter-tag race to gate on.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/WaitForWorkspaceDepsConfig"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "ChangelogAiConfig": {
      "description": "AI-powered changelog enhancement configuration.",
      "type": "object",
      "properties": {
        "model": {
          "description": "Model name (e.g. \"claude-sonnet-4-6\", \"gpt-4o-mini\", \"llama3.1\"). Defaults to the provider's default model when unset.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "prompt": {
          "description": "Prompt template for the AI. Can be a string, or use `from_url`/`from_file`. Template variable `{{ ReleaseNotes }}` contains the current changelog.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ChangelogAiPrompt"
            },
            {
              "type": "null"
            }
          ]
        },
        "use": {
          "description": "AI provider to use. Valid: \"anthropic\", \"openai\", \"ollama\". Empty disables the feature.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "ChangelogAiPrompt": {
      "description": "Prompt source for AI changelog: inline string, URL, or file path.",
      "anyOf": [
        {
          "description": "Inline prompt string (supports templates).",
          "type": "string"
        },
        {
          "description": "Structured prompt with from_url/from_file sources.",
          "allOf": [
            {
              "$ref": "#/definitions/ChangelogAiPromptSource"
            }
          ]
        }
      ]
    },
    "ChangelogAiPromptSource": {
      "description": "Structured prompt source: load from URL or file.",
      "type": "object",
      "properties": {
        "from_file": {
          "description": "Load prompt from a local file. Overrides from_url if both set.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ContentFromFile"
            },
            {
              "type": "null"
            }
          ]
        },
        "from_url": {
          "description": "Load prompt from a URL.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ContentFromUrl"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "ChangelogConfig": {
      "type": "object",
      "properties": {
        "abbrev": {
          "description": "Hash abbreviation length. Default: 0 (no truncation, emit the full SHA). Set to -1 to omit the hash entirely; positive values truncate to N chars. Values below `-1` are clamped to `-1` (a `git log --abbrev=N` would otherwise reject `-2`, `-3`, ...).",
          "default": null,
          "type": [
            "integer",
            "null"
          ],
          "format": "int32"
        },
        "ai": {
          "description": "AI-powered changelog enhancement configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ChangelogAiConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "divider": {
          "description": "Divider string inserted between changelog groups (e.g. `\"---\"`). Supports templates.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "files": {
          "description": "Changelog file-layout controls: which `CHANGELOG.md` files a release writes (per-crate vs the aggregate root). Separate from the content-generation keys above (`use`, `format`, `groups`, `filters`, `paths`, `sort`, ...) so file management and content concerns stay orthogonal. See [`ChangelogFilesConfig`].",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ChangelogFilesConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "filters": {
          "description": "Commit message filters to include or exclude from the changelog.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ChangelogFilters"
            },
            {
              "type": "null"
            }
          ]
        },
        "footer": {
          "description": "Text appended to the changelog. Same shape as `header`.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ContentSource"
            },
            {
              "type": "null"
            }
          ]
        },
        "format": {
          "description": "Template for each changelog commit line. Available variables: SHA (full hash), ShortSHA (abbreviated), Message (commit subject), AuthorName, AuthorEmail, Login (per-commit GitHub username, `github` backend only), Logins (per-entry comma-separated list of GitHub usernames for that commit, `github` backend only), AllLogins (comma-separated list of all GitHub usernames across the entire release, `github` backend only).<br><br>Default depends on backend (the full SHA is used):<br>&bull; `git` backend (default): `\"{{ SHA }} {{ Message }}\"`<br>&bull; `github`/`gitlab`/`gitea` backend: `\"{{ SHA }}: {{ Message }} (@Login or AuthorName <AuthorEmail>)\"` — falls back to `AuthorName <AuthorEmail>` when `Login` is empty.<br><br>When `abbrev < 0`, the default reduces to `\"{{ Message }}\"` (no hash prefix).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "groups": {
          "description": "Groups for organizing changelog entries by commit message prefix.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/ChangelogGroup"
          }
        },
        "header": {
          "description": "Text prepended to the changelog. Inline string, `from_file: <path>`, or `from_url: <url>` — symmetric with the release block's header/footer so users can compose headers from a templated file or remote endpoint (the upstream uses a plain string here; anodizer extends to ContentSource for consistency with `release.header`).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ContentSource"
            },
            {
              "type": "null"
            }
          ]
        },
        "paths": {
          "description": "Optional path filter that NARROWS the per-crate scope by intersection — it never replaces it. Each changelog track already scopes to its own commits (a per-crate track to its crate directory; the aggregate to the union of every crate directory plus the workspace manifests). When set, `paths` further restricts that derived scope to commits whose touched files match these globs; it can only ever drop commits, never widen to another track's directory. A `paths` value that is a superset of the derived scope (e.g. `[\"crates/**\", \"Cargo.toml\", \"Cargo.lock\"]` over a workspace) is therefore a no-op — and so is the recommended default of leaving `paths` unset, where scoping is fully derived. The same derived scope and intersect drive all three changelog formats (`keep-a-changelog`, `json`, and `release-notes`), so they cannot drift.\n\nWith `use: git` the intersect is precise (commits are filtered by their touched files). With `use: github` only the first path is used for API queries; with `use: gitlab` / `gitea` path filtering is unsupported, so a narrowing `paths` there is coarse and a warning is emitted. Supports template rendering.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "skip": {
          "description": "Skip changelog generation. Accepts bool or template string (e.g. `\"{{ if IsSnapshot }}true{{ endif }}\"` for conditional skip).\n\nAccepts `disable:` as an alias so imported configs (which use `changelog.disable:`) parse cleanly without a rename. Anodizer's broader convention is `skip:` (mirrors `release.skip_upload`, stage-level `skip:` flags), so the canonical key stays `skip:`.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "snapshot": {
          "description": "When `true`, render the changelog even in snapshot mode. Anodizer matches the default (skip changelog on snapshot) and lets users opt back in here for local preview / draft generation. Wired in `crates/stage-changelog/src/lib.rs::ChangelogStage::run`.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "sort": {
          "description": "Sort order for changelog entries: \"asc\" or \"desc\" (default: \"asc\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "title": {
          "description": "Title heading for the changelog. Default: \"Changelog\". Supports templates.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "use": {
          "description": "Changelog source: `\"git\"` (default), `\"github\"`, or `\"github-native\"`. `\"github\"` fetches commits via the GitHub API, enriching entries with author login information (available as the `{{ Logins }}` per-entry template variable and the `{{ AllLogins }}` release-wide variable). `\"github-native\"` delegates entirely to GitHub's auto-generated notes.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "ChangelogFilesConfig": {
      "description": "Changelog file-layout controls: which `CHANGELOG.md` files a release writes.\n\nNested under `changelog.files` to keep file-management keys distinct from the content-generation keys on [`ChangelogConfig`] (`use`, `format`, `groups`, `filters`, `paths`, `sort`, ...).",
      "type": "object",
      "properties": {
        "per_crate": {
          "description": "When `true`, write a per-crate `crates/<name>/CHANGELOG.md` for each crate instead of (or in addition to) the single root `CHANGELOG.md`. Default: `false`. With `per_crate: true` and no `root:` block, only the per-crate files are produced; add a `root:` block to keep the aggregate root changelog as well.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "root": {
          "description": "Controls the single aggregate root `CHANGELOG.md`. Presence of this block forces the root changelog on even when `per_crate: true`. When omitted, the root changelog is on unless `per_crate: true` turned it off.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/RootChangelogConfig"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "ChangelogFilters": {
      "description": "Regex-based commit filters for the changelog stage.\n\nPatterns are NOT compile-validated at config-load — a malformed regex only surfaces when the changelog stage runs, which on a release pipeline is well past the point of cheap failure. Test patterns locally (`anodizer changelog --check` or any external regex tool) before committing config changes.",
      "type": "object",
      "properties": {
        "exclude": {
          "description": "Regex patterns: commits matching any of these are excluded from the changelog.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "exclude_version_sync_commits": {
          "description": "Exclude anodizer's own version-sync bump commits (`chore(release): bump …`, optionally ` [skip ci]`) from the generated changelog. They are release machinery, not user-facing changes, so this defaults to `true`. Set `false` to keep them. No effect in include mode (`include` already drops anything that does not match a pattern).",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "include": {
          "description": "Regex patterns: only commits matching at least one of these are included.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        }
      },
      "additionalProperties": false
    },
    "ChangelogGroup": {
      "type": "object",
      "properties": {
        "groups": {
          "description": "Nested subgroups within this group. Rendered as sub-sections (e.g. `###`).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/ChangelogGroup"
          }
        },
        "order": {
          "description": "Sort order for this group relative to other groups (lower = first).",
          "default": null,
          "type": [
            "integer",
            "null"
          ],
          "format": "int32"
        },
        "regexp": {
          "description": "Regex pattern matching commit messages to include in this group.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "title": {
          "description": "Section heading for this group (e.g., \"Features\", \"Bug Fixes\").",
          "default": "",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "ChecksumConfig": {
      "type": "object",
      "properties": {
        "algorithm": {
          "description": "Hash algorithm: sha256, sha512, sha1, md5, crc32 (default: sha256).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "extra_files": {
          "description": "Extra files to include in the checksum file (beyond build artifacts).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/ExtraFileSpec"
          }
        },
        "ids": {
          "description": "Build IDs filter: only checksum artifacts from builds whose `id` is in this list.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "name_template": {
          "description": "Checksum filename template (default: \"{{ ProjectName }}_{{ Version }}_checksums.txt\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "skip": {
          "description": "Disable checksums. Accepts bool or template string. Accepts the legacy `disable:` spelling via serde alias for back-compat.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "split": {
          "description": "When true, produce one checksum file per artifact instead of a combined file.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "templated_extra_files": {
          "description": "Extra files whose contents are rendered through the template engine before inclusion. Unlike `extra_files` which copy as-is, template variables like `{{ Tag }}` are expanded.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/TemplatedExtraFile"
          }
        }
      },
      "additionalProperties": false
    },
    "ChocolateyConfig": {
      "type": "object",
      "properties": {
        "amd64_variant": {
          "description": "amd64 microarchitecture variant filter (e.g. \"v1\", \"v2\", \"v3\", \"v4\"). Only artifacts matching this variant are included. Default: \"v1\".",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "api_key": {
          "description": "Chocolatey API key for `choco push`. Falls back to `CHOCOLATEY_API_KEY` env var.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "authors": {
          "description": "Package author(s) displayed in the Chocolatey gallery.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "bug_tracker_url": {
          "description": "Bug tracker URL.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "copyright": {
          "description": "Copyright notice.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "dependencies": {
          "description": "Package dependencies with optional version constraints.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/ChocolateyDependency"
          }
        },
        "description": {
          "description": "Package description (supports markdown).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "docs_url": {
          "description": "Documentation URL.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "icon_url": {
          "description": "URL to the package icon image shown in the Chocolatey gallery.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs filter: only include artifacts whose `id` is in this list.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional gate: when the rendered result is falsy (`\"false\"` / `\"0\"` / `\"no\"` / empty), the Chocolatey publisher is skipped. Render failure hard-errors. Config key: `chocolateys[].if:`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "license": {
          "description": "SPDX license identifier (e.g., \"MIT\", \"Apache-2.0\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "license_url": {
          "description": "Optional explicit license URL. Falls back to `https://opensource.org/licenses/<license>` when not set.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "name": {
          "description": "Override the package name (default: crate name).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "owners": {
          "description": "Package owners (Chocolatey gallery user).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "package_source_url": {
          "description": "URL shown as the package source in the Chocolatey gallery.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "post_publish_poll": {
          "description": "Post-publish moderation-queue polling settings. Polling is disabled by default — Chocolatey's community moderation queue routinely takes hours to days, and blocking a CI workflow on that wait is wrong. Opt in per-publisher with `post_publish_poll: { enabled: true }` when running locally and willing to wait, or disable globally via `--no-post-publish-poll`.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/PostPublishPollConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "project_source_url": {
          "description": "Source code project URL.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "project_url": {
          "description": "Project homepage URL.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "release_notes": {
          "description": "Release notes for this version.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "repository": {
          "description": "Unified project repo config (owner/name). Used to derive `<projectUrl>` (the Chocolatey gallery link) and download URLs. `<projectUrl>` resolves through `project_url:` (if set) → derived `https://github.com/{repository.owner}/{repository.name}`.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/RepositoryConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "republish_in_moderation": {
          "description": "When true, re-push the nupkg even when a version is already in the community moderation queue (PackageStatus=Submitted). Chocolatey's API accepts re-pushes of in-moderation versions; the new nupkg replaces the queued one. When false (default), the push is skipped and a warning is emitted so the operator sees that the publisher did not push.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "require_license_acceptance": {
          "description": "Require license acceptance before install.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "required": {
          "description": "Override whether this publisher failing should fail the overall release.\n\nDefault: `false` — a failure here is logged but does not abort the release. Set to `true` to fail the release on any error.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "retain_on_rollback": {
          "description": "When `true`, a triggered rollback leaves this publisher's work in place rather than attempting to undo it. Default `false`.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "skip": {
          "description": "Skip pushing to the Chocolatey community repository. Bool, string, or template expression (e.g. `\"{{ IsSnapshot }}\"`). Accepts the legacy `skip_publish:` spelling for back-compat with configs; canonical name is `skip:` to align with every other publisher.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "source_repo": {
          "description": "Push source URL (default: \"https://push.chocolatey.org/\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "summary": {
          "description": "Short summary of the package.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "tags": {
          "description": "Tags for the Chocolatey gallery (joined with single spaces in the emitted nuspec). Always a typed list — the legacy space-separated-string form was dropped now for IDE-completion friendliness and to remove whitespace ambiguity.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "title": {
          "description": "Package title (default: project name).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "url_template": {
          "description": "Custom URL template for download URLs (overrides release URL).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "use": {
          "description": "Artifact selection: \"archive\" (default), \"msi\", or \"nsis\".",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "ChocolateyDependency": {
      "description": "Chocolatey package dependency with optional version constraint.",
      "type": "object",
      "properties": {
        "id": {
          "description": "Chocolatey package ID of the dependency.",
          "default": "",
          "type": "string"
        },
        "version": {
          "description": "Minimum version constraint for the dependency (e.g., \"[1.0.0,)\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "Chronology": {
      "description": "Ordering of release sections in the aggregate root `CHANGELOG.md`.",
      "oneOf": [
        {
          "description": "Order sections by release date (default).",
          "type": "string",
          "enum": [
            "date"
          ]
        },
        {
          "description": "Order sections by semantic tag version.",
          "type": "string",
          "enum": [
            "tag"
          ]
        }
      ]
    },
    "CloudSmithConfig": {
      "description": "CloudSmith publisher configuration. Pushes packages to CloudSmith repositories.",
      "type": "object",
      "properties": {
        "component": {
          "description": "Debian component name (e.g. \"main\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "distributions": {
          "description": "Distribution mapping per format. Each entry accepts either a single slug (`deb: \"ubuntu/focal\"`) or an array of slugs (`deb: [\"ubuntu/focal\", \"ubuntu/jammy\"]`); the array form issues one upload per entry.",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {
            "$ref": "#/definitions/CloudSmithDistributions"
          }
        },
        "formats": {
          "description": "Package format filter: only publish artifacts matching these formats.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "ids": {
          "description": "Build IDs filter: only publish artifacts from builds whose `id` is in this list.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional gate: when the rendered result is falsy (`\"false\"` / `\"0\"` / `\"no\"` / empty), the CloudSmith publisher is skipped. Render failure hard-errors. Config key: `cloudsmiths[].if:`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "organization": {
          "description": "CloudSmith organization slug.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "repository": {
          "description": "CloudSmith repository slug.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "republish": {
          "description": "When true, allow republishing over existing package versions.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "required": {
          "description": "Override whether this publisher failing should fail the overall release.\n\nDefault: `false` — a failure here is logged but does not abort the release. Set to `true` to fail the release on any error.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "retain_on_rollback": {
          "description": "When `true`, a triggered rollback leaves this publisher's work in place rather than attempting to undo it. Default `false`.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "secret_name": {
          "description": "Environment variable name containing the CloudSmith API key.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "skip": {
          "description": "Template-conditional skip: if rendered result is `\"true\"`, skip this publisher.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "CloudSmithDistributions": {
      "description": "Per-format distribution value. Accepts either a single distribution string (`deb: \"ubuntu/focal\"`) or an array of distribution slugs (`deb: [\"ubuntu/focal\", \"ubuntu/jammy\"]`) — the array form causes the publisher to issue one upload per distribution slug.",
      "anyOf": [
        {
          "description": "Single distribution slug (`\"ubuntu/focal\"`).",
          "type": "string"
        },
        {
          "description": "Multiple distribution slugs; the publisher uploads once per entry.",
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      ]
    },
    "CommitAuthorConfig": {
      "description": "Shared commit author configuration with optional GPG/SSH signing. Commit-author identity for publisher commits.",
      "type": "object",
      "properties": {
        "email": {
          "description": "Git commit author email address.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "name": {
          "description": "Git commit author display name.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "signing": {
          "description": "Commit signing configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/CommitSigningConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "use_github_app_token": {
          "description": "When true, omit the explicit `-c user.name=` / `-c user.email=` overrides at commit time and let the running git client use the invoking GitHub App's identity (i.e. the `<app-slug>[bot]@users.noreply.github.com` account that the GitHub Actions checkout step has already configured in the repo's local git config).\n\nThe use-github-app-token toggle uses the local git identity; the canonical use-case is PRs against `homebrew/homebrew-core` / `kubernetes-sigs/krew-index` / `microsoft/winget-pkgs` opened from a GitHub App workflow, where EasyCLA / DCO / signed-commit policies require the App's identity (rather than a per-user bot identity) to land the merge.",
          "default": false,
          "type": "boolean"
        }
      },
      "additionalProperties": false
    },
    "CommitSigningConfig": {
      "description": "Commit signing configuration (GPG, x509, or SSH).",
      "type": "object",
      "properties": {
        "enabled": {
          "description": "Enable commit signing.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "format": {
          "description": "Signing format: \"openpgp\" (default), \"x509\", or \"ssh\".",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "key": {
          "description": "Signing key identifier.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "program": {
          "description": "Signing program (e.g. `gpg`, `gpg2`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "CompletionsConfig": {
      "description": "Shell-completion generation for an archive entry.\n\nExactly one of `generate` / `from_build_out` / `copy` must be set (validated at deserialize time). Setting none is a no-op; setting more than one is a config error.\n\nYAML examples: ```yaml completions: generate: \"{{ ArtifactPath }} completions {{ Shell }}\"   # mode A shells: [bash, zsh, fish, powershell, nushell, elvish] dst: \"completions/\" # mode B: from_build_out: \"**/out/{{ Binary }}.{bash,fish}\" # mode C: copy: \"contrib/completion/*\" ```\n\n`{{ Binary }}` resolves to the host-native binary's recorded name; when no host artifact exists (modes B/C on a pure cross build) it falls back to the crate name. If your binary name differs from the crate name, spell it literally in the glob rather than relying on `{{ Binary }}` in that case.",
      "type": "object",
      "properties": {
        "copy": {
          "description": "Mode C: glob/path of committed completion files to copy verbatim.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "dst": {
          "description": "Destination directory inside the archive (and dist staging tree) for the generated files. Defaults to `\"completions/\"`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "from_build_out": {
          "description": "Mode B: per-target glob harvesting files a `build.rs` wrote into the crate's `OUT_DIR` (e.g. `\"**/out/{{ Binary }}.{bash,fish}\"`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "generate": {
          "description": "Mode A: command run once on the host-native binary, per shell. The `{{ Shell }}` template var is bound to each entry in `shells`, and `{{ ArtifactPath }}` / `{{ Binary }}` reference the built binary. Stdout is captured into one file per shell under `dst`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "shells": {
          "description": "Shells to generate for in mode A. Arbitrary user-supplied list — not limited to bash/zsh/fish/powershell; `nushell`, `elvish`, `fig`, etc. are all valid. Ignored by modes B and C. Defaults to the four common shells when omitted in mode A.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        }
      },
      "additionalProperties": false
    },
    "ContentFromFile": {
      "description": "Load content from a local file.",
      "type": "object",
      "properties": {
        "path": {
          "description": "Path to the file (supports templates).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "ContentFromUrl": {
      "description": "Load content from a URL with optional headers.",
      "type": "object",
      "properties": {
        "headers": {
          "description": "HTTP headers to send with the request.",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {
            "type": "string"
          }
        },
        "url": {
          "description": "URL to fetch (supports templates).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "ContentSource": {
      "description": "A content source that can be an inline string, read from a file, or fetched from a URL. Used for release header/footer values.\n\nYAML examples: header: \"inline text\" header: from_file: ./RELEASE_HEADER.md header: from_url: https://example.com/header.md header: from_url: https://example.com/header.md headers: X-API-Token: \"{{ Env.API_TOKEN }}\" Accept: \"text/markdown\"\n\nBoth `from_file` path and `from_url` URL are template-rendered before use. Header values are template-rendered.",
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "object",
          "required": [
            "from_file"
          ],
          "properties": {
            "from_file": {
              "type": "string"
            }
          }
        },
        {
          "type": "object",
          "required": [
            "from_url"
          ],
          "properties": {
            "from_url": {
              "type": "string"
            },
            "headers": {
              "description": "Optional HTTP headers (value templates allowed). Enables private mirrors and authenticated endpoints.",
              "type": [
                "object",
                "null"
              ],
              "additionalProperties": {
                "type": "string"
              }
            }
          }
        }
      ]
    },
    "CrateConfig": {
      "type": "object",
      "properties": {
        "app_bundles": {
          "description": "macOS app bundle configurations for this crate.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/AppBundleConfig"
          }
        },
        "archives": {
          "description": "Archive configurations for this crate. Set to false to disable archiving, or provide an array of archive configs.",
          "default": [],
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/ArchiveConfig"
          }
        },
        "binstall": {
          "description": "cargo-binstall metadata configuration for this crate.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/BinstallConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "blobs": {
          "description": "Cloud storage (S3/GCS/Azure) upload configurations for this crate.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/BlobConfig"
          }
        },
        "builds": {
          "description": "Build configurations for this crate. One entry per binary by default.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/BuildConfig"
          }
        },
        "checksum": {
          "description": "Checksum configuration for this crate.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ChecksumConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "cross": {
          "description": "Cross-compilation strategy for this crate: auto, zigbuild, cross, or cargo.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/CrossStrategy"
            },
            {
              "type": "null"
            }
          ]
        },
        "depends_on": {
          "description": "Other crates this crate depends on; ensures release ordering.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "dmgs": {
          "description": "macOS DMG disk image configurations for this crate.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/DmgConfig"
          }
        },
        "docker_digest": {
          "description": "Docker image digest file configuration for this crate.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/DockerDigestConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "docker_manifests": {
          "description": "Docker multi-platform manifest configurations for this crate.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/DockerManifestConfig"
          }
        },
        "dockers_v2": {
          "description": "Docker V2 image build configurations for this crate (canonical API: images+tags, annotations, build_args, sbom, disable). The legacy `docker:` block was removed; this is the only docker surface. The `docker_v2:` spelling is still accepted via serde alias for back-compat.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/DockerV2Config"
          }
        },
        "flatpaks": {
          "description": "Linux Flatpak bundle configurations for this crate.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/FlatpakConfig"
          }
        },
        "msis": {
          "description": "Windows MSI installer configurations for this crate.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/MsiConfig"
          }
        },
        "name": {
          "description": "Crate name as published (must match the Cargo.toml package name).",
          "default": "",
          "type": "string"
        },
        "nfpms": {
          "description": "Linux package (deb, rpm, apk) configurations for this crate. Renamed from `nfpm:` (singular) for spelling parity with `Defaults.nfpms` and the rest of the plural-name per-crate packaging lists (`dmgs`, `msis`, `pkgs`, `nsis`, ...). The `nfpm:` spelling is still accepted via serde alias for back-compat.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/NfpmConfig"
          }
        },
        "no_unique_dist_dir": {
          "description": "When true (or template evaluating to \"true\"), all build outputs are placed in a flat `dist/` directory instead of `dist/{target}/`.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "nsis": {
          "description": "NSIS installer configurations for this crate.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/NsisConfig"
          }
        },
        "path": {
          "description": "Relative path to the crate directory from the project root.",
          "default": "",
          "type": "string"
        },
        "pkgs": {
          "description": "macOS PKG installer configurations for this crate.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/PkgConfig"
          }
        },
        "publish": {
          "description": "Publishing targets (Homebrew, Scoop, AUR, etc.) for this crate.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/PublishConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "release": {
          "description": "GitHub release configuration for this crate.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ReleaseConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "snapcrafts": {
          "description": "Snapcraft package configurations for this crate.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/SnapcraftConfig"
          }
        },
        "tag_template": {
          "description": "Git tag template used to tag and identify releases (supports templates).",
          "default": "",
          "type": "string"
        },
        "universal_binaries": {
          "description": "macOS universal binary (fat binary) configurations for this crate.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/UniversalBinaryConfig"
          }
        },
        "version": {
          "description": "Pinned semver version. When set, `anodizer bump --strict` refuses to edit this crate's `Cargo.toml` to anything other than this value; without `--strict`, the bump proceeds with a warning. Lets a release captain freeze a crate's version while still running broad `--workspace` bumps.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "version_files": {
          "description": "Repo-committed files that embed this crate's release version outside `Cargo.toml` (repo-root-relative path strings). At `tag` time each file has its occurrences of the old version rewritten to the new version — both bare and `v`-prefixed forms, word-boundary anchored — and is staged into the same bump commit as this crate's `Cargo.toml`. Overrides the workspace-level `defaults.version_files`.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "version_sync": {
          "description": "Automatic version number synchronization configuration for this crate.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/VersionSyncConfig"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "CrossStrategy": {
      "type": "string",
      "enum": [
        "auto",
        "zigbuild",
        "cross",
        "cargo"
      ]
    },
    "Defaults": {
      "description": "Workspace-level defaults that path-mirror the `CrateConfig` (and select top-level `Config`) shape. Each field here is folded into every resolved crate by `defaults_merge::apply_defaults` according to the deep-merge / merge-by-identity semantics documented in `defaults_merge`.\n\nMulti-publisher fields are single-struct on both sides today: defaults supplies one struct per publisher, and per-crate `publish.*` fields are also single-struct. A future change may introduce list-or-scalar via `OneOrMany<T>` on the per-crate side so a crate can declare multiple homebrew taps / scoop buckets / etc.; the defaults side would stay single-struct and merge into the first per-crate entry by identity.",
      "type": "object",
      "properties": {
        "app_bundles": {
          "description": "Default app-bundle settings applied to all crates.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/AppBundleConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "archives": {
          "description": "Default archive settings applied to all crates.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ArchiveConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "binary_signs": {
          "description": "Default binary-signing settings.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/SignConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "builds": {
          "description": "Default build settings applied to every crate's builds (deep-merged into each `CrateConfig.builds[]` entry by identity on `id`/`binary`).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/BuildConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "checksum": {
          "description": "Default checksum settings applied to all crates. Mirrors `CrateConfig.checksum` so checksum config can be hoisted to defaults.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ChecksumConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "crates": {
          "description": "Crate-axis defaults marker. Only valid when top-level `crates:` is set. Reserved for per-crate overrides keyed by crate id (future waves).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/DefaultsCrateBlock"
            },
            {
              "type": "null"
            }
          ]
        },
        "cross": {
          "description": "Default cross-compilation strategy: auto, zigbuild, cross, or cargo. Mirrors `CrateConfig.cross` so the strategy can be hoisted to defaults.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/CrossStrategy"
            },
            {
              "type": "null"
            }
          ]
        },
        "dmgs": {
          "description": "Default DMG settings applied to all crates.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/DmgConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "docker_signs": {
          "description": "Default Docker image signing settings.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/DockerSignConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "dockers_v2": {
          "description": "Default Docker (V2 API) image settings applied to all crates. The `docker_v2:` spelling is still accepted via serde alias for back-compat.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/DockerV2Config"
            },
            {
              "type": "null"
            }
          ]
        },
        "env": {
          "description": "Default environment variables (`KEY=VALUE` strings) hoisted across crates.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "flatpaks": {
          "description": "Default flatpak settings applied to all crates.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/FlatpakConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "makeselves": {
          "description": "Default makeself settings applied to all crates.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/MakeselfConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "msis": {
          "description": "Default MSI settings applied to all crates.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/MsiConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "nfpms": {
          "description": "Default nfpm (deb/rpm/apk) settings applied to all crates.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/NfpmConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "notarize": {
          "description": "Default macOS notarization settings.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/NotarizeConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "nsis": {
          "description": "Default NSIS settings applied to all crates.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/NsisConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "pkgs": {
          "description": "Default macOS PKG settings applied to all crates.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/PkgConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "publish": {
          "description": "Default publisher configurations (single-struct per publisher). Per-crate `publish.*` entries are merged into these by identity.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/PublishDefaults"
            },
            {
              "type": "null"
            }
          ]
        },
        "sbom": {
          "description": "Default SBOM generation settings.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/SbomConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "sign": {
          "description": "Default artifact signing settings.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/SignConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "snapcrafts": {
          "description": "Default snapcraft settings applied to all crates.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/SnapcraftConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "source": {
          "description": "Default source-archive settings applied to all crates.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/SourceConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "srpms": {
          "description": "Default SRPM settings applied to all crates.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/SrpmConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "targets": {
          "description": "Default build targets (e.g., [\"x86_64-unknown-linux-gnu\", \"aarch64-apple-darwin\"]).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "upx": {
          "description": "Default UPX compression settings applied to all crates.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/UpxConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "version_files": {
          "description": "Default repo-committed files whose embedded release version is rewritten at `tag` time (repo-root-relative path strings). Hoisted across crates; folded into each crate's `version_files` by `defaults_merge` when the crate does not set its own list. Mirrors `CrateConfig.version_files`.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "workspaces": {
          "description": "Workspace-axis defaults marker. Only valid when top-level `workspaces:` is set. Reserved for per-workspace overrides keyed by workspace name (future waves).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/DefaultsWorkspaceBlock"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "DefaultsCrateBlock": {
      "description": "Marker block under `defaults.crates:` that signals crate-axis defaults scope. Required to drive the axis-mismatch validator. Currently empty; future per-crate-id overrides will live here.\n\n`deny_unknown_fields` so that typing `defaults.crates: { foo: bar }` surfaces as a parse error rather than silently being accepted — without it, the empty struct is a sink that swallows arbitrary keys.",
      "type": "object",
      "additionalProperties": false
    },
    "DefaultsWorkspaceBlock": {
      "description": "Marker block under `defaults.workspaces:` that signals workspace-axis defaults scope. Required to drive the axis-mismatch validator. Currently empty; future per-workspace-name overrides will live here.\n\n`deny_unknown_fields` per the same rationale as `DefaultsCrateBlock`.",
      "type": "object",
      "additionalProperties": false
    },
    "DiscordAnnounce": {
      "type": "object",
      "properties": {
        "author": {
          "description": "Author name displayed in the embed.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "color": {
          "description": "Embed color as a decimal integer string (default: \"3888754\", a blue). Parsed to u32 at runtime. Supports template expressions.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "enabled": {
          "description": "Enable Discord announcements (supports template expressions).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "icon_url": {
          "description": "Icon URL for the embed footer.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "message_template": {
          "description": "Message template for the Discord embed. Default: \"{{ ProjectName }} {{ Tag }} is out! Check it out at {{ ReleaseURL }}\"",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "webhook_url": {
          "description": "Discord webhook URL.\n\nPrefer `{{ Env.DISCORD_WEBHOOK }}` (or similar) over an in-config literal — plaintext webhook URLs grant full posting access and are NOT redacted from error messages or `dist/config.yaml` after a dry-run / snapshot run.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "DiscourseAnnounce": {
      "type": "object",
      "properties": {
        "category_id": {
          "description": "Category ID to post in (required, must be non-zero).",
          "default": null,
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0.0
        },
        "enabled": {
          "description": "Enable Discourse announcements (supports template expressions).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "message_template": {
          "description": "Message body template for the forum topic. Default: \"{{ ProjectName }} {{ Tag }} is out! Check it out at {{ ReleaseURL }}\"",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "server": {
          "description": "Discourse forum URL (e.g. \"https://forum.example.com\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "title_template": {
          "description": "Title template for the forum topic. Default: \"{{ ProjectName }} {{ Tag }} is out!\"",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "username": {
          "description": "Username for the API request (default: \"system\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "DmgConfig": {
      "type": "object",
      "properties": {
        "amd64_variant": {
          "description": "amd64 microarchitecture variant filter (`v1` / `v2` / `v3` / `v4`), set via the `amd64_variant:` key. When set, only artifacts with the matching `amd64_variant` metadata are included. The legacy `goamd64:` spelling is accepted via serde alias for back-compat with imported configs. When unset, all amd64 variants are included (no filtering).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "extra_files": {
          "description": "Additional files to include in the DMG (glob or {glob, name_template}).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/ExtraFileSpec"
          }
        },
        "id": {
          "description": "Unique identifier for this DMG config.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs to include. Empty means all builds.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional: skip this DMG config if rendered result is \"false\" or empty. Render failure hard-errors (not silent-skip).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "mod_timestamp": {
          "description": "Output timestamp for reproducible builds.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "name": {
          "description": "Output DMG filename (supports templates).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "replace": {
          "description": "Remove source archives from artifacts, keeping only DMG.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "skip": {
          "description": "Skip this DMG config. Accepts bool or template string.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "templated_extra_files": {
          "description": "Extra files whose contents are rendered through the template engine before inclusion. Unlike `extra_files` which copy as-is, template variables like `{{ Tag }}` are expanded. Conditional-skip gate.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/TemplatedExtraFile"
          }
        },
        "use": {
          "description": "Which artifact type to package: \"binary\" (default) or \"appbundle\".",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "volume_name": {
          "description": "Volume label shown in Finder when the image is mounted.\n\nSupports template variables. Defaults to the project name.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "DockerDigestConfig": {
      "description": "Controls docker image digest file creation.\n\nAfter each docker image push, a digest file (containing the sha256 digest) is written to the dist directory. This config controls whether that happens and how the files are named.",
      "type": "object",
      "properties": {
        "name_template": {
          "description": "Template for the digest artifact filename. Default: tag-based naming (e.g., \"ghcr.io_owner_app_v1.0.0.digest\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "skip": {
          "description": "When truthy, disable docker digest artifact creation. Accepts the legacy `disable:` spelling via serde alias for back-compat.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "DockerHubConfig": {
      "description": "DockerHub description sync configuration. Pushes image descriptions and README content to DockerHub repositories.",
      "type": "object",
      "properties": {
        "description": {
          "description": "Short description for the DockerHub repository (max 100 chars).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "full_description": {
          "description": "Full description (README) source for the DockerHub repository.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/DockerHubFullDescription"
            },
            {
              "type": "null"
            }
          ]
        },
        "if": {
          "description": "Template-conditional gate: when the rendered result is falsy (`\"false\"` / `\"0\"` / `\"no\"` / empty), the DockerHub publisher is skipped. Render failure hard-errors. The `dockerhub[].if:`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "images": {
          "description": "DockerHub image names to update (e.g. `myorg/myapp`).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "required": {
          "description": "Override whether this publisher failing should fail the overall release.\n\nDefault: `false` — a failure here is logged but does not abort the release. Set to `true` to fail the release on any error.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "retain_on_rollback": {
          "description": "When `true`, a triggered rollback leaves this publisher's work in place rather than attempting to undo it. Default `false`.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "secret_name": {
          "description": "Environment variable name containing the DockerHub token.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "skip": {
          "description": "Skip this publisher. Accepts bool or template string. Accepts the legacy `disable:` spelling via serde alias for back-compat with imported configs (the legacy `disable:` spelling).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "username": {
          "description": "DockerHub username for authentication.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "DockerHubFromFile": {
      "description": "Read DockerHub full description content from a local file.",
      "type": "object",
      "properties": {
        "path": {
          "description": "Path to the file containing the full description.",
          "default": "",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "DockerHubFromUrl": {
      "description": "Fetch DockerHub full description content from a URL.",
      "type": "object",
      "properties": {
        "headers": {
          "description": "Optional HTTP headers for the request.",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {
            "type": "string"
          }
        },
        "url": {
          "description": "URL to fetch the full description from.",
          "default": "",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "DockerHubFullDescription": {
      "description": "Full description source for DockerHub: either from a URL or a local file.",
      "type": "object",
      "properties": {
        "from_file": {
          "description": "Read full description content from a local file.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/DockerHubFromFile"
            },
            {
              "type": "null"
            }
          ]
        },
        "from_url": {
          "description": "Fetch full description content from a URL.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/DockerHubFromUrl"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "DockerManifestConfig": {
      "description": "Deprecated: prefer `dockers_v2` (which produces multi-arch manifests via the `platforms:` field automatically). `DockerManifestConfig` is retained for back-compat with imported configs and for the niche case of stitching together manifest lists from images that were not built by `dockers_v2` in the same run.\n\nThe v1 docker / docker manifest pipes deprecated in favour of the v2 buildx flow. The rustdoc here is the load-bearing surface for the deprecation: it flows into the schemars-generated JSON Schema (consumed by IDEs / editor tooling) and rustdoc HTML, both of which are how downstream config authors discover that the v2 pipe is the preferred entry point.",
      "type": "object",
      "properties": {
        "create_flags": {
          "description": "Extra flags for `docker manifest create`.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "id": {
          "description": "Unique identifier for this manifest config.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "image_templates": {
          "description": "Image references to include in the manifest.",
          "default": [],
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "name_template": {
          "description": "Template for the manifest name, e.g. \"ghcr.io/owner/app:{{ Version }}\".",
          "default": "",
          "type": "string"
        },
        "push_flags": {
          "description": "Extra flags for `docker manifest push`.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "retry": {
          "description": "Retry configuration for manifest push (handles transient registry errors).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/DockerRetryConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "skip_push": {
          "description": "Skip push: true, false, or \"auto\" (skip for prereleases).",
          "default": null,
          "oneOf": [
            {
              "type": "string",
              "enum": [
                "auto"
              ]
            },
            {
              "type": "boolean"
            }
          ]
        },
        "use": {
          "description": "Docker backend for manifest commands: `\"docker\"` (default) or `\"podman\"`. The `\"podman\"` backend is **Linux-only** (per Pro): configs on macOS or Windows fail at config-validation time with a clear error rather than blowing up later when `podman` is not on `PATH`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "DockerRetryConfig": {
      "description": "Per-pipe retry configuration for `docker.retry` / `docker_manifest.retry`.\n\n**Deprecated**: prefer the top-level `retry:` block ([`super::RetryConfig`]) which applies to docker pipes (and every other network-bound stage) via `Project.Retry`. When a per-pipe block is present alongside the top-level block, the per-pipe values win for back-compat, but `stage-docker::resolve_retry_params` emits a one-shot deprecation warning. New configs should leave this field unset.",
      "type": "object",
      "properties": {
        "attempts": {
          "description": "Number of retry attempts for failed docker push operations (default: 10, set in `crates/stage-docker/src/lib.rs::resolve_retry_settings`).",
          "default": null,
          "type": [
            "integer",
            "null"
          ],
          "format": "uint32",
          "minimum": 0.0
        },
        "delay": {
          "description": "Duration string for the initial retry delay (default: `\"10s\"`). Examples: `\"1s\"`, `\"500ms\"`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "max_delay": {
          "description": "Maximum delay between retries (default: `\"5m\"`). Caps the exponential backoff so attempt-9 with a 10s base does not stretch to ~42 min. Example: `\"30s\"`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "DockerSignConfig": {
      "type": "object",
      "properties": {
        "args": {
          "description": "Arguments passed to the signing command (supports templates).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "artifacts": {
          "description": "Docker artifact types to sign: \"all\", \"image\", or \"manifest\" (default: \"none\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "certificate": {
          "description": "Certificate file to embed in the signature (Cosign bundle signing).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "cmd": {
          "description": "Signing command to invoke (default: \"cosign\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "env": {
          "description": "Environment variables passed to the signing command.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "id": {
          "description": "Unique identifier for this docker sign config.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Docker config IDs filter: only sign images from configs whose `id` is in this list.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional: skip this docker sign config if rendered result is \"false\" or empty.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "output": {
          "description": "Capture and log stdout/stderr of the docker signing command.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "signature": {
          "description": "Signature output filename template (supports templates).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "stdin": {
          "description": "Content written to the signing command's stdin.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "stdin_file": {
          "description": "Path to a file whose content is written to the signing command's stdin.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "DockerV2Config": {
      "description": "Docker V2 configuration — the canonical Docker build API.\n\nNotable surface: - `images` + `tags` (cleaner separation than a single `image_templates` list) - `annotations` map for OCI annotations (`--annotation`) - `build_args` map for build-time variables - `skip` as a [`StringOrBool`] template for conditional opt-out - `sbom` as a [`StringOrBool`] — when truthy, adds `--sbom=true` to buildx - `flags` for arbitrary extra `docker build` flags - `platforms` is the only target selector — no per-arch field overrides",
      "type": "object",
      "properties": {
        "annotations": {
          "description": "OCI annotations to apply via `--annotation key=value` flags.",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {
            "type": "string"
          }
        },
        "build_args": {
          "description": "Build arguments passed as `--build-arg KEY=VALUE`.\n\nEach value is template-expanded and forwarded verbatim to buildx (one argv token per pair, no shell tokenization). Prefer `{{ Env.VAR }}` over raw user-config strings for secrets — buildx records build-args in image history by default, so plaintext values here propagate into the image metadata.",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {
            "type": "string"
          }
        },
        "dockerfile": {
          "description": "Path to the Dockerfile relative to the project root.",
          "default": "",
          "type": "string"
        },
        "extra_files": {
          "description": "Extra files to copy into the Docker build context.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "flags": {
          "description": "Arbitrary extra flags passed to the docker build command.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "hooks": {
          "description": "Pre/post hooks for this dockers_v2 config. Each hook accepts the same `cmd`/`dir`/`env`/`output` shape as build/archive hooks. `pre` hooks run after the staging directory is prepared but before `docker buildx build`; `post` hooks run after the image digest is captured. Hook commands, working directories, and env values are template-expanded; in addition to the standard template surface, hooks see:\n\n- `{{ Images }}` — list of `image:tag` references for this build. Iterate via `{% for img in Images %}{{ img }}{% endfor %}` to mirror a list exposure of the same field; `{{ Images | join(sep=\",\") }}` reproduces a flat comma-separated string for legacy templates. - `{{ Dockerfile }}` — path to the rendered Dockerfile - `{{ ContextDir }}` — path to the buildx context staging directory - `{{ Digest }}` — image manifest digest (post hooks only) - `{{ BaseImage }}` / `{{ BaseImageDigest }}` — final-stage base image (the `BaseImage` / `BaseImageDigest` overlay)",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/BuildHooksConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "id": {
          "description": "Unique identifier for this Docker V2 config.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs filter: only include binary artifacts whose metadata `id` is in this list.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "images": {
          "description": "Base image names (e.g., [\"ghcr.io/owner/app\"]). Combined with `tags` to form full references.",
          "default": [],
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "labels": {
          "description": "OCI labels to apply to the image via `--label key=value` flags.",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {
            "type": "string"
          }
        },
        "platforms": {
          "description": "Target platforms for multi-arch builds (e.g., [\"linux/amd64\", \"linux/arm64\"]).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "retry": {
          "description": "Retry configuration for docker push operations.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/DockerRetryConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "sbom": {
          "description": "When truthy, adds `--sbom=true` to buildx. Supports templates.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "skip": {
          "description": "When truthy, skip this docker build entirely. Supports templates. Accepts the legacy `disable:` spelling via serde alias for back-compat.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "tags": {
          "description": "Tag suffixes (e.g., [\"latest\", \"{{ Version }}\"]). Each image is tagged with each tag.",
          "default": [],
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "use": {
          "description": "Docker backend for build commands: `\"buildx\"` (default) or `\"podman\"`.\n\nThe default `\"buildx\"` invokes `docker buildx build` with the full set of BuildKit features (multi-platform, attestations, `--rewrite-timestamp`, SBOM, OCI exporter). Setting `use: podman` swaps the binary to `podman build` and disables every buildx-only flag — anodizer rejects configs that mix `use: podman` with `sbom: true`, `--rewrite-timestamp`, `--provenance`, `--attest`, `--cache-from`, `--cache-to`, `--output`, or `--sbom` because plain podman does not recognise them.\n\n**Linux-only.** The podman backend is restricted to Linux hosts. Configs setting `use: podman` on macOS or Windows fail at config-validation time with a clear error rather than blowing up later when `podman` is not on `PATH`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "Duration": {
      "type": "object",
      "required": [
        "nanos",
        "secs"
      ],
      "properties": {
        "nanos": {
          "type": "integer",
          "format": "uint32",
          "minimum": 0.0
        },
        "secs": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0.0
        }
      }
    },
    "EmailAnnounce": {
      "type": "object",
      "properties": {
        "enabled": {
          "description": "Enable email announcements (supports template expressions).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "encryption": {
          "description": "Transport encryption mode. `auto` (the default) picks SMTPS for port 465, plain SMTP for port 25, and STARTTLS for everything else; `tls` forces SMTPS, `starttls` forces STARTTLS, `none` forces plain SMTP.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/EmailEncryption"
            },
            {
              "type": "null"
            }
          ]
        },
        "from": {
          "description": "Sender email address.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "host": {
          "description": "SMTP server hostname. When set, uses SMTP transport. When absent, falls back to sendmail/msmtp.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "insecure_skip_verify": {
          "description": "Skip TLS certificate verification (default: false).",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "message_template": {
          "description": "Email body template.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "port": {
          "description": "SMTP server port (default: 587 for STARTTLS).\n\nAnodize-additive UX win (locked 2026-04-28): an unset SMTP `port` would otherwise be an error when it is unset (zero value). Anodize defaults to 587 — the IETF submission port — so the common case (corporate / SaaS SMTP relays exposing STARTTLS on 587) works out of the box without a config knob. The `auto` encryption mode then resolves to STARTTLS for 587, which is the conventional pairing. Pinned by `test_email_smtp_port_defaults_to_587`.",
          "default": null,
          "type": [
            "integer",
            "null"
          ],
          "format": "uint16",
          "minimum": 0.0
        },
        "subject_template": {
          "description": "Email subject template. Default: \"{{ ProjectName }} {{ Tag }} is out!\"",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "to": {
          "description": "Recipient email addresses.",
          "default": [],
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "username": {
          "description": "SMTP username (can also be set via SMTP_USERNAME env var).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "EmailEncryption": {
      "description": "Email transport encryption mode.",
      "oneOf": [
        {
          "description": "Pick based on port: 465 → SMTPS, 25 → none, otherwise STARTTLS.",
          "type": "string",
          "enum": [
            "auto"
          ]
        },
        {
          "description": "Implicit TLS on connect (typically port 465).",
          "type": "string",
          "enum": [
            "tls"
          ]
        },
        {
          "description": "Plain SMTP that upgrades to TLS via STARTTLS (typically port 587).",
          "type": "string",
          "enum": [
            "starttls"
          ]
        },
        {
          "description": "Plain SMTP, no TLS. Only safe on trusted local relays (port 25).",
          "type": "string",
          "enum": [
            "none"
          ]
        }
      ]
    },
    "EnvFilesConfig": {
      "description": "Environment file configuration.\n\nAccepts two forms: - **List form** (anodizer extension): array of `.env` file paths loaded as KEY=VALUE. ```yaml env_files: - .env - .release.env ``` - **Struct form**: paths to files containing provider tokens. ```yaml env_files: github_token: ~/.config/goreleaser/github_token gitlab_token: ~/.config/goreleaser/gitlab_token gitea_token: ~/.config/goreleaser/gitea_token ```",
      "anyOf": [
        {
          "description": "List of `.env` file paths to load (KEY=VALUE format).",
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        {
          "description": "Structured token file paths.",
          "allOf": [
            {
              "$ref": "#/definitions/EnvFilesTokenConfig"
            }
          ]
        }
      ]
    },
    "EnvFilesTokenConfig": {
      "description": "Structured token file paths for provider authentication.\n\nEach field points to a file containing a single-line token. When present, the file is read and the corresponding environment variable is set (e.g., `github_token` file -> `GITHUB_TOKEN` env var).\n\nToken-file path overrides.",
      "type": "object",
      "properties": {
        "gitea_token": {
          "description": "Path to file containing the Gitea token. Default: `~/.config/goreleaser/gitea_token`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "github_token": {
          "description": "Path to file containing the GitHub token. Default: `~/.config/goreleaser/github_token`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "gitlab_token": {
          "description": "Path to file containing the GitLab token. Default: `~/.config/goreleaser/gitlab_token`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "ExtraFileSpec": {
      "description": "Specifies an extra file to include in checksums or release uploads. Can be a simple glob string or a detailed object with glob and name_template fields.\n\nSee [`ArchiveFileSpec`] doc comment for why this is a separate type.",
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "object",
          "required": [
            "glob"
          ],
          "properties": {
            "allow_empty": {
              "description": "When true, treat a glob that matches zero files as a no-op rather than a hard error. Useful for assets produced only in CI (e.g. signing public keys derived from a secret) that must not break local snapshot/dry-run flows. Defaults to false, matching the prior fail-fast behavior.",
              "default": false,
              "type": "boolean"
            },
            "glob": {
              "type": "string"
            },
            "name_template": {
              "description": "Optional override for the upload filename.",
              "default": null,
              "type": [
                "string",
                "null"
              ]
            }
          }
        }
      ]
    },
    "FileInfo": {
      "description": "Shared file metadata (owner, group, mode, mtime) used by both archive entries and nFPM package contents. Previously duplicated as `ArchiveFileInfo` and `NfpmFileInfo`; now unified.",
      "type": "object",
      "properties": {
        "group": {
          "description": "File group name (e.g., \"root\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "mode": {
          "description": "File permission mode. Accepts a YAML int (decimal, e.g. `420` for `0o644`) or an octal-prefixed string (`\"0o644\"`, `\"0644\"`). This a `uint32` type for `Mode` on archive/nfpm contents while letting users spell octal naturally in YAML.",
          "default": null,
          "type": [
            "integer",
            "null"
          ],
          "format": "uint32",
          "minimum": 0.0
        },
        "mtime": {
          "description": "File modification time in RFC3339 format (e.g., \"2024-01-01T00:00:00Z\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "owner": {
          "description": "File owner name (e.g., \"root\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "FlatpakConfig": {
      "type": "object",
      "properties": {
        "app_id": {
          "description": "Flatpak application ID in reverse-DNS notation (e.g. org.example.MyApp). Required.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "command": {
          "description": "Command to run inside the Flatpak sandbox. Defaults to first binary name.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "extra_files": {
          "description": "Additional files to include alongside the binary (glob or {glob, name_template}).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/ExtraFileSpec"
          }
        },
        "finish_args": {
          "description": "Sandbox permissions (e.g. --share=network, --socket=x11).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "id": {
          "description": "Unique identifier for this Flatpak config.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs to include. Empty means all builds.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "mod_timestamp": {
          "description": "Output timestamp for reproducible builds.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "name_template": {
          "description": "Output .flatpak filename (supports templates).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "replace": {
          "description": "Remove source archives from artifacts, keeping only the Flatpak bundle.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "runtime": {
          "description": "Flatpak runtime (e.g. org.freedesktop.Platform). Required.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "runtime_version": {
          "description": "Flatpak runtime version (e.g. \"24.08\"). Required.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "sdk": {
          "description": "Flatpak SDK (e.g. org.freedesktop.Sdk). Required.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "skip": {
          "description": "Skip this Flatpak config. Accepts bool or template string. Accepts the legacy `disable:` spelling via serde alias for back-compat.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "ForceTokenKind": {
      "description": "Which SCM token to force for authentication, overriding automatic detection.",
      "type": "string",
      "enum": [
        "github",
        "gitlab",
        "gitea"
      ]
    },
    "FormatOverride": {
      "type": "object",
      "required": [
        "os"
      ],
      "properties": {
        "formats": {
          "description": "Plural format overrides for this OS: tar.gz, tar.xz, tar.zst, tar, zip, gz, xz, or binary.",
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "os": {
          "description": "Operating system this override applies to (e.g., \"windows\", \"darwin\", \"linux\").",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "GemFuryConfig": {
      "description": "GemFury package registry publisher configuration.\n\nPushes deb / rpm / apk artifacts to `https://push.fury.io/<account>`. Authenticates via HTTP Basic auth using the push token as the username (empty password) — the conventional Fury push surface.",
      "type": "object",
      "properties": {
        "account": {
          "description": "GemFury account name. Required; rendered through the template engine so `account: \"{{ Env.MY_FURY_ACCOUNT }}\"` works.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "api_secret_name": {
          "description": "Environment variable name carrying the API (delete) token. Default `FURY_API_TOKEN`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "api_token": {
          "description": "Optional API token used by rollback to issue `DELETE /<account>/packages/<name>/versions/<version>`. When unset, the env var named by `api_secret_name` (default `FURY_API_TOKEN`) is consulted at rollback time. If both are absent at rollback time, the publisher falls back to a manual-cleanup warn.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "formats": {
          "description": "Package format filter: only push artifacts matching these formats. Defaults to `[\"apk\", \"deb\", \"rpm\"]`.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "id": {
          "description": "Unique identifier for selecting this entry from the CLI (`--id=...`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs filter: only include artifacts whose archive `id` is in this list.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional gate: when the rendered result is falsy (`\"false\"` / `\"0\"` / `\"no\"` / empty), the GemFury publisher entry is skipped. Render failure hard-errors. The `gemfury[].if:`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "required": {
          "description": "Override whether this publisher failing should fail the overall release.\n\nDefault: `true` — GemFury is a Manager-group publisher (mutable but reversible via the delete API), so a failed publish aborts by default to avoid surprising the operator with a half-released version. Set to `false` to log failures but continue.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "retain_on_rollback": {
          "description": "When `true`, a triggered rollback leaves this publisher's work in place rather than attempting to undo it. Default `false`.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "secret_name": {
          "description": "Environment variable name carrying the push token. Default `FURY_TOKEN`. The actual token VALUE is read from this env var at publish/rollback time.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "skip": {
          "description": "Template-conditional skip: if rendered result is `\"true\"`, skip this publisher entry. Accepts bool or template string. Accepts the legacy `disable:` spelling via serde alias for back-compat with imported `gemfury[].disable:` configs.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "token": {
          "description": "Push token used as the HTTP Basic auth username (empty password). When unset, the env var named by `secret_name` (default `FURY_TOKEN`) is consulted at publish time. NEVER logged.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "GitConfig": {
      "description": "Git-level tag discovery and sorting settings.\n\nControls how anodizer discovers and orders tags when determining the current and previous versions. This is separate from `TagConfig`, which controls version *bumping* logic.",
      "type": "object",
      "properties": {
        "ignore_tag_prefixes": {
          "description": "Tag prefixes to ignore during version detection (supports templates). Tags starting with any prefix in this list are excluded. The ignore-tag-prefixes feature.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "ignore_tags": {
          "description": "Tag patterns to ignore during version detection (supports templates). Tags matching any pattern in this list are excluded from version detection entirely.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "prerelease_suffix": {
          "description": "Suffix that identifies pre-release tags for sorting purposes. When set, tags ending with this suffix are treated as pre-releases and sorted accordingly during tag discovery.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "tag_sort": {
          "description": "How to sort git tags when determining the latest version.\n\nAccepted values: - `\"-version:refname\"` (default) — lexicographic version sort on the tag name. - `\"-version:creatordate\"` — sort by the tag's creation date (newest first). - `\"semver\"` — strict SemVer 2.0.0 ordering computed in Rust; prereleases sort below their release per spec section 11. Bypasses git's native sort. - `\"smartsemver\"` — same ordering as `\"semver\"`, but when the current version (resolved from the template `Version` variable) is non-prerelease, prerelease tags are filtered out before previous-tag selection. Prevents `v0.2.0-beta.3` from being picked as the predecessor of `v0.2.0` (which would otherwise produce an empty changelog).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "GitHubUrlsConfig": {
      "description": "Custom GitHub API/upload/download URLs for GitHub Enterprise installations. GitHub API/download URL overrides.",
      "type": "object",
      "properties": {
        "api": {
          "description": "GitHub API base URL (e.g. `https://github.example.com/api/v3/`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "download": {
          "description": "GitHub download URL for release assets (e.g. `https://github.example.com/`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "skip_tls_verify": {
          "description": "When true, skip TLS certificate verification for the custom URLs.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "upload": {
          "description": "GitHub upload URL for release assets (e.g. `https://github.example.com/api/uploads/`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "GitLabUrlsConfig": {
      "description": "Custom GitLab API/download URLs for self-hosted GitLab installations. GitLab API/download URL overrides.",
      "type": "object",
      "properties": {
        "api": {
          "description": "GitLab API base URL (e.g. `https://gitlab.example.com/api/v4/`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "download": {
          "description": "GitLab download URL for release assets.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "skip_tls_verify": {
          "description": "When true, skip TLS certificate verification for the custom URLs.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "use_job_token": {
          "description": "When true, use the CI_JOB_TOKEN for authentication instead of a personal token.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "use_package_registry": {
          "description": "When true, use the GitLab Package Registry for uploads instead of Generic Packages.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "GitRepoConfig": {
      "description": "Git-specific repository settings for SSH-based publishing.",
      "type": "object",
      "properties": {
        "private_key": {
          "description": "Path to SSH private key file.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ssh_command": {
          "description": "Custom SSH command (e.g. `ssh -i /path/to/key`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "url": {
          "description": "Git URL (e.g. `ssh://git@github.com/owner/repo.git`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "GiteaUrlsConfig": {
      "description": "Custom Gitea API/download URLs for self-hosted Gitea installations. Gitea API/download URL overrides.",
      "type": "object",
      "properties": {
        "api": {
          "description": "Gitea API base URL (e.g. `https://gitea.example.com/api/v1/`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "download": {
          "description": "Gitea download URL for release assets.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "skip_tls_verify": {
          "description": "When true, skip TLS certificate verification for the custom URLs.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "HomebrewCaskBinary": {
      "description": "Cask `binary` stanza entry.\n\nTwo shapes accepted in YAML: - bare string — `\"my-cli\"` → renders `binary \"my-cli\"`. - `{ name, target }` object — `{ name: \"my-cli\", target: \"mycli\" }` → renders `binary \"my-cli\", target: \"mycli\"`. The `target:` form is the Homebrew Ruby cask DSL rename: install the symlink at `/usr/local/bin/<target>` instead of `/usr/local/bin/<name>`.",
      "anyOf": [
        {
          "description": "Bare binary name. Equivalent to `{ name: \"<n>\", target: None }`.",
          "type": "string"
        },
        {
          "description": "Structured `{ name, target }` rename form.",
          "type": "object",
          "required": [
            "name"
          ],
          "properties": {
            "name": {
              "description": "Path inside the .app bundle (e.g. `\"my-cli\"`).",
              "type": "string"
            },
            "target": {
              "description": "Optional rename target — the symlink name in `/usr/local/bin`. When `None`, the symlink uses `name`.",
              "type": [
                "string",
                "null"
              ]
            }
          }
        }
      ]
    },
    "HomebrewCaskCompletions": {
      "description": "Shell completion file paths for Homebrew Cask.",
      "type": "object",
      "properties": {
        "bash": {
          "description": "Path to bash completion file.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "fish": {
          "description": "Path to fish completion file.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "zsh": {
          "description": "Path to zsh completion file.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "HomebrewCaskConfig": {
      "description": "Unified Homebrew Cask configuration.\n\nUsed at both call-sites: - `homebrew_casks:` — top-level array; carries `repository`, `commit_author`, `directory`, `ids`, `url`, structured `uninstall`/`zap`, etc. - `crates[].publish.homebrew_cask:` — per-crate override; same shape, with `url_template` as the simpler URL alternative.\n\nFields from both original types are present; any field may be `None` at either call-site. The union avoids a two-type bifurcation while keeping both axes.",
      "type": "object",
      "properties": {
        "alternative_names": {
          "description": "Alternative cask names (aliases).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "app": {
          "description": "macOS .app bundle name (e.g. \"MyApp.app\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "binaries": {
          "description": "Binary stubs to create in /usr/local/bin.\n\nEach entry is either a bare string (`\"my-cli\"` → emits `binary \"my-cli\"`) or a structured `{ name, target }` object (`{ name: \"my-cli\", target: \"mycli\" }` → emits `binary \"my-cli\", target: \"mycli\"`). The `target:` form mirrors the Homebrew Ruby cask DSL for binary renames — without it, a wrapped binary installs at the wrong path. Cask binary entry.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/HomebrewCaskBinary"
          }
        },
        "binary": {
          "description": "Deprecated singular spelling of [`Self::binaries`]. The upstream replaced `binary: foo` with `binaries: [foo]`; this field captures the legacy spelling so imported configs keep parsing. [`apply_homebrew_cask_legacy_singulars`](super::super::apply_homebrew_cask_legacy_singulars) folds the value into [`Self::binaries`] at config-load time and emits a one-time deprecation warning per occurrence. The field is excluded from serialization so a round-tripped config emits only the canonical plural form.",
          "writeOnly": true,
          "type": [
            "string",
            "null"
          ]
        },
        "caveats": {
          "description": "Custom caveats shown after install.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "commit_author": {
          "description": "Commit author with optional signing.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/CommitAuthorConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "commit_msg_template": {
          "description": "Custom commit message template. Default: \"Brew cask update for {{ ProjectName }} version {{ Tag }}\"",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "completions": {
          "description": "Shell completion definitions.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/HomebrewCaskCompletions"
            },
            {
              "type": "null"
            }
          ]
        },
        "conflicts": {
          "description": "Conflicting casks or formulae.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/HomebrewCaskConflictEntry"
          }
        },
        "custom_block": {
          "description": "Arbitrary Ruby code inserted into the cask block.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "dependencies": {
          "description": "Cask dependencies (other casks or formulae).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/HomebrewCaskDependencyEntry"
          }
        },
        "description": {
          "description": "Cask description.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "directory": {
          "description": "Subdirectory in the tap repo for cask placement (default: \"Casks\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "generate_completions_from_executable": {
          "description": "Auto-generate shell completions from an executable.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/HomebrewCaskGeneratedCompletions"
            },
            {
              "type": "null"
            }
          ]
        },
        "homepage": {
          "description": "Project homepage URL.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "hooks": {
          "description": "Pre/post install/uninstall hooks.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/HomebrewCaskHooks"
            },
            {
              "type": "null"
            }
          ]
        },
        "ids": {
          "description": "Build IDs filter: only include artifacts from builds whose `id` is in this list.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional gate: when the rendered result is falsy (`\"false\"` / `\"0\"` / `\"no\"` / empty), the Homebrew Cask config is skipped. Render failure hard-errors. Config key: `homebrew_casks[].if:`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "license": {
          "description": "License identifier (SPDX).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "manpage": {
          "description": "Deprecated singular spelling of [`Self::manpages`]. The upstream replaced `manpage: foo.1` with `manpages: [foo.1]`; this field captures the legacy spelling so imported configs keep parsing. [`apply_homebrew_cask_legacy_singulars`](super::super::apply_homebrew_cask_legacy_singulars) folds the value into [`Self::manpages`] at config-load time and emits a one-time deprecation warning per occurrence. The field is excluded from serialization so a round-tripped config emits only the canonical plural form.",
          "writeOnly": true,
          "type": [
            "string",
            "null"
          ]
        },
        "manpages": {
          "description": "Manual page references to install.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "name": {
          "description": "Cask name (default: crate / project name).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "repository": {
          "description": "Unified repository config for the Homebrew tap.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/RepositoryConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "required": {
          "description": "Override whether this publisher failing should fail the overall release.\n\nDefault: `false` — a failure here is logged but does not abort the release. Set to `true` to fail the release on any error.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "retain_on_rollback": {
          "description": "When `true`, a triggered rollback leaves this publisher's work in place rather than attempting to undo it. Default `false`.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "service": {
          "description": "Homebrew service definition.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "skip_upload": {
          "description": "Skip publishing the cask. `\"true\"` always skips; `\"auto\"` skips for prerelease versions. Accepts bool or template string.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "uninstall": {
          "description": "Structured uninstall stanza configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/HomebrewCaskUninstall"
            },
            {
              "type": "null"
            }
          ]
        },
        "update_existing_pr": {
          "description": "When true, force-push the updated cask file to the existing PR branch when a PR for the same head branch already exists. The PR content is updated in place rather than creating a duplicate. When false (default), the push is skipped and a warning is emitted so the operator sees that the publisher did not update the PR.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "url": {
          "description": "Structured download URL configuration (top-level axis).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/HomebrewCaskURL"
            },
            {
              "type": "null"
            }
          ]
        },
        "url_template": {
          "description": "Simple URL template for the .dmg/.zip download (per-crate shorthand).\n\nCannot be combined with `url.template:` — set one or the other. If both are present, config validation rejects the config at parse time. Use `url:` for the structured form (verified domain, custom headers, etc.) or `url_template:` for a bare string shorthand — never both simultaneously.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "zap": {
          "description": "Deep uninstall (zap) stanza configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/HomebrewCaskUninstall"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "HomebrewCaskConflictEntry": {
      "description": "Cask conflict (with another cask or formula).",
      "type": "object",
      "properties": {
        "cask": {
          "description": "Conflicting cask name.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "formula": {
          "description": "Conflicting formula name (deprecated by Homebrew).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "HomebrewCaskDependencyEntry": {
      "description": "Cask dependency (on another cask or formula).",
      "type": "object",
      "properties": {
        "cask": {
          "description": "Dependent cask name.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "formula": {
          "description": "Dependent formula name.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "HomebrewCaskGeneratedCompletions": {
      "description": "Auto-generate shell completions from an executable.",
      "type": "object",
      "properties": {
        "args": {
          "description": "Arguments to pass to the executable.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "base_name": {
          "description": "Base name for completion files.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "executable": {
          "description": "Binary to generate completions from.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "shell_parameter_format": {
          "description": "Shell completion framework type (arg, clap, click, cobra, flag, none, typer).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "shells": {
          "description": "Target shells (bash, zsh, fish, pwsh).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        }
      },
      "additionalProperties": false
    },
    "HomebrewCaskHook": {
      "description": "Individual hook for install/uninstall phases.",
      "type": "object",
      "properties": {
        "install": {
          "description": "Ruby code for preflight/postflight during install.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "uninstall": {
          "description": "Ruby code for uninstall_preflight/uninstall_postflight.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "HomebrewCaskHooks": {
      "description": "Pre/post install/uninstall hooks for Homebrew Cask.",
      "type": "object",
      "properties": {
        "post": {
          "description": "Post-install/uninstall hooks.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/HomebrewCaskHook"
            },
            {
              "type": "null"
            }
          ]
        },
        "pre": {
          "description": "Pre-install/uninstall hooks.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/HomebrewCaskHook"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "HomebrewCaskURL": {
      "description": "Structured URL configuration for Homebrew Cask downloads.",
      "type": "object",
      "properties": {
        "cookies": {
          "description": "HTTP cookies for the download.",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {
            "type": "string"
          }
        },
        "data": {
          "description": "POST data for form submissions.",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {
            "type": "string"
          }
        },
        "headers": {
          "description": "Custom HTTP headers.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "referer": {
          "description": "Referer header for the download.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "template": {
          "description": "URL template for the download.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "user_agent": {
          "description": "Custom user agent string.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "using": {
          "description": "Custom downloader (e.g. `:homebrew_curl`, `:post`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "verified": {
          "description": "Verification string (domain shown to user).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "HomebrewCaskUninstall": {
      "description": "Structured uninstall/zap configuration for Homebrew Cask. Used for both `uninstall` and `zap` stanzas.",
      "type": "object",
      "properties": {
        "delete": {
          "description": "File paths to delete.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "launchctl": {
          "description": "Launch daemon/agent identifiers to stop.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "login_item": {
          "description": "Login item names to remove.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "quit": {
          "description": "Application bundle IDs to quit.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "trash": {
          "description": "File paths to trash (preserves app state).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        }
      },
      "additionalProperties": false
    },
    "HomebrewConfig": {
      "type": "object",
      "properties": {
        "amd64_variant": {
          "description": "amd64 microarchitecture variant filter (e.g. \"v1\", \"v2\", \"v3\", \"v4\"). Only artifacts matching this variant are included. Default: \"v1\".",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "arm_variant": {
          "description": "ARM version filter (e.g. \"6\", \"7\"). Only artifacts matching this variant are included.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "cask": {
          "description": "Homebrew Cask configuration (macOS .app bundles).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/HomebrewCaskConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "caveats": {
          "description": "Post-install user-facing notes shown by `brew info`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "commit_author": {
          "description": "Commit author with optional signing.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/CommitAuthorConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "commit_msg_template": {
          "description": "Custom commit message template. Rendered via Tera with the standard release template variables (`ProjectName`, `Tag`, `Version`, etc.). Default: `\"Brew formula update for {{ ProjectName }} version {{ Tag }}\"` (set in `crates/stage-publish/src/homebrew.rs::default_commit_msg_template`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "conflicts": {
          "description": "Conflicting formula names with optional reason.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/HomebrewConflict"
          }
        },
        "custom_block": {
          "description": "Custom Ruby code block inserted into the formula class body.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "custom_require": {
          "description": "Ruby `require` statement for custom download strategies.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "dependencies": {
          "description": "Package dependencies (e.g. `openssl`, `libgit2`).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/HomebrewDependency"
          }
        },
        "description": {
          "description": "Short description of the formula (shown in `brew info`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "directory": {
          "description": "Formula directory in the tap (e.g. \"Formula\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "download_strategy": {
          "description": "Custom download strategy class name (e.g. `:using => GitHubPrivateRepositoryReleaseDownloadStrategy`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "extra_install": {
          "description": "Additional install commands appended after the main install block.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "homepage": {
          "description": "Project homepage URL. Falls back to the GitHub release URL when unset.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs filter: only include artifacts whose `id` is in this list.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional gate: when the rendered result is falsy (`\"false\"` / `\"0\"` / `\"no\"` / empty), the Homebrew publisher is skipped. Render failure hard-errors. Config key: `brews[].if:`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "install": {
          "description": "Ruby `install` block content for the formula.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "license": {
          "description": "SPDX license identifier (e.g., \"MIT\", \"Apache-2.0\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "name": {
          "description": "Override the formula name (default: crate name).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "plist": {
          "description": "Launchd plist content for `brew services`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "post_install": {
          "description": "Post-install commands (separate `def post_install` block in formula).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "repository": {
          "description": "Unified repository config with branch, token, PR, git SSH support. (Replaces the legacy `tap: TapConfig` owner/name-only form.)",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/RepositoryConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "required": {
          "description": "Override whether this publisher failing should fail the overall release.\n\nDefault: `false` — a failure here is logged but does not abort the release. Set to `true` to fail the release on any error.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "retain_on_rollback": {
          "description": "When `true`, a triggered rollback leaves this publisher's work in place rather than attempting to undo it. Default `false`.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "service": {
          "description": "Homebrew service block content (alternative to plist).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "skip_upload": {
          "description": "Skip publishing the formula.  `\"true\"` always skips; `\"auto\"` skips for prerelease versions. Accepts bool or template string.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "test": {
          "description": "Ruby `test` block content for the formula (run by `brew test`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "url_headers": {
          "description": "HTTP headers to include in download requests (e.g. for private repos).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "url_template": {
          "description": "Custom URL template for download URLs (overrides release URL).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "HomebrewConflict": {
      "description": "A Homebrew conflict entry, supporting both a bare name string and a structured object with an optional `because` reason.",
      "anyOf": [
        {
          "description": "Just the formula name (e.g. `\"other-tool\"`).",
          "type": "string"
        },
        {
          "description": "Name with reason (e.g. `{name: \"other-tool\", because: \"both install a bin/foo binary\"}`).",
          "type": "object",
          "required": [
            "name"
          ],
          "properties": {
            "because": {
              "type": [
                "string",
                "null"
              ]
            },
            "name": {
              "type": "string"
            }
          }
        }
      ]
    },
    "HomebrewDependency": {
      "type": "object",
      "properties": {
        "name": {
          "description": "Homebrew formula name of the dependency.",
          "default": "",
          "type": "string"
        },
        "os": {
          "description": "Restrict to a specific OS: `\"mac\"` or `\"linux\"`.",
          "type": [
            "string",
            "null"
          ]
        },
        "type": {
          "description": "Dependency type, e.g. `\"optional\"`.",
          "type": [
            "string",
            "null"
          ]
        },
        "version": {
          "description": "Version constraint for the dependency (e.g. `\">= 1.1\"`).",
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "HookEntry": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "$ref": "#/definitions/StructuredHook"
        }
      ]
    },
    "HooksConfig": {
      "description": "Top-level lifecycle hooks for `before` and `after` blocks. Each block carries a list of hook commands that run around the entire pipeline (not individual stages).\n\nThe canonical key is `hooks:` for both `before:` and `after:` to the conventional spelling. The `post:` spelling is accepted as a serde alias on `hooks` for back-compat with the previous anodizer spelling; users with `after: { post: [...] }` keep working and a deprecation warning is logged when both spellings appear in the same block (see [`HooksConfig::merge_hook_aliases`]).",
      "type": "object",
      "properties": {
        "hooks": {
          "description": "Commands to run when the block fires. The wire format accepts either `hooks:` (canonical) or the legacy `post:` spelling; both fold into this field at parse time.",
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/HookEntry"
          }
        },
        "post": {
          "description": "Legacy alias for `hooks:` (anodizer pre-v0.4). Always `None` after parsing — `merge_hook_aliases` collapses it into `hooks`. Present on the struct only because `Deserialize` writes through it before the fold step.",
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/HookEntry"
          }
        }
      },
      "additionalProperties": false
    },
    "HumanDuration": {
      "description": "A typed duration value parsed from a humantime-style string in YAML.\n\nAccepts `\"10m\"`, `\"15s\"`, `\"1h30m\"`, `\"500ms\"`, etc. Used by notarize timeouts so the schema is typed and validation catches malformed values at config-load time instead of during the notarize stage.",
      "allOf": [
        {
          "$ref": "#/definitions/Duration"
        }
      ]
    },
    "IncludeFilePath": {
      "description": "File path for a structured include.",
      "type": "object",
      "required": [
        "path"
      ],
      "properties": {
        "path": {
          "description": "Path to the include file (relative to the config file).",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "IncludeSpec": {
      "description": "An include specification: either a plain path string or a structured from_file/from_url.\n\nYAML examples: ```yaml includes: - ./defaults.yaml                           # plain string (backward compat) - from_file: path: ./config/release.yaml              # structured file path - from_url: url: https://example.com/config.yaml     # URL fetch headers: x-api-token: \"${MYCOMPANY_TOKEN}\"       # env var expansion in headers ```",
      "anyOf": [
        {
          "description": "Plain string path (backward compatible): \"path/to/file.yaml\"",
          "type": "string"
        },
        {
          "description": "Structured file include with `from_file.path`.",
          "type": "object",
          "required": [
            "from_file"
          ],
          "properties": {
            "from_file": {
              "$ref": "#/definitions/IncludeFilePath"
            }
          }
        },
        {
          "description": "Structured URL include with `from_url.url` and optional headers.",
          "type": "object",
          "required": [
            "from_url"
          ],
          "properties": {
            "from_url": {
              "$ref": "#/definitions/IncludeUrlConfig"
            }
          }
        }
      ]
    },
    "IncludeUrlConfig": {
      "description": "URL configuration for a structured include.",
      "type": "object",
      "required": [
        "url"
      ],
      "properties": {
        "headers": {
          "description": "Optional HTTP headers. Values support `${VAR_NAME}` environment variable expansion.",
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {
            "type": "string"
          }
        },
        "url": {
          "description": "URL to fetch. If it does not start with `http://` or `https://`, `https://raw.githubusercontent.com/` is prepended (GitHub shorthand).",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "InstallSmokeConfig": {
      "description": "Per-package install smoke-test image overrides.\n\nEach field is the container image used to install + version-check that package type. A `None` field falls back to its sane default ([`DEFAULT_DEB_IMAGE`], [`DEFAULT_RPM_IMAGE`], [`DEFAULT_APK_IMAGE`]).",
      "type": "object",
      "properties": {
        "apk": {
          "description": "Image override for `.apk` packages. Default [`DEFAULT_APK_IMAGE`].",
          "anyOf": [
            {
              "$ref": "#/definitions/SmokeImage"
            },
            {
              "type": "null"
            }
          ]
        },
        "deb": {
          "description": "Image override for `.deb` packages. Default [`DEFAULT_DEB_IMAGE`].",
          "anyOf": [
            {
              "$ref": "#/definitions/SmokeImage"
            },
            {
              "type": "null"
            }
          ]
        },
        "rpm": {
          "description": "Image override for `.rpm` packages. Default [`DEFAULT_RPM_IMAGE`].",
          "anyOf": [
            {
              "$ref": "#/definitions/SmokeImage"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "KrewConfig": {
      "type": "object",
      "properties": {
        "amd64_variant": {
          "description": "amd64 microarchitecture variant filter (e.g. \"v1\", \"v2\", \"v3\", \"v4\"). Only artifacts matching this variant are included. Default: \"v1\".",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "arm_variant": {
          "description": "ARM version filter (e.g. \"6\", \"7\"). Only artifacts matching this variant are included.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "caveats": {
          "description": "Post-install message shown to the user.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "commit_author": {
          "description": "Commit author with optional signing.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/CommitAuthorConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "commit_msg_template": {
          "description": "Custom commit message template.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "description": {
          "description": "Full description of the kubectl plugin.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "homepage": {
          "description": "Project homepage URL for the plugin.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs filter: only include artifacts whose `id` is in this list.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional gate: when the rendered result is falsy (`\"false\"` / `\"0\"` / `\"no\"` / empty), the Krew publisher is skipped. Render failure hard-errors. Config key: `krews[].if:`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "mode": {
          "description": "Which krew-index submission path to take.\n\n- `auto` (default): probe whether the plugin already exists in `kubernetes-sigs/krew-index`. Already present → `bot` (the hosted krew-release-bot opens the version-bump PR server-side); definitively absent → `pr-direct` (anodizer opens the initial fork PR). A probe that can't reach a definitive answer (rate-limit, network error) hard-errors rather than guessing, so a transient blip never routes an existing plugin into a maintainer-hostile fork PR. - `bot`: always POST to the krew-release-bot webhook. Use when the plugin is known to be in krew-index and you want to skip the membership probe entirely. - `pr-direct`: always open a fork PR against krew-index. Use for the initial submission, or a self-hosted krew-index mirror the hosted bot can't reach.",
          "anyOf": [
            {
              "$ref": "#/definitions/KrewMode"
            },
            {
              "type": "null"
            }
          ]
        },
        "name": {
          "description": "Override the plugin name (default: crate name).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "repository": {
          "description": "Unified repository config with branch, token, PR, git SSH support. (Replaces the legacy `manifests_repo:` / `upstream_repo:` form.) The upstream PR target is derived from `repository.pull_request.base` when set, falling back to the canonical kubernetes-sigs/krew-index.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/RepositoryConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "required": {
          "description": "Override whether this publisher failing should fail the overall release.\n\nDefault: `false` — a failure here is logged but does not abort the release. Set to `true` to fail the release on any error.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "retain_on_rollback": {
          "description": "When `true`, a triggered rollback leaves this publisher's work in place rather than attempting to undo it. Default `false`.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "short_description": {
          "description": "One-line summary of the kubectl plugin (max 255 chars).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "skip": {
          "description": "Skip this Krew config. Accepts bool or template string (e.g. `\"{{ if .IsSnapshot }}true{{ endif }}\"` for conditional skip). Distinct from `skip_upload` so users can opt out of generating the manifest entirely (common when a project is not a kubectl plugin and has no krew channel).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "skip_upload": {
          "description": "Skip publishing. `\"true\"` always skips; `\"auto\"` skips for prereleases. Accepts bool or template string.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "update_existing_pr": {
          "description": "When true, force-push the updated plugin manifest to the existing PR branch when a PR for the same head branch already exists. The PR content is updated in place rather than creating a duplicate. When false (default), the push is skipped and a warning is emitted so the operator sees that the publisher did not update the PR.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "url_template": {
          "description": "Custom URL template for download URLs (overrides release URL).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "KrewMode": {
      "description": "Which krew-index submission path the krew publisher takes.\n\nSelects between the self-contained krew-release-bot webhook and the fork-PR flow. Defaults to [`KrewMode::Auto`], which probes krew-index membership to decide.",
      "oneOf": [
        {
          "description": "Probe krew-index membership and pick `bot` (present) or `pr-direct` (absent). An indeterminate probe hard-errors.",
          "type": "string",
          "enum": [
            "auto"
          ]
        },
        {
          "description": "Always submit via the krew-release-bot webhook.",
          "type": "string",
          "enum": [
            "bot"
          ]
        },
        {
          "description": "Always open a fork PR against krew-index.",
          "type": "string",
          "enum": [
            "pr-direct"
          ]
        }
      ]
    },
    "LinkedInAnnounce": {
      "type": "object",
      "properties": {
        "enabled": {
          "description": "Enable LinkedIn announcements. Requires LINKEDIN_ACCESS_TOKEN env var (supports template expressions).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "message_template": {
          "description": "Message template for the LinkedIn share post. Default: \"{{ ProjectName }} {{ Tag }} is out! Check it out at {{ ReleaseURL }}\"",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "MacOSNativeArtifactKind": {
      "description": "Artifact-type selector for native macOS notarization. Constrains the YAML `use:` field on `notarize.macos_native` so an unsupported value fails at parse time. Only `dmg` and `pkg` are valid — `notarytool` (the only supported tool) is implicit.",
      "type": "string",
      "enum": [
        "dmg",
        "pkg"
      ]
    },
    "MacOSNativeNotarizeConfig": {
      "description": "Native notarization configuration for `xcrun notarytool`.",
      "type": "object",
      "properties": {
        "profile_name": {
          "description": "Notarytool stored credentials profile name. Templates allowed.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "timeout": {
          "description": "Timeout for `xcrun notarytool submit --timeout`. Humantime-style string (e.g. `\"10m\"`, `\"15s\"`, `\"1h\"`).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/HumanDuration"
            },
            {
              "type": "null"
            }
          ]
        },
        "wait": {
          "description": "Whether to wait for notarization to complete.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "MacOSNativeSignConfig": {
      "description": "Keychain-based signing configuration for native `codesign`.",
      "type": "object",
      "properties": {
        "entitlements": {
          "description": "Path to entitlements XML file. Only used for DMGs. Templates allowed.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "identity": {
          "description": "Keychain identity (e.g., \"Developer ID Application: Name\"). Templates allowed.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "keychain": {
          "description": "Path to Keychain file. Templates allowed.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "options": {
          "description": "Options to pass to codesign (e.g., [\"runtime\"]). Only used for DMGs.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        }
      },
      "additionalProperties": false
    },
    "MacOSNativeSignNotarizeConfig": {
      "description": "Native macOS signing and notarization via `codesign` + `xcrun notarytool`.",
      "type": "object",
      "properties": {
        "enabled": {
          "description": "Back-compat `enabled:` alias (opt-in, default false). Inverted into [`Self::skip`] at deserialize time. Surfaced here only so the generated JSON schema documents the field; always `None` at runtime. See [`MacOSSignNotarizeConfig::enabled`].",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "ids": {
          "description": "Build IDs to filter. Default: project name.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "notarize": {
          "description": "Native notarization configuration (xcrun notarytool).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/MacOSNativeNotarizeConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "sign": {
          "description": "Native signing configuration (Keychain).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/MacOSNativeSignConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "skip": {
          "description": "Skip this configuration. Accepts bool or template string. Replaces `enabled:` with the canonical `skip:`. Imported configs may continue to write `enabled:` — the deserializer inverts it into `skip:` so both spellings work.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "use": {
          "description": "Artifact type to sign and notarize: `dmg` (default) or `pkg`.\n\nAnodizer-original (signs binaries directly via rcodesign). Constrained to a typed enum at parse time so an unsupported value (`zip`, `app`, etc.) fails fast instead of producing a silent no-op signing pipe.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/MacOSNativeArtifactKind"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "MacOSNotarizeApiConfig": {
      "description": "App Store Connect API key configuration for `rcodesign notary-submit`.",
      "type": "object",
      "properties": {
        "issuer_id": {
          "description": "App Store Connect API key issuer UUID. Templates allowed.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "key": {
          "description": "Path to .p8 key file or base64-encoded contents. Templates allowed.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "key_id": {
          "description": "API key ID. Templates allowed.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "timeout": {
          "description": "Timeout for notarization status polling. Humantime-style string (e.g. `\"10m\"`, `\"15s\"`, `\"1h\"`). Default when omitted: `\"10m\"`.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/HumanDuration"
            },
            {
              "type": "null"
            }
          ]
        },
        "wait": {
          "description": "Whether to wait for notarization to complete.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "MacOSSignConfig": {
      "description": "P12-certificate signing configuration for `rcodesign sign`.",
      "type": "object",
      "properties": {
        "certificate": {
          "description": "Path to .p12 certificate file or base64-encoded contents. Templates allowed.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "entitlements": {
          "description": "Path to entitlements XML file. Templates allowed.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "password": {
          "description": "Password for the .p12 certificate. Templates allowed.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "timestamp_url": {
          "description": "RFC-3161 timestamp service URL passed to `rcodesign sign --timestamp-url`. Defaults to Apple's public timestamp service. Override when running behind a corporate proxy or when Apple's service is unreachable.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "MacOSSignNotarizeConfig": {
      "description": "Cross-platform macOS signing and notarization via `rcodesign`.",
      "type": "object",
      "properties": {
        "enabled": {
          "description": "Back-compat `enabled:` alias (opt-in, default false). Inverted into [`Self::skip`] at deserialize time. Surfaced here purely so the generated JSON schema documents the field — editors/IDEs validating against the schema must recognize `enabled:` rather than flag it as unknown. Always `None` at runtime (the deserializer folds it into `skip`); runtime logic never reads it.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "ids": {
          "description": "Build IDs to filter. Default: project name.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "notarize": {
          "description": "Notarization configuration (App Store Connect API key). Omit for sign-only.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/MacOSNotarizeApiConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "sign": {
          "description": "Signing configuration (P12 certificate).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/MacOSSignConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "skip": {
          "description": "Skip this configuration. Accepts bool or template string. Replaces the previous `enabled:` toggle with the canonical `skip:` (inverted semantic) to align with every other publisher / pipe in anodizer.\n\nBack-compat: the upstream uses `enabled:` (opt-in, default false). A YAML carrying `enabled:` is accepted via the wire-level `enabled:` alias that inverts the bool — `enabled: true` becomes `skip: false`, `enabled: false` becomes `skip: true`. The canonical field at runtime is `skip:`.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "MakeselfConfig": {
      "type": "object",
      "properties": {
        "arch": {
          "description": "Target architecture filter.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "compression": {
          "description": "Compression algorithm: gzip, bzip2, xz, lzo, compress, or none.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "description": {
          "description": "Description for LSM metadata.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "extra_args": {
          "description": "Extra arguments passed to the makeself command.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "filename": {
          "description": "Output filename template (default includes project, version, os, arch).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "files": {
          "description": "Additional files to include in the archive.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/MakeselfFile"
          }
        },
        "homepage": {
          "description": "Homepage URL for LSM metadata.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "id": {
          "description": "Unique identifier for this makeself config (default: \"default\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs filter: only include artifacts whose `id` is in this list.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "keywords": {
          "description": "Keywords for LSM metadata.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "license": {
          "description": "License for LSM metadata.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "maintainer": {
          "description": "Maintainer for LSM metadata.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "name": {
          "description": "Display name embedded in the self-extracting archive.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "os": {
          "description": "Target OS filter (default: [\"linux\", \"darwin\"]).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "script": {
          "description": "Startup script to run when the archive is extracted and executed. Required — the archive will not be created without this.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "skip": {
          "description": "Skip this config. Accepts bool or template string. Accepts the legacy `disable:` spelling via serde alias for back-compat with imported configs.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "MakeselfFile": {
      "type": "object",
      "properties": {
        "destination": {
          "description": "Destination path inside the archive. Accepts the `dst:` spelling via serde alias for back-compat with imported configs.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "source": {
          "description": "Source file path (relative to project root). Accepts the `src:` spelling via serde alias for back-compat with imported configs.",
          "default": "",
          "type": "string"
        },
        "strip_parent": {
          "description": "Strip the parent directory from the source path.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "ManpagesConfig": {
      "description": "Man-page generation for an archive entry.\n\nSame three mutually-exclusive modes as [`CompletionsConfig`], minus the per-shell `shells` axis (man pages are shell-agnostic).\n\nYAML examples: ```yaml manpages: generate: \"{{ ArtifactPath }} --man\"     # mode A dst: \"man/man1/\" # mode B: from_build_out: \"**/out/{{ Binary }}.1\" # mode C: copy: \"man/*.1\" ```",
      "type": "object",
      "properties": {
        "copy": {
          "description": "Mode C: glob/path of committed man files to copy verbatim.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "dst": {
          "description": "Destination directory inside the archive (and dist staging tree) for the generated man files. Defaults to `\"man/man1/\"`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "from_build_out": {
          "description": "Mode B: per-target glob harvesting man files a `build.rs` wrote into the crate's `OUT_DIR` (e.g. `\"**/out/{{ Binary }}.1\"`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "generate": {
          "description": "Mode A: command run once on the host-native binary; stdout is captured into a single man file under `dst` named `<binary>.1`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "MastodonAnnounce": {
      "type": "object",
      "properties": {
        "enabled": {
          "description": "Enable Mastodon announcements. Requires `MASTODON_ACCESS_TOKEN` env var (supports template expressions).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "message_template": {
          "description": "Toot message template. Default: \"{{ ProjectName }} {{ Tag }} is out! Check it out at {{ ReleaseURL }}\"",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "server": {
          "description": "Mastodon instance URL (e.g. \"https://mastodon.social\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "MattermostAnnounce": {
      "type": "object",
      "properties": {
        "channel": {
          "description": "Channel override (e.g. \"town-square\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "color": {
          "description": "Attachment color (hex string, e.g. \"#36a64f\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "enabled": {
          "description": "Enable Mattermost announcements (supports template expressions).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "icon_emoji": {
          "description": "Icon emoji for the bot post (e.g. \":rocket:\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "icon_url": {
          "description": "Icon URL for the bot post.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "message_template": {
          "description": "Message template for the Mattermost post. Default: \"{{ ProjectName }} {{ Tag }} is out! Check it out at {{ ReleaseURL }}\"",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "title_template": {
          "description": "Title template for the Mattermost attachment.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "username": {
          "description": "Username override for the bot post.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "webhook_url": {
          "description": "Mattermost incoming webhook URL.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "McpAuth": {
      "description": "Authentication method + token for the MCP registry's `/v0/publish` endpoint.",
      "type": "object",
      "properties": {
        "token": {
          "description": "Static token for the `none` and `github` methods. Templated, so `{{ envOrDefault \"MCP_GITHUB_TOKEN\" \"\" }}` works. Unused for `github-oidc` (the OIDC token is fetched from GitHub Actions at publish time).",
          "type": "string"
        },
        "type": {
          "description": "Auth provider: `none` (anonymous), `github` (PAT exchange via `/v0/auth/github-at`), or `github-oidc` (Actions OIDC token exchange via `/v0/auth/github-oidc`). Templated.",
          "default": "none",
          "allOf": [
            {
              "$ref": "#/definitions/McpAuthMethod"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "McpAuthMethod": {
      "description": "MCP auth method. Default is `None` (anonymous).",
      "oneOf": [
        {
          "description": "Anonymous publish — for testing or registries that allow it. Serializes / deserializes as `none`.",
          "type": "string",
          "enum": [
            "none"
          ]
        },
        {
          "description": "GitHub Personal Access Token exchange via `/v0/auth/github-at`. Serializes / deserializes as `github`.",
          "type": "string",
          "enum": [
            "github"
          ]
        },
        {
          "description": "GitHub Actions OIDC token exchange via `/v0/auth/github-oidc`. Serializes / deserializes as `github-oidc`.",
          "type": "string",
          "enum": [
            "github-oidc"
          ]
        }
      ]
    },
    "McpConfig": {
      "description": "MCP server registry publisher configuration.\n\nPublishes an `apiv0.ServerJSON` document to the MCP registry (`https://registry.modelcontextprotocol.io/v0/publish` by default). MCP config (server details flattened onto the publisher block).",
      "type": "object",
      "properties": {
        "auth": {
          "description": "Authentication method for the registry's `/v0/publish` endpoint. Defaults to `none` (anonymous publish, allowed for development / staging registries).",
          "default": {
            "type": "none"
          },
          "allOf": [
            {
              "$ref": "#/definitions/McpAuth"
            }
          ]
        },
        "description": {
          "description": "Clear human-readable description of server functionality (max 100 chars).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "homepage": {
          "description": "Optional URL to the server's homepage, documentation, or project website. Serialized as `websiteUrl` in the registry payload.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "if": {
          "description": "Template-conditional gate: when the rendered result is falsy (`\"false\"` / `\"0\"` / `\"no\"` / empty), the MCP publisher is skipped. Render failure hard-errors. The `mcp.if:` conditional gate.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "name": {
          "description": "Server name in reverse-DNS format (e.g. `io.github.user/weather`). Must contain exactly one forward slash separating namespace from server name. An empty / unset value skips the publisher entirely.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "packages": {
          "description": "Distribution packages — one entry per package registry (npm, pypi, nuget, oci, mcpb).",
          "default": [],
          "type": "array",
          "items": {
            "$ref": "#/definitions/McpPackage"
          }
        },
        "registry": {
          "description": "Override the registry endpoint (for staging or a private mirror). Defaults to `https://registry.modelcontextprotocol.io` when unset.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "repository": {
          "description": "Optional source repository metadata. Emitted as the `repository` object in the registry payload — omitted entirely when `url` is empty.",
          "default": {
            "url": "",
            "source": "",
            "id": "",
            "subfolder": ""
          },
          "allOf": [
            {
              "$ref": "#/definitions/McpRepository"
            }
          ]
        },
        "required": {
          "description": "Override whether this publisher failing should fail the overall release.\n\nDefault: `false` — a failure here is logged but does not abort the release. Set to `true` to fail the release on any error.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "retain_on_rollback": {
          "description": "When `true`, a triggered rollback leaves this publisher's work in place rather than attempting to undo it. Default `false`.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "skip": {
          "description": "Skip this publisher when the expression evaluates truthy. Accepts a bool or a Tera template that renders to `\"true\"`/`\"false\"` (e.g. `\"{{ if .IsSnapshot }}true{{ endif }}\"`). Accepts the legacy `disable:` spelling via serde alias for back-compat with imported imported configs (the MCP config field `MCP.Disable string`).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "title": {
          "description": "Optional human-readable title shown in registry UIs (max 100 chars). Templated; supports `{{ ProjectName | title }}`, `{{ Version }}`, etc.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "transports": {
          "description": "Top-level transports list. Intentional config-portability shim: `McpConfig` carries `deny_unknown_fields`, so a migrated an imported config containing `transports:` would fail to parse if the field were absent. The list is accepted and discarded — the current MCP server schema derives transports per-package via `packages[].transport`, so the top-level list is never read after deserialization and is intentionally not emitted to the registry.",
          "default": [],
          "type": "array",
          "items": {
            "$ref": "#/definitions/McpTransport"
          }
        }
      },
      "additionalProperties": false
    },
    "McpHeader": {
      "description": "A single HTTP header attached to a remote MCP transport — mirrors the registry schema's `KeyValueInput` (`{ name, value }`).",
      "type": "object",
      "required": [
        "name"
      ],
      "properties": {
        "name": {
          "description": "Header name (e.g. `Authorization`).",
          "type": "string"
        },
        "value": {
          "description": "Header value. Templated, so it can reference an environment variable — `value: \"Bearer {{ Env.MCP_TOKEN }}\"`.",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "McpPackage": {
      "description": "A single package distribution descriptor.",
      "type": "object",
      "properties": {
        "identifier": {
          "description": "Package identifier. For npm/pypi/nuget: the package name; for OCI: the full image reference (e.g. `ghcr.io/owner/repo:v1.0.0`); for mcpb: the download URL. Templated.",
          "default": "",
          "type": "string"
        },
        "registry_type": {
          "description": "Registry type indicating how to download packages (e.g. `oci`, `npm`, `pypi`, `nuget`, `mcpb`).",
          "default": "npm",
          "allOf": [
            {
              "$ref": "#/definitions/McpRegistryType"
            }
          ]
        },
        "transport": {
          "description": "Transport protocol configuration for this package.",
          "default": {
            "type": "stdio"
          },
          "allOf": [
            {
              "$ref": "#/definitions/McpTransport"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "McpRegistryType": {
      "description": "Package registry type enum and upstream `model.RegistryType*` constants.",
      "oneOf": [
        {
          "description": "OCI image (registry_type = \"oci\"). The `version` field in the published ServerJSON is intentionally empty for OCI packages — the version is encoded in the image identifier's `:tag` suffix.",
          "type": "string",
          "enum": [
            "oci"
          ]
        },
        {
          "description": "npm registry (registry_type = \"npm\").",
          "type": "string",
          "enum": [
            "npm"
          ]
        },
        {
          "description": "PyPI registry (registry_type = \"pypi\").",
          "type": "string",
          "enum": [
            "pypi"
          ]
        },
        {
          "description": "NuGet registry (registry_type = \"nuget\").",
          "type": "string",
          "enum": [
            "nuget"
          ]
        },
        {
          "description": "MCPB direct-download (registry_type = \"mcpb\").",
          "type": "string",
          "enum": [
            "mcpb"
          ]
        }
      ]
    },
    "McpRepository": {
      "description": "Repository metadata for the MCP registry payload. Source-repository metadata for the MCP server.",
      "type": "object",
      "properties": {
        "id": {
          "description": "Repository identifier from the hosting service (e.g. GitHub repo ID).",
          "default": "",
          "type": "string"
        },
        "source": {
          "description": "Repository hosting service identifier. Used by registries to determine validation and API access methods.",
          "default": "",
          "type": "string"
        },
        "subfolder": {
          "description": "Optional relative path from repository root to the server location within a monorepo or nested package structure.",
          "default": "",
          "type": "string"
        },
        "url": {
          "description": "Repository URL for browsing source code. Must support both web browsing and git-clone operations. An empty value omits the entire `repository` object from the published payload.",
          "default": "",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "McpTransport": {
      "description": "Transport descriptor for upstream `model.Transport`.",
      "type": "object",
      "properties": {
        "headers": {
          "description": "HTTP headers attached to a remote transport's requests. Each entry is a `{ name, value }` pair; the `value` is templated, so a header can carry a secret such as `value: \"Bearer {{ Env.MCP_TOKEN }}\"`. Omitted entirely for `stdio` and for remote transports with no headers.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/McpHeader"
          }
        },
        "type": {
          "description": "Transport type: `stdio`, `streamable-http`, or `sse`.",
          "default": "stdio",
          "allOf": [
            {
              "$ref": "#/definitions/McpTransportType"
            }
          ]
        },
        "url": {
          "description": "Endpoint URL for the remote transports (`streamable-http`, `sse`). Required by the registry for those types and forbidden for `stdio`, so it stays an optional plain string: leave it empty for `stdio`, and set it for a remote transport. Templated, so `url: \"https://{{ Env.MCP_HOST }}/v1\"` resolves at publish time.",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "McpTransportType": {
      "description": "Transport protocol — mirrors upstream `model.TransportType*` constants.",
      "oneOf": [
        {
          "description": "Local stdio transport.",
          "type": "string",
          "enum": [
            "stdio"
          ]
        },
        {
          "description": "Streamable HTTP remote transport.",
          "type": "string",
          "enum": [
            "streamable-http"
          ]
        },
        {
          "description": "Server-Sent Events remote transport.",
          "type": "string",
          "enum": [
            "sse"
          ]
        }
      ]
    },
    "MetadataConfig": {
      "type": "object",
      "properties": {
        "commit_author": {
          "description": "Commit author identity for commit workflows. Reuses the shared `CommitAuthorConfig` (name + email + optional signing). Exposed as `{{ Metadata.CommitAuthor.Name }}` / `{{ Metadata.CommitAuthor.Email }}`.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/CommitAuthorConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "description": {
          "description": "Human-readable project description (exposed as `{{ Metadata.Description }}`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "full_description": {
          "description": "Long-form project description. Supports inline string, `from_file`, or `from_url`. Exposed as `{{ Metadata.FullDescription }}`. FromUrl is resolved lazily (requires the release stage); FromFile is resolved at context-populate time with template-rendered path.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ContentSource"
            },
            {
              "type": "null"
            }
          ]
        },
        "homepage": {
          "description": "Project homepage URL (exposed as `{{ Metadata.Homepage }}`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "license": {
          "description": "Project license identifier, e.g. \"MIT\" or \"Apache-2.0\" (exposed as `{{ Metadata.License }}`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "maintainers": {
          "description": "List of project maintainers (exposed as `{{ Metadata.Maintainers }}`).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "mod_timestamp": {
          "description": "Global modification timestamp for metadata output files (metadata.json and artifacts.json). Template string (e.g. \"{{ CommitTimestamp }}\") or unix timestamp. When set, rendered late in the pipeline and applied as file mtime. Exposed as `{{ Metadata.ModTimestamp }}`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "MilestoneConfig": {
      "type": "object",
      "properties": {
        "close": {
          "description": "Close the milestone on release. Default: false.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "fail_on_error": {
          "description": "Fail the pipeline if milestone close fails. Default: false.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "name_template": {
          "description": "Milestone name template (default: \"{{ Tag }}\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "repo": {
          "description": "Repository owner/name. Auto-detected from git remote if not set.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ScmRepoConfig"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "MonorepoConfig": {
      "description": "Monorepo configuration.\n\nWhen configured, tag discovery filters by `tag_prefix` and the working directory is scoped to `dir`.\n\nThis is DIFFERENT from `TagConfig.tag_prefix`: - `MonorepoConfig.tag_prefix`: tags in git already HAVE the prefix (e.g. `subproject1/v1.2.3`). The prefix is STRIPPED for `{{ Tag }}` while `{{ PrefixedTag }}` retains the full tag. - `TagConfig.tag_prefix`: a prefix to PREPEND when constructing `{{ PrefixedTag }}` from a plain tag.\n\nWhen `monorepo` is configured, it takes precedence over `tag.tag_prefix` for `PrefixedTag` / `PrefixedPreviousTag` behavior.",
      "type": "object",
      "properties": {
        "dir": {
          "description": "Working directory for this subproject.\n\nUsed for changelog path filtering (when no explicit `changelog.paths` or `crate.path` is configured) and as the default build `dir`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "tag_prefix": {
          "description": "Tag prefix for this subproject (e.g. `\"subproject1/\"`).\n\nTags matching this prefix are selected during tag discovery, and the prefix is stripped from `{{ Tag }}` while `{{ PrefixedTag }}` retains the full tag.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "MsiConfig": {
      "type": "object",
      "properties": {
        "amd64_variant": {
          "description": "amd64 microarchitecture variant filter (`v1` / `v2` / `v3` / `v4`), set via the `amd64_variant:` key. When set, only artifacts with the matching `amd64_variant` metadata are included. The legacy `goamd64:` spelling is accepted via serde alias for back-compat with imported configs.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "extensions": {
          "description": "WiX extensions to enable (e.g., \"WixUIExtension\"). Templates allowed.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "extra_files": {
          "description": "Additional files available in the WiX build context (simple filenames).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "hooks": {
          "description": "Pre/post MSI-build hooks. Accepts `pre`/`post` or `before`/`after` via BuildHooksConfig's serde aliases. Runs before / after candle+light for each matched artifact.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/BuildHooksConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "id": {
          "description": "Unique identifier for this MSI config.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs to include. Empty means all builds.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional: skip this MSI config if rendered result is \"false\" or empty. Render failure hard-errors (not silent-skip).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "mod_timestamp": {
          "description": "Output timestamp for reproducible builds.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "name": {
          "description": "Output MSI filename (supports templates).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "replace": {
          "description": "Remove source archives from artifacts, keeping only MSI.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "skip": {
          "description": "Skip this MSI config. Accepts bool or template string. Accepts the legacy `disable:` spelling via serde alias for back-compat with imported configs.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "version": {
          "description": "WiX schema version: v3 or v4 (auto-detected from .wxs if omitted).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "wxs": {
          "description": "Path to the WiX source file (.wxs). Goes through template engine. Required.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "NfpmApkConfig": {
      "type": "object",
      "properties": {
        "scripts": {
          "description": "APK-specific lifecycle scripts (preupgrade/postupgrade).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/NfpmApkScripts"
            },
            {
              "type": "null"
            }
          ]
        },
        "signature": {
          "description": "APK signing configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/NfpmSignatureConfig"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "NfpmApkScripts": {
      "description": "APK-specific upgrade lifecycle scripts.",
      "type": "object",
      "properties": {
        "postupgrade": {
          "description": "Script to run after upgrading an existing package.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "preupgrade": {
          "description": "Script to run before upgrading an existing package.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "NfpmArchlinuxConfig": {
      "type": "object",
      "properties": {
        "packager": {
          "description": "Packager identity (e.g. \"Build Team <build@example.com>\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "pkgbase": {
          "description": "Base package name for split packages.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "scripts": {
          "description": "Archlinux-specific lifecycle scripts.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/NfpmArchlinuxScripts"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "NfpmArchlinuxScripts": {
      "type": "object",
      "properties": {
        "postupgrade": {
          "description": "Script to run after upgrading an existing package.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "preupgrade": {
          "description": "Script to run before upgrading an existing package.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "NfpmConfig": {
      "type": "object",
      "properties": {
        "amd64_variant": {
          "description": "amd64 microarchitecture variant filter (`[\"v1\"]`, `[\"v2\", \"v3\"]`, etc.), set via the `amd64_variant:` key. When set, only amd64 binaries with `amd64_variant` matching one of the listed values are included. The legacy `goamd64:` spelling is accepted via serde alias for back-compat with imported configs. When unset, all amd64 variants are included (no filtering).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "apk": {
          "description": "APK-specific configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/NfpmApkConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "archlinux": {
          "description": "Archlinux-specific configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/NfpmArchlinuxConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "bin_alias": {
          "description": "Rename the installed binary inside the package only.\n\nWhen set, the auto-emitted binary content entry is installed under this name (in `bindir`) instead of the built file's name; the archive/build output is untouched. Use this to resolve Debian/RPM name clashes — e.g. `fd` ships its binary as `fdfind` in the Debian package while the tarball keeps `fd`. Templated.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "bindir": {
          "description": "Installation directory for binaries (default: /usr/bin).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "changelog": {
          "description": "Path to a YAML-format changelog file for deb/rpm packages.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "conflicts": {
          "description": "Packages this package conflicts with.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "contents": {
          "description": "Files to include in the package beyond the main binary.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/NfpmContent"
          }
        },
        "deb": {
          "description": "Deb-specific configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/NfpmDebConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "dependencies": {
          "description": "Runtime package dependencies keyed by format (e.g., {\"deb\": [\"libc6\"], \"rpm\": [\"glibc\"]}).",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "description": {
          "description": "Package description (multiline supported).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "epoch": {
          "description": "Package epoch for versioning (integer as string).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "file_name_template": {
          "description": "Package filename template (supports templates).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "formats": {
          "description": "Package formats to produce: deb, rpm, apk, archlinux (at least one required).",
          "default": [],
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "homepage": {
          "description": "Project homepage URL.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "id": {
          "description": "Unique identifier for cross-referencing this nFPM config.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs filter: only include artifacts from builds whose `id` is in this list. Accepts the deprecated `builds:` spelling via serde alias for back-compat with imported configs (the legacy `builds` key marked `deprecated`, aliasing `ids`).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional: skip this nfpm config if rendered result is \"false\" or empty. Conditional-skip gate.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ipk": {
          "description": "IPK-specific configuration (OpenWrt packages).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/NfpmIpkConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "libdirs": {
          "description": "CGo library installation directories (header, carchive, cshared).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/NfpmLibdirs"
            },
            {
              "type": "null"
            }
          ]
        },
        "license": {
          "description": "SPDX license identifier (e.g., \"MIT\", \"Apache-2.0\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "maintainer": {
          "description": "Package maintainer in \"Name <email>\" format.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "meta": {
          "description": "Whether this is a meta-package (no files, only dependencies).",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "mtime": {
          "description": "Default modification time for files in the package.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "overrides": {
          "description": "Per-format setting overrides (e.g., {\"deb\": {compression: \"xz\"}}).",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": true
        },
        "package_name": {
          "description": "Package name (defaults to crate name).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "prerelease": {
          "description": "Prerelease version suffix.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "priority": {
          "description": "Package priority (e.g. \"optional\", \"required\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "provides": {
          "description": "Virtual packages provided by this package.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "recommends": {
          "description": "Packages recommended (soft dependency) by this package.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "release": {
          "description": "Package release number.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "replaces": {
          "description": "Packages this package replaces (for upgrade paths from old package names).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "rpm": {
          "description": "RPM-specific configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/NfpmRpmConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "scripts": {
          "description": "Package lifecycle scripts (preinstall, postinstall, preremove, postremove).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/NfpmScripts"
            },
            {
              "type": "null"
            }
          ]
        },
        "section": {
          "description": "Package section (e.g. \"utils\", \"devel\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "suggests": {
          "description": "Packages suggested (weaker than recommends) by this package.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "templated_contents": {
          "description": "Extra file contents whose source files are Tera-rendered before packaging. Each entry mirrors `contents`; the difference is that at stage time the file at `src` is read, rendered through the template engine, written to a temp file, and then included in the package at `dst` using the temp file as the real source. Useful for shipping config files with templated values (version, commit, maintainer, etc.).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/NfpmContent"
          }
        },
        "templated_scripts": {
          "description": "Lifecycle scripts whose script-file bodies are Tera-rendered before packaging Each path is read, rendered through the template engine, written to a temp file, and used as the real script. If a field is set on both `scripts` and `templated_scripts`, the templated version wins.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/NfpmScripts"
            },
            {
              "type": "null"
            }
          ]
        },
        "umask": {
          "description": "File permission umask. Accepts a YAML int (`18`), an octal-prefixed string (`\"0o022\"`), or a leading-zero octal string (`\"022\"`).",
          "default": null,
          "type": [
            "integer",
            "null"
          ],
          "format": "uint32",
          "minimum": 0.0
        },
        "vendor": {
          "description": "Package vendor name.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "version_metadata": {
          "description": "Version metadata (e.g. git commit hash).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "NfpmContent": {
      "description": "A single file/directory entry in an nFPM (or SRPM) package's `contents` list. Merged the formerly-separate `NfpmContentConfig` (used for SRPM) into this struct — `source` / `destination` / `type` are accepted as aliases for `src` / `dst` / the renamed `type` so srpm-style keys still parse.\n\n`Default` is intentionally **not** derived because `src` and `dst` are required fields with no meaningful defaults — forcing callers to provide them explicitly prevents accidentally packaging empty paths.",
      "type": "object",
      "required": [
        "dst",
        "src"
      ],
      "properties": {
        "dst": {
          "description": "Destination path inside the package (absolute path, supports templates).\n\nSame caveat as `src`: `..` segments are passed through to nfpm verbatim. Templated values from untrusted sources should be canonicalised by the caller before use.",
          "type": "string"
        },
        "expand": {
          "description": "When true, expand template variables in the `src` and `dst` paths.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "file_info": {
          "description": "File ownership and permission metadata.",
          "anyOf": [
            {
              "$ref": "#/definitions/FileInfo"
            },
            {
              "type": "null"
            }
          ]
        },
        "packager": {
          "description": "Per-packager filter: only include this content entry for the specified packager (e.g. \"deb\", \"rpm\", \"apk\").",
          "type": [
            "string",
            "null"
          ]
        },
        "src": {
          "description": "Source path on the build machine (supports glob patterns and templates).\n\nPaths are resolved relative to the project root. `..` segments are NOT stripped, so a templated value resolving to `../../etc/passwd` will reach outside the project tree — avoid splicing untrusted template inputs (e.g. arbitrary `{{ Env.X }}` values) into `src`.",
          "type": "string"
        },
        "type": {
          "description": "Content entry type: \"config\", \"config|noreplace\", \"doc\", \"dir\", \"symlink\", \"ghost\", or empty for regular file.",
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "NfpmDebConfig": {
      "type": "object",
      "properties": {
        "arch_variant": {
          "description": "Target architecture variant in deb nomenclature (e.g. `amd64v3`).\n\nAuto-derived from the built binary's `amd64_variant` (`v1`..`v4`) GOAMD64 microarchitecture metadata when unset, so an amd64 deb is tagged with the microarch it was compiled for. Maps to nfpm's `deb.arch_variant`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "breaks": {
          "description": "Packages this package breaks (Breaks relationship).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "compression": {
          "description": "Deb compression algorithm (e.g. \"gzip\", \"xz\", \"zstd\", \"none\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "fields": {
          "description": "Additional control fields (e.g. Bugs, Built-Using).",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {
            "type": "string"
          }
        },
        "lintian_overrides": {
          "description": "Lintian overrides to embed in the package.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "predepends": {
          "description": "Pre-dependency packages (stronger than Depends).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "scripts": {
          "description": "Deb-specific maintainer scripts (rules, templates, config).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/NfpmDebScripts"
            },
            {
              "type": "null"
            }
          ]
        },
        "signature": {
          "description": "Deb signing configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/NfpmSignatureConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "triggers": {
          "description": "Deb trigger definitions.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/NfpmDebTriggers"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "NfpmDebScripts": {
      "description": "Deb-specific maintainer scripts for package configuration and rules.",
      "type": "object",
      "properties": {
        "config": {
          "description": "Path to debian/config script (debconf configuration).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "rules": {
          "description": "Path to debian/rules file.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "templates": {
          "description": "Path to debian/templates file (debconf templates).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "NfpmDebTriggers": {
      "type": "object",
      "properties": {
        "activate": {
          "description": "Deb activate triggers: package activates these triggers after install.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "activate_await": {
          "description": "Deb activate-await triggers: activate and wait for synchronous trigger processing.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "activate_noawait": {
          "description": "Deb activate-noawait triggers: activate without waiting.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "interest": {
          "description": "Deb interest triggers: package waits for these triggers to complete.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "interest_await": {
          "description": "Deb interest-await triggers: package waits with synchronous trigger processing.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "interest_noawait": {
          "description": "Deb interest-noawait triggers: package registers interest without waiting.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        }
      },
      "additionalProperties": false
    },
    "NfpmIpkAlternative": {
      "description": "An alternative file link for IPK's update-alternatives system.",
      "type": "object",
      "properties": {
        "link_name": {
          "description": "Symlink name in the alternatives directory.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "priority": {
          "description": "Priority for alternative selection (higher wins).",
          "default": null,
          "type": [
            "integer",
            "null"
          ],
          "format": "int32"
        },
        "target": {
          "description": "Target file path that the alternative points to.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "NfpmIpkConfig": {
      "description": "IPK (OpenWrt) package-specific configuration.",
      "type": "object",
      "properties": {
        "abi_version": {
          "description": "ABI version string for the package.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "alternatives": {
          "description": "Alternative file links managed by the update-alternatives system.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/NfpmIpkAlternative"
          }
        },
        "auto_installed": {
          "description": "Whether the package was automatically installed as a dependency.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "essential": {
          "description": "Whether the package is essential for the system.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "fields": {
          "description": "Additional control fields as key-value pairs.",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {
            "type": "string"
          }
        },
        "predepends": {
          "description": "Strong pre-dependencies that must be fully installed before this package.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "tags": {
          "description": "Tags for categorizing the package.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        }
      },
      "additionalProperties": false
    },
    "NfpmLibdirs": {
      "description": "Installation directories for CGo library outputs.\n\nControls where header files, static archives, and shared libraries are installed in the package.",
      "type": "object",
      "properties": {
        "carchive": {
          "description": "Installation directory for carchive (.a) static libraries.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "cshared": {
          "description": "Installation directory for cshared (.so / .dylib) shared libraries.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "header": {
          "description": "Installation directory for C header files.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "NfpmRpmConfig": {
      "type": "object",
      "properties": {
        "build_host": {
          "description": "RPM BuildHost tag value.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "compression": {
          "description": "RPM compression algorithm (e.g. \"lzma\", \"gzip\", \"xz\", \"zstd\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "group": {
          "description": "RPM group classification (e.g. \"System/Tools\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "packager": {
          "description": "RPM packager identity (e.g. \"Build Team <build@example.com>\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "prefixes": {
          "description": "Relocatable RPM prefix paths (e.g. [\"/usr\", \"/etc\"]).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "scripts": {
          "description": "RPM-specific lifecycle scripts (pretrans/posttrans).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/NfpmRpmScripts"
            },
            {
              "type": "null"
            }
          ]
        },
        "signature": {
          "description": "RPM signing configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/NfpmSignatureConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "summary": {
          "description": "One-line package summary (RPM Summary tag).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "NfpmRpmScripts": {
      "description": "RPM-specific transaction scripts that run outside the normal install/remove lifecycle.",
      "type": "object",
      "properties": {
        "posttrans": {
          "description": "Script to run after the RPM transaction completes.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "pretrans": {
          "description": "Script to run before the RPM transaction begins.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "NfpmScripts": {
      "type": "object",
      "properties": {
        "postinstall": {
          "description": "Path to script run after package installation.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "postremove": {
          "description": "Path to script run after package removal.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "preinstall": {
          "description": "Path to script run before package installation.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "preremove": {
          "description": "Path to script run before package removal.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "NfpmSignatureConfig": {
      "description": "Unified signature configuration shared by nFPM (deb/rpm/apk) and SRPM packages — SRPM's surface is a strict subset, so a single struct covers both. The legacy SRPM `passphrase:` key is accepted as a serde alias for `key_passphrase:` so both spellings parse.\n\nThere are three distinct signature types (`NFPMRPMSignature`, `NFPMDebSignature`, `NFPMAPKSignature`) with overlapping but slightly different fields. Anodizer's union here avoids the 3-struct cascade when 90% of fields overlap.",
      "type": "object",
      "properties": {
        "key_file": {
          "description": "Path to the signing key file.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "key_id": {
          "description": "Key ID to use for signing.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "key_name": {
          "description": "Public key name for APK signatures (defaults to `<maintainer email>.rsa.pub`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "key_passphrase": {
          "description": "Passphrase for the signing key. Falls back to `NFPM_PASSPHRASE` / `SRPM_PASSPHRASE` env vars in their respective stages.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "type": {
          "description": "Signature type for deb packages: \"origin\", \"maint\", or \"archive\" (default: \"origin\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "NightlyConfig": {
      "type": "object",
      "properties": {
        "draft": {
          "description": "Override `release.draft` for nightly runs only. `None` falls through to `release.draft`; `Some(v)` overrides it.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "keep_single_release": {
          "description": "Delete the prior release that points at the same tag before creating the new one. Default: `false`. Set `true` to maintain a single rolling nightly release on GitHub.\n\nBack-compat alias for `retention: { keep_last: 1 }`. When both `keep_single_release` and `retention` are set, `retention` wins. Destructive: deletes a published release via the GitHub Releases API. GitHub-only.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "name_template": {
          "description": "Template for the release name. Default: `\"{{ ProjectName }}-nightly\"`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "publish_release": {
          "description": "Whether to publish a GitHub Release at all. Default: `true`. Set `false` for nightly-only docker pushes / blob uploads.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "publish_repo": {
          "description": "Publish the nightly release to a DIFFERENT repository than the source repo, in `\"owner/repo\"` form (e.g. `\"nushell/nightly\"`). Default (`None`) publishes to the configured `release.github` repo, unchanged.\n\nWhen set, the nightly release create, asset upload, AND retention (`keep_single_release` / `retention.keep_last`) delete calls all target this repo. The active SCM token is assumed to have write access to `publish_repo`. GitHub-only (the nushell adoption target).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "retention": {
          "description": "Retention policy for nightly releases on GitHub. Generalizes `keep_single_release` (which is `keep_last: 1`): keeps the N newest nightly releases matching the nightly tag/name and deletes the rest (releases + the tags anodizer created for them). Operates on `publish_repo` when set. Default (`None`): no retention sweep.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/RetentionConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "tag_name": {
          "description": "Tag name used for the nightly release. Default: `\"nightly\"`. Templates allowed.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "version_template": {
          "description": "Template for the rendered version string the nightly run sets on `Version` / `RawVersion`. Default: `\"{{ incpatch(v=Version) }}-{{ ShortCommit }}-nightly\"` — produces commit-immutable nightly versions (two same-day commits yield two distinct nightly versions).\n\nThe `{{ NightlyBuild }}` template var (a stateless per-base-version build counter derived from `git rev-list --count <last-tag>..HEAD`) enables nushell-style schemes such as `\"{{ Base }}-nightly.{{ NightlyBuild }}+{{ ShortCommit }}\"`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "NixConfig": {
      "type": "object",
      "properties": {
        "amd64_variant": {
          "description": "amd64 microarchitecture variant filter (e.g. \"v1\", \"v2\", \"v3\", \"v4\"). Only artifacts matching this variant are included. Default: \"v1\".",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "commit_author": {
          "description": "Commit author with optional signing.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/CommitAuthorConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "commit_msg_template": {
          "description": "Custom commit message template.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "dependencies": {
          "description": "Nix package dependencies with optional OS filtering.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/NixDependency"
          }
        },
        "description": {
          "description": "Short description of the Nix derivation.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "extra_install": {
          "description": "Additional install commands appended after the main install.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "formatter": {
          "description": "Nix formatter to run on the generated file: \"alejandra\" or \"nixfmt\".",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "homepage": {
          "description": "Project homepage URL.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs filter: only include artifacts whose `id` is in this list.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional gate: when the rendered result is falsy (`\"false\"` / `\"0\"` / `\"no\"` / empty), the Nix publisher is skipped. Render failure hard-errors. Config key: `nix[].if:`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "install": {
          "description": "Custom install commands (replaces auto-generated binary install).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "license": {
          "description": "Nix license identifier (e.g. \"mit\", \"asl20\"). Validated against known licenses.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "main_program": {
          "description": "Value for `meta.mainProgram` in the generated Nix derivation. When set, the rendered derivation includes `mainProgram = \"<value>\";` inside the `meta` block, telling Nix which binary `nix run` should execute when the derivation contains multiple executables. Templated: supports `{{ Version }}` etc. Omitted when unset.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "name": {
          "description": "Override the derivation name (default: crate name).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "path": {
          "description": "Path for the .nix file in the repository (default: `pkgs/<name>/default.nix`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "post_install": {
          "description": "Post-install commands (postInstall phase).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "repository": {
          "description": "Unified repository config with branch, token, PR, git SSH support.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/RepositoryConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "required": {
          "description": "Override whether this publisher failing should fail the overall release.\n\nDefault: `false` — a failure here is logged but does not abort the release. Set to `true` to fail the release on any error.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "retain_on_rollback": {
          "description": "When `true`, a triggered rollback leaves this publisher's work in place rather than attempting to undo it. Default `false`.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "skip": {
          "description": "Skip this Nix config. Accepts bool or template string (e.g. `\"{{ if .IsSnapshot }}true{{ endif }}\"` for conditional skip). Distinct from `skip_upload` so users can model both intents — disable means \"don't generate at all\", skip_upload means \"generate but don't push\". Without this field, `nix: { skip: true }` was silently dropped by the serde unknown-field default.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "skip_upload": {
          "description": "Skip publishing. `\"true\"` always skips; `\"auto\"` skips for prereleases. Accepts bool or template string.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "url_template": {
          "description": "Custom URL template for download URLs (overrides release URL).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "NixDependency": {
      "description": "Nix package dependency with optional OS restriction.",
      "type": "object",
      "properties": {
        "name": {
          "description": "Nix attribute path for the dependency (e.g., \"openssl\", \"pkgs.libgit2\").",
          "default": "",
          "type": "string"
        },
        "os": {
          "description": "OS restriction: \"linux\", \"darwin\", or empty for all.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "NotarizeConfig": {
      "description": "Top-level notarization configuration supporting both cross-platform (`rcodesign`) and native macOS (`codesign` + `xcrun notarytool`) modes.",
      "type": "object",
      "properties": {
        "macos": {
          "description": "Cross-platform signing/notarization (rcodesign-based, works on any OS).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/MacOSSignNotarizeConfig"
          }
        },
        "macos_native": {
          "description": "Native signing/notarization (codesign + xcrun, macOS only).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/MacOSNativeSignNotarizeConfig"
          }
        },
        "skip": {
          "description": "Skip all notarization. Accepts bool or template string.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "NpmConfig": {
      "description": "NPM package registry publisher configuration.\n\nIn the default `optional-deps` mode anodizer emits one thin npm package per built platform (with `os`/`cpu`/`libc` selectors derived from the target triple) plus a metapackage whose `optionalDependencies` lists every platform package; npm's native resolution installs only the one matching the host. In `postinstall` mode a single package carries a `postinstall` script that downloads the matching release archive at `npm install` time. Each `npms[]` entry produces one publish.",
      "type": "object",
      "properties": {
        "access": {
          "description": "NPM access level for scoped packages. Accepts `\"public\"` / `\"restricted\"`. Scoped packages on npmjs.org default to `restricted` unless this is set to `public`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "author": {
          "description": "Templated `author` field for `package.json`. Falls back to `metadata.maintainers[0]` when unset.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "bin": {
          "description": "Command name installed by the metapackage's `bin` map (`optional-deps` mode). Falls back to the metapackage basename when unset.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "bugs": {
          "description": "Templated bug tracker URL. Emitted as `bugs.url` in `package.json`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "description": {
          "description": "Templated package description. Falls back to the project-level `metadata.description` when unset.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "extra": {
          "description": "Free-form root-level `package.json` fields. Shallow-merged into the generated `package.json`. Useful for `engines`, `mcpName`, or other npm metadata fields anodizer does not surface.",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": true
        },
        "extra_files": {
          "description": "Additional files to include in the published package alongside the generated metadata. Default `[\"README*\", \"LICENSE*\"]` (applied at the `Default` pass).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "format": {
          "description": "Archive format the `postinstall` script downloads (`tgz`, `tar.gz`, `tar`, `zip`, `binary`). Default `tgz`. Only consulted in `postinstall` mode.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "homepage": {
          "description": "Templated homepage URL. Falls back to `metadata.homepage` when unset.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "id": {
          "description": "Unique identifier for selecting this entry from the CLI (`--id=...`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs filter: only include artifacts whose archive `id` is in this list.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional gate: when the rendered result is falsy (`\"false\"` / `\"0\"` / `\"no\"` / empty), the NPM publisher entry is skipped. Render failure hard-errors.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "keywords": {
          "description": "NPM `keywords` list.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "libc_aware": {
          "description": "In `optional-deps` mode, emit separate per-platform packages for linux `musl` vs `glibc` (distinguished by the npm `libc` selector). When `false`, a single linux package per cpu is emitted with no `libc` selector. Default `true` — musl and glibc binaries are not interchangeable, so collapsing them risks installing the wrong one.",
          "default": true,
          "type": "boolean"
        },
        "license": {
          "description": "Templated SPDX license identifier (e.g. `MIT`, `Apache-2.0`). Falls back to `metadata.license` when unset.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "metapackage": {
          "description": "Metapackage name for `optional-deps` mode (e.g. `biome`). This is the package users `npm install`; it lists every per-platform package under `optionalDependencies` and ships the `bin` shim. Falls back to `name` (or the crate name) when unset.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "mode": {
          "description": "Binary-distribution strategy. `optional-deps` (default) emits npm's native per-platform packages; `postinstall` emits a download shim.",
          "default": "optional-deps",
          "allOf": [
            {
              "$ref": "#/definitions/NpmMode"
            }
          ]
        },
        "name": {
          "description": "NPM package name (the metapackage / postinstall package). May be scoped (`@org/foo`) or unscoped (`foo`). Falls back to the crate name when unset.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "registry": {
          "description": "Override the registry endpoint (default `https://registry.npmjs.org`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "repository": {
          "description": "Templated repository URL. Emitted as `repository.url` in `package.json` with `type: git`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "required": {
          "description": "Override whether this publisher failing should fail the overall release.\n\nDefault: `true` — NPM is a Manager-group publisher (one-way 72-hour unpublish window), so a failed publish aborts by default to avoid surprising the operator with a half-released version. Set to `false` to log failures but continue.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "retain_on_rollback": {
          "description": "When `true`, a triggered rollback leaves this publisher's work in place rather than attempting to undo it. Default `false`.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "scope": {
          "description": "npm scope for the per-platform packages emitted in `optional-deps` mode (e.g. `@biomejs`). The per-platform packages are named `<scope>/<bin>-<os>-<cpu>[-<libc>]`. Required for `optional-deps` mode; ignored in `postinstall` mode.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "skip": {
          "description": "Skip this publisher. Accepts bool or template string. Accepts the legacy `disable:` spelling via serde alias for back-compat.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "tag": {
          "description": "NPM dist-tag for the publish (default `latest`). Templated.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "templated_extra_files": {
          "description": "Template-rendered file mappings (`src` may be a glob; rendered contents written to `dst`).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/NpmTemplatedExtraFile"
          }
        },
        "token": {
          "description": "Auth token for the registry. Falls back to the `NPM_TOKEN` env var when unset. Stored in `.npmrc` as `//<registry>/:_authToken=...` at publish time and never passed via argv.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "url_template": {
          "description": "Override the download URL emitted into the postinstall script (templated). When unset, anodizer derives the URL from the release context. Only consulted in `postinstall` mode.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "NpmMode": {
      "description": "Binary-distribution strategy for an [`NpmConfig`] entry.\n\n`optional-deps` (the default for a Rust release) emits npm's native platform-resolution layout: one thin per-platform package whose `os`/`cpu`/`libc` selectors are derived from the built target triples, plus a metapackage that lists every platform package under `optionalDependencies` and ships a `bin` shim resolving the installed one via `require.resolve`. npm installs only the matching platform package; there is no download and no postinstall script. This is the pattern leading Rust CLIs ship binaries through npm with (biome, git-cliff).\n\n`postinstall` emits a single package carrying a `postinstall.js` shim that downloads + sha256-verifies the OS/arch-matching release archive at `npm install` time — for registries or policies that disallow per-platform packages.",
      "oneOf": [
        {
          "description": "Emit per-platform packages + a metapackage with `optionalDependencies` and a `require.resolve` bin shim. npm's native `os`/`cpu`/`libc` resolution selects the right prebuilt package — no download, no postinstall. Default.",
          "type": "string",
          "enum": [
            "optional-deps"
          ]
        },
        {
          "description": "Emit a single package with a `postinstall.js` shim that downloads and sha256-verifies the matching archive at install time.",
          "type": "string",
          "enum": [
            "postinstall"
          ]
        }
      ]
    },
    "NpmTemplatedExtraFile": {
      "description": "Template-rendered file mapping for [`NpmConfig::templated_extra_files`].",
      "type": "object",
      "properties": {
        "dst": {
          "description": "Destination path inside the published package.",
          "default": "",
          "type": "string"
        },
        "src": {
          "description": "Source path (may be a glob; relative to the project root).",
          "default": "",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "NsisConfig": {
      "type": "object",
      "properties": {
        "amd64_variant": {
          "description": "amd64 microarchitecture variant filter (`v1` / `v2` / `v3` / `v4`), set via the `amd64_variant:` key. When set, only artifacts with the matching `amd64_variant` metadata are included. The legacy `goamd64:` spelling is accepted via serde alias for back-compat with imported configs.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "extra_files": {
          "description": "Additional files to include alongside the installer (glob or {glob, name_template}).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/ExtraFileSpec"
          }
        },
        "id": {
          "description": "Unique identifier for this NSIS config.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs to include. Empty means all builds.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional: skip this NSIS config if rendered result is \"false\" or empty. Render failure hard-errors (not silent-skip).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "mod_timestamp": {
          "description": "Output timestamp for reproducible builds.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "name": {
          "description": "Output installer filename (supports templates).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "replace": {
          "description": "Remove source archives from artifacts, keeping only the installer.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "script": {
          "description": "Path to the NSIS script template (.nsi). Goes through template engine.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "skip": {
          "description": "Skip this NSIS config. Accepts bool or template string. Accepts the legacy `disable:` spelling via serde alias for back-compat with imported configs.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "templated_extra_files": {
          "description": "Extra files whose contents are rendered through the template engine before inclusion. Unlike `extra_files` which copy as-is, template variables like `{{ Tag }}` are expanded. Conditional-skip gate.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/TemplatedExtraFile"
          }
        }
      },
      "additionalProperties": false
    },
    "OpenCollectiveAnnounce": {
      "type": "object",
      "properties": {
        "enabled": {
          "description": "Enable OpenCollective announcements. Requires OPENCOLLECTIVE_TOKEN env var (supports template expressions).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "message_template": {
          "description": "HTML message template for the update. Default includes <br/> and <a> tags with ReleaseURL.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "slug": {
          "description": "Collective slug (e.g. \"my-project\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "title_template": {
          "description": "Title template for the update. Default: \"{{ Tag }}\"",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "PartialConfig": {
      "type": "object",
      "properties": {
        "by": {
          "description": "How to split builds: \"os\" (by OS, default) or \"target\" (by full triple). \"os\" groups all arch variants for the same OS into one split job. \"target\" gives each unique target triple its own split job.\n\nThe legacy `goos` spelling is accepted as a back-compat alias for `os` (folded at parse time, with a deprecation warning); imported configs keep loading.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "PkgConfig": {
      "type": "object",
      "properties": {
        "extra_files": {
          "description": "Additional files to include in the package (glob or {glob, name_template}). Anodizer-additive.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/ExtraFileSpec"
          }
        },
        "id": {
          "description": "Unique identifier for this PKG config.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "identifier": {
          "description": "Package identifier in reverse-domain notation (e.g. com.example.myapp). Required. Templates allowed (e.g. `com.example.{{ ProjectName }}`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs to include. Empty means all builds.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional: skip this PKG config if rendered result is \"false\" or empty. Render failure hard-errors (not silent-skip).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "install_location": {
          "description": "Installation path. Default: /usr/local/bin. Templates allowed.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "min_os_version": {
          "description": "Minimum macOS version (e.g. \"10.13\"). Forwarded to `pkgbuild --min-os-version`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "mod_timestamp": {
          "description": "Output timestamp for reproducible builds. Templates allowed (e.g. `{{ CommitTimestamp }}`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "name": {
          "description": "Output PKG filename (supports templates). Default: `{{ ProjectName }}_{{ Arch }}` (no extension enforced; user controls it).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "replace": {
          "description": "Remove source archives from artifacts, keeping only PKG.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "scripts": {
          "description": "Path to scripts directory containing preinstall/postinstall scripts. Templates allowed.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "skip": {
          "description": "Skip this PKG config. Accepts bool or template string. Accepts the legacy `disable:` spelling via serde alias for back-compat with imported configs.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "templated_extra_files": {
          "description": "Extra files whose contents are rendered through the template engine before inclusion. Unlike `extra_files` which copy as-is, template variables like `{{ Tag }}` are expanded. Anodizer-additive.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/TemplatedExtraFile"
          }
        },
        "use": {
          "description": "Which artifact type to package: \"binary\" (default) or \"appbundle\".",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "PostPublishPollConfig": {
      "description": "Per-publisher post-publish polling config block.\n\nSee module-level docs for the polling lifecycle. Default values: `enabled: true`, `interval: 30s`, `timeout: 30m`.",
      "type": "object",
      "properties": {
        "enabled": {
          "description": "Whether to poll at all. Default `false` — the upstream moderation queues these publishers feed (Chocolatey, winget-pkgs) routinely take HOURS to DAYS; the publish stage cannot reasonably block on them in a CI workflow. Opt in to in-band verification by setting `true` per-publisher (e.g. when running locally and willing to wait).",
          "default": false,
          "type": "boolean"
        },
        "interval": {
          "description": "How long to wait between successive status checks. Default `30s`.",
          "default": "30s",
          "allOf": [
            {
              "$ref": "#/definitions/HumanDuration"
            }
          ]
        },
        "timeout": {
          "description": "Total wall-clock budget for polling. When exhausted, the poller emits `PostPublishStatus::Timeout` with the last observed state. Default `30m`.",
          "default": "30m",
          "allOf": [
            {
              "$ref": "#/definitions/HumanDuration"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "PrebuiltConfig": {
      "description": "Per-build options for `builder: prebuilt`. Required when `builder: prebuilt` is set on the same `builds[]` entry.",
      "type": "object",
      "properties": {
        "path": {
          "description": "Template path to the imported binary on disk. Rendered once per target with these template variables available in addition to the project-wide globals (`Version`, `ProjectName`, ...):\n\n- `{{ Target }}` — the full Rust target triple (e.g. `x86_64-unknown-linux-gnu`). - `{{ Os }}` — the OS slug (`linux`, `darwin`, `windows`, ...). - `{{ Arch }}` — the architecture slug (`amd64`, `arm64`, `armv7`, ...). - `{{ Amd64 }}` — AMD64 micro-architecture variant (`v1` / `v2` / `v3` / `v4`); set for `x86_64-*` triples. - `{{ Arm64 }}` — ARM64 micro-architecture variant (`v8`); set for `aarch64-*` triples. - `{{ Arm }}` — ARM micro-architecture variant (`6` / `7`); set for `armv6*` / `armv7*` triples. - `{{ I386 }}` — i386 micro-architecture variant (`sse2`); set for `i686-*` / `i386-*` / `i586-*` triples. - `{{ ArtifactExt }}` — `.exe` on Windows targets, empty elsewhere. - `{{ ArtifactID }}` — the build entry's `id:` (empty when unset).\n\nThe rendered path is `stat()`-ed before the import, unless `--dry-run` is active, in which case the stat is skipped and the path is accepted as given. A missing file, a permission error, or any other I/O failure aborts the build with a message that names both the rendered path and the originating target triple, matching the \"build will fail\" contract.\n\nRecommendation: place the staged binaries OUTSIDE `dist/`. The release pipeline removes `dist/` on every run; pointing `path:` at `dist/...` will resolve against an empty directory.",
          "default": "",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "PublishConfig": {
      "type": "object",
      "properties": {
        "aur": {
          "description": "AUR (Arch User Repository) binary package publishing configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/AurConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "aur_source": {
          "description": "AUR source package publishing configuration (source-only PKGBUILD, not -bin).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/AurSourceConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "cargo": {
          "description": "Publish to crates.io. Presence opts in; use `cargo: { skip: true }` to opt out.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/CargoPublishConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "chocolatey": {
          "description": "Chocolatey package publishing configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ChocolateyConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "homebrew": {
          "description": "Homebrew formula publishing configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/HomebrewConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "homebrew_cask": {
          "description": "Homebrew Cask publishing configuration (macOS .app bundles).\n\nUses the unified `HomebrewCaskConfig` which carries all fields from both the per-crate cask config and the top-level `homebrew_casks:` config.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/HomebrewCaskConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "krew": {
          "description": "Krew (kubectl plugin manager) manifest publishing configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/KrewConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "nix": {
          "description": "Nix derivation publishing configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/NixConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "on_error": {
          "description": "Hooks that fire once per FAILED publisher, after rollback has been attempted. Each entry is a standard hook (`cmd` / `dir` / `env` / `output`); the template surface adds `{{ .Publisher }}`, `{{ .Error }}`, `{{ .Version }}`, `{{ .Tag }}`, `{{ .Group }}` (Assets/Manager/Submitter), `{{ .Required }}`, and `{{ .RolledBack }}` — true if any publisher was rolled back (or rollback was attempted and failed) during this run. The same values are also exported to the hook process as environment variables: `ANODIZER_PUBLISHER`, `ANODIZER_ERROR`, `ANODIZER_VERSION`, `ANODIZER_TAG`, `ANODIZER_GROUP`, `ANODIZER_REQUIRED`, `ANODIZER_ROLLED_BACK`. A hook's own failure is logged as a warning and never changes the release outcome.\n\nSecurity: the rendered `cmd` string is parsed by `sh -c`, and `{{ .Error }}` carries untrusted remote text (HTTP error bodies, git stderr) — interpolating it into `cmd` lets crafted error content break quoting and execute. Read untrusted values from the env vars instead:\n\n```yaml publish: on_error: - cmd: 'notify \"anodizer: $ANODIZER_PUBLISHER failed @ $ANODIZER_VERSION: $ANODIZER_ERROR\"' ```",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/HookEntry"
          }
        },
        "scoop": {
          "description": "Scoop manifest publishing configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ScoopConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "winget": {
          "description": "WinGet manifest publishing configuration.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/WingetConfig"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "PublishDefaults": {
      "description": "Workspace-default publishers. Each publisher is single-struct in defaults; per-crate `publish.*` may be either a single struct or a list, reconciled by the merge engine.",
      "type": "object",
      "properties": {
        "aur": {
          "description": "Default AUR (binary) settings.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/AurConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "aur_source": {
          "description": "Default AUR (source) settings.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/AurSourceConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "cargo": {
          "description": "Default crates.io publish settings, merged into per-crate `publish.cargo`.\n\nSingle-struct.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/CargoPublishConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "chocolatey": {
          "description": "Default Chocolatey package settings.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ChocolateyConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "homebrew": {
          "description": "Default Homebrew formula settings.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/HomebrewConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "homebrew_cask": {
          "description": "Default Homebrew Cask settings, merged into per-crate `publish.homebrew_cask`.\n\nSingle-struct.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/HomebrewCaskConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "krew": {
          "description": "Default Krew (kubectl plugin manager) settings.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/KrewConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "nix": {
          "description": "Default Nix derivation settings.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/NixConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "on_error": {
          "description": "Hooks fired once per failed publisher — same surface as `publish.on_error` on individual crate configs. Merged into every crate's resolved publish config.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/HookEntry"
          }
        },
        "scoop": {
          "description": "Default Scoop manifest settings.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ScoopConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "winget": {
          "description": "Default WinGet manifest settings.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/WingetConfig"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "PublisherConfig": {
      "type": "object",
      "properties": {
        "args": {
          "description": "Arguments passed to the publish command (supports templates).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "artifact_types": {
          "description": "Artifact type filter: only publish artifacts of these types (e.g., \"archive\", \"binary\").",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "checksum": {
          "description": "Include checksums in published artifacts.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "cmd": {
          "description": "Command to invoke for publishing.",
          "default": "",
          "type": "string"
        },
        "dir": {
          "description": "Working directory for the publisher command.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "env": {
          "description": "Environment variables passed to the publish command.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "extra_files": {
          "description": "Extra files to include in publishing (glob patterns with optional name override).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/ExtraFileSpec"
          }
        },
        "ids": {
          "description": "Build IDs filter: only publish artifacts from builds whose `id` is in this list.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional gate: when the rendered result is falsy (`\"false\"` / `\"0\"` / `\"no\"` / empty), the publisher is skipped. Render failure hard-errors. The `customization/publishers/` `if:` field. Distinct from `skip:` (which expresses \"always skip\") and provides config-import parity.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "meta": {
          "description": "Include metadata artifacts in published artifacts.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "name": {
          "description": "Human-readable name for this publisher (used in logs).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "signature": {
          "description": "Include signatures in published artifacts.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "skip": {
          "description": "Template-conditional skip: if rendered result is `\"true\"`, skip this publisher. Accepts bool or template string (e.g. `\"{{ if .IsSnapshot }}true{{ endif }}\"`). Accepts the legacy `disable:` spelling via serde alias for back-compat.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "templated_extra_files": {
          "description": "Extra files whose contents are rendered through the template engine before publishing. Unlike `extra_files` which copy as-is, template variables like `{{ Tag }}` are expanded.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/TemplatedExtraFile"
          }
        }
      },
      "additionalProperties": false
    },
    "PullRequestBaseConfig": {
      "description": "Target base for pull requests (upstream repo to PR against).",
      "type": "object",
      "properties": {
        "branch": {
          "description": "Base branch of the upstream repository to target with the PR.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "name": {
          "description": "Name of the upstream repository to PR against.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "owner": {
          "description": "Owner of the upstream repository to PR against.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "PullRequestConfig": {
      "description": "Pull request configuration for fork-based publisher workflows.",
      "type": "object",
      "properties": {
        "base": {
          "description": "Target base repository/branch for the PR.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/PullRequestBaseConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "body": {
          "description": "Body text for the pull request.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "draft": {
          "description": "Create PR as draft.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "enabled": {
          "description": "Enable PR creation instead of direct push.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "RedditAnnounce": {
      "type": "object",
      "properties": {
        "application_id": {
          "description": "Reddit application (OAuth client) ID.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "enabled": {
          "description": "Enable Reddit announcements. Requires REDDIT_SECRET and REDDIT_PASSWORD env vars (supports template expressions).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "sub": {
          "description": "Subreddit to post to (without /r/ prefix).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "title_template": {
          "description": "Title template for the Reddit link post. Default: \"{{ ProjectName }} {{ Tag }} is out!\"",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "url_template": {
          "description": "URL template for the Reddit link post. Default: \"{{ ReleaseURL }}\"",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "username": {
          "description": "Reddit username for posting.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "ReleaseConfig": {
      "type": "object",
      "properties": {
        "discussion_category_name": {
          "description": "GitHub Discussion category name for the release.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "draft": {
          "description": "When true, create the release as a draft (unpublished).",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "extra_files": {
          "description": "Extra files to upload to the release beyond build artifacts.\n\nPaths / globs are resolved relative to the project root. `..` segments are accepted, so an entry like `../sibling/dist/*` will reach outside the project tree — security-conscious users should keep the entries inside the repo or canonicalise them before invoking the release pipeline.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/ExtraFileSpec"
          }
        },
        "footer": {
          "description": "Text appended to the release body (inline string, from_file, or from_url).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ContentSource"
            },
            {
              "type": "null"
            }
          ]
        },
        "gitea": {
          "description": "Gitea repository to release to (owner and name).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ScmRepoConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "github": {
          "description": "GitHub repository to release to (owner and name).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ScmRepoConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "gitlab": {
          "description": "GitLab repository to release to (owner and name).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ScmRepoConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "header": {
          "description": "Text prepended to the release body (inline string, from_file, or from_url).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ContentSource"
            },
            {
              "type": "null"
            }
          ]
        },
        "ids": {
          "description": "Artifact IDs filter for uploads. Release-wide artifacts (checksums, source archive, extra files, metadata) always upload regardless of the filter, and derived artifacts (signatures, certificates, SBOMs) inherit the verdict of the artifact they derive from — a signature uploads iff the artifact it signs uploads.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "include_meta": {
          "description": "Upload metadata.json and artifacts.json as release assets.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "make_latest": {
          "description": "Mark release as latest: true, false, or \"auto\" (latest non-prerelease).",
          "default": null,
          "oneOf": [
            {
              "type": "string",
              "enum": [
                "auto"
              ]
            },
            {
              "type": "boolean"
            }
          ]
        },
        "mode": {
          "description": "Release mode: \"keep-existing\", \"append\", \"prepend\", or \"replace\".",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "name_template": {
          "description": "Release title template (supports templates).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "prerelease": {
          "description": "Mark release as pre-release: true, false, or \"auto\" (inferred from tag).",
          "default": null,
          "oneOf": [
            {
              "type": "string",
              "enum": [
                "auto"
              ]
            },
            {
              "type": "boolean"
            }
          ]
        },
        "provider": {
          "description": "Explicit publish target — the SCM provider whose `release.<provider>` block the publisher uses. When set, overrides the implicit token-type fallback chain in [`crate::scm::resolve_token_type`].\n\nUse this for **cross-platform publishing** pattern: source repo on one provider (e.g. GitLab) but releases land on another (e.g. GitHub). Without it, the publish target is inferred from which `*_TOKEN` env-var is set — fine for single-provider setups but ambiguous when both tokens are available.\n\n```yaml release: provider: github github: owner: my-org name: my-app ```",
          "anyOf": [
            {
              "$ref": "#/definitions/ForceTokenKind"
            },
            {
              "type": "null"
            }
          ]
        },
        "replace_existing_artifacts": {
          "description": "When true, replace existing release artifacts with the same name.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "replace_existing_draft": {
          "description": "When true, replace an existing draft release instead of failing.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "required": {
          "description": "Override whether this publisher failing should fail the overall release.\n\nDefault: `true` — a failure here aborts the release. Set to `false` to log failures but continue.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "retain_on_rollback": {
          "description": "When `true`, a triggered rollback leaves this publisher's work in place rather than attempting to undo it. Default `false`.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "skip": {
          "description": "Skip the release stage. Accepts bool or template string (e.g. `\"{{ if IsSnapshot }}true{{ endif }}\"` for conditional skip). Template strings are supported here. Accepts the legacy `disable:` spelling via serde alias for back-compat with imported configs (the legacy `disable:` spelling).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "skip_upload": {
          "description": "Skip uploading artifacts: true, false, or \"auto\" (skip for snapshots). Accepts bool or template string.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "tag": {
          "description": "Override the release tag (template string). When set, this tag is used as the `tag_name` in the GitHub release API instead of the crate's `tag_template`. Useful in monorepo setups to strip a tag prefix (e.g. `\"{{ Tag }}\"` to publish `v1.0.0` instead of `myapp/v1.0.0`). A cross-platform publishing feature provided for free by anodizer.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "target_commitish": {
          "description": "Target branch or SHA for the release tag.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "templated_extra_files": {
          "description": "Extra files whose contents are rendered through the template engine before upload. Unlike `extra_files` which copy as-is, template variables like `{{ Tag }}` are expanded.\n\nSame path-traversal caveat as `extra_files`: `..` segments reach outside the project tree.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/TemplatedExtraFile"
          }
        },
        "upload_concurrency": {
          "description": "Maximum number of asset-upload requests in flight simultaneously.\n\nGitHub's secondary rate-limit is triggered by burst traffic. Keeping this value low avoids tripping the limit even for releases with many artifacts. Default: 4. Override at runtime with `ANODIZER_GITHUB_UPLOAD_CONCURRENCY`.",
          "default": null,
          "type": [
            "integer",
            "null"
          ],
          "format": "uint32",
          "minimum": 0.0
        },
        "use_existing_draft": {
          "description": "Reuse an existing draft release instead of creating a new one.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "RepositoryConfig": {
      "description": "Shared repository configuration used by all git-based publishers (Homebrew, Scoop, Winget, Krew, Nix). A repository reference.",
      "type": "object",
      "properties": {
        "branch": {
          "description": "Branch to push to (default: repo default branch).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "git": {
          "description": "Git-specific settings for SSH-based publishing.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/GitRepoConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "name": {
          "description": "Repository name.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "owner": {
          "description": "Repository owner (GitHub user or organization).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "pull_request": {
          "description": "Pull request settings for fork-based workflows.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/PullRequestConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "token": {
          "description": "Auth token for the repository. Falls back to env-based resolution.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "token_type": {
          "description": "Token type: \"github\" (default), \"gitlab\", \"gitea\".",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "RetentionConfig": {
      "description": "Retention policy for nightly releases on the publish repo.\n\n`keep_last: N` keeps the N newest nightly releases (matched by the nightly tag/name) and deletes the older ones, including the git tags anodizer created for them.",
      "type": "object",
      "properties": {
        "keep_last": {
          "description": "Number of newest nightly releases to keep. `0` is treated as `1` (never delete every nightly), matching the `keep_single_release` floor. nushell keeps 10.",
          "default": 0,
          "type": "integer",
          "format": "uint",
          "minimum": 0.0
        }
      },
      "additionalProperties": false
    },
    "RetryConfig": {
      "description": "User-facing retry configuration block (`retry:` at config root).\n\nAll fields are optional in YAML; missing fields fall back to the defaults (10 attempts, 10s base delay, 5m cap).",
      "type": "object",
      "properties": {
        "attempts": {
          "description": "Total attempts (including the first). Default `10`. Values < 1 are clamped up to 1 by the policy layer.",
          "default": 10,
          "type": "integer",
          "format": "uint32",
          "minimum": 0.0
        },
        "delay": {
          "description": "Initial delay before the second attempt. Default `10s`. Subsequent delays grow exponentially (`delay × 2^(n-2)`) up to [`Self::max_delay`].",
          "default": "10s",
          "allOf": [
            {
              "$ref": "#/definitions/HumanDuration"
            }
          ]
        },
        "max_delay": {
          "description": "Upper bound on any individual sleep between attempts. Default `5m`. Without this cap, an exponential backoff with `delay=10s` would stretch attempt 9 to ~42 minutes.",
          "default": "5m",
          "allOf": [
            {
              "$ref": "#/definitions/HumanDuration"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "RootChangelogConfig": {
      "description": "Configuration for the single aggregate root `CHANGELOG.md`.",
      "type": "object",
      "properties": {
        "chronology": {
          "description": "Ordering of release sections in the root changelog: `date` (default) or `tag`.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/Chronology"
            },
            {
              "type": "null"
            }
          ]
        },
        "crates": {
          "description": "Crates that contribute a `### <crate>` subsection to the root changelog. When omitted, every crate contributes a subsection.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        }
      },
      "additionalProperties": false
    },
    "RuntimeHarvest": {
      "description": "Runtime-asset harvest hook for an AppImage config. The `command` template runs the freshly-built host-native binary to populate `dir`; the resulting directory is then bundled into the AppDir (and staged at a stable dist path so an archive `extra_files` glob can reuse it).",
      "type": "object",
      "properties": {
        "command": {
          "description": "Command template run once on the host to populate the harvest dir. `{{ .ArtifactPath }}` resolves to the host-native binary's path and `{{ .HarvestDir }}` to the absolute harvest output directory. Run via `sh -c`.",
          "default": "",
          "type": "string"
        },
        "dir": {
          "description": "Directory (relative to the AppDir root) the harvested assets are bundled into. Also the AppDir-relative destination for the staged host-harvested tree.",
          "default": "",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "SbomConfig": {
      "type": "object",
      "properties": {
        "args": {
          "description": "Command-line arguments (supports templates and $artifact, $document vars).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "artifacts": {
          "description": "Which artifacts to catalog: \"source\", \"archive\", \"binary\", \"package\", \"diskimage\", \"installer\", \"any\" (default: \"archive\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "cmd": {
          "description": "Command to run for SBOM generation (default: \"syft\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "documents": {
          "description": "Output document path templates (supports templates).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "env": {
          "description": "Environment variables to pass to the command, as `KEY=VALUE` strings. Order is preserved. Values are template-rendered before being set.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "id": {
          "description": "Unique identifier for this SBOM config (default: \"default\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Filter by artifact IDs (ignored if artifacts=\"source\").",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "skip": {
          "description": "Skip this SBOM config. Accepts bool or template string. Accepts the legacy `disable:` spelling via serde alias for back-compat.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "SchemaEntry": {
      "description": "One schema registration. `url` XOR `schema_file` selects the mode.",
      "type": "object",
      "properties": {
        "crate": {
          "description": "Crate whose version a vendored/versioned schema tracks (per-crate workspaces).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "description": {
          "description": "Catalog description (required at publish time; derived if omitted).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "file_match": {
          "description": "Well-known config filenames this schema validates (folder globs need `**/`).",
          "default": [],
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Per-entry Tera condition.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "name": {
          "description": "Catalog display name (may be Title Case, e.g. `Anodizer`).",
          "default": "",
          "type": "string"
        },
        "required": {
          "description": "Whether a failure here fails the release. Collapsed across `schemas`.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "schema_file": {
          "description": "VENDOR mode: repo-root-relative path to the generated schema file.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "skip": {
          "description": "Per-entry skip. Alias: `disable`.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "slug": {
          "description": "Vendor filename / url basename. Defaults to `name` slugified. Vendor-only.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "url": {
          "description": "EXTERNAL mode: the URL you host the schema at.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "versioned": {
          "description": "Emit a version-suffixed vendored file + `versions` map. Vendor-only.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "SchemastoreConfig": {
      "description": "Top-level `schemastore:` block. Shared fields here are defaults for every entry in `schemas`; a per-entry field overrides them (cascade).",
      "type": "object",
      "properties": {
        "commit_author": {
          "description": "Commit author for the SchemaStore commit (defaults to git config).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/CommitAuthorConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "if": {
          "description": "Tera condition; when it renders falsy the publisher is skipped.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "repository": {
          "description": "Fork of `SchemaStore/schemastore` to push branches to and open the PR from.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/RepositoryConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "retain_on_rollback": {
          "description": "When `true`, a triggered rollback leaves this publisher's work in place rather than attempting to undo it. Default `false`.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "schemas": {
          "description": "The schema entries to register/refresh.",
          "default": [],
          "type": "array",
          "items": {
            "$ref": "#/definitions/SchemaEntry"
          }
        },
        "skip": {
          "description": "Skip the whole publisher. Alias: `disable`.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "versioned": {
          "description": "Default for `SchemaEntry::versioned`.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "ScmRepoConfig": {
      "type": "object",
      "required": [
        "name",
        "owner"
      ],
      "properties": {
        "name": {
          "description": "Repository name.",
          "type": "string"
        },
        "owner": {
          "description": "Repository owner (user or organization).",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "ScoopConfig": {
      "type": "object",
      "properties": {
        "amd64_variant": {
          "description": "amd64 microarchitecture variant filter (e.g. \"v1\", \"v2\", \"v3\", \"v4\"). Only artifacts matching this variant are included. Default: \"v1\".",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "commit_author": {
          "description": "Commit author with optional signing.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/CommitAuthorConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "commit_msg_template": {
          "description": "Custom commit message template.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "depends": {
          "description": "Application dependencies (other Scoop packages).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "description": {
          "description": "Short description of the package (shown in `scoop info`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "directory": {
          "description": "Subdirectory in the bucket repo for manifest placement.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "homepage": {
          "description": "Project homepage URL. Falls back to the GitHub-derived URL when unset.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs filter: only include artifacts whose `id` is in this list.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional gate: when the rendered result is falsy (`\"false\"` / `\"0\"` / `\"no\"` / empty), the Scoop publisher is skipped. Render failure hard-errors. Config key: `scoop[].if:`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "license": {
          "description": "SPDX license identifier (e.g., \"MIT\", \"Apache-2.0\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "name": {
          "description": "Override the manifest name (default: crate name).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "persist": {
          "description": "Data paths persisted between Scoop updates.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "post_install": {
          "description": "Commands to run after installation.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "pre_install": {
          "description": "Commands to run before installation.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "repository": {
          "description": "Unified repository config with branch, token, PR, git SSH support. (Replaces the legacy `bucket: BucketConfig` owner/name-only form.)",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/RepositoryConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "required": {
          "description": "Override whether this publisher failing should fail the overall release.\n\nDefault: `false` — a failure here is logged but does not abort the release. Set to `true` to fail the release on any error.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "retain_on_rollback": {
          "description": "When `true`, a triggered rollback leaves this publisher's work in place rather than attempting to undo it. Default `false`.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "shortcuts": {
          "description": "Start menu shortcuts as `[executable, label]` pairs.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "skip_upload": {
          "description": "Skip publishing the manifest.  `\"true\"` always skips; `\"auto\"` skips for prerelease versions. Accepts bool or template string.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "url_template": {
          "description": "Custom URL template for download URLs (overrides release URL).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "use": {
          "description": "Artifact selection: \"archive\" (default), \"msi\", or \"nsis\".",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "SignConfig": {
      "type": "object",
      "properties": {
        "args": {
          "description": "Arguments passed to the signing command (supports templates with ${artifact} and ${signature}).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "artifacts": {
          "description": "Artifact types to sign: \"all\", \"archive\", \"binary\", \"checksum\", \"package\", \"sbom\" (default: \"none\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "certificate": {
          "description": "Certificate file to embed in the signature (Cosign bundle signing).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "cmd": {
          "description": "Signing command to invoke (default: \"cosign\" or \"gpg\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "env": {
          "description": "Environment variables passed to the signing command.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "id": {
          "description": "Unique identifier for this sign config.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs filter: only sign artifacts from builds whose `id` is in this list.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional: skip this sign config if rendered result is \"false\" or empty.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "output": {
          "description": "Capture and log stdout/stderr of the signing command. Accepts bool or template string (e.g., \"{{ IsSnapshot }}\").",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "signature": {
          "description": "Signature output filename template (supports templates).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "stdin": {
          "description": "Content written to the signing command's stdin.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "stdin_file": {
          "description": "Path to a file whose content is written to the signing command's stdin.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "SlackAnnounce": {
      "type": "object",
      "properties": {
        "attachments": {
          "description": "Slack legacy attachments (typed for schema validation).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/SlackAttachment"
          }
        },
        "blocks": {
          "description": "Slack Block Kit blocks (typed for schema validation).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/SlackBlock"
          }
        },
        "channel": {
          "description": "Override the webhook's default channel (e.g. \"#releases\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "enabled": {
          "description": "Enable Slack announcements (supports template expressions).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "icon_emoji": {
          "description": "Override the webhook's default icon with an emoji (e.g. \":rocket:\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "icon_url": {
          "description": "Override the webhook's default icon with an image URL.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "message_template": {
          "description": "Message template for the Slack post. Default: \"{{ ProjectName }} {{ Tag }} is out! Check it out at {{ ReleaseURL }}\"",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "username": {
          "description": "Override the webhook's default username (e.g. \"release-bot\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "webhook_url": {
          "description": "Slack incoming webhook URL. Use template `{{ Env.SLACK_WEBHOOK }}` to reference an environment variable.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "SlackAttachment": {
      "description": "A Slack legacy attachment. Common fields are typed; additional fields are captured via flatten.",
      "type": "object",
      "properties": {
        "color": {
          "description": "Attachment sidebar color (hex string, e.g., \"#36a64f\" for green).",
          "type": [
            "string",
            "null"
          ]
        },
        "fallback": {
          "description": "Plain-text summary shown in notifications that cannot render attachments.",
          "type": [
            "string",
            "null"
          ]
        },
        "footer": {
          "description": "Small text shown at the bottom of the attachment.",
          "type": [
            "string",
            "null"
          ]
        },
        "pretext": {
          "description": "Text shown above the attachment block.",
          "type": [
            "string",
            "null"
          ]
        },
        "text": {
          "description": "Main body text of the attachment (supports template variables).",
          "type": [
            "string",
            "null"
          ]
        },
        "title": {
          "description": "Bold title text at the top of the attachment.",
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": true
    },
    "SlackBlock": {
      "description": "A Slack Block Kit block element. Common fields are typed; additional block-type-specific fields are captured via flatten.",
      "type": "object",
      "required": [
        "type"
      ],
      "properties": {
        "block_id": {
          "description": "Block ID for interactive payloads.",
          "type": [
            "string",
            "null"
          ]
        },
        "text": {
          "description": "Text object for the block (used by header, section, context types).",
          "anyOf": [
            {
              "$ref": "#/definitions/SlackTextObject"
            },
            {
              "type": "null"
            }
          ]
        },
        "type": {
          "description": "Block type (e.g., \"header\", \"section\", \"divider\", \"actions\", \"context\", \"image\").",
          "type": "string"
        }
      },
      "additionalProperties": true
    },
    "SlackTextObject": {
      "description": "A Slack text composition object.",
      "type": "object",
      "required": [
        "text",
        "type"
      ],
      "properties": {
        "emoji": {
          "description": "Whether to render emoji shortcodes (plain_text only).",
          "type": [
            "boolean",
            "null"
          ]
        },
        "text": {
          "description": "Text content (supports template variables).",
          "type": "string"
        },
        "type": {
          "description": "Text type: \"plain_text\" or \"mrkdwn\".",
          "type": "string"
        },
        "verbatim": {
          "description": "Whether to render verbatim (mrkdwn only).",
          "type": [
            "boolean",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "SmokeImage": {
      "description": "A single per-package smoke-test image selection.",
      "type": "object",
      "required": [
        "image"
      ],
      "properties": {
        "image": {
          "description": "The container image reference (e.g. `debian:12`, `fedora:40`).",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "SnapcraftApp": {
      "type": "object",
      "properties": {
        "adapter": {
          "description": "Snap adapter type: \"none\" or \"full\" (default: \"full\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "after": {
          "description": "Services that must start before this app.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "aliases": {
          "description": "Alternative names for the command.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "args": {
          "description": "Additional arguments passed to the command.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "autostart": {
          "description": "Desktop file for autostart.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "before": {
          "description": "Services that must start after this app.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "bus_name": {
          "description": "D-Bus well-known bus name.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "command": {
          "description": "Command to run (relative to snap root).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "command_chain": {
          "description": "Wrapper commands run before the main command.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "common_id": {
          "description": "AppStream metadata common ID.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "completer": {
          "description": "Path to bash completion script relative to snap.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "daemon": {
          "description": "Daemon type: simple, forking, oneshot, notify, dbus.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "desktop": {
          "description": "Path to .desktop file relative to snap.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "environment": {
          "description": "Environment variables for the app (supports string, integer, and boolean values).",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": true
        },
        "extensions": {
          "description": "Snap extensions to apply.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "install_mode": {
          "description": "Installation mode: \"enable\" or \"disable\".",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "passthrough": {
          "description": "Arbitrary YAML passed through to snap.yaml.",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": true
        },
        "plugs": {
          "description": "Interface plugs the app needs.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "post_stop_command": {
          "description": "Command to run after daemon stops.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "refresh_mode": {
          "description": "Refresh behavior: \"endure\" or \"restart\".",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "reload_command": {
          "description": "Command to reload daemon config.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "restart_condition": {
          "description": "Restart condition: on-failure, always, on-success, on-abnormal, on-abort, on-watchdog, never.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "restart_delay": {
          "description": "Delay between restarts (duration string).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "slots": {
          "description": "Interface slots this app provides.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "sockets": {
          "description": "Socket definitions map.",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": true
        },
        "start_timeout": {
          "description": "Start timeout duration string.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "stop_command": {
          "description": "Command to gracefully stop the daemon.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "stop_mode": {
          "description": "How to stop the daemon: sigterm, sigkill, etc.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "stop_timeout": {
          "description": "Stop timeout duration string.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "timer": {
          "description": "Timer definition (systemd timer syntax).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "watchdog_timeout": {
          "description": "Watchdog timeout duration string.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "SnapcraftConfig": {
      "type": "object",
      "properties": {
        "apps": {
          "description": "Application configurations defining daemons, commands, env vars.",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {
            "$ref": "#/definitions/SnapcraftApp"
          }
        },
        "assumes": {
          "description": "Required snapd features/versions.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "base": {
          "description": "Runtime base snap: core, core18, core20, core22, core24, bare.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "channel_templates": {
          "description": "Distribution channels: edge, beta, candidate, stable.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "confinement": {
          "description": "Security confinement level: strict, devmode, classic.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "description": {
          "description": "Extended description (user-facing in store).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "extra_files": {
          "description": "Additional static files to bundle (string shorthand or structured form).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/SnapcraftExtraFileSpec"
          }
        },
        "grade": {
          "description": "Release stability level: stable, devel.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "hooks": {
          "description": "Snap hooks — maps hook name to arbitrary hook config.",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": true
        },
        "icon": {
          "description": "Path to the snap icon image (`.png` or `.svg`).\n\nWhen set, anodizer copies the file to `meta/gui/<name>.<ext>` inside the staged prime directory before `snapcraft pack` runs. The icon is delivered to the Snap Store via snapcraft's GUI metadata channel and never appears in `snap.json`, keeping uploads schema-clean. (The Snap Store rejects `snap.json` that contains an `icon:` key with \"Additional properties are not allowed ('icon' was unexpected)\".)\n\nThe source path may be absolute or relative to the project root. Anodizer errors before staging if the file does not exist.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "id": {
          "description": "Unique identifier for this snapcraft config.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs to include. Empty means all builds.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional gate: when the rendered result is falsy (`\"false\"` / `\"0\"` / `\"no\"` / empty), the snapcraft config is skipped. Render failure hard-errors. The `snapcrafts[].if:`. Distinct from `skip:` (always-skip predicate).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "layout": {
          "description": "Directory mappings for sandbox accessibility.\n\nAccepts the legacy plural `layouts:` spelling via serde alias for back-compat with imported configs.",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {
            "$ref": "#/definitions/SnapcraftLayout"
          }
        },
        "license": {
          "description": "License identifier (SPDX format).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "mod_timestamp": {
          "description": "Output timestamp for reproducible builds.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "name": {
          "description": "Snap package name in the store.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "name_template": {
          "description": "Template for the output snap filename.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "plugs": {
          "description": "Top-level snap plug definitions (structured map). Keys are plug names, values are either `null` (simple plug) or an object with `interface` and optional attributes (e.g. `{ interface: \"content\", target: \"$SNAP/shared\" }`). An arbitrary key/value map for this field.",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": true
        },
        "publish": {
          "description": "Whether to publish to the snapcraft store.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "replace": {
          "description": "Remove source archives from artifacts, keeping only snap.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "skip": {
          "description": "Skip this snapcraft config. Accepts bool or template string (e.g. `\"{{ if .IsSnapshot }}true{{ endif }}\"` for conditional skip). Accepts the legacy `disable:` spelling via serde alias for back-compat.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "summary": {
          "description": "Single-line elevator pitch (max 79 characters).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "templated_extra_files": {
          "description": "Extra files whose contents are rendered through the template engine before bundling. Unlike `extra_files` which copy as-is, template variables like `{{ Tag }}` are expanded.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/TemplatedExtraFile"
          }
        },
        "title": {
          "description": "Canonical application title (user-facing in store).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "SnapcraftExtraFileSpec": {
      "description": "Specifies an extra file for snapcraft. Can be a simple source path string or a structured object with source, destination, and mode fields (matching the snapcraft extra-files shape).",
      "anyOf": [
        {
          "description": "Simple source path string.",
          "type": "string"
        },
        {
          "description": "Structured form with source, destination, and mode.",
          "type": "object",
          "required": [
            "source"
          ],
          "properties": {
            "destination": {
              "type": [
                "string",
                "null"
              ]
            },
            "mode": {
              "type": [
                "integer",
                "null"
              ],
              "format": "uint32",
              "minimum": 0.0
            },
            "source": {
              "type": "string"
            }
          }
        }
      ]
    },
    "SnapcraftLayout": {
      "type": "object",
      "properties": {
        "bind": {
          "description": "Bind-mount a directory to the snap's layout.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "bind_file": {
          "description": "Bind-mount a single file to the snap's layout.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "symlink": {
          "description": "Symlink a path to a location in the snap.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "type": {
          "description": "Layout entry type.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "SnapshotConfig": {
      "type": "object",
      "required": [
        "version_template"
      ],
      "properties": {
        "version_template": {
          "description": "Version string template for snapshot builds (e.g., \"{{ Commit }}-SNAPSHOT\"). Accepts the deprecated `name_template:` alias (renamed to `version_template`): a non-empty `name_template` is folded into `version_template`. A deprecation warning is emitted at config-load time when the alias is hit (see `apply_snapshot_legacy_aliases`).",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "SourceConfig": {
      "type": "object",
      "properties": {
        "enabled": {
          "description": "When true, generate a source code archive for the release.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "files": {
          "description": "Extra files to include in the source archive. Accepts strings (glob patterns) or objects with src/dst/info.",
          "default": [],
          "type": "array",
          "items": {
            "$ref": "#/definitions/SourceFileEntry"
          }
        },
        "format": {
          "description": "Archive format for the source tarball: tar.gz, tgz, tar, or zip (default: tar.gz).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "name_template": {
          "description": "Filename template for the source archive (supports templates).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "prefix_template": {
          "description": "Prefix prepended to all paths inside the archive (supports templates). Defaults to name_template value. Use this to set a different prefix than the archive name.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "SourceFileEntry": {
      "description": "An individual file entry for the source archive, supporting src/dst mapping and file metadata overrides.",
      "type": "object",
      "properties": {
        "dst": {
          "description": "Destination path within the archive prefix directory.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "info": {
          "description": "File metadata overrides.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/SourceFileInfo"
            },
            {
              "type": "null"
            }
          ]
        },
        "src": {
          "description": "Source file path or glob pattern.",
          "default": "",
          "type": "string"
        },
        "strip_parent": {
          "description": "Strip the parent directory from the source path.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "SourceFileInfo": {
      "description": "File metadata overrides for source archive entries.",
      "type": "object",
      "properties": {
        "group": {
          "description": "File group.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "mode": {
          "description": "File permissions mode. Accepts a YAML int (decimal) or an octal-prefixed string (`\"0o755\"`, `\"0755\"`). Stored as a `u32` after parsing — see [`StringOrU32`].",
          "default": null,
          "type": [
            "integer",
            "null"
          ],
          "format": "uint32",
          "minimum": 0.0
        },
        "mtime": {
          "description": "Modification time in RFC3339 format (supports templates).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "owner": {
          "description": "File owner.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "SrpmConfig": {
      "type": "object",
      "properties": {
        "bins": {
          "description": "Map of binary name → install path declared in the spec's `%files` section. Each entry tells the generated `.spec` which installed file the package owns. When omitted, each binary produced by the build for this crate defaults to `%{_bindir}/<name>` (i.e. `/usr/bin/<name>`, the RPM-idiomatic location for a built binary). Provide this only to override the install path or to declare extra owned paths. Stored as a `BTreeMap` so the emitted `%files` section iterates in deterministic key order.",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {
            "type": "string"
          }
        },
        "build_host": {
          "description": "Override the build host recorded in the RPM header. Useful for reproducible builds where the actual hostname leaks build-env detail.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "compression": {
          "description": "Compression algorithm (gzip, xz, zstd, none).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "contents": {
          "description": "Additional contents to include in the source RPM. Shares the unified [`NfpmContent`] type with nFPM contents; SRPM-style `source:` / `destination:` / `type:` keys are accepted via serde aliases.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/NfpmContent"
          }
        },
        "description": {
          "description": "Package description.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "docs": {
          "description": "Documentation files to include.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "enabled": {
          "description": "Enable source RPM generation. Default: false.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "epoch": {
          "description": "RPM epoch.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "file_name_template": {
          "description": "Output filename template.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "group": {
          "description": "RPM group.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "license": {
          "description": "License identifier.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "license_file_name": {
          "description": "License file name to include.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "maintainer": {
          "description": "Package maintainer.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "package_name": {
          "description": "Package name (default: project_name).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "packager": {
          "description": "RPM packager field.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "posttrans": {
          "description": "`%posttrans` scriptlet — executed *after* all packages in the transaction have been installed. Path to a script file.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "prefixes": {
          "description": "Filesystem prefixes the package may install to (RPM `Prefix:` tag). Each entry becomes one `Prefix:` directive — relocatable RPMs need at least one prefix declared.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "prerelease": {
          "description": "Prerelease suffix appended to the version (e.g. `rc1`, `beta2`). Prerelease component of the package version.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "pretrans": {
          "description": "`%pretrans` scriptlet — executed on the package transaction *before* any package in the transaction is installed. Path to a script file.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "section": {
          "description": "RPM section.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "signature": {
          "description": "RPM signature configuration. Shares the unified [`NfpmSignatureConfig`] type with nFPM.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/NfpmSignatureConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "skip": {
          "description": "Skip this config. Accepts bool or template string.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "spec_file": {
          "description": "Path to the RPM spec file template.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "summary": {
          "description": "Summary line.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "url": {
          "description": "Homepage URL.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "vendor": {
          "description": "Package vendor.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "version_metadata": {
          "description": "Build metadata appended to the version (e.g. git commit hash). Version-metadata component of the package version.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "StringOrBool": {
      "description": "A value that can be either a bool or a template string. Used by `skip`, `skip_upload`, and similar fields across multiple config structs to support both `skip: true` and template conditionals like `skip: \"{{ if .IsSnapshot }}true{{ endif }}\"`.",
      "anyOf": [
        {
          "type": "boolean"
        },
        {
          "type": "string"
        }
      ]
    },
    "StructuredHook": {
      "type": "object",
      "properties": {
        "artifacts": {
          "description": "Artifact-kind filter (`before_publish:` only). When `Some`, the per-artifact iteration only fires for artifacts whose [`ArtifactKind`] matches the filter. `None` is equivalent to [`BeforePublishArtifactFilter::All`] (every registered artifact). Ignored by lifecycle hook sites for the same reason as `ids`.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/BeforePublishArtifactFilter"
            },
            {
              "type": "null"
            }
          ]
        },
        "cmd": {
          "description": "Command to run.\n\nThe entire string is interpreted by `sh -c`, so shell metacharacters (`|`, `;`, `&&`, backticks, `$()`, redirects, globs) are honoured — any templated values folded into `cmd` become part of the shell command and are subject to word-splitting and metacharacter expansion. Keep templated user-config values out of `cmd` when possible, or quote them defensively (e.g. `'{{ Env.FOO }}'`). Hooks already run with `env_clear()` plus an allow-list, so secrets in `$ENV` are not inherited unless explicitly listed in `env`.",
          "default": "",
          "type": "string"
        },
        "dir": {
          "description": "Working directory for the command (defaults to project root).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "env": {
          "description": "Environment variables for the command.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "ids": {
          "description": "Artifact-id allow-list (`before_publish:` only). When `Some`, the per-artifact iteration only fires for artifacts whose `metadata[\"id\"]` matches one of these strings. `None` (the default) imposes no id constraint. Ignored by lifecycle hook sites (`before:` / `after:` / per-build / per-archive) — those run once per pipeline tick, not per artifact.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional: when set, the hook only runs if the rendered result is truthy (not `\"false\"` / `\"0\"` / `\"no\"` / empty). Render failure hard-errors (not silent-skip). `before.hooks[].if:` / per-build / per-archive hook `if:` surface.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "output": {
          "description": "When true, capture and log stdout/stderr of the command.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "TagConfig": {
      "type": "object",
      "properties": {
        "branch_history": {
          "description": "Branch history mode for determining the previous tag: \"full\" or \"last\".",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "bump_minor_pre_major": {
          "description": "While the current major version is `0`, demote a conventional breaking change (`feat!:` / `BREAKING CHANGE`) from a major bump to a minor bump (e.g. `0.5.0` → `0.6.0` instead of `1.0.0`). Honors the SemVer rule that anything may change in the `0.y.z` range. An explicit `#major`/`#minor` token, a `custom_tag`, or a manually-ahead `Cargo.toml` version always wins over this demotion. No-op once a real tag reaches `1.x`. Default false.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "bump_patch_for_minor_pre_major": {
          "description": "While the current major version is `0`, demote a conventional feature (`feat:`) from a minor bump to a patch bump (e.g. `0.5.0` → `0.5.1` instead of `0.6.0`). Independent of `bump_minor_pre_major`. An explicit token / `custom_tag` / ahead `Cargo.toml` always wins. No-op at `1.x`. Default false.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "custom_tag": {
          "description": "Custom version tag to use instead of auto-incrementing.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "default_bump": {
          "description": "Default bump when a commit range carries no explicit `#` token and no conventional-commit marker: \"major\", \"minor\", \"patch\", or \"none\". Defaults to \"none\" — a range of only chore/docs/style/refactor/test/ build/ci commits produces no release (the conventional-commit contract). Set \"patch\"/\"minor\" to cut a release on every range regardless of type.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "force_without_changes": {
          "description": "When true, create a new tag even if no commits have changed since the last tag.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "force_without_changes_pre": {
          "description": "Like force_without_changes but only for pre-release versions.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "git_api_tagging": {
          "description": "When true, use the GitHub/GitLab API for tagging instead of git CLI.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "initial_version": {
          "description": "Version string to use when no previous tag exists (default: \"0.1.0\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "major_string_token": {
          "description": "Conventional commit token triggering a major bump (default: \"major\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "minor_string_token": {
          "description": "Conventional commit token triggering a minor bump (default: \"minor\" or \"feat\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "none_string_token": {
          "description": "Conventional commit token suppressing a version bump entirely (default: \"none\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "patch_string_token": {
          "description": "Conventional commit token triggering a patch bump (default: \"patch\" or \"fix\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "prerelease": {
          "description": "When true, apply a pre-release suffix to the generated version.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "prerelease_suffix": {
          "description": "Suffix appended to pre-release versions (e.g., \"beta\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "push": {
          "description": "When true, `anodizer tag` also pushes the version-sync bump commit to the release branch (atomically with the tag), not just the tag. CLI `--push` / `--no-push` override this. Default false preserves the \"push the tag, inspect the branch locally before pushing\" workflow.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "release_branches": {
          "description": "Branch name patterns (supports wildcards) that trigger releases (default: [\"master\", \"main\"]).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "skip_ci_on_bump": {
          "description": "Append `[skip ci]` to the version-sync bump commit subject.\n\nOff by default. Only enable with a `workflow_run`-triggered release workflow: `[skip ci]` on the bump commit (which becomes the tag target) ALSO suppresses an `on: push: tags:` release trigger, so enabling this with a tag-push-triggered release silently skips the release. Leave off for the tag-push pattern; enable for the `workflow_run` pattern to skip the (already crate-gated, harmless) redundant CI re-run.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "tag_context": {
          "description": "Source for determining the previous tag: \"repo\" (default) or \"branch\".",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "tag_post_hooks": {
          "description": "Commands to run after `anodizer tag` successfully creates and pushes the tag. Env and template vars same as `tag_pre_hooks`.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/HookEntry"
          }
        },
        "tag_pre_hooks": {
          "description": "Commands to run before `anodizer tag` creates the tag. Useful for updating lockfiles or committing sibling changes that must be part of the tagged commit. Env: `ANODIZER_CURRENT_TAG`, `ANODIZER_PREVIOUS_TAG` are set; template vars `{{ Tag }}`, `{{ PreviousTag }}`, `{{ Version }}`, `{{ PrefixedTag }}` are available.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/HookEntry"
          }
        },
        "tag_prefix": {
          "description": "Prefix prepended to version tags (e.g., \"v\" produces \"v1.2.3\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "verbose": {
          "description": "When true, print verbose tag calculation output.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "TeamsAnnounce": {
      "type": "object",
      "properties": {
        "color": {
          "description": "Theme color for the card (hex string, e.g. \"0076D7\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "enabled": {
          "description": "Enable Microsoft Teams announcements (supports template expressions).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "icon_url": {
          "description": "Icon URL displayed in the card header.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "message_template": {
          "description": "Message template for the Adaptive Card body. Default: \"{{ ProjectName }} {{ Tag }} is out! Check it out at {{ ReleaseURL }}\"",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "title_template": {
          "description": "Title template for the Adaptive Card header. Default: \"{{ ProjectName }} {{ Tag }} is out!\"",
          "default": "{{ ProjectName }} {{ Tag }} is out!",
          "type": [
            "string",
            "null"
          ]
        },
        "webhook_url": {
          "description": "Teams incoming webhook URL.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "TelegramAnnounce": {
      "type": "object",
      "properties": {
        "bot_token": {
          "description": "Telegram Bot API token. Get one from @BotFather.\n\nPrefer `{{ Env.TELEGRAM_BOT_TOKEN }}` over an in-config literal — plaintext tokens grant full bot impersonation and are NOT redacted from error messages or `dist/config.yaml` after a dry-run / snapshot run.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "chat_id": {
          "description": "Telegram chat ID to send the message to (supports template variables).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "enabled": {
          "description": "Enable Telegram announcements. Requires bot_token and chat_id (supports template expressions).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "message_template": {
          "description": "Message template. Default: \"{{ ProjectName }} {{ Tag }} is out! Check it out at {{ ReleaseURL }}\"",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "message_thread_id": {
          "description": "Message thread ID for sending to a specific topic in a forum group. Supports template expressions; parsed to i64 at runtime.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "parse_mode": {
          "description": "Parse mode: \"MarkdownV2\" or \"HTML\" (defaults to \"MarkdownV2\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "TemplateFileConfig": {
      "description": "Configuration for a template file that is rendered through the template engine and placed in the dist directory as a release artifact.\n\nAll rendered template files are uploaded to the release by default. Both `src` and `dst` paths support template rendering.",
      "type": "object",
      "properties": {
        "dst": {
          "description": "Destination filename, prefixed with the dist directory. Templates: allowed.",
          "default": "",
          "type": "string"
        },
        "id": {
          "description": "Identifier for this template file entry (default: \"default\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "mode": {
          "description": "File permissions in octal notation as a string, e.g. `\"0755\"` (default: `\"0655\"`). Parsed at runtime via `parse_octal_mode()` to avoid YAML interpreting as decimal.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "skip": {
          "description": "Skip this entry when truthy. Accepts a literal bool or a Tera template that renders to `\"true\"`/`\"false\"` (e.g. `'{{ if eq .Os \"windows\" }}true{{ end }}'`). Mirrors the per-entry `skip:` pattern used by `ChangelogConfig`, `ChecksumConfig`, and the publishers.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "src": {
          "description": "Source template file path. The file contents are rendered through the template engine. Templates: allowed (in path itself).",
          "default": "",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "TemplatedExtraFile": {
      "description": "A file whose contents are rendered through the template engine before use. Used by `templated_extra_files` across multiple stages.",
      "type": "object",
      "properties": {
        "dst": {
          "description": "Destination filename for the rendered output. Supports template variables (e.g. `\"{{ ProjectName }}-NOTES.txt\"`).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "mode": {
          "description": "File permissions in octal notation as a string, e.g. `\"0755\"`. Parsed at runtime via `parse_octal_mode()` to avoid YAML interpreting as decimal.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "src": {
          "description": "Source template file path.",
          "default": "",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "TwitterAnnounce": {
      "type": "object",
      "properties": {
        "enabled": {
          "description": "Enable Twitter/X announcements. Requires TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET, TWITTER_ACCESS_TOKEN, TWITTER_ACCESS_TOKEN_SECRET env vars (supports template expressions).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "message_template": {
          "description": "Tweet message template. Default: \"{{ ProjectName }} {{ Tag }} is out! Check it out at {{ ReleaseURL }}\"",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "UniversalBinaryConfig": {
      "type": "object",
      "properties": {
        "hooks": {
          "description": "Pre/post hooks around universal binary creation.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/BuildHooksConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "id": {
          "description": "Unique identifier for this universal binary, propagated into the artifact's metadata as `id`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs filter: only combine artifacts from builds whose `id` is in this list.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "mod_timestamp": {
          "description": "Override the modification timestamp for reproducible universal binaries.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "name_template": {
          "description": "Output filename template for the universal binary (supports templates).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "replace": {
          "description": "When true, remove the individual arch binaries after creating the universal binary.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "UploadConfig": {
      "type": "object",
      "properties": {
        "checksum": {
          "description": "Include checksums in uploaded artifacts.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "checksum_header": {
          "description": "Header name for the SHA256 checksum of the artifact.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "client_x509_cert": {
          "description": "Path to PEM-encoded client X.509 certificate for mTLS.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "client_x509_key": {
          "description": "Path to PEM-encoded client X.509 key for mTLS.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "custom_artifact_name": {
          "description": "When true, use the artifact name as-is (don't append to target URL).",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "custom_headers": {
          "description": "Custom HTTP headers (each value is template-expanded).",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {
            "type": "string"
          }
        },
        "extra_files": {
          "description": "Extra files to include in uploading.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/ExtraFileSpec"
          }
        },
        "extra_files_only": {
          "description": "Upload only extra files, skip normal artifacts.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "exts": {
          "description": "File extension filter: only upload artifacts with these extensions.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "ids": {
          "description": "Build IDs filter: only upload artifacts whose `id` is in this list.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional gate: when the rendered result is falsy (`\"false\"` / `\"0\"` / `\"no\"` / empty), the upload is skipped. Render failure hard-errors. The `uploads[].if:` conditional gate.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "meta": {
          "description": "Include metadata artifacts in uploaded artifacts.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "method": {
          "description": "HTTP method: PUT or POST (default: PUT).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "mode": {
          "description": "Upload mode: \"archive\" (default) or \"binary\".",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "name": {
          "description": "Human-readable name for this upload config.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "password": {
          "description": "Password for HTTP basic auth.\n\nStrongly prefer `{{ Env.UPLOAD_PASSWORD }}` (or any other env-var template) over an in-config literal — plaintext values here are NOT redacted from dry-run output and will land in `dist/config.yaml` when the pipeline runs with `--dry-run` / `--snapshot`. Resolution order: rendered `password` template → env `UPLOAD_{NAME}_SECRET`. Password-resolution cascade.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "signature": {
          "description": "Include signatures in uploaded artifacts.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "skip": {
          "description": "Skip condition template (if rendered to \"true\", skip this upload).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "target": {
          "description": "Target URL template (supports template variables like {{ ProjectName }}, {{ Version }}).",
          "default": "",
          "type": "string"
        },
        "trusted_certificates": {
          "description": "Path to PEM-encoded trusted CA certificates.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "username": {
          "description": "Username for HTTP basic auth. Resolution order: rendered `username` template → env `UPLOAD_{NAME}_USERNAME`. Set this to a literal value or a `{{ Env.X }}` template.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "UpxConfig": {
      "type": "object",
      "properties": {
        "args": {
          "description": "Extra arguments passed to UPX (e.g., [\"-9\", \"--brute\"]).",
          "default": [],
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "binary": {
          "description": "UPX executable path or name (default: \"upx\").",
          "default": "upx",
          "type": "string"
        },
        "brute": {
          "description": "Use brute-force compression (--brute flag). Very slow but produces smallest output.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "compress": {
          "description": "UPX compression level string (e.g., \"1\"-\"9\", \"best\"). Maps to `--compress` flag.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "enabled": {
          "description": "Whether to compress binaries with UPX. Accepts a bool or a template string that evaluates to a bool.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "id": {
          "description": "Unique identifier for this UPX config.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs filter: only compress binaries from builds whose `id` is in this list.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "lzma": {
          "description": "Use LZMA compression (--lzma flag).",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "required": {
          "description": "When true, fail the build if UPX is not found.",
          "default": false,
          "type": "boolean"
        },
        "targets": {
          "description": "Target triples to compress binaries for (empty means all targets).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        }
      },
      "additionalProperties": false
    },
    "VerifyReleaseConfig": {
      "description": "Top-level `verify_release:` block.\n\nSee the module-level docs for the verification lifecycle. The gate is a no-op unless `enabled: true`.",
      "type": "object",
      "properties": {
        "assert_assets": {
          "description": "Assert that every produced artifact has a matching uploaded asset on the published release, and that every signature / certificate / SBOM asset the resolved `signs:` / `sboms:` config demands exists there too (derived from config + the artifact set, so a sign or SBOM stage that silently produced nothing still fails the gate with the exact missing names; intentional skips — `if:` falsy, `skip:` truthy, `--skip=sign` — create no expectations). Default `true` (no extra config: anodizer already knows the produced set and can fetch the release's asset list). Independent of Docker and the network smoke-test.",
          "default": true,
          "type": "boolean"
        },
        "enabled": {
          "description": "Whether to run the post-release verification gate at all. Default `false` — the gate is opt-in because it needs the published release to already exist (it runs after publish) and, for install-smoke, a Docker daemon.",
          "default": false,
          "type": "boolean"
        },
        "glibc_ceiling": {
          "description": "glibc version ceiling, e.g. `\"2.36\"`. When any glibc-linked `.deb` requires a glibc NEWER than this floor, the gate reports it and exits non-zero. `None` (the default) disables the libc check entirely. musl binaries have no glibc requirement and are skipped.",
          "type": [
            "string",
            "null"
          ]
        },
        "install_smoke": {
          "description": "Per-package install smoke-test images. When `None`, smoke-testing is off. When present, each package type that produced an artifact is installed in its (configured or default) container and `<bin> --version` is run.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/InstallSmokeConfig"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "VersionSyncConfig": {
      "type": "object",
      "properties": {
        "enabled": {
          "description": "When true, synchronize the crate version with the git tag during release.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "mode": {
          "description": "Sync mode: \"cargo\" (updates Cargo.toml) or \"tag\" (derives version from tag).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "WaitForWorkspaceDepsConfig": {
      "description": "Pre-publish polling gate for `cargo publish`. When `enabled`, the cargo publisher reads its crate's manifest, identifies every dep that points at another crate in the same anodize workspace, and polls `https://index.crates.io/<prefix>/<name>` until each `(name, version)` pair is queryable. Only then does `cargo publish` run.\n\nDefault: disabled. Anodize's own workspaces publish lockstep with one tag; this feature only kicks in for multi-tag-multi-crate workspaces like cfgd where downstream crates can otherwise race the sparse-index propagation of their upstream deps.\n\nComplementary to `cargo.index_timeout`: this gate runs BEFORE publish (waits for *upstream* deps to land), while `index_timeout` runs AFTER publish (waits for the *just-published* crate to land before the next dependent in the same run starts).\n\n```yaml publish: cargo: wait_for_workspace_deps: enabled: true poll_interval: 5s max_wait: 5m ```",
      "type": "object",
      "properties": {
        "enabled": {
          "description": "Master switch. Default `false` preserves today's behavior for single-crate workspaces and lockstep monorepos.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "max_wait": {
          "description": "Hard ceiling on the total wait. The publisher bails with a clear error once `max_wait` elapses without every dep appearing. Humantime-style string (e.g. `\"5m\"`, `\"30s\"`). Default: `\"5m\"`.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/HumanDuration"
            },
            {
              "type": "null"
            }
          ]
        },
        "poll_interval": {
          "description": "Time between successive index probes. Humantime-style string (e.g. `\"5s\"`, `\"500ms\"`, `\"1m\"`). Default: `\"5s\"`.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/HumanDuration"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "WebhookConfig": {
      "type": "object",
      "properties": {
        "content_type": {
          "description": "Content-Type header value. Default: \"application/json\".",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "enabled": {
          "description": "Enable generic webhook announcements (supports template expressions).",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "endpoint_url": {
          "description": "Webhook endpoint URL (supports template variables).\n\nPrefer `{{ Env.WEBHOOK_URL }}` for any URL containing a secret token in its path / query string — plaintext values are NOT redacted from error messages or `dist/config.yaml` after a dry-run / snapshot run.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "expected_status_codes": {
          "description": "HTTP status codes to accept as success (default: [200, 201, 202, 204]).",
          "default": [],
          "type": "array",
          "items": {
            "type": "integer",
            "format": "uint16",
            "minimum": 0.0
          }
        },
        "headers": {
          "description": "Custom HTTP headers to include in the request.\n\nPrecedence — **anodizer-specific**: - anodizer: a config-supplied `Authorization` header wins over the `BASIC_AUTH_HEADER_VALUE` / `BEARER_TOKEN_HEADER_VALUE` env var. - The conventional behaviour: env-supplied `Authorization` is appended FIRST; most servers honour the first occurrence, so the env value effectively wins.\n\nMigrating configs that relied on env-overriding the config header must either remove the config entry or be reconfigured. Use templated config (`Authorization: \"Bearer {{ Env.MY_TOKEN }}\"`) for the cleanest migration.",
          "default": null,
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {
            "type": "string"
          }
        },
        "message_template": {
          "description": "Message body template. Default: \"{{ ProjectName }} {{ Tag }} is out! Check it out at {{ ReleaseURL }}\"",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "skip_tls_verify": {
          "description": "When true, skip TLS certificate verification for the webhook endpoint.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "WingetConfig": {
      "type": "object",
      "properties": {
        "amd64_variant": {
          "description": "amd64 microarchitecture variant filter (e.g. \"v1\", \"v2\", \"v3\", \"v4\"). Only artifacts matching this variant are included. Default: \"v1\".",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "author": {
          "description": "Author name.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "commit_author": {
          "description": "Commit author with optional signing.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/CommitAuthorConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "commit_msg_template": {
          "description": "Custom commit message template.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "copyright": {
          "description": "Copyright notice.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "copyright_url": {
          "description": "Copyright URL.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "dependencies": {
          "description": "Package dependencies.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/WingetDependency"
          }
        },
        "description": {
          "description": "Full package description displayed in the WinGet gallery.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "homepage": {
          "description": "Project homepage URL.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "ids": {
          "description": "Build IDs filter: only include artifacts whose `id` is in this list.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "if": {
          "description": "Template-conditional gate: when the rendered result is falsy (`\"false\"` / `\"0\"` / `\"no\"` / empty), the WinGet publisher is skipped. Render failure hard-errors. Config key: `winget[].if:`.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "installation_notes": {
          "description": "Post-install notes shown to the user.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "license": {
          "description": "License identifier (required, e.g. \"MIT\").",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "license_url": {
          "description": "License URL.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "name": {
          "description": "Override the package name (default: crate name).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "package_identifier": {
          "description": "WinGet package identifier (e.g. \"Publisher.AppName\"). Auto-generated if empty.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "package_name": {
          "description": "Package name as displayed (default: same as name).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "path": {
          "description": "Manifest file path (auto-generated if empty from publisher/name/version).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "post_publish_poll": {
          "description": "Post-publish PR-validation polling settings. Polling is disabled by default — winget-pkgs PR validation routinely takes hours to days, and blocking a CI workflow on that wait is wrong. Opt in per-publisher with `post_publish_poll: { enabled: true }` when running locally and willing to wait, or disable globally via `--no-post-publish-poll`.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/PostPublishPollConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "privacy_url": {
          "description": "Privacy policy URL.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "product_code": {
          "description": "Product code for the installer (used in Add/Remove Programs).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "publisher": {
          "description": "Publisher name (required).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "publisher_support_url": {
          "description": "Publisher support URL.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "publisher_url": {
          "description": "Publisher homepage URL shown in the WinGet manifest.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "release_notes": {
          "description": "Release notes for this version.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "release_notes_url": {
          "description": "URL to full release notes.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "repository": {
          "description": "Unified repository config with branch, token, PR, git SSH support. (Replaces the legacy `manifests_repo: WingetManifestsRepoConfig`.)",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/RepositoryConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "required": {
          "description": "Override whether this publisher failing should fail the overall release.\n\nDefault: `false` — a failure here is logged but does not abort the release. Set to `true` to fail the release on any error.",
          "type": [
            "boolean",
            "null"
          ]
        },
        "retain_on_rollback": {
          "description": "When `true`, a triggered rollback leaves this publisher's work in place rather than attempting to undo it. Default `false`.",
          "default": null,
          "type": [
            "boolean",
            "null"
          ]
        },
        "short_description": {
          "description": "Short description (required, max 256 chars).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "skip_upload": {
          "description": "Skip publishing. `\"true\"` always skips; `\"auto\"` skips for prereleases. Accepts bool or template string.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "tags": {
          "description": "Tags for package discovery (lowercased, spaces→hyphens).",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "update_existing_pr": {
          "description": "When true, force-push the updated manifest to the existing PR branch when a PR for the same head branch already exists. The PR content is updated in place rather than creating a duplicate. When false (default), the push is skipped and a warning is emitted so the operator sees that the publisher did not update the PR.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/StringOrBool"
            },
            {
              "type": "null"
            }
          ]
        },
        "url_template": {
          "description": "Custom URL template for download URLs (overrides release URL).",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "use": {
          "description": "Artifact selection: \"archive\" (default), \"msi\", or \"nsis\".",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "WingetDependency": {
      "description": "WinGet package dependency.",
      "type": "object",
      "properties": {
        "minimum_version": {
          "description": "Minimum required version of the dependency.",
          "default": null,
          "type": [
            "string",
            "null"
          ]
        },
        "package_identifier": {
          "description": "WinGet package identifier of the dependency (e.g., \"Publisher.App\").",
          "default": "",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "WorkspaceConfig": {
      "description": "A workspace represents an independent project root within a monorepo. Each workspace has its own crates, changelog, and release configuration, allowing independently-versioned components that aren't Cargo workspace members.",
      "type": "object",
      "properties": {
        "after": {
          "description": "Hooks run after this workspace's pipeline completes.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/HooksConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "before": {
          "description": "Hooks run before this workspace's pipeline starts.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/HooksConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "binary_signs": {
          "description": "Binary-specific signing configs (same shape as `signs` but only for binary artifacts). The `artifacts` field on each entry is constrained at parse time to `binary` / `none` (or omitted) — a broader filter on `binary_signs` would silently match nothing because the loop only iterates Binary artifacts. Constraint lives in `deserialize_binary_signs`.",
          "default": [],
          "type": "array",
          "items": {
            "$ref": "#/definitions/SignConfig"
          }
        },
        "changelog": {
          "description": "Changelog configuration for this workspace.",
          "default": null,
          "anyOf": [
            {
              "$ref": "#/definitions/ChangelogConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "crates": {
          "description": "Crates belonging to this workspace.",
          "default": [],
          "type": "array",
          "items": {
            "$ref": "#/definitions/CrateConfig"
          }
        },
        "env": {
          "description": "Environment variables scoped to this workspace.\n\nList of `KEY=VALUE` strings. Order is preserved. Values are template-rendered at pipeline startup.",
          "default": null,
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string"
          }
        },
        "name": {
          "description": "Workspace identifier used in logs and template variables.",
          "default": "",
          "type": "string"
        },
        "signs": {
          "description": "Signing configurations for binaries, archives, and checksums.",
          "default": [],
          "type": "array",
          "items": {
            "$ref": "#/definitions/SignConfig"
          }
        },
        "skip": {
          "description": "Pipeline stages to skip when releasing this workspace. Stage names match the CLI `--skip` flag (e.g., `announce`, `publish`).",
          "default": [],
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "additionalProperties": false
    },
    "WrapInDirectory": {
      "anyOf": [
        {
          "type": "boolean"
        },
        {
          "type": "string"
        }
      ]
    }
  }
}
