{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://porter.sh/schemas/porter.yaml.json",
  "title": "Porter Bundle Manifest",
  "description": "Schema for the porter.yaml bundle manifest file used to author Cloud Native Application Bundles (CNAB) with Porter. The manifest defines a bundle's metadata, actions, parameters, credentials, outputs, and the mixin steps to execute for each action.",
  "type": "object",
  "required": ["schemaType", "name", "version", "registry"],
  "properties": {
    "schemaType": {
      "type": "string",
      "description": "Identifies the document type as a Porter bundle manifest.",
      "const": "Bundle"
    },
    "schemaVersion": {
      "type": "string",
      "description": "Version of the Porter bundle schema this manifest conforms to.",
      "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
      "examples": ["1.0.1"]
    },
    "name": {
      "type": "string",
      "description": "Name of the bundle. Used as the repository name when publishing to an OCI registry.",
      "pattern": "^[a-z0-9][a-z0-9-]*$",
      "maxLength": 128
    },
    "version": {
      "type": "string",
      "description": "Semantic version of the bundle.",
      "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+.*$",
      "examples": ["1.0.0", "0.2.3-beta.1"]
    },
    "description": {
      "type": "string",
      "description": "Human-readable description of what the bundle installs or manages."
    },
    "registry": {
      "type": "string",
      "description": "OCI registry where the bundle will be published, such as 'ghcr.io/myorg' or 'docker.io/myuser'."
    },
    "reference": {
      "type": "string",
      "description": "Full OCI reference override for the bundle image. If omitted, the reference is constructed from registry, name, and version."
    },
    "maintainers": {
      "type": "array",
      "description": "List of bundle maintainers.",
      "items": {
        "$ref": "#/$defs/Maintainer"
      }
    },
    "labels": {
      "type": "object",
      "description": "Arbitrary key-value labels for the bundle.",
      "additionalProperties": {
        "type": "string"
      }
    },
    "annotations": {
      "type": "object",
      "description": "OCI annotations to attach to the bundle image.",
      "additionalProperties": {
        "type": "string"
      }
    },
    "dockerfile": {
      "type": "string",
      "description": "Path to a custom Dockerfile template for building the bundle's invocation image."
    },
    "mixins": {
      "type": "array",
      "description": "List of mixins used in this bundle. Each mixin provides pre-built steps for interacting with tools like Helm, Kubernetes, or Terraform.",
      "items": {
        "$ref": "#/$defs/MixinDeclaration"
      }
    },
    "parameters": {
      "type": "object",
      "description": "Parameter definitions for configuring the bundle at install or upgrade time.",
      "additionalProperties": {
        "$ref": "#/$defs/Parameter"
      }
    },
    "credentials": {
      "type": "object",
      "description": "Credential definitions for secrets required by the bundle, such as kubeconfig files or cloud provider tokens.",
      "additionalProperties": {
        "$ref": "#/$defs/Credential"
      }
    },
    "outputs": {
      "type": "object",
      "description": "Output definitions for values produced by the bundle during action execution.",
      "additionalProperties": {
        "$ref": "#/$defs/Output"
      }
    },
    "state": {
      "type": "array",
      "description": "State definitions for values that are persisted between bundle action runs.",
      "items": {
        "$ref": "#/$defs/StateVariable"
      }
    },
    "dependencies": {
      "$ref": "#/$defs/Dependencies"
    },
    "install": {
      "type": "array",
      "description": "Steps to execute when running the install action. Each step invokes a mixin or custom action.",
      "items": {
        "$ref": "#/$defs/Step"
      }
    },
    "upgrade": {
      "type": "array",
      "description": "Steps to execute when running the upgrade action.",
      "items": {
        "$ref": "#/$defs/Step"
      }
    },
    "uninstall": {
      "type": "array",
      "description": "Steps to execute when running the uninstall action.",
      "items": {
        "$ref": "#/$defs/Step"
      }
    },
    "custom": {
      "type": "object",
      "description": "Custom actions defined beyond the standard install, upgrade, and uninstall CNAB actions.",
      "additionalProperties": {
        "$ref": "#/$defs/CustomAction"
      }
    },
    "images": {
      "type": "object",
      "description": "Container images referenced by the bundle for relocation to air-gapped environments.",
      "additionalProperties": {
        "$ref": "#/$defs/BundleImage"
      }
    },
    "required": {
      "type": "array",
      "description": "Names of extensions required by this bundle.",
      "items": {
        "type": "string"
      }
    }
  },
  "$defs": {
    "Maintainer": {
      "type": "object",
      "description": "A bundle maintainer with contact information.",
      "properties": {
        "name": {
          "type": "string",
          "description": "Name of the maintainer."
        },
        "email": {
          "type": "string",
          "format": "email",
          "description": "Email address of the maintainer."
        },
        "url": {
          "type": "string",
          "format": "uri",
          "description": "URL for the maintainer's website or profile."
        }
      }
    },
    "MixinDeclaration": {
      "description": "Declaration of a mixin used in the bundle, optionally with version and configuration.",
      "oneOf": [
        {
          "type": "string",
          "description": "Simple mixin name without version pinning.",
          "examples": ["exec", "kubernetes", "helm3", "terraform"]
        },
        {
          "type": "object",
          "description": "Mixin declaration with version and optional configuration.",
          "minProperties": 1,
          "maxProperties": 1,
          "additionalProperties": {
            "type": "object",
            "properties": {
              "version": {
                "type": "string",
                "description": "Version of the mixin to use."
              },
              "clientVersion": {
                "type": "string",
                "description": "Version of the client tool the mixin wraps."
              }
            }
          }
        }
      ]
    },
    "Parameter": {
      "type": "object",
      "description": "A configurable parameter that can be passed to the bundle at execution time.",
      "properties": {
        "description": {
          "type": "string",
          "description": "Human-readable description of the parameter."
        },
        "type": {
          "type": "string",
          "description": "JSON Schema type of the parameter.",
          "enum": ["string", "integer", "number", "boolean", "object", "array"]
        },
        "required": {
          "type": "boolean",
          "description": "Whether a value must be provided for this parameter. Defaults to false."
        },
        "default": {
          "description": "Default value used when the parameter is not supplied."
        },
        "sensitive": {
          "type": "boolean",
          "description": "If true, the parameter value is treated as sensitive and masked in logs."
        },
        "enum": {
          "type": "array",
          "description": "List of allowed values for this parameter.",
          "items": {}
        },
        "minimum": {
          "type": "number",
          "description": "Minimum value for numeric parameters."
        },
        "maximum": {
          "type": "number",
          "description": "Maximum value for numeric parameters."
        },
        "minLength": {
          "type": "integer",
          "description": "Minimum string length for string parameters.",
          "minimum": 0
        },
        "maxLength": {
          "type": "integer",
          "description": "Maximum string length for string parameters.",
          "minimum": 0
        },
        "applyTo": {
          "type": "array",
          "description": "List of actions this parameter applies to. If omitted, applies to all actions.",
          "items": {
            "type": "string"
          }
        },
        "path": {
          "type": "string",
          "description": "File path inside the bundle container where the parameter value is written."
        },
        "env": {
          "type": "string",
          "description": "Environment variable name inside the bundle container where the parameter value is set."
        }
      }
    },
    "Credential": {
      "type": "object",
      "description": "A secret or credential required by the bundle for accessing external resources.",
      "properties": {
        "description": {
          "type": "string",
          "description": "Description of what this credential is used for."
        },
        "required": {
          "type": "boolean",
          "description": "Whether this credential must be provided. Defaults to true."
        },
        "path": {
          "type": "string",
          "description": "File path inside the bundle container where the credential is written."
        },
        "env": {
          "type": "string",
          "description": "Environment variable name inside the bundle container for the credential."
        },
        "applyTo": {
          "type": "array",
          "description": "List of actions this credential applies to.",
          "items": {
            "type": "string"
          }
        }
      }
    },
    "Output": {
      "type": "object",
      "description": "A value produced and written by the bundle during an action execution.",
      "required": ["type"],
      "properties": {
        "description": {
          "type": "string",
          "description": "Description of what this output represents."
        },
        "type": {
          "type": "string",
          "description": "JSON Schema type of the output value.",
          "enum": ["string", "integer", "number", "boolean", "object", "array", "file"]
        },
        "sensitive": {
          "type": "boolean",
          "description": "If true, the output value is treated as sensitive and masked in logs."
        },
        "path": {
          "type": "string",
          "description": "File path inside the bundle container where the output value is written by the bundle."
        },
        "applyTo": {
          "type": "array",
          "description": "List of actions that produce this output.",
          "items": {
            "type": "string"
          }
        }
      }
    },
    "StateVariable": {
      "type": "object",
      "description": "A state variable that persists values between bundle action runs.",
      "required": ["name"],
      "properties": {
        "name": {
          "type": "string",
          "description": "Name of the state variable."
        },
        "description": {
          "type": "string",
          "description": "Description of the state variable's purpose."
        },
        "mixin": {
          "type": "string",
          "description": "Name of the mixin that manages this state variable."
        },
        "path": {
          "type": "string",
          "description": "File path inside the bundle container where the state is stored."
        }
      }
    },
    "Dependencies": {
      "type": "object",
      "description": "Dependencies on other bundles that must be installed before or alongside this bundle.",
      "properties": {
        "requires": {
          "type": "array",
          "description": "List of required bundle dependencies.",
          "items": {
            "$ref": "#/$defs/Dependency"
          }
        }
      }
    },
    "Dependency": {
      "type": "object",
      "description": "A dependency on another Porter bundle.",
      "required": ["name"],
      "properties": {
        "name": {
          "type": "string",
          "description": "Alias for the dependency, used to reference it in steps."
        },
        "bundle": {
          "type": "string",
          "description": "OCI reference to the dependent bundle.",
          "examples": ["ghcr.io/getporter/examples/mysql:v0.1.0"]
        },
        "version": {
          "type": "string",
          "description": "Version constraint for the dependency."
        },
        "parameters": {
          "type": "object",
          "description": "Parameter mappings to pass from this bundle to the dependency.",
          "additionalProperties": {
            "type": "string"
          }
        },
        "credentials": {
          "type": "object",
          "description": "Credential mappings to pass from this bundle to the dependency.",
          "additionalProperties": {
            "type": "string"
          }
        }
      }
    },
    "Step": {
      "type": "object",
      "description": "A single step in a bundle action, invoking a mixin with specific configuration.",
      "minProperties": 1,
      "maxProperties": 1,
      "additionalProperties": {
        "type": "object",
        "description": "Mixin-specific step configuration keyed by mixin name.",
        "properties": {
          "description": {
            "type": "string",
            "description": "Human-readable description of what this step does."
          },
          "outputs": {
            "type": "array",
            "description": "Outputs to capture from this step's execution.",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string",
                  "description": "Output name as defined in the bundle outputs."
                }
              }
            }
          }
        }
      }
    },
    "CustomAction": {
      "type": "object",
      "description": "A custom action definition beyond the standard CNAB install, upgrade, and uninstall actions.",
      "properties": {
        "description": {
          "type": "string",
          "description": "Description of what this action does."
        },
        "modifies": {
          "type": "boolean",
          "description": "If true, the action modifies the installation and its state is tracked."
        },
        "stateless": {
          "type": "boolean",
          "description": "If true, the action can run without an existing installation."
        },
        "steps": {
          "type": "array",
          "description": "Steps to execute when this action is invoked.",
          "items": {
            "$ref": "#/$defs/Step"
          }
        }
      }
    },
    "BundleImage": {
      "type": "object",
      "description": "A container image referenced by the bundle for air-gapped environment support.",
      "required": ["repository"],
      "properties": {
        "repository": {
          "type": "string",
          "description": "OCI repository of the image."
        },
        "tag": {
          "type": "string",
          "description": "Tag of the image."
        },
        "digest": {
          "type": "string",
          "description": "OCI digest of the image for content-addressable references.",
          "pattern": "^sha256:[a-f0-9]{64}$"
        },
        "description": {
          "type": "string",
          "description": "Description of the image's purpose within the bundle."
        },
        "imageType": {
          "type": "string",
          "description": "Type of the image.",
          "enum": ["oci", "docker"]
        }
      }
    }
  },
  "examples": [
    {
      "schemaType": "Bundle",
      "schemaVersion": "1.0.1",
      "name": "hello",
      "version": "0.2.0",
      "description": "A very simple bundle that demonstrates Porter's capabilities.",
      "registry": "ghcr.io/getporter/examples",
      "mixins": ["exec"],
      "parameters": {
        "name": {
          "type": "string",
          "description": "Name to greet.",
          "default": "World"
        }
      },
      "install": [
        {
          "exec": {
            "description": "Install Hello World",
            "command": "bash",
            "flags": {
              "c": "echo Hello ${bundle.parameters.name}"
            }
          }
        }
      ],
      "upgrade": [
        {
          "exec": {
            "description": "World Hello",
            "command": "bash",
            "flags": {
              "c": "echo World ${bundle.parameters.name}"
            }
          }
        }
      ],
      "uninstall": [
        {
          "exec": {
            "description": "Uninstall Hello World",
            "command": "bash",
            "flags": {
              "c": "echo Goodbye ${bundle.parameters.name}"
            }
          }
        }
      ]
    }
  ]
}
