Skip to content

feat(ls-remote): add strict metadata mode#9448

Merged
jdx merged 8 commits intomainfrom
codex/strict-ls-remote-metadata
Apr 28, 2026
Merged

feat(ls-remote): add strict metadata mode#9448
jdx merged 8 commits intomainfrom
codex/strict-ls-remote-metadata

Conversation

@jdx
Copy link
Copy Markdown
Owner

@jdx jdx commented Apr 28, 2026

Summary

  • add mise ls-remote --no-versions-host to explicitly bypass mise-versions for direct backend checks
  • require --strict-metadata to be used with both --json and --no-versions-host, so strict mode validates direct backend metadata behavior instead of cached rows
  • keep non-metadata backends usable under strict mode instead of rejecting valid all-null created_at output
  • make Aqua release/tag GitHub API failures and Ruby release-date GitHub API failures surface in strict mode instead of silently returning empty or partial metadata
  • remove liqoctl from the registry because its default aqua:liqotech/liqo package does not exist in aqua-registry
  • regenerate usage metadata, CLI docs, manpage, and Fig spec

Why

The mise-versions update job needs a mode that does not silently accept empty fallback results when metadata-producing upstream calls fail. Requiring every backend row to contain created_at is too broad because some registry defaults are not GitHub-backed and cannot provide timestamps.

--no-versions-host keeps the direct-upstream behavior explicit instead of baking backend allowlists into strict metadata mode.

Validation

  • cargo fmt --check
  • cargo check
  • cargo build
  • cargo build --all-features
  • target/debug/mise run render:usage
  • target/debug/mise run render:mangen
  • target/debug/mise run render:fig
  • target/debug/mise ls-remote github:cli/cli --json --strict-metadata fails because --no-versions-host is required
  • target/debug/mise ls-remote github:cli/cli --no-versions-host --strict-metadata fails because --json is required
  • target/debug/mise ls-remote github:cli/cli --json --no-versions-host --strict-metadata | jq 'length, .[0]'
  • target/debug/mise ls-remote bun --json --no-versions-host --strict-metadata | jq 'length, .[0]'
  • target/debug/mise ls-remote ruby --json --no-versions-host --strict-metadata | jq 'length, .[0]'
  • pre-commit hk suite, including all-features cargo check

Note

Low Risk
Behavior changes are gated behind new ls-remote flags, but strict mode alters error handling by surfacing upstream metadata failures (aqua/ruby) that previously returned empty/partial results.

Overview
mise ls-remote now supports --no-versions-host to force direct backend checks and --strict-metadata (requires --json + --no-versions-host) to fail instead of silently falling back when metadata-producing upstream calls fail.

Introduces a shared strict-metadata toggle in backend and updates the Aqua backend and Ruby core plugin to propagate GitHub/aqua metadata fetch errors in strict mode. Removes the liqoctl registry entry due to an invalid default aqua package, and regenerates usage docs, the manpage, and the Fig completion spec to document the new flags.

Reviewed by Cursor Bugbot for commit 5af4202. Bugbot is set up for automated code reviews on this repo. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 28, 2026

Greptile Summary

This PR adds --no-versions-host (bypass the mise-versions cache) and --strict-metadata (propagate upstream API errors instead of silently returning empty results) to mise ls-remote. Aqua and Ruby release-date fetch errors now surface in strict mode, liqotech/liqo is removed from the registry, and all usage artifacts are regenerated.

  • P1: run_single does not validate that returned VersionInfo entries satisfy the strict-metadata contract — backends that succeed but return all-null created_at rows exit 0 with incomplete data, undermining the fail-closed guarantee.

Confidence Score: 4/5

Safe to merge with the understanding that strict-metadata does not yet enforce created_at completeness at the run_single output layer

One P1 finding: strict-metadata mode does not validate that returned versions actually carry created_at timestamps, so a silent all-null result still exits 0. All other changes are well-scoped and correctly wired.

src/cli/ls_remote.rs — missing post-fetch created_at completeness check in run_single under --strict-metadata

Important Files Changed

Filename Overview
src/cli/ls_remote.rs Adds --no-versions-host and --strict-metadata flags; strict-metadata validation is partially applied (via backend error propagation) but run_single does not validate returned VersionInfo for created_at completeness
src/backend/mod.rs Adds STRICT_METADATA global AtomicBool with get/set helpers; versions-host fallthrough in strict mode is effectively prevented because --no-versions-host is required by --strict-metadata
src/backend/aqua.rs Propagates strict_metadata check to Aqua tag-fetching error path; correctly surfaces API failures in strict mode
src/plugins/core/ruby.rs fetch_ruby_release_dates now returns Result and propagates GitHub API errors in strict mode; call site updated to propagate with ?
src/cli/asdf.rs Struct initialisation updated with new fields hardcoded to false; correct for asdf compatibility mode
registry/liqoctl.toml Removed because the default aqua:liqotech/liqo package does not exist in aqua-registry

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[mise ls-remote] --> B{--strict-metadata?}
    B -- yes --> C[requires --json + --no-versions-host\nclap enforces]
    C --> D[set_strict_metadata true\nskip versions host]
    B -- no --> E[normal path\nversions host optional]
    D --> F{single tool or all?}
    E --> F
    F -- single --> G[backend._list_remote_versions]
    F -- all --> H[iterate all backends]
    G --> I{backend type}
    I -- Aqua --> J[get_tags_with_created_at]
    J -- Err + strict --> K[bail with wrap_err]
    J -- Err + not strict --> L[warn + return empty]
    J -- Ok --> M[return versions]
    I -- Ruby --> N[fetch_ruby_release_dates]
    N -- Err + strict --> O[propagate error via ?]
    N -- Err + not strict --> P[debug log + empty map]
    N -- Ok --> Q[map versions + timestamps]
    M --> R[run_single: output JSON/plain]
    Q --> R
    R -. P1: no created_at\ncompleteness check .-> S[exit 0 with null timestamps]
Loading

Comments Outside Diff (1)

  1. src/cli/ls_remote.rs, line 101-115 (link)

    P1 --strict-metadata not validated in run_single

    strict_metadata is set globally via backend::set_strict_metadata(self.strict_metadata) and propagates correctly into backend error paths (Aqua, Ruby), but run_single never actually checks whether the returned versions satisfy the strict-metadata contract. If a backend silently returns versions all missing created_at (e.g. a non-GitHub-backed backend that returns VersionInfo with no timestamp) the command exits 0 with [{"version":"…","prerelease":false},…]. The strict-metadata guarantee only covers upstream API errors that currently bail!, not backends that successfully return all-null created_at rows. Consumers relying on the flag for fail-closed timestamp validation will receive silently incomplete data.

    Fix in Claude Code

Fix All in Claude Code

Reviews (8): Last reviewed commit: "fix(ls-remote): sort long flags" | Re-trigger Greptile

Comment thread src/backend/mod.rs Outdated
Comment thread src/cli/ls_remote.rs Outdated
Comment thread src/backend/mod.rs
Comment on lines +79 to +87
static STRICT_METADATA: AtomicBool = AtomicBool::new(false);

pub fn set_strict_metadata(strict: bool) {
STRICT_METADATA.store(strict, Ordering::Relaxed);
}

pub fn strict_metadata() -> bool {
STRICT_METADATA.load(Ordering::Relaxed)
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Global mutable state can leak across parallel integration tests

STRICT_METADATA is a process-global AtomicBool. Integration tests that invoke set_strict_metadata(true) will affect any other test running concurrently in the same process, since the Rust test harness runs tests on multiple threads by default. The unit tests added in this PR don't touch the flag, so they're fine, but future integration tests for ls-remote could be silently affected.

Consider resetting to false at the end of LsRemote::run (or using a scoped guard) to limit the blast radius.

Fix in Claude Code

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new --strict-metadata flag for the ls-remote command, designed to ensure that JSON output includes complete version metadata, such as created_at timestamps. When enabled, the system will fail with an error if metadata cannot be fetched, rather than issuing a warning and providing a fallback list. The changes span documentation, CLI argument parsing, and backend logic across several modules. A review comment suggests using format! instead of eyre! within wrap_err_with for consistency with existing idiomatic patterns in the codebase.

Comment thread src/backend/mod.rs Outdated
Comment on lines +808 to +811
eyre!(
"failed to fetch version metadata from versions host for {}",
ba.to_string()
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For consistency with other parts of the codebase (e.g., src/backend/aqua.rs), it's more idiomatic to use format! here instead of eyre! when providing context to wrap_err_with. The eyre! macro is typically used for creating new errors, whereas format! is sufficient for generating a displayable context message.

Suggested change
eyre!(
"failed to fetch version metadata from versions host for {}",
ba.to_string()
)
format!(
"failed to fetch version metadata from versions host for {}",
ba.to_string()
)

autofix-ci Bot and others added 2 commits April 28, 2026 12:38
# Conflicts:
#	docs/cli/ls-remote.md
#	mise.usage.kdl
#	src/cli/ls_remote.rs
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 33f708e. Configure here.

Comment thread src/backend/mod.rs
Comment thread src/cli/ls_remote.rs
Comment thread src/cli/ls_remote.rs
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 28, 2026

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.25 x -- echo 24.4 ± 0.8 22.6 28.2 1.00
mise x -- echo 24.4 ± 0.7 22.4 28.9 1.00 ± 0.04

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.25 env 24.7 ± 1.1 22.4 30.1 1.06 ± 0.06
mise env 23.2 ± 0.8 21.4 28.4 1.00

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.25 hook-env 23.5 ± 0.8 22.0 26.7 1.00
mise hook-env 24.3 ± 0.8 22.5 26.8 1.03 ± 0.05

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.25 ls 24.6 ± 0.9 22.3 29.2 1.02 ± 0.05
mise ls 24.1 ± 0.7 22.7 28.1 1.00

xtasks/test/perf

Command mise-2026.4.25 mise Variance
install (cached) 161ms 162ms +0%
ls (cached) 84ms 85ms -1%
bin-paths (cached) 86ms 87ms -1%
task-ls (cached) 843ms 840ms +0%

@jdx jdx merged commit a006549 into main Apr 28, 2026
37 checks passed
@jdx jdx deleted the codex/strict-ls-remote-metadata branch April 28, 2026 14:18
mise-en-dev added a commit that referenced this pull request Apr 29, 2026
### 🚀 Features

- **(deps)** add aube provider by @jdx in
[#9452](#9452)
- **(ls-remote)** add strict metadata mode by @jdx in
[#9448](#9448)

### 🐛 Bug Fixes

- **(env)** parse concatenated short form `-Eval` correctly by @bts in
[#9456](#9456)
- **(http)** improve HTML detection by using Content-Type header by
@phateffect in [#9407](#9407)
- **(task)** install monorepo subdir tools before running deps by @jdx
in [#9454](#9454)

### 📦️ Dependency Updates

- update astral-tokio-tar advisory by @jdx in
[#9449](#9449)
- respect -q flag for provider command stream by @JamBalaya56562 in
[#9457](#9457)

### New Contributors

- @JamBalaya56562 made their first contribution in
[#9457](#9457)
- @bts made their first contribution in
[#9456](#9456)
- @phateffect made their first contribution in
[#9407](#9407)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant