Skip to content

@pierre/theme@2.0.0 lost provenance, so no-downgrade trust policies block hunkdiff 0.19.0 installs #836

Description

@connorads

What happens

@pierre/theme carried npm provenance from 0.0.20 through 1.0.3, then stopped at 1.1.0 when it moved into the pierre monorepo. @pierre/diffs@1.3.5 pins @pierre/theme@2.0.0 exactly, and hunkdiff 0.19.0 pins that diffs, so any package manager enforcing provenance continuity refuses to resolve.

With aube as mise's npm backend:

# ~/.config/mise/config.toml
npm.package_manager = "aube"   # mise's default is "auto"

[tools]
"npm:hunkdiff" = "0"
$ mise upgrade npm:hunkdiff
ERR_AUBE_TRUST_DOWNGRADE
  × failed to resolve dependencies
  ╰─▶ trust downgrade for @pierre/theme@2.0.0 (trustPolicy=no-downgrade):
      earlier published version 0.0.20 had provenance attestation but this
      version has no trust evidence

(mise progress lines and aube's help: block trimmed; that block notes it may be benign release-process drift and points at trustPolicyExclude.) Worth knowing that no-downgrade is aube's default, so this is a stock install, not a hardened config. pnpm has the same check but ships it off by default. The 0.0.20 in the message is the oldest attested version, not the nearest; the last attested release is 1.0.3.

0.18.2 is the last release that resolves cleanly. Everything up to and including it pins @pierre/diffs@1.2.2, which pins the attested @pierre/theme@1.0.3; 0.19.0 is the first to move to 1.3.5.

I raised it upstream (pierrecomputer/pierre#1080) and a Pierre org member replied "we intentionally do not use any cloud based publishing", so I'm not sure a fix is coming from that side. It also couldn't be retroactive: 2.0.0 can't gain an attestation now, so even a change of heart wouldn't help until diffs bumps its pin.

Worth saying that hunk itself does this properly. Every npm publication from 0.18.0-beta.0 on, platform packages included, carries provenance naming .github/workflows/release-prebuilt-npm.yml (#640, #661). The gate is refusing a well-attested package over a transitive dep that isn't, which seems like a shame.

A fix that might not need Pierre

I think @pierre/diffs is already bundled into what you publish, though you'll know better than me whether that's the whole picture.

In the 0.19.0 tarball, every static import in dist/npm/main.js is a Node builtin. Its only dynamic imports naming a package are the eight @opentui/core-* natives, ws, and readline/promises; the rest resolve file URLs. Every declared dep appears inside it as inlined source, tagged by bundler // node_modules/... markers:

@pierre/diffs 37   zod 77   diff 11   commander 8
get-east-asian-width 4   shell-quote 3   chokidar 2   string-width 1

bin/hunk.cjs honours HUNK_BIN_PATH, then looks for a prebuilt node_modules/hunkdiff-<platform>-<arch>/bin/hunk, and only falls back to require.resolve("bun/bin/bun") plus main.js. So an install needs a platform binary or bun, and not much else.

@pierre/diffs does stay live in one shipped runtime file, dist/npm/opentui/index.js (six from "@pierre/diffs" statements), where build-npm.ts marks it --external. I assume that's deliberate so extension authors get the same instance. What caught my eye is that its neighbours in that same file, react, @opentui/core and @opentui/react, are declared as peerDependencies. @pierre/diffs is the only live specifier there carried as a full runtime dependency instead.

One possible fix

Move @pierre/diffs to peerDependencies alongside them, rather than dropping it, since the hunkdiff/opentui subpath genuinely needs it resolvable and would fail with ERR_MODULE_NOT_FOUND otherwise. That would also mean adding it to the install line in docs/opentui-component.md, which already lists the other three.

A plain CLI install would then pull no @pierre/* at all and the trust gate would have nothing to look at, while anyone importing hunkdiff/opentui brings their own copy, as they already do for react. The same reasoning might apply to the rest of the bundled block, which could also help #518, though bun needs care since bin/hunk.cjs resolves it at runtime.

Alternatives I considered

  • Pin @pierre/diffs back to 1.2.2, as 0.18.2 does. Stopgap at best, and it gives up 1.3.x.
  • Bundle @pierre/diffs into the opentui entry too. Removes the import, but probably hands extension authors a duplicate module, which I'd guess is why it's external in the first place.
  • Vendor the theme tokens. BUNDLED_SHIKI_THEME_DIFF_COLORS is a precedent, but Bundled diff-color catalog stores mis-sourced VS Code theme tokens #823 flags that table as mis-sourced and Themes: Harvest bundled diff accents from real VS Code tokens #828 is already moving it to values generated from a pinned devDependency. That generated shape would be the one to copy, and it's upkeep that isn't needed if the dep is just declared differently.

Entirely possible I've misread something here, so treat the suggestion as a starting point rather than a diagnosis.

Environment

hunkdiff 0.19.0 fails; 0.18.2 installs cleanly
mise 2026.7.10 macos-arm64
aube 1.38.0 (also reproduced on 1.41.0), trustPolicy = no-downgrade (default)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions