From 912ace04d67f9d7b60bb0d46efdab9a552204bfd Mon Sep 17 00:00:00 2001 From: Konrad Komorowski Date: Wed, 19 Aug 2026 17:53:00 +0100 Subject: [PATCH 1/3] fix(registry): point aqua backends at renamed packages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Twelve registry entries name their aqua package by an id that aqua-registry now keeps only as an `aliases:` entry, because the upstream repo was renamed or transferred. `AquaBackend::use_versions_host_for_github_metadata` gates the mise-versions mirror on the registry's aqua id matching the repo the package resolves to, so for these tools the gate is false and metadata requests go straight to api.github.com — installation fails outright wherever that host is unreachable even though the release assets are not. The same stale id also keeps the mirror's allowlist from covering the repo: mise-versions builds it from `mise registry --json` and takes the slug literally, so the canonical repo answers 403 while the stale one serves the release JSON. Point each entry at the package's canonical id. Binary names are unaffected: where the repo name diverges from the tool (dekit, gradle-distributions, sealed-secrets) the aqua package pins the binary with its own `files:`. --- registry/d2.toml | 2 +- registry/dagu.toml | 2 +- registry/gitui.toml | 2 +- registry/gradle.toml | 2 +- registry/ktlint.toml | 2 +- registry/kubeseal.toml | 2 +- registry/kubie.toml | 2 +- registry/mprocs.toml | 2 +- registry/oauth2c.toml | 2 +- registry/tart.toml | 2 +- registry/typstyle.toml | 2 +- registry/velero.toml | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/registry/d2.toml b/registry/d2.toml index 65d7697b6ff..22591be4d02 100644 --- a/registry/d2.toml +++ b/registry/d2.toml @@ -4,7 +4,7 @@ version_order = "semver" bins = ["d2"] [[backends]] -full = "aqua:terrastruct/d2" +full = "aqua:d2lang/d2" [[backends]] full = "github:terrastruct/d2" diff --git a/registry/dagu.toml b/registry/dagu.toml index 6bc3c3ff73e..88618540c73 100644 --- a/registry/dagu.toml +++ b/registry/dagu.toml @@ -1,4 +1,4 @@ -backends = ["aqua:dagu-org/dagu"] +backends = ["aqua:dagucloud/dagu"] bins = ["dagu"] description = "Yet another cron alternative with a Web UI, but with much more capabilities. It aims to solve greater problems" test = { cmd = "dagu version", expected = "{{version}}" } diff --git a/registry/gitui.toml b/registry/gitui.toml index b108429086a..73d3af82d53 100644 --- a/registry/gitui.toml +++ b/registry/gitui.toml @@ -1,4 +1,4 @@ -backends = ["aqua:extrawurst/gitui", "asdf:looztra/asdf-gitui", "cargo:gitui"] +backends = ["aqua:gitui-org/gitui", "asdf:looztra/asdf-gitui", "cargo:gitui"] bins = ["gitui"] description = "Blazing 💥 fast terminal-ui for git written in rust" version_order = "semver" diff --git a/registry/gradle.toml b/registry/gradle.toml index 05099cdfdd3..3cafa3b97af 100644 --- a/registry/gradle.toml +++ b/registry/gradle.toml @@ -1,4 +1,4 @@ -backends = ["aqua:gradle/gradle", "vfox:mise-plugins/vfox-gradle"] +backends = ["aqua:gradle/gradle-distributions", "vfox:mise-plugins/vfox-gradle"] bins = ["gradle"] description = "Gradle is the open source build system of choice for Java, Android, and Kotlin developers" test = { cmd = "gradle -V", expected = "Gradle", tools = ["java"] } diff --git a/registry/ktlint.toml b/registry/ktlint.toml index 4e2a431fc20..af5c64f75ac 100644 --- a/registry/ktlint.toml +++ b/registry/ktlint.toml @@ -1,4 +1,4 @@ -backends = ["aqua:pinterest/ktlint", "asdf:mise-plugins/mise-ktlint"] +backends = ["aqua:ktlint/ktlint", "asdf:mise-plugins/mise-ktlint"] bins = ["ktlint"] description = "An anti-bikeshedding Kotlin linter with built-in formatter" version_order = "semver" diff --git a/registry/kubeseal.toml b/registry/kubeseal.toml index 151eae65316..880fa55864a 100644 --- a/registry/kubeseal.toml +++ b/registry/kubeseal.toml @@ -1,5 +1,5 @@ backends = [ - "aqua:bitnami-labs/sealed-secrets", + "aqua:bitnami/sealed-secrets", "asdf:stefansedich/asdf-kubeseal", ] bins = ["kubeseal"] diff --git a/registry/kubie.toml b/registry/kubie.toml index 6c8c11f1d6a..9091adf902f 100644 --- a/registry/kubie.toml +++ b/registry/kubie.toml @@ -1,4 +1,4 @@ -backends = ["aqua:sbstp/kubie", "asdf:johnhamelink/asdf-kubie"] +backends = ["aqua:kubie-org/kubie", "asdf:johnhamelink/asdf-kubie"] bins = ["kubie"] description = "A more powerful alternative to kubectx and kubens" version_order = "semver" diff --git a/registry/mprocs.toml b/registry/mprocs.toml index 81c77bfc5a9..5011f947976 100644 --- a/registry/mprocs.toml +++ b/registry/mprocs.toml @@ -1,4 +1,4 @@ -backends = ["aqua:pvolok/mprocs"] +backends = ["aqua:pvolok/dekit"] bins = ["mprocs"] description = "Run multiple commands in parallel" test = { cmd = "mprocs --version", expected = "mprocs {{version}}" } diff --git a/registry/oauth2c.toml b/registry/oauth2c.toml index 1114d5b15bb..e044d1cf224 100644 --- a/registry/oauth2c.toml +++ b/registry/oauth2c.toml @@ -1,4 +1,4 @@ -backends = ["aqua:cloudentity/oauth2c"] +backends = ["aqua:SecureAuthCorp/oauth2c"] bins = ["oauth2c"] description = "User-friendly OAuth2 CLI" test = { cmd = "oauth2c version", expected = "oauth2c version {{version}}" } diff --git a/registry/tart.toml b/registry/tart.toml index 06f7bb7b726..1d3b09c3b78 100644 --- a/registry/tart.toml +++ b/registry/tart.toml @@ -1,4 +1,4 @@ -backends = ["aqua:cirruslabs/tart"] +backends = ["aqua:openai/tart"] description = "macOS and Linux VMs on Apple Silicon to use in CI and other automations" os = ["macos"] test = { cmd = "tart --version", expected = "{{version}}" } diff --git a/registry/typstyle.toml b/registry/typstyle.toml index cf2ce2a909e..e562043b838 100644 --- a/registry/typstyle.toml +++ b/registry/typstyle.toml @@ -1,4 +1,4 @@ -backends = ["aqua:Enter-tainer/typstyle", "cargo:typstyle"] +backends = ["aqua:typstyle-rs/typstyle", "cargo:typstyle"] bins = ["typstyle"] description = "Beautiful and reliable typst code formatter" test = { cmd = "typstyle --version | grep 'Version:' | awk '{print $2}'", expected = "{{version}}" } diff --git a/registry/velero.toml b/registry/velero.toml index 921902a903c..ffd0ab37407 100644 --- a/registry/velero.toml +++ b/registry/velero.toml @@ -1,4 +1,4 @@ -backends = ["aqua:vmware-tanzu/velero", "asdf:looztra/asdf-velero"] +backends = ["aqua:velero-io/velero", "asdf:looztra/asdf-velero"] bins = ["velero"] description = "Backup and migrate Kubernetes applications and their persistent volumes" version_order = "semver" From d230ee9b489e08e843f5618c67372db4ff538d93 Mon Sep 17 00:00:00 2001 From: Konrad Komorowski Date: Wed, 19 Aug 2026 17:58:38 +0100 Subject: [PATCH 2/3] test(registry): assert aqua backends name canonical packages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An aqua id left behind by an upstream rename still resolves to its package through the registry's `aliases:`, so the tool installs and nothing looks wrong — but `use_versions_host_for_github_metadata` compares that id against the repo the package resolves to, and mise-versions builds its allowlist from the same string, so the mirror silently drops out and the tool can only be installed where api.github.com is reachable. Assert the ids are canonical instead of auditing them by hand. build.rs already bakes an alias-to-canonical map out of the vendored aqua-registry, so the check needs no network and runs with the rest of the unit tests, and a rename surfaces in the aqua-registry bump that introduces it, naming the id to switch to. Aliases differing only in case are left alone: the gate lowercases both sides, so those still match. --- src/aqua/standard_registry.rs | 14 ++++++++++++++ src/registry.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/aqua/standard_registry.rs b/src/aqua/standard_registry.rs index bfc04f18626..e0f3285140c 100644 --- a/src/aqua/standard_registry.rs +++ b/src/aqua/standard_registry.rs @@ -43,6 +43,11 @@ fn baked_registry_file(package_id: &str) -> Option<&'static [u8]> { .copied() } +/// The package id an alias resolves to, or `None` for anything else. +pub fn canonical_package_id(package_id: &str) -> Option<&'static str> { + AQUA_STANDARD_REGISTRY_ALIASES.get(package_id).copied() +} + #[cfg(test)] mod tests { use super::*; @@ -107,6 +112,15 @@ mod tests { assert_eq!(alias_package.repo_name, canonical_package.repo_name); } + #[test] + fn test_canonical_package_id() { + assert_eq!( + canonical_package_id("Enter-tainer/typstyle"), + Some("typstyle-rs/typstyle") + ); + assert_eq!(canonical_package_id("typstyle-rs/typstyle"), None); + } + #[test] fn test_baked_registry_numeric_replacement_keys() { let package = package("sharkdp/hyperfine").unwrap().unwrap(); diff --git a/src/registry.rs b/src/registry.rs index 241f10bb7ce..0c6054285cb 100644 --- a/src/registry.rs +++ b/src/registry.rs @@ -1275,4 +1275,30 @@ idiomatic_files = [{ path = ".example-version", parser = "shell" }] "https://github.com/attacker/vfox-cmake.git" )); } + + #[test] + fn aqua_backends_name_canonical_packages() { + let stale = super::baked_registry() + .iter() + .flat_map(|(short, tool)| { + tool.backends + .iter() + .map(move |backend| (short, backend.full)) + }) + .filter_map(|(short, full)| { + let id = full.strip_prefix("aqua:")?; + let id = id.split('[').next().unwrap_or(id); + let canonical = crate::aqua::standard_registry::canonical_package_id(id)?; + // The gate lowercases both sides, so a case-only alias still matches. + (!canonical.eq_ignore_ascii_case(id)) + .then(|| format!(" registry/{short}.toml: aqua:{id} -> aqua:{canonical}")) + }) + .collect::>(); + + assert!( + stale.is_empty(), + "aqua backends naming a renamed package by its old id:\n{}", + stale.join("\n") + ); + } } From 78d4024a377ede75aef5dcd13b85dab832a590f0 Mon Sep 17 00:00:00 2001 From: Konrad Komorowski Date: Wed, 19 Aug 2026 18:03:52 +0100 Subject: [PATCH 3/3] fix(aqua): resolve renamed aqua ids before gating the mise-versions mirror MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `use_versions_host_for_github_metadata` decides whether GitHub metadata may come from the mise-versions mirror by comparing the backend's aqua id against the repo the aqua package resolves to. Both that comparison and the registry lookup guarding it are exact, so an id upstream has renamed away from fails them: the package still resolves through aqua-registry's `aliases:`, but the tool quietly drops to api.github.com and cannot be installed where that host is unreachable. Resolve the alias to the id the package is keyed by first. The registry's own entries are canonical, so this is about the ids that outlive a rename elsewhere — a mise.toml or a lockfile written before it, which would otherwise lose the mirror the moment the registry entry is corrected. Nothing is lost when the mirror declines: get_release_with_options falls through to api.github.com on any failure. --- src/backend/aqua.rs | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/backend/aqua.rs b/src/backend/aqua.rs index dd6b72ca65c..d1492f817d8 100644 --- a/src/backend/aqua.rs +++ b/src/backend/aqua.rs @@ -1944,10 +1944,16 @@ impl AquaBackend { fn use_versions_host_for_github_metadata(&self, repo: &str) -> bool { let full = self.ba.full_without_opts(); - if !backend_arg_matches_registry_backend(&self.ba) && shorts_for_full(&full).is_empty() { + // aqua-registry keeps a renamed repo's old id as an alias, so an id from an older config + // or lockfile and `repo` can be one package spelled two ways. + let canonical_full = Self::canonical_aqua_backend(&full); + if !backend_arg_matches_registry_backend(&self.ba) + && shorts_for_full(&full).is_empty() + && shorts_for_full(&canonical_full).is_empty() + { return false; } - let Some(aqua_id) = full.strip_prefix("aqua:") else { + let Some(aqua_id) = canonical_full.strip_prefix("aqua:") else { return false; }; let aqua_id = aqua_id.to_ascii_lowercase(); @@ -1955,6 +1961,16 @@ impl AquaBackend { aqua_id == repo || aqua_id.starts_with(&format!("{repo}/")) } + fn canonical_aqua_backend(full: &str) -> String { + let Some(aqua_id) = full.strip_prefix("aqua:") else { + return full.to_string(); + }; + match crate::aqua::standard_registry::canonical_package_id(aqua_id) { + Some(canonical) => format!("aqua:{canonical}"), + None => full.to_string(), + } + } + async fn get_github_release(&self, repo: &str, tag: &str) -> Result { github::get_release_for_url_with_versions_host( github::API_URL, @@ -3664,6 +3680,18 @@ mod tests { ); } + #[test] + fn test_use_versions_host_for_github_metadata_resolves_renamed_aqua_ids() { + // A mise.toml or lockfile pinned before the typstyle repo moved still names it this way. + let renamed_backend = AquaBackend::from_arg(BackendArg::new( + "typstyle".to_string(), + Some("aqua:Enter-tainer/typstyle".to_string()), + )); + assert!(renamed_backend.use_versions_host_for_github_metadata("typstyle-rs/typstyle")); + // The id is resolved, `repo` is not. + assert!(!renamed_backend.use_versions_host_for_github_metadata("Enter-tainer/typstyle")); + } + #[test] fn test_has_github_attestations_config_requires_enabled_config() { let mut pkg = AquaPackage::default();