Reference

Provisioning Sources

How policy chooses approved sources for runtimes and tools.

referenceautomation buildersintermediatestable2026-05-30

When to use this page

Use this page when a repo needs a runtime or tool and the organization wants to say where it may come from.

Policy can approve a feed, mirror, bucket, tap, or source URL without changing the repo contract.

  • repo contracts declare what they need with runtimes, tools, and checks
  • org policy declares approved source origins and allowed versions
  • version_policy is the version-governance layer when you want approved versions without turning on provisioning
  • receipts and doctor output should explain which effective source resolved for this target

Current boundary

policies.env.values

The shipped policy env-value map. Use it to supply approved shared values for env vars the repo contract already declares. This is not the provisioning surface and it should not invent new repo requirements.

policies.provisioning

The policy surface for approved runtime and tool sources.

policies.version_policy

The policy surface for approved runtime and tool versions when governance is needed without install-source selection.

policies.adapter_bootstrap

The policy surface for getting ota's own adapter binaries onto the host or into the container.

Container execution

When ota up runs in container mode, the shipped provisioning adapters run inside that container instead of on the host, and explicit --mode container stops before any host fallback if no supported engine is available.

  • Policy should use source: <adapter> from the shipped set when it wants ota to provision through a built-in backend.
  • source selects the adapter family, then source_config can narrow approved feed/tap/bucket/mirror details where supported.
  • sdkman and uv are the runtime-oriented adapters in that shipped set.
  • release-asset is the exact standalone-binary lane for tools delivered as direct release artifacts or extractable release archives rather than package-manager installs.
  • Chocolatey rules may add source_config.feed for an approved internal feed or mirror.
  • ota doctor --json and ota workspace doctor --json may include provisioning_request, and workspace repo items may also include adapter_bootstrap when policy declares it.
Shipped provisioning adapterstext
miseasdfsdkmanuvwingetchocoscoopbrewaptdnfpacmanrelease-asset

Provisioning field meaning

Each policies.provisioning entry is a small execution contract and should be read left-to-right:

source (who can install), optional platforms.<os> (which host-specific override applies), then approved_versions (what versions that source may install), then optional package/source_config (how to call that source).

  • source is required and must be a shipped adapter.
  • approved_versions is required and checked against the contract version expression.
  • platforms selects a whole OS-specific rule; when present for the active OS, its source, approved_versions, package, and source_config replace the base rule rather than merging field-by-field.
  • package maps the logical runtime/tool name to backend package identifiers where the selected source expects one.
  • source_config is adapter-specific policy detail (for example choco feed, apt source list, winget source name, brew tap, or release-asset platform URL and archive map).
  • Validation is strict: any required field missing for the selected source is a hard, deterministic failure.

Release asset shape

Use source: release-asset when one tool should come from an approved direct binary artifact instead of a package manager.

This is the shipped exact-binary path for tools like Mike Farah yq.

  • release-asset currently supports tools, not runtime installation.
  • source_config.asset_by_platform is required and must map one or more supported target keys to either direct asset URLs or objects with url plus optional archive extraction metadata.
  • Supported platform keys are linux_x86_64, linux_aarch64, macos_x86_64, macos_aarch64, windows_x86_64, and windows_aarch64.
  • Asset URLs may interpolate {version} and {name}.
  • archive.format currently supports tar_gz and zip.
  • archive.executable_path tells ota which extracted file becomes the final executable in the managed tool path.
  • source_config.version_args is optional and defaults to --version.
  • Ota materializes the executable into a source-managed workspace path so later task execution can use it without repo-local bootstrap glue.
Release Asset Policyyaml
policies:  provisioning:    yq:      source: release-asset      source_config:        asset_by_platform:          linux_x86_64: https://github.com/mikefarah/yq/releases/download/v{version}/yq_linux_amd64          linux_aarch64: https://github.com/mikefarah/yq/releases/download/v{version}/yq_linux_arm64          macos_x86_64: https://github.com/mikefarah/yq/releases/download/v{version}/yq_darwin_amd64          macos_aarch64: https://github.com/mikefarah/yq/releases/download/v{version}/yq_darwin_arm64          windows_x86_64: https://github.com/mikefarah/yq/releases/download/v{version}/yq_windows_amd64.exe        version_args:          - --version      approved_versions:        - "4.52.5"     migrate:      source: release-asset      source_config:        asset_by_platform:          macos_aarch64:            url: https://github.com/golang-migrate/migrate/releases/download/v{version}/migrate.darwin-arm64.tar.gz            archive:              format: tar_gz              executable_path: migrate        version_args:          - -version      approved_versions:        - "4.19.1" 

Source selection is explicit

  • policy can never partially combine sources; one prerequisite resolves to exactly one effective source on each target OS.
  • when a contract prerequisite is inactive on an OS, provisioning is not applied on that OS.
  • even with multiple candidate sources, ota must preserve a single deterministic effective choice and report it in diagnostics/receipts.

Version governance boundary

Contract says what the repo needs

Use runtimes and tools in ota.yaml to declare required versions and optional per-OS overrides with platforms.

Version policy says which versions are allowed

Use policies.version_policy when the org wants to constrain repo-declared versions without also selecting an install source.

Provisioning says where installs may come from

Use policies.provisioning only when ota should also be allowed to install or select the prerequisite through an approved source.

  • a repo can be governed by version_policy without declaring any provisioning rules
  • doctor should report version-policy failures as contract-versus-policy mismatches, not as missing provisioning configuration
  • use platforms.<os> in both the contract and version policy when a requirement only applies on some operating systems

How source resolution works

Many rules overall, one source per prerequisite

A policy can approve many sources across the whole pack, but ota resolves one effective source for each runtime or tool on the current target.

Platform overrides are selection, not a race

When platforms is present, ota selects the matching OS rule. It does not try brew, apt, and choco on one machine and then pick a winner.

One OS can still support many adapters

Windows may use choco for one tool and winget for another. Linux may use apt for one tool and uv for Python. The policy chooses per prerequisite.

  • the root rule is the default for that prerequisite
  • a matching platforms.<os> rule overrides the root rule for that prerequisite
  • after resolution, ota should have one effective source for node, one for java, one for python, and so on

Version resolution rules

What policy may approve

Policy can authorize exact versions and semver ranges such as ^24, ~20.10, or >=18 <23.

What ota records

Doctor JSON records the contract requested_version, the semver normalized_requirement, the matched policy_match, and any package mapping when policy-backed provisioning applies.

When ota resolves

ota only emits resolved_version when policy provides an explicit concrete install candidate. Otherwise it keeps the original contract version as the backend input.

What ota will not invent

Range-only policy approval can authorize a request, but it does not give ota a deterministic concrete version to install.

Deterministic resolutiontext
Allowed and installablerequest: node >=18approved_versions: 22.11.0resolved_version: 22.11.0 Allowed but still blockedrequest: node >=18approved_versions: ^22result: authorized, but not deterministic enough to install

Package mapping rules

  • package keeps the contract key stable while mapping to the backend install identifier.
  • use package whenever the selected source needs an exact package identifier; keep versions in approved_versions, not in package.
  • package is required for apt, dnf, pacman, winget, choco, and scoop
  • package is optional for brew, mise, asdf, sdkman, and uv

When ota will not provision

Rule mismatch

The policy key does not match the contract key, or the contract version does not satisfy any approved exact version or semver range.

No deterministic version

The contract uses a true range while policy authorizes only ranges, or the contract uses * while policy expects pins, so ota still has no concrete version to install.

Incomplete backend rule

The selected backend requires package, but the rule does not declare one.

Wrong target or missing backend

The rule only overrides a different OS, approves an unshipped source adapter, or depends on a manager that is missing and not allowed through policies.adapter_bootstrap.

Example policy

Repo contractyaml
runtimes:  java: "22"tools:  maven: "3.9"  pwsh:    version: "7.6.0"    only_on:      - windowschecks:  - name: java-installed    kind: precondition    severity: error    run: java --version  - name: maven-installed    kind: precondition    severity: error    run: mvn -version
Policy-approved sourcesyaml
policies:  version_policy:    tools:      pwsh:        platforms:          windows:            approved_versions:              - "7.6.0"  provisioning:    java:      source: org-mirror      approved_versions:        - "22"    maven:      source: approved-manager      approved_versions:        - "3.9"    node:      source: choco      package: nodejs      source_config:        feed: internal-choco      approved_versions:        - "22"

What it does today

  • explain which approved source resolved for a requested runtime or tool on the current target, so users see why ota used that source
  • enforce version_policy separately from provisioning so repos can be version-governed without forcing ota-managed installs
  • authorize major shorthand and semver ranges without falling back to naive exact-string comparison
  • surface requested versus resolved version and the matched policy rule when ota can explain that decision honestly
  • reject unapproved source paths
  • record the chosen source in receipts and diagnostics
  • keep repo intent, org policy, and execution provenance separate

Example output

ota policytext
🦦 POLICY ./ota.yaml Policy source: repo policyPolicy path: ./.ota/org-policy.yaml policies:  provisioning:    node:      source: brew      approved_versions:        - "22"

What it is not

  • not a general package manager
  • not a hidden workstation manager
  • not a raw download URL surface
  • not a replacement for env policy