{
  "$defs": {
    "AuthoringBundle": {
      "description": "Bundle package metadata in authoring form.\n\nSame shape as the published [`Bundle`] plus the sidecar-only `platforms`\ntarget set and authoring-form dependencies.",
      "properties": {
        "dependencies": {
          "$ref": "#/$defs/AuthoringDependencies",
          "description": "Ordered list of package dependencies in authoring form (digest\noptional; per-platform pin maps allowed). Array order defines the\nenvironment import order."
        },
        "entrypoints": {
          "$ref": "#/$defs/Entrypoints",
          "description": "Named entrypoints that `ocx package install` generates launchers for."
        },
        "env": {
          "$ref": "#/$defs/Env",
          "description": "Environment variables the package contributes."
        },
        "platforms": {
          "anyOf": [
            {
              "$ref": "#/$defs/TargetPlatforms"
            },
            {
              "type": "null"
            }
          ],
          "description": "The package's target-platform set, written by `ocx package create`\nwhen `--platform` is given. Authoring sidecar only — stripped at\npublish. `ocx package push` fans out to every platform in this set."
        },
        "strip_components": {
          "description": "Number of leading path components to strip when extracting the bundle.",
          "format": "uint8",
          "maximum": 255,
          "minimum": 0,
          "type": [
            "integer",
            "null"
          ]
        },
        "version": {
          "$ref": "#/$defs/Version",
          "description": "The version of the bundle metadata format."
        }
      },
      "required": [
        "version"
      ],
      "type": "object"
    },
    "AuthoringDependencies": {
      "items": {
        "$ref": "#/$defs/AuthoringDependency"
      },
      "type": "array"
    },
    "AuthoringDependency": {
      "description": "A dependency in authoring (sidecar) form.\n\nUnlike the published [`Dependency`], the identifier's digest is optional:\na tag-only identifier declares \"resolve me at `ocx package create` time\".\nThe optional `platforms` map carries per-platform manifest pins (key =\n[`Platform::lock_key`](crate::oci::Platform::lock_key), the lock V2\nencoding) for packages whose dependency ships platform-specific manifests.\n\nProjection to the published form ([`AuthoringDependency::pin_for`])\ncollapses the map to a single [`PinnedIdentifier`](oci::PinnedIdentifier);\nthe sidecar-only `platforms` field is stripped by construction because the\npublished type has no such field.",
      "properties": {
        "identifier": {
          "$ref": "#/$defs/Identifier",
          "description": "OCX identifier with a required explicit registry. The digest is\noptional in the authoring form: absent means \"pin me at\n`ocx package create` time\". The tag is advisory once a digest or\nplatforms map is present."
        },
        "name": {
          "anyOf": [
            {
              "$ref": "#/$defs/DependencyName"
            },
            {
              "type": "null"
            }
          ],
          "description": "Optional name for this dependency used in `${deps.NAME.installPath}`\ninterpolation. Defaults to the last path segment of the repository."
        },
        "platforms": {
          "additionalProperties": {
            "$ref": "#/$defs/Digest"
          },
          "description": "Per-platform manifest pins written by `ocx package create` when the\ndependency ships platform-specific manifests. Key = platform lock key\n(e.g. `linux/amd64`, `any`), value = that platform's manifest digest.\nAuthoring sidecar only — stripped at publish.\n\nDeserialization rejects duplicate JSON keys (see\n[`deserialize_platforms`]) instead of silently keeping the last value\n— the same registry-data-unsafe class of bug fixed for\n[`Entrypoints`](crate::package::metadata::entrypoint::Entrypoints)'s\ncustom `MapAccess` deserializer.",
          "type": [
            "object",
            "null"
          ]
        },
        "visibility": {
          "$ref": "#/$defs/Visibility",
          "default": "sealed",
          "description": "Controls how this dependency's environment variables propagate.\nDefault: `sealed` — no env contribution."
        }
      },
      "required": [
        "identifier"
      ],
      "type": "object"
    },
    "Constant": {
      "description": "A constant-type environment variable.\n\nConstant variables replace any existing value of the environment variable.\nThe `${installPath}` template is replaced with the package's content directory at resolution time.",
      "properties": {
        "value": {
          "description": "The value template. Use `${installPath}` to reference the package content directory.",
          "type": "string"
        }
      },
      "required": [
        "value"
      ],
      "type": "object"
    },
    "DependencyName": {
      "description": "Interpolation name for this dependency. Must match ^[a-z0-9][a-z0-9_-]*$ (max 64 chars).",
      "maxLength": 64,
      "pattern": "^[a-z0-9][a-z0-9_-]*$",
      "type": "string"
    },
    "Digest": {
      "description": "OCI content-addressed digest (e.g. 'sha256:abcdef...').",
      "pattern": "^sha(256|384|512):[0-9a-f]+$",
      "type": "string"
    },
    "Entrypoint": {
      "description": "A single named entrypoint for a package.\n\nThe map key in [`Entrypoints`] supplies the *invocable name* — the\nfilename of the generated launcher. This struct holds the per-entry\nvalue.\n\nThe launcher generated for each entry re-enters via\n`ocx launcher exec '<package-root>' -- <name> [args...]`, preserving\nclean-env execution semantics. `ocx launcher exec` resolves the\n*dispatch command* against the composed `PATH` from the package's `env`\nblock: [`Entrypoint::command`] when set, otherwise the invocable name\nitself (the common case where they coincide).",
      "properties": {
        "args": {
          "description": "Fixed leading arguments the generated launcher prepends before the user's\nown arguments. Each element supports `${installPath}` interpolation (the\npackage content directory); `${deps.*}` is NOT permitted here. Absent/empty\nserializes to nothing (wire-compatible with the pre-`args` shape).",
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "command": {
          "anyOf": [
            {
              "$ref": "#/$defs/EntrypointName"
            },
            {
              "type": "null"
            }
          ],
          "description": "Dispatch target resolved on the composed `PATH`, when it differs from\nthe invocable name. Absent means the entrypoint name *is* the command\n(the common case): a package may expose `hello` while dispatching a\ndifferently named binary such as `hello-bin`."
        }
      },
      "type": "object"
    },
    "EntrypointName": {
      "description": "Entrypoint name for invocation by users. Must match ^[a-z0-9][a-z0-9_-]*$ and be at most 64 characters.",
      "maxLength": 64,
      "pattern": "^[a-z0-9][a-z0-9_-]*$",
      "type": "string"
    },
    "Entrypoints": {
      "additionalProperties": {
        "$ref": "#/$defs/Entrypoint"
      },
      "description": "Map of entrypoint names to entrypoint definitions. Each key is the user-invokable command name; the value object carries an optional `command` field naming the binary the generated launcher dispatches to when it differs from the invokable name (omit it and the name is dispatched directly). An optional `args` array supplies fixed leading arguments the generated launcher prepends before user args; each element supports `${installPath}` interpolation (`${deps.*}` is not permitted in args).",
      "propertyNames": {
        "maxLength": 64,
        "pattern": "^[a-z0-9][a-z0-9_-]*$"
      },
      "type": "object"
    },
    "Env": {
      "items": {
        "$ref": "#/$defs/Var"
      },
      "type": "array"
    },
    "Identifier": {
      "description": "OCI identifier in the format 'registry/repository[:tag][@digest]'.",
      "type": "string"
    },
    "Path": {
      "description": "A path-type environment variable.\n\nPath variables are prepended to any existing value of the environment variable.\nThe `${installPath}` template is replaced with the package's content directory at resolution time.",
      "properties": {
        "required": {
          "default": false,
          "description": "Whether the resolved path must exist on disk. If `true` and the path is missing, installation fails.\nDefaults to `false`.",
          "type": "boolean"
        },
        "value": {
          "description": "The value template. Use `${installPath}` to reference the package content directory.",
          "type": "string"
        }
      },
      "required": [
        "value"
      ],
      "type": "object"
    },
    "TargetPlatforms": {
      "description": "Target-platform set written by `ocx package create` (authoring sidecar only; stripped at publish). Non-empty array of canonical platform strings such as 'linux/amd64' or 'any'.",
      "items": {
        "type": "string"
      },
      "minItems": 1,
      "type": "array"
    },
    "Var": {
      "description": "An environment variable declaration.\n\nEach variable has a key (the variable name), a [modifier](Modifier) that\ndetermines how the value is resolved, and a visibility that controls which\nexec surfaces load the entry. The modifier's type and fields are flattened\ninto this object in JSON.\n\n`visibility` defaults to [`Visibility::PRIVATE`] per ADR\n`adr_visibility_two_axis_and_exec_modes.md` Tension 1 (A): publishers must\nopt in explicitly to expose entries on the consumer axis. `\"sealed\"` is\nrejected at parse time — a `Var` invisible on every surface is dead config\n(ADR Tension 4).",
      "oneOf": [
        {
          "$ref": "#/$defs/Path",
          "description": "A path variable is prepended to any existing value of the environment variable.",
          "properties": {
            "type": {
              "const": "path",
              "type": "string"
            }
          },
          "required": [
            "type"
          ],
          "type": "object"
        },
        {
          "$ref": "#/$defs/Constant",
          "description": "A constant variable replaces any existing value of the environment variable.",
          "properties": {
            "type": {
              "const": "constant",
              "type": "string"
            }
          },
          "required": [
            "type"
          ],
          "type": "object"
        }
      ],
      "properties": {
        "key": {
          "description": "The environment variable name (e.g. `PATH`, `JAVA_HOME`).",
          "type": "string"
        },
        "visibility": {
          "default": "private",
          "description": "Visibility on the entry axis — controls which exec surface (interface vs private)\nsees this entry; see [`crate::package_manager::composer`]. Defaults to\n`private` — publishers explicitly mark contract entries as `public` or\n`interface` to expose them to consumers. `\"sealed\"` is rejected at parse\ntime (ADR Tension 4).",
          "enum": [
            "private",
            "public",
            "interface"
          ],
          "type": "string"
        }
      },
      "required": [
        "key"
      ],
      "type": "object"
    },
    "Version": {
      "description": "Bundle metadata format version.",
      "enum": [
        1
      ],
      "type": "integer"
    },
    "Visibility": {
      "enum": [
        "sealed",
        "private",
        "public",
        "interface"
      ],
      "type": "string"
    }
  },
  "$id": "https://ocx.sh/schemas/metadata/v1.json",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "description": "OCX package metadata in authoring (sidecar) form.\n\nSuperset of the published [`Metadata`]: dependency digests are optional\nand sidecar-only fields (`platforms`) are allowed. See the module docs.",
  "oneOf": [
    {
      "$ref": "#/$defs/AuthoringBundle",
      "properties": {
        "type": {
          "const": "bundle",
          "type": "string"
        }
      },
      "required": [
        "type"
      ],
      "type": "object"
    }
  ],
  "title": "AuthoringMetadata"
}
