Skip to content

fix(schema): enforce additionalProperties constraint for env#8328

Merged
jdx merged 5 commits intojdx:mainfrom
adamliang0:main
Feb 24, 2026
Merged

fix(schema): enforce additionalProperties constraint for env#8328
jdx merged 5 commits intojdx:mainfrom
adamliang0:main

Conversation

@adamliang0
Copy link
Contributor

[env] showed a schema error when attempting to use age-encrypted values (see https://mise.jdx.dev/environments/secrets/age.html). This happened because the first oneOf branch was effectively an unconstrained object schema: it didn’t require any properties and allowed additional properties. That made it a catch-all that also matched the age object shape, so multiple oneOf branches matched and validation failed.

adamliang0 and others added 3 commits February 24, 2026 03:08
`[env]` showed a schema error when attempting to use age-encrypted values (see https://mise.jdx.dev/environments/secrets/age.html). This happened because the first `oneOf` branch was effectively an unconstrained object schema: it didn’t require any properties and allowed additional properties. That made it a catch-all that also matched the `age` object shape, so multiple `oneOf` branches matched and validation failed.
## Summary

Replaces the experimental conda backend's ~1,625 lines of custom code
with the [rattler](https://github.com/conda/rattler) Rust crates — the
same crates that power [pixi](https://github.com/prefix-dev/pixi).
Motivated by [jdx#8318](jdx#8318) from
a conda maintainer who noted the backend was directly using the
unsupported `api.anaconda.org` API.

**What was replaced:**
- Custom version matching and comparison logic
- Recursive dependency resolution via raw anaconda.org API calls
- Manual `.conda` ZIP+tar.zst and `.tar.bz2` extraction
- Hardcoded `SKIP_PACKAGES` list for virtual packages
- Custom patchelf/install_name_tool/codesign binary patching
(`conda_common.rs`, `conda_linux.rs`, `conda_macos.rs` deleted)

**With rattler:**
- `rattler_repodata_gateway` — fetches repodata from conda channels
(proper CDN-cached repodata.json)
- `rattler_solve` (resolvo) — SAT-based dependency solver, same as used
by pixi/conda-libmamba
- `rattler_package_streaming` — extracts `.conda` and `.tar.bz2`
archives
- `rattler_virtual_packages` — detects system virtual packages
(`__glibc`, `__osx`, etc.) properly
- `rattler::install::link_package` — proper conda installation with text
AND binary prefix replacement, file permissions, and macOS codesigning

**Key fix:** The old code explicitly skipped binary files during prefix
replacement (checking for null bytes). `link_package` correctly handles
binary prefix replacement by padding with null bytes to preserve byte
length, which is how conda is designed to work.

**Kept unchanged:**
- `lockfile.rs` — `CondaPackageInfo` type and `[conda-packages]` TOML
format
- All registry entries and settings

Since `EXPERIMENTAL = true`, breaking changes are acceptable.

## Test plan

- [x] `cargo build` — compiles cleanly
- [x] `mise run test:unit` — 481 tests pass
- [x] `mise run lint` — all checks pass
- [x] `mise run test:e2e test_conda`:
  - `conda:ruff@0.8.0` — installs with 24 deps, runs correctly
  - `conda:bat@0.24.0` — installs with 4 deps, runs correctly
  - `conda:jq@1.7.1` — installs with deps (oniguruma), runs correctly
  - `conda:postgresql@17.2` — installs with 29 deps, runs correctly
- [x] `mise lock` — lockfile generated correctly with per-platform deps

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Large rewrite of conda install/solve behavior (networking, dependency
resolution, and prefix handling) that could change which packages get
installed or how they’re linked; mitigated somewhat by being confined to
the experimental conda backend and adding checksum-verified,
lockfile-driven installs.
> 
> **Overview**
> Switches the experimental `conda` backend from bespoke anaconda.org
API calls, ad-hoc version/dependency selection, and manual archive
extraction/prefix patching to the `rattler` ecosystem:
`rattler_repodata_gateway` for repodata retrieval/caching,
`rattler_solve` (resolvo) for dependency solving with virtual package
detection, and `rattler::install::link_package` +
`rattler_package_streaming` for extraction and correct text/binary
prefix replacement.
> 
> Lockfile behavior is preserved but now populated from solver
`RepoDataRecord`s (URLs + sha256) and can perform deterministic installs
by downloading the locked URL set with checksum verification; Windows
bin path discovery is broadened to include both `Library/bin` and `bin`.
The previous platform-specific patching modules (`conda_common.rs`,
`conda_linux.rs`, `conda_macos.rs`) are removed, and Cargo
dependencies/lockfile are updated to include the new `rattler*` crates
and transitive deps.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
21d3602. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
## Summary
- Adds a native core plugin for .NET SDK that installs all versions
side-by-side under a shared `DOTNET_ROOT`, matching .NET's native
multi-version model
- Supports `global.json` as an idiomatic version file for per-project
SDK pinning
- Uses Microsoft's official `dotnet-install.sh`/`.ps1` script for
installation, with cross-platform support

## Motivation
Closes discussion jdx#7939 — users need multiple .NET SDK versions
installed simultaneously for multi-targeting (e.g., net6.0 + net8.0 in
one solution). The existing vfox-based plugin installs each version in
isolation, breaking .NET's native side-by-side model.

## Changes
- **`src/plugins/core/dotnet.rs`** — Core plugin implementation (version
listing from Microsoft releases API, install via official script, shared
DOTNET_ROOT, global.json parsing)
- **`src/plugins/core/mod.rs`** — Register the new plugin
- **`registry/dotnet.toml`** — Add `core:dotnet` as primary backend
(vfox/asdf remain as fallbacks)
- **`settings.toml`** — Add `dotnet.dotnet_root` setting
(`MISE_DOTNET_ROOT` env)
- **`docs/lang/dotnet.md`** — Documentation
- **`e2e/core/test_dotnet`** — E2E smoke test
- **`schema/mise.json`** — Auto-generated schema update

## Test plan
- [x] `mise run render` — regenerated settings struct, schema,
completions
- [x] `mise run lint-fix` — all linters pass
- [x] `mise run build` — compiles cleanly
- [x] `mise run test:unit` — all 481 tests pass
- [ ] `mise run test:e2e test_dotnet` — installs dotnet@8.0.408,
verifies version, tests global.json
- [ ] Manual: `mise use dotnet@8 && mise use dotnet@9 && dotnet
--list-sdks` shows both

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Adds a new core installer that downloads and executes the upstream
`dotnet-install` script and changes the default backend resolution for
`dotnet`, which could affect installs/uninstalls and environment setup
across platforms.
> 
> **Overview**
> Adds a new **core** `dotnet` tool plugin that installs .NET SDKs via
Microsoft’s official `dotnet-install` script and lists available SDK
versions from the Microsoft releases metadata API.
> 
> Introduces a shared `DOTNET_ROOT` install model by default (with
symlinked per-version install paths for tracking), plus an opt-in
`dotnet.isolated` mode for per-version directories; the plugin also
supports `global.json` as an idiomatic version file and sets
`DOTNET_MULTILEVEL_LOOKUP` and optional `DOTNET_CLI_TELEMETRY_OPTOUT`.
> 
> Makes `core:dotnet` the first backend in `registry/dotnet.toml`, adds
new settings (`dotnet.dotnet_root`, `dotnet.isolated`,
`dotnet.cli_telemetry_optout`) to `settings.toml`/schema, and includes
docs + an e2e smoke test for install and `global.json` resolution.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e35fbbe. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @adamliang0, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances mise's capabilities by adding a new core plugin for seamless .NET SDK management, including support for idiomatic version files and configurable installation modes. Concurrently, the Conda backend has undergone a substantial upgrade, now leveraging the rattler library to provide a more robust and modern approach to package dependency resolution and installation. These changes aim to improve the developer experience for users working with .NET and Conda environments within mise.

Highlights

  • New .NET Core Plugin: Introduced a new core plugin for managing .NET SDKs, providing native support for installation, version resolution, and global.json integration.
  • Conda Backend Refactor with Rattler: Performed a major refactor of the Conda backend, migrating its package resolution and installation logic to use the rattler library for improved reliability and efficiency.
  • Schema Validation Fix: Resolved a schema validation issue for the env configuration, specifically addressing problems when using age-encrypted values by enforcing additionalProperties: false.
Changelog
  • Cargo.lock
    • Updated dependencies to reflect the integration of the rattler library and other package updates.
  • Cargo.toml
    • Added new rattler dependencies, including rattler, rattler_conda_types, rattler_repodata_gateway, rattler_solve, rattler_package_streaming, and rattler_virtual_packages.
    • Included native-tls and rustls features for rattler and rattler_repodata_gateway.
  • docs/lang/dotnet.md
    • Added comprehensive documentation for the new .NET core plugin, detailing usage, global.json support, isolated mode, environment variables, and settings.
  • e2e/core/test_dotnet
    • Added end-to-end tests for the new .NET core plugin, verifying installation and global.json functionality.
  • registry/dotnet.toml
    • Registered the new core:dotnet backend, making the .NET core plugin available.
  • schema/mise.json
    • Corrected the env schema by adding "additionalProperties": false to prevent validation errors with unconstrained object schemas.
    • Added new configuration properties (cli_telemetry_optout, dotnet_root, isolated) for the .NET plugin under a new dotnet object.
  • settings.toml
    • Defined new settings for the .NET plugin: cli_telemetry_optout, dotnet_root, and isolated, including their descriptions and default values.
  • src/backend/conda.rs
    • Rewrote the Conda backend logic to use the rattler library for package resolution, downloading, and installation.
    • Removed custom dependency resolution, package extraction, and checksum verification logic, replacing it with rattler's capabilities.
    • Updated _list_remote_versions, install_version_, and get_platform_info to integrate with the rattler framework.
  • src/plugins/core/dotnet.rs
    • Implemented the new core .NET plugin, including logic for fetching remote versions from Microsoft's release API, parsing global.json files, installing SDKs via dotnet-install scripts, and configuring environment variables.
  • src/plugins/core/mod.rs
    • Integrated the new dotnet plugin into the list of core plugins.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
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 several significant changes, including a fix for a schema validation issue, a major refactoring of the conda backend to use the rattler library, and the addition of a new core plugin for .NET. While the individual changes are valuable improvements, combining them into a single pull request makes it difficult to review and understand the history of the project. The PR title "fix(schema): enforce additionalProperties constraint for env" is misleading as it only describes a very small part of the changes. In the future, please split such changes into separate pull requests. For example, this could have been three PRs: one for the schema fix, one for the conda refactoring, and one for the new .NET plugin.

Despite the scope, the changes themselves are excellent. The refactoring of the conda backend to use rattler is a significant improvement in maintainability and correctness. The new .NET core plugin is a great addition and seems well-implemented. The schema fix is also correct.

@jdx jdx merged commit 08d3c9f into jdx:main Feb 24, 2026
32 of 33 checks passed
mise-en-dev added a commit that referenced this pull request Feb 25, 2026
### 🚀 Features

- **(conda)** replace custom backend with rattler crates by @jdx in
[#8325](#8325)
- **(task)** enforce per-task timeout configuration by @tvararu in
[#8250](#8250)
- **(vsix)** added vsix archives to http backend by @sosumappu in
[#8306](#8306)
- add core dotnet plugin for .NET SDK management by @jdx in
[#8326](#8326)

### 🐛 Bug Fixes

- **(conda)** preserve conda_packages on locked install and fix temp
file race by @jdx in [#8335](#8335)
- **(conda)** deduplicate repodata records to fix solver error on Linux
by @jdx in [#8337](#8337)
- **(env)** include watch_files in fast-path early exit check by @jdx in
[#8317](#8317)
- **(env)** clear fish completions when setting/unsetting shell aliases
by @jdx in [#8324](#8324)
- **(lockfile)** prevent lockfile writes when --locked is set by @jdx in
[#8308](#8308)
- **(lockfile)** prune orphan tool entries on mise lock by @mackwic in
[#8265](#8265)
- **(lockfile)** error on contradictory locked=true + lockfile=false
config by @jdx in [#8329](#8329)
- **(regal)** Update package location by @charlieegan3 in
[#8315](#8315)
- **(release)** strip markdown heading prefix from communique release
title by @jdx in [#8303](#8303)
- **(schema)** enforce additionalProperties constraint for env by
@adamliang0 in [#8328](#8328)

### 📚 Documentation

- Remove incorrect oh-my-zsh plugin ordering comment by @bvosk in
[#8323](#8323)
- require AI disclosure on GitHub comments by @jdx in
[#8330](#8330)

### 📦 Registry

- add `oxfmt` by @taoufik07 in
[#8316](#8316)

### New Contributors

- @adamliang0 made their first contribution in
[#8328](#8328)
- @tvararu made their first contribution in
[#8250](#8250)
- @bvosk made their first contribution in
[#8323](#8323)
- @taoufik07 made their first contribution in
[#8316](#8316)
- @charlieegan3 made their first contribution in
[#8315](#8315)
- @sosumappu made their first contribution in
[#8306](#8306)

## 📦 Aqua Registry Updates

#### New Packages (3)

- [`Tyrrrz/FFmpegBin`](https://github.com/Tyrrrz/FFmpegBin)
- [`elixir-lang/expert`](https://github.com/elixir-lang/expert)
- [`erikjuhani/basalt`](https://github.com/erikjuhani/basalt)

#### Updated Packages (5)

- [`caarlos0/fork-cleaner`](https://github.com/caarlos0/fork-cleaner)
-
[`firecow/gitlab-ci-local`](https://github.com/firecow/gitlab-ci-local)
- [`jackchuka/mdschema`](https://github.com/jackchuka/mdschema)
-
[`kunobi-ninja/kunobi-releases`](https://github.com/kunobi-ninja/kunobi-releases)
- [`peco/peco`](https://github.com/peco/peco)
risu729 pushed a commit to risu729/mise that referenced this pull request Feb 27, 2026
`[env]` showed a schema error when attempting to use age-encrypted
values (see https://mise.jdx.dev/environments/secrets/age.html). This
happened because the first `oneOf` branch was effectively an
unconstrained object schema: it didn’t require any properties and
allowed additional properties. That made it a catch-all that also
matched the `age` object shape, so multiple `oneOf` branches matched and
validation failed.

---------

Co-authored-by: jdx <216188+jdx@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
risu729 pushed a commit to risu729/mise that referenced this pull request Feb 27, 2026
### 🚀 Features

- **(conda)** replace custom backend with rattler crates by @jdx in
[jdx#8325](jdx#8325)
- **(task)** enforce per-task timeout configuration by @tvararu in
[jdx#8250](jdx#8250)
- **(vsix)** added vsix archives to http backend by @sosumappu in
[jdx#8306](jdx#8306)
- add core dotnet plugin for .NET SDK management by @jdx in
[jdx#8326](jdx#8326)

### 🐛 Bug Fixes

- **(conda)** preserve conda_packages on locked install and fix temp
file race by @jdx in [jdx#8335](jdx#8335)
- **(conda)** deduplicate repodata records to fix solver error on Linux
by @jdx in [jdx#8337](jdx#8337)
- **(env)** include watch_files in fast-path early exit check by @jdx in
[jdx#8317](jdx#8317)
- **(env)** clear fish completions when setting/unsetting shell aliases
by @jdx in [jdx#8324](jdx#8324)
- **(lockfile)** prevent lockfile writes when --locked is set by @jdx in
[jdx#8308](jdx#8308)
- **(lockfile)** prune orphan tool entries on mise lock by @mackwic in
[jdx#8265](jdx#8265)
- **(lockfile)** error on contradictory locked=true + lockfile=false
config by @jdx in [jdx#8329](jdx#8329)
- **(regal)** Update package location by @charlieegan3 in
[jdx#8315](jdx#8315)
- **(release)** strip markdown heading prefix from communique release
title by @jdx in [jdx#8303](jdx#8303)
- **(schema)** enforce additionalProperties constraint for env by
@adamliang0 in [jdx#8328](jdx#8328)

### 📚 Documentation

- Remove incorrect oh-my-zsh plugin ordering comment by @bvosk in
[jdx#8323](jdx#8323)
- require AI disclosure on GitHub comments by @jdx in
[jdx#8330](jdx#8330)

### 📦 Registry

- add `oxfmt` by @taoufik07 in
[jdx#8316](jdx#8316)

### New Contributors

- @adamliang0 made their first contribution in
[jdx#8328](jdx#8328)
- @tvararu made their first contribution in
[jdx#8250](jdx#8250)
- @bvosk made their first contribution in
[jdx#8323](jdx#8323)
- @taoufik07 made their first contribution in
[jdx#8316](jdx#8316)
- @charlieegan3 made their first contribution in
[jdx#8315](jdx#8315)
- @sosumappu made their first contribution in
[jdx#8306](jdx#8306)

## 📦 Aqua Registry Updates

#### New Packages (3)

- [`Tyrrrz/FFmpegBin`](https://github.com/Tyrrrz/FFmpegBin)
- [`elixir-lang/expert`](https://github.com/elixir-lang/expert)
- [`erikjuhani/basalt`](https://github.com/erikjuhani/basalt)

#### Updated Packages (5)

- [`caarlos0/fork-cleaner`](https://github.com/caarlos0/fork-cleaner)
-
[`firecow/gitlab-ci-local`](https://github.com/firecow/gitlab-ci-local)
- [`jackchuka/mdschema`](https://github.com/jackchuka/mdschema)
-
[`kunobi-ninja/kunobi-releases`](https://github.com/kunobi-ninja/kunobi-releases)
- [`peco/peco`](https://github.com/peco/peco)
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.

2 participants