Skip to content

fix(packslip): let a workflow list carry the signer pin across a workflow move - #14338

Merged
jdx merged 2 commits into
mainfrom
claude/mise-discussion-13948-775c6a
Oct 12, 2026
Merged

jdx merged 2 commits into
mainfrom
claude/mise-discussion-13948-775c6a

Conversation

@jdx

@jdx jdx commented Oct 12, 2026 •

Copy link
Copy Markdown
Owner

https://entire.io/gh/jdx/mise/trails/663

A machine that installed aube 2.2–2.5 could not upgrade it. aube moved its signing workflow from release-plz.yml to release.yml at 2.6.0. mise's signer pin remembered the first one, so mise upgrade and latest resolution refused every newer release. This happened even though the registry entry's workflow list (#14092) names both workflows:

$ mise upgrade
mise WARN  Error getting latest version for aube: packslip:github.com/aubepkg/aube: this release is signed by https://github.com/aubepkg/aube/.github/workflows/release.yml (sigstore-oidc), but https://github.com/aubepkg/aube/.github/workflows/release-plz.yml (sigstore-oidc) signed what mise accepted before.
mise All tools are up to date

A workflow list is the explicit trust decision the signer pin waits for. The pin now accepts a release when both the pinned signer and the release's signer are among the listed workflows, and records the new one. The same machine now upgrades without mise packslip forget:

$ mise upgrade
Upgraded 1 tool:
  aube 2.5.1 → 2.7.0

This applies to a list in the user's own tool options as well as a registry default:

[tools]
"packslip:github.com/example/tool" = { version = "latest", workflow = ["release-plz.yml", "release.yml"] }

A single workflow, or a list that doesn't name the pinned signer, still refuses a new signer as before.

Reported in discussion #13948.

Validation

  • New unit test in packslip_pins.rs: the move is refused without the list, accepted and recorded with it, and still refused when only one side is listed.
  • Ran a debug build against isolated state: installed aube 2.5.1, which pinned release-plz.yml. Then mise upgrade installed 2.7.0 and moved the pin to release.yml, and reinstalling 2.5.1 moved it back. With workflow = "release.yml@refs/heads/main" alone, 2.7.0 is still refused against the old pin.
  • cargo clippy --workspace --all-features --all-targets -- -D warnings is clean, and the packslip unit tests pass.

AI-assisted — Tool: Claude Code; model: anthropic/claude-opus-5-5; version: 2.1.295.

🤖 Generated with Claude Code


Note

Medium Risk
Changes packslip trust and pin persistence logic; scope is limited to workflow-list continuity with existing refusal paths for unrelated signers.

Overview
Fixes upgrades that failed when a vendor moved its signing workflow (e.g. release-plz.yml → release.yml) even though the tool’s workflow list already trusted both paths.

Signer pin continuity now treats a multi-workflow workflow option as an explicit trust decision: if both the stored pin and the release’s signer appear in that list, the release is accepted and the pin is updated to the current workflow—no mise packslip forget. A single workflow or a list that omits the pinned signer still blocks a new signer.

Implementation adds listed on Observed, derives it from Pin::listed_signers() in the packslip backend, and adjusts record so the remembered signer follows accepted workflow moves (not only forge renames). Docs note the link between workflow lists and pinned signers; a unit test covers refuse/accept/partial-list cases.

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

Summary by CodeRabbit

  • New Features
    • Packslip can now accept signer transitions between workflows listed in the project’s workflow option, without requiring you to reset the signer pin.
  • Documentation
    • Clarified that changes to a workflow path or signing key still require an explicit trust decision.

… names

A machine that installed aube 2.2–2.5 (signed by release-plz.yml) refused
2.6.0 and later (signed by release.yml) on upgrade and latest resolution,
although the registry's workflow list names both. A workflow list is the
person's say-so for that move, so the signer pin now accepts a release
whose signer and the pinned one are both listed, and records the new one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M4S05V5MBY3YAQBE27W08FVD
@coderabbitai

coderabbitai Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 15 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository YAML (base), Central YAML (inherited), Organization UI (inherited)
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: ac44459c-3c23-4365-8b69-1d135cb90ced

📥 Commits

Reviewing files that changed from the base of the PR and between 6189cf9 and a80a5f4.


📒 Files selected for processing (1)
  • crates/mise-util/src/packslip_pins.rs

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository YAML (base), Central YAML (inherited), Organization UI (inherited)
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 4affe016-146b-4cd1-a6a6-016d01d6e947

📥 Commits

Reviewing files that changed from the base of the PR and between 76c6466 and 6189cf9.


📒 Files selected for processing (5)
  • crates/mise-util/src/packslip_pins.rs
  • docs/dev-tools/backends/packslip.md
  • docs/dev-tools/packslip-verification.md
  • src/backend/packslip.rs
  • src/packslip_forge.rs

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 0 remain after this review.



📝 Walkthrough

Walkthrough

Packslip pin checks now accept signer transitions between workflows named in the workflow list. The listed signers pass through release verification and installation, and recording stores the observed signer after an accepted release.

Changes

Signer workflow continuity

Layer / File(s) Summary
Pass listed signers through pin operations
crates/mise-util/src/packslip_pins.rs, src/backend/packslip.rs
The observed-pin data and pending-pin state now carry listed workflow signers through release verification and installation.
Match and record workflow signer transitions
crates/mise-util/src/packslip_pins.rs, src/packslip_forge.rs, docs/dev-tools/backends/packslip.md, docs/dev-tools/packslip-verification.md
Pin checks accept a signer transition when both signers are listed. Recording stores the observed signer. Tests and documentation cover the transition and the empty-list default.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant WorkflowOptions
  participant PinCheck
  participant PendingPin
  participant PinRecord
  WorkflowOptions->>PinCheck: provide listed workflow signers with observed signer
  PinCheck->>PinCheck: check pinned signer, listed transition, or forge continuation
  PinCheck-->>PendingPin: retain listed signers after accepted installation
  PendingPin->>PinRecord: record observed signer and listed signers
Loading

Merge Risk: ⚪ Minimal · up to 6189c

Listed workflows can carry the machine signer pin across a workflow move without silently changing an existing lockfile signer commitment. No issue identified here needs to block merging.

Pre-merge checks · Passed 4 · Failed 1

Failed Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 14 functions across 3 files. (2 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks (4 passed)
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: preserving signer pins across workflow transitions when a workflow list authorizes the move.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.

Full details: Docstring Coverage

Explanation

Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 14 functions across 3 files. (2 skipped: 2 unsupported.)


  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

[Medium impact] The PR appears safe to merge.

Summary

The PR lets Packslip move a signer pin between workflows when both are named in the configured workflow list.

  • Workflow lists let signer pins move between listed workflows.

Reviews (2) · Last reviewed commit: "test(packslip): refuse a move when only ..." · Reviewed by Greptile

Comment thread crates/mise-util/src/packslip_pins.rs Resolved
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M4S0JZ8C8R4J980113DWY4F8
@jdx
jdx merged commit f92bddd into main Oct 12, 2026
52 checks passed
@jdx
jdx deleted the claude/mise-discussion-13948-775c6a branch October 12, 2026 22:12
@github-actions

Copy link
Copy Markdown
Contributor

Instruction counts

Nothing was compared, and so nothing was gated. No series appears on both sides: either the base has no measurements recorded, or the two were measured on different runner classes, which are deliberately not comparable — counts shift between machine types by more than a real regression does.

New, nothing to compare against: env on jdx-perf-v1-ubuntu24.04-x64-mise-rust1.97.1-img5263c143, hook-env on jdx-perf-v1-ubuntu24.04-x64-mise-rust1.97.1-img5263c143, ls on jdx-perf-v1-ubuntu24.04-x64-mise-rust1.97.1-img5263c143, registry on jdx-perf-v1-ubuntu24.04-x64-mise-rust1.97.1-img5263c143, startup on jdx-perf-v1-ubuntu24.04-x64-mise-rust1.97.1-img5263c143

Only instruction counts gate. Wall clock is shown for context — on identical hardware it moves 4-20% run to run.

Measured by tak — instruction-counted CLI benchmarks, stored in this repository's git notes.

a80a5f443c95 vs 1cfa50cf9822 · measured on the runner, not pushed to the history.

jdx pushed a commit that referenced this pull request Oct 13, 2026
<!-- entire-trail-link-start -->
https://entire.io/gh/jdx/mise/trails/640
<!-- entire-trail-link-end -->

### 🚀 Features

- **(bootstrap)** add apt repositories and PPAs with
[bootstrap.apt.sources] by @jdx in
[#14306](#14306)
- **(bootstrap)** embed apt source signing keys inline in .sources files
by @jdx in [#14348](#14348)
- **(bootstrap)** render templates in [bootstrap.repos] checkout paths
by @jdx in [#14359](#14359)
- **(bootstrap)** declare macOS login items by @jdx in
[#14354](#14354)
- **(bootstrap)** layer dnf packages with rpm-ostree on Fedora Atomic
hosts by @jdx in [#14357](#14357)
- **(bootstrap)** support run0 and doas for privilege elevation by @jdx
in [#14351](#14351)
- **(dotfiles)** show tracked entries that no variant selects in status
by @jdx in [#14266](#14266)
- **(dotfiles)** group mise dot status into sections by @jdx in
[#14361](#14361)
- **(github)** add oauth_copy_code to copy the device code to the
clipboard by @jdx in [#14269](#14269)
- **(github)** keep the native OAuth refresh token in a password manager
or keychain by @jdx in [#14360](#14360)
- **(http)** add libc() and avx2() template functions by @jdx in
[#14298](#14298)
- **(pypi)** read upload times from PEP 691 simple indexes by @jdx in
[#14352](#14352)
- **(rust)** download rustup-init from RUSTUP_UPDATE_ROOT by @jdx in
[#14356](#14356)

### 🐛 Bug Fixes

- **(aqua)** warn once for packages with no repo to list versions from
by @jdx in [#14336](#14336)
- **(backend)** keep decoded download file names inside the download
directory by @JamBalaya56562 in
[#14274](#14274)
- **(bootstrap)** support dnf package groups by @jdx in
[#14347](#14347)
- **(bootstrap)** don't print a stdin-only helper as a manual command by
@jdx in [#14350](#14350)
- **(bootstrap)** explain why dnf packages cannot install on ostree
hosts by @jdx in [#14353](#14353)
- **(brew)** install bottle etc files and run post_install_steps when
pouring by @jdx in [#14272](#14272)
- **(brew)** refuse to chown a prefix owned by another user by @jdx in
[#14345](#14345)
- **(brew)** preserve protected post-install copy destinations by @jdx
in [#14311](#14311)
- **(brew-cask)** support generate completions in evaluated casks by
@pmmmwh in [#14255](#14255)
- **(docker)** install libatomic1 in the Debian image so Node.js 26 runs
by @jdx in [#14303](#14303)
- **(dotfiles)** keep existing ciphertext when an encrypted file is
unchanged by @jdx in [#14300](#14300)
- **(dotfiles)** stop a newly selected profile from deleting its shared
file by @jdx in [#14275](#14275)
- **(dotfiles)** restore config entries when adopting under a symlinked
home by @jdx in [#14315](#14315)
- **(dotfiles)** show per-file diffs for directory copy entries in dot
diff by @jdx in [#14333](#14333)
- **(dotfiles)** apply mise's own config before planning the other
entries by @jdx in [#14339](#14339)
- **(go)** read an exact go line in go.mod as the toolchain version by
@jdx in [#14308](#14308)
- **(http)** retry artifact downloads started by mise exec and shims by
@jdx in [#14342](#14342)
- **(npm)** resolve unlocked latest to the npm version of a graph-locked
install by @jdx in [#14307](#14307)
- **(npm)** give unlocked requests their own install under the identity
layout by @jdx in [#14309](#14309)
- **(oci)** ignore host apt hooks when installing apt bootstrap packages
by @jdx in [#14296](#14296)
- **(packslip)** let a workflow list carry the signer pin across a
workflow move by @jdx in
[#14338](#14338)
- **(packslip)** keep a renamed project's lockfile signer under packslip
1.7 by @jdx in [#14362](#14362)
- **(prune)** keep a uv-locked pipx tool's installs for every Python by
@jdx in [#14335](#14335)
- **(prune)** keep versions of task-scoped tools by @jdx in
[#14334](#14334)
- **(schema)** accept [bootstrap.secrets] by @JamBalaya56562 in
[#14322](#14322)
- **(schema)** accept [bootstrap.groups] and [bootstrap.users] by
@JamBalaya56562 in [#14340](#14340)
- **(schema)** accept table forms for vars._.file and vars._.source by
@JamBalaya56562 in [#14383](#14383)
- **(shim)** keep other projects' command wrappers on reshim by @jdx in
[#14355](#14355)
- **(task)** bump gix so remote tasks work in git hooks by @any-victor
in [#14316](#14316)
- hide the Windows console for the tool-update service by @jdx in
[#14344](#14344)

### 🚜 Refactor

- replace serde_yaml with serde-saphyr by @jdx in
[#14328](#14328)

### 📚 Documentation

- **(bootstrap)** explain when to use --from versus --adopt by @jdx in
[#14301](#14301)
- **(bootstrap)** recommend fish = "auto" for fish shell activation by
@jdx in [#14304](#14304)
- **(dotfiles)** explain when to use sync, pull, and apply by @jdx in
[#14343](#14343)
- **(shims)** explain how to check whether a tool is installed by @jdx
in [#14337](#14337)
- switch body text to DM Sans and tighten the releases page by @jdx in
[#14302](#14302)
- self-host DM Sans and JetBrains Mono so they load on mise.jdx.dev by
@jdx in [#14310](#14310)

### 🧪 Testing

- **(bootstrap)** don't depend on bc being absent in the apt sources
test by @jdx in [#14371](#14371)

### 📦️ Dependency Updates

- install Homebrew uses_from_macos dependencies on Linux by @itskyf in
[#14288](#14288)
- bump packslip to 1.7.0 by @jdx in
[#14363](#14363)
- lock file maintenance by @renovate[bot] in
[#14320](#14320)
- update github actions by @renovate[bot] in
[#14380](#14380)
- update dependency python to v3.14.8 by @renovate[bot] in
[#14381](#14381)
- update rust crates by @renovate[bot] in
[#14382](#14382)
- update docker images by @renovate[bot] in
[#14379](#14379)

### 📦 Registry

- install opencode 2 from npm by @jdx in
[#14295](#14295)

### Chore

- **(ci)** switch to jactionlint v2 and drop zizmor by @jdx in
[#14256](#14256)
- fix CI for the aqua registry update and the unsafe-libyaml advisory by
@jdx in [#14326](#14326)

### Ci

- double the unit-macos job timeout by @jdx in
[#14346](#14346)

### Security

- **(config)** require trust for path: tool versions by @jdx in
[#14358](#14358)

### New Contributors

- @pmmmwh made their first contribution in
[#14255](#14255)
- @itskyf made their first contribution in
[#14288](#14288)

## 📦 Aqua Registry Updates

### New Packages (3)

- [`Alice39s/xmtr`](https://github.com/Alice39s/xmtr)
-
[`bufbuild/protoschema-plugins/protoc-gen-jsonschema`](https://github.com/bufbuild/protoschema-plugins)
- [`takumin/qemu-bin`](https://github.com/takumin/qemu-bin)

### Updated Packages (3)

- [`bootandy/dust`](https://github.com/bootandy/dust)
-
[`connectrpc/connect-go/protoc-gen-connect-go`](https://github.com/connectrpc/connect-go)
- [`sharkdp/hyperfine`](https://github.com/sharkdp/hyperfine)
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