Skip to content

aube: sync vendored engine to upstream v1.32.0#519

Open
colinhacks wants to merge 8 commits into
mainfrom
aube-sync-v132
Open

aube: sync vendored engine to upstream v1.32.0#519
colinhacks wants to merge 8 commits into
mainfrom
aube-sync-v132

Conversation

@colinhacks

@colinhacks colinhacks commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Syncs the vendored engine from aube v1.25.1 to v1.32.0 — 133 upstream commits.

Merge base

vendor/aube was at v1.25.1 while the nub-fork merge venue was at v1.23.0: an earlier sync went straight into vendor/aube and bypassed the venue, so git had been merging against a two-release-stale base.

Re-parenting the reconciliation snapshot onto upstream's v1.25.1 release commit:

base conflicted files hunks
v1.23.0 (stale) 72 205
v1.25.1 (correct) 23 48

Cargo.lock, the changelogs, and generated docs auto-merge at the correct base. vendor/aube/UPSTREAM now records the base commit so the next bump reads it instead of inferring it from a version string.

Resolution

Preserved: GVS/phantom linking, force-materialization, concurrent OSV and trust-policy gating, the defaultTrust floor, embedder-profile plumbing, nub-identity config scoping, pnpm-11 namedRegistries, patch-group range resolution.

Grafted from upstream: plain unified patch parsing (jdx/aube#1021), file:/portal: stale-materialization removal, proxy passthrough to lifecycle scripts (ordered so nub's env overlay still applies last), rustls/hickory-dns feature gating with nub's Android carve-out, stale (patch_hash=…) stripping, hash-only patch decoration (jdx/aube#1035), the berry patch-selector superset, and upstream's install cancellation points re-sited into nub's concurrent structure.

Seven further defects were found by the compiler, not by conflict markers — a new required parse_one parameter, upstream's new access.rs written against a signature nub had changed, a TrustExcludeRule field rename under a nub-added method, a new progress Mode::Events variant, and two new required struct fields.

Two pre-existing bugs fixed

Both predate this merge; both are fixed here because the merge widens them.

  1. decide_with_floor dropped source_key, so the build-approval warning seam disagreed with the runner about file:/git/tarball-backed packages — a bare-name allowBuilds approval vouched for bytes the runner refuses. Upstream v1.32 moves all three seams to decide_package_with_git_repository, which would widen the gap to two missing keys.
  2. The pnpm writer required patched_dependencies to contain the source key, but nub's pnpm reader leaves that map empty by design, so every parse and re-emit dropped (patch_hash=…) suffixes and changed dep-path identity.

nub-side

jdx/aube#1068 and #1069 feature-gated the TLS backend and the publish stack, so crates/nub-cli/Cargo.toml now names what it needs:

  • auberustls, publish. publish gates commands::publish, which pm_engine/publish_family.rs calls directly; rustls is the crate's only TLS backend. Without them nub-cli does not compile.
  • aube-registryhickory-dns. Default-preserving: this crate called .hickory_dns(cfg!(not(target_os = "android"))) unconditionally before v1.32.
  • hickory-dns is deliberately left off the aube crate — reqwest's feature flips the default resolver for every client in the binary.

Verification

  • aube: cargo check --workspace --all-targets, clippy --all-targets --all-features -- -D warnings, 2,590 tests — all green.
  • nub: check -p nub-cli --all-targets, clippy --all-targets --all-features -- -D warnings, fmt --check, and 443 tests across the 15 sync-relevant binaries — all green. The full suite was not run in one pass (pm_two_mode alone takes 41 minutes); CI covers it.
  • aube-util's new cfg partition checked under no-default-features, rustls, and the Windows target. The Android branch is exhaustive and mutually exclusive by construction.
  • The 18 files failing cargo fmt --check inside vendor/aube are an identical set before and after this merge. nub's root workspace excludes vendor/aube, so they do not gate nub CI.

Patch handling brought to pnpm parity

Two further pnpm-compat gaps, both confirmed against real pnpm 10.15.1 rather than inferred.

Patches now apply to npm-aliased installs. patchedDependencies: { "is-odd@3.0.1": … } did not patch odd-alias: npm:is-odd@3.0.1; pnpm does, because it resolves patches against the resolved manifest's name, where the alias is not a distinct node. The rule lives in one place — PatchGroups::resolve_package, called by both the resolver and the pnpm writer, keyed by spec_key() so the linker's Patches map, the graph hash, and the delta fingerprint all inherit it. The no-churn write guard carried a second copy of the matching logic and now routes through the same entry point.

Resolution is by registry name only. A key naming the alias matches nothing, because pnpm can never match one either.

aube v1.32.0 has the same gap, and additionally records (patch_hash=…) on the alias's dep path — so its lockfile claims a patched identity the install does not produce. Reported upstream as jdx/aube discussion #1082.

Fixing this exposed a second, pre-existing reader bug: pnpm/read.rs baked the write-time (patch_hash=…) marker into parsed dep paths, so a parsed patched graph could never hash-match a fresh resolve and the no-churn guard could never fire. The reader now strips the marker and the writer re-derives it — one owner per direction, writer output unchanged.

An unused patch key now fails the install. A patchedDependencies key matching no installed package was silently ignored; pnpm exits 1 with no node_modules and no lockfile, even when the dead key sits beside keys that do apply. Nub now matches, with the message text byte-identical to pnpm's, and the gate in the same place pnpm runs it (inside the resolution step, so a warm install whose resolution is skipped does not re-check).

allowUnusedPatches downgrades it to a warning. All seven candidate spellings were probed against pnpm 10.15.1: this is a manifest and workspace-YAML setting and .npmrc is not a home for it, so nub reads it from exactly the homes patchedDependencies uses. The existing config gating then gives the brand boundary for free — a pnpm-incumbent project reads pnpm.allowUnusedPatches, a nub-identity project reads the neutral top-level key and ignores the branded one, the same shape allowBuilds already has. pnpm 10's deprecated allowNonAppliedPatches spelling is accepted.

This fails installs that previously succeeded. A typo, a removed dependency, or a version bump that outran a patch selector now fails on the next resolving install. That is the intended parity, but it is the user-visible blast radius of this PR.

Flagged for review

Merges jdx/aube v1.25.1..v1.32.0 (133 commits) into vendor/aube.

The merge was done on nubjs/aube's nub-fork branch, which carries real
upstream ancestry, after reconciling a broken merge base: vendor/aube on
main was at v1.25.1 while nub-fork was still at v1.23.0, because an earlier
sync went straight into vendor/aube and bypassed the venue. Recording the
v1.25.1 release commit as a parent of the reconciliation commit cut the
conflict surface from 72 files / 205 hunks to 23 files / 48 hunks.

Nub's PM delta is preserved: GVS and phantom linking, force-materialization,
concurrent OSV and trust-policy gating, the defaultTrust floor, the TTY
progress line, embedder-profile plumbing, nub-identity config scoping,
pnpm-11 namedRegistries, and patch-group range resolution. Upstream
capabilities grafted on top include plain unified patch parsing, proxy
passthrough to lifecycle scripts, stale patch-hash stripping, hash-only
patch decoration, the berry patch-selector superset, and upstream's install
cancellation points re-sited into nub's concurrent structure.

Two pre-existing defects are fixed because this merge widens them:

- decide_with_floor dropped source_key, so the build-approval warning seam
  disagreed with the runner about file:/git/tarball-backed packages. It now
  passes source and git-repository keys, matching the runner and upstream.
- The pnpm writer required patched_dependencies to contain the source key,
  but nub's pnpm reader leaves that map empty by design, so every parse and
  re-emit dropped (patch_hash=...) suffixes and changed dep-path identity.

nub-cli now names the features upstream made optional in #1068 and #1069:
aube gains rustls and publish; aube-registry gains hickory-dns, which
restores the unconditional in-process DNS cache this crate had before
v1.32. hickory-dns is deliberately left off the aube crate, since reqwest's
feature flips the default resolver for every client in the binary.
The merge base for the next bump was previously inferable only from the
version string in vendor/aube/Cargo.toml, which is why the v1.32 bump
started against a two-release-stale base. Recording the commit makes it a
fact the next bump reads instead of reverse-engineers.
Copilot AI review requested due to automatic review settings July 22, 2026 15:55
@vercel

vercel Bot commented Jul 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
nub Ready Ready Preview, Comment Jul 22, 2026 9:12pm

Request Review

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

@pullfrog pullfrog Bot left a comment

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.

✅ No new issues found.

Reviewed changes — a plain-in-tree vendor/aube sync from v1.25.1 to v1.32.0 (133 upstream commits). The bulk is upstream jdx/aube code, docs, CI, and benchmarks; the review focused on the nub-side integration: feature-gating, conflict resolutions, and the two flagged fixes.

  • Re-base the vendored tree onto the correct upstream commitvendor/aube/UPSTREAM now records the merge base (9f2f5f8255 / v1.32.0), cutting the conflict surface from 72 files/205 hunks against the stale base to 23/48 against the correct one.
  • Feature-gate the engine deps in crates/nub-cli/Cargo.tomlaube moves to default-features = false, features = ["rustls", "publish"] (both now required to compile after jdx/aube#1068/#1069), and aube-registry names hickory-dns to preserve its pre-v1.32 unconditional behavior. hickory-dns is left off the aube crate deliberately.
  • Unify the build-approval decision seam (decide_with_floor) — all five allow-decision sites (run_dep_lifecycle_scripts, should_jail/build_jail, decide_with_floor, the ignored_builds scan, and the graph-hash allow closure) now route through decide_package_with_git_repository with both the source and git-repository approval keys via the new package_build_is_allowed helper, closing a gap where a bare-name allowBuilds approval vouched for file:/git/tarball-backed bytes the runner refuses.
  • Fix the pnpm (patch_hash=…) writer — drops the patched_dependencies.contains_key guard (nub's reader leaves that map empty for hash entries), and with_patch_hash now strips-then-restamps so a re-emit no longer changes dep-path identity.
  • Absorb upstream-driven signature changesParseOptions (default-preserving strict integrity), the TrustExcludeRule exact-version→range generalization under nub's pub(crate) methods, the tokio task-local dependency-chain index with scope_current re-siting into nub's concurrent lifecycle spawn, and the new InstallControl / Mode::Events plumbing (nub defaults to Human).

The integration is coherent and exceptionally well-documented — every conflict resolution and compiler-forced change is grounded in an inline rationale, and the flagged fixes each carry a test. I verified the five decision seams are consistent, the aube-util cfg partition is exhaustive and mutually exclusive across the rustls/Android/other-target matrix, and the default parse/output paths preserve prior behavior. Two items surfaced only for awareness, neither blocking.

ℹ️ Security-posture change rides in a sync PR

The decide_with_floor fix is a real behavior change to the build-approval path, not a mechanical merge: before this PR the unreviewed-builds warning could disagree with the runner about file:/git/tarball-backed packages, so a bare-name allowBuilds approval effectively vouched for bytes the runner would refuse. The fix is correct and the author already called it out, but it is worth an explicit maintainer read since it changes what a given allowBuilds entry authorizes — landing inside a 219-file sync makes it easy to skim past.

Technical details
# Security-posture change: build-approval seam now honors source / git-repository keys

## Affected sites
- `vendor/aube/crates/aube/src/commands/install/default_trust.rs:256-264``decide_with_floor` now calls `decide_package_with_git_repository(name, ver, source_key, git_repository_key)` instead of the old `policy.decide(name, ver)`.
- `vendor/aube/crates/aube/src/commands/install/lifecycle.rs:467-476` (runner), `:174-180` (`should_jail`), `:189-194` (`build_jail`) — same seam.
- `vendor/aube/crates/aube/src/commands/install/mod.rs:215-230` — new `package_build_is_allowed` helper; also consumed by `ignored_builds.rs` and `install/link.rs:348`.
- `vendor/aube/crates/aube-lockfile/src/lib.rs:620-634` — new `git_repository_approval_key` on `LockedPackage`.

## Required outcome
- Confirm the tightened authorization is intended: a bare-name approval no longer authorizes builds for a `file:`/git/tarball-backed instance of that name; an explicit source or `git+<repo>` key is required. This is the desired behavior per the PR body — the note exists so the change gets an explicit sign-off rather than being merged implicitly as part of the sync.

## Open questions for the human
- None blocking. Just confirm the posture change is acceptable to ship in the same PR as the version bump rather than as its own change.

ℹ️ Aliased packages still don't inherit patches by real name

The author disclosed that patchedDependencies: is-odd@3.0.1 does not patch odd-alias: npm:is-odd@3.0.1, whereas real pnpm does. This is pre-existing and unchanged by this PR, but the pnpm writer touched here is adjacent code — worth a follow-up issue so the gap is tracked rather than rediscovered next time this file is edited.

Technical details
# Aliased packages do not inherit real-name patch declarations

## Affected sites
- `vendor/aube/crates/aube-lockfile/src/pnpm/write.rs` — the patch-selector resolution keys off the alias name, never the shadowed registry name (the inline comment at the `patch_groups.resolve` call documents this: "an ALIAS resolves under its alias name, never the registry name it shadows").

## Required outcome
- Track as a follow-up; not in scope for this sync. Divergence from real pnpm, which applies the patch to the aliased instance.

## Open questions for the human
- Is matching pnpm here desired, or is nub's alias-scoped patching an intentional divergence? Answer determines whether the follow-up is a bug fix or a documented behavior note.

Pullfrog  | View workflow run | Using Claude Opus𝕏

`patchedDependencies: { "is-odd@3.0.1": ... }` did not patch
`odd-alias: npm:is-odd@3.0.1`. Real pnpm does, because it resolves the patch
against the resolved manifest's name, where the alias does not exist as a
distinct node. aube v1.32.0 has the same gap and additionally records
`(patch_hash=...)` on the alias's dep path, so its lockfile claims a patched
identity the install never produces.

The rule lives in one place: PatchGroups::resolve_package wraps resolve() with
the alias fallback, and both resolve_patched_by_version and the pnpm writer
call it. Output stays keyed by spec_key(), so the linker's Patches map, the
graph hash, and the delta fingerprint inherit it. The no-churn write guard in
io.rs carried a second copy of the matching logic and now routes through the
same entry point.

Precedence is declared-name-first: a key naming the alias wins over one naming
the registry package. pnpm can never match an alias key, so such a key is
nub-only with no pnpm behavior to preserve, and it is the more specific of the
two.

Also fixes a pre-existing reader gap this exposed. pnpm/read.rs baked the
write-time (patch_hash=...) marker into parsed dep paths, so a parsed patched
graph was keyed differently from the fresh graph it is compared against: the
identity hash could never match and the no-churn guard could never fire. The
reader now strips the marker and the writer re-derives it, one owner per
direction. Writer output is unchanged.

@pullfrog pullfrog Bot left a comment

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.

✅ No new issues found.

Reviewed changes — the one new commit since the prior review (9036306, "pm: apply patches declared against a package's real name to npm aliases"), which closes the aliased-patch gap the first review disclosed as pre-existing.

  • Inherit registry-name patches on npm aliases — new PatchGroups::resolve_package(pkg) tries the resolved name@version first, then falls back to the aliased alias_of@version, so patchedDependencies: is-odd@3.0.1 now patches odd-alias: npm:is-odd@3.0.1 (matching pnpm, which has no separate alias node). Group-level precedence with a documented rationale for the alias-name-key-wins tie-break.
  • Route every consumer through one ruleresolve_patched_by_version now calls resolve_package, so the linker (aube/src/patches.rs), graph-hash fold, drift check, pnpm writer, and the no-op write guard all key patches off the same resolution. io.rs's lockfile_write_is_noop was rewritten from a hand-rolled PatchGroups::resolve to resolve_patched_by_version, keyed by spec_key().
  • Strip write-time (patch_hash=…) markers on parsestrip_patch_hash_suffix + PATCH_HASH_MARKER moved into dep_path.rs as shared pub(super) items; read.rs erases the markers before graph construction so an alias key never reparses as odd-alias@3.0.1(patch_hash=…).
  • Tests — unit coverage for alias inheritance, the alias-name-key-beats-registry-name-key precedence, and conflict propagation, plus a full pnpm read→write→reparse round-trip asserting the aliased node serializes patched with no undecorated duplicate snapshot.

The change is coherent and correct. I verified the io.rs closure contract holds — resolve_patched_by_version's output is keyed by spec_key() (format!("{name}@{version}")), and graph_identity_hash_with_patches invokes the patch closure with a package's plain name/version (never a dep_path or peer-suffixed string), so the lookup cannot diverge. All five patch consumers now share resolve_package, so the writer's decorated snapshot and the linker's materialized folder agree. The one behavioral shift in io.rs — a per-package conflict now returns false (proceed to the real write) instead of the old None-swallow — is effect-preserving, since both paths defer the branded error to the real write. The prior review's disclosed aliased-patch gap is now resolved; the security-posture note on decide_with_floor still stands for a maintainer read.

Pullfrog  | View workflow run | Using Claude Opus𝕏

…as key

Reverses the precedence added in the previous commit. Patch keys now resolve
solely against a package's registry name, matching pnpm, which calls
getPatchInfo on the resolved manifest and so can never match a key naming an
npm alias. Honoring such a key would have invented nub-only config semantics
in a field the pnpm-compat surface is meant to mirror.

The alias inheritance itself is unchanged and remains the point of the fix: a
patch declared as is-odd@3.0.1 still applies to odd-alias: npm:is-odd@3.0.1.

A key that names the alias now matches nothing, which would be silent dead
config, so it is reported: WARN_AUBE_PATCH_KEY_ALIAS_NAME names the key and
suggests the registry-name spelling, swapping only the name prefix so the
user's version selector survives as a drop-in replacement. It fires from
record_patches_on_graph beside the existing patch-key conflict gate.

Note this is narrower than pnpm, which fails the install outright on any
unused patch key (ERR_PNPM_UNUSED_PATCH, allowUnusedPatches defaults to
false). Nub silently ignores every dead patch key today, alias-shaped or not;
this warning covers only the slice this change could newly create. Full
verifyPatches parity is a separate, install-failing change.

@pullfrog pullfrog Bot left a comment

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.

✅ No new issues found.

Reviewed changes — the one net commit since the prior review (b73a35f6, "pm: resolve patch keys against the registry name only, warn on an alias key"). The merge commit 52134d5 only pulls already-merged origin/main work into the branch and carries no new PR contribution.

  • Reverse the alias-name patch precedence to pnpm-faithful resolutionPatchGroups::resolve_package(pkg) now resolves solely against registry_name() (alias_of when set, else name), dropping the earlier "alias-name key wins its group" rule. This matches pnpm, which calls getPatchInfo on the resolved manifest and can never match a key naming an npm alias, so honoring one would have invented nub-only semantics in a pnpm-mirrored field.
  • Keep the inheritance that is the point of the fix — a patch declared as is-odd@3.0.1 still applies to odd-alias: npm:is-odd@3.0.1; the retained test asserts the aliased node inherits the registry-name patch keyed by its spec_key().
  • Report dead alias-name keys instead of silently dropping them — new alias_only_patch_keys finds keys that match nothing under the registry-name rule but would have matched the alias's installed name, and warn_alias_only_patch_keys (called once from record_patches_on_graph) emits WARN_AUBE_PATCH_KEY_ALIAS_NAME with a drop-in registry-name suggestion.
  • Register the new warning codeWARN_AUBE_PATCH_KEY_ALIAS_NAME added to the aube-codes warnings const + ALL array and error-codes.data.json.

The reversal is coherent and correct. I verified resolve_patched_by_version still keys its output by spec_key() (alias name@version), so the linker, graph-hash fold, drift check, and no-op write guard all agree with the writer's direct resolve_package(pkg) call — and the writer's inline comment was corrected to match. The suggested slice &source_key[alias.len()..] is UTF-8-safe because a group's source key always begins with its classified name, and the dedup on source_key keeps the warning firing once per dead key. The commit message honestly scopes this warning as narrower than pnpm's install-failing ERR_PNPM_UNUSED_PATCH, covering only the alias-shaped slice this change could newly create. The prior review's disclosed aliased-patch gap is resolved; the decide_with_floor security-posture note still stands for a maintainer read.

Pullfrog  | View workflow run | Using Claude Opus𝕏

…ile name

aube v1.32 added a bats test asserting sha1 SRI derived from dist.shasum
lands in aube-lock.yaml. Under nub a fresh project writes pnpm-lock.yaml, so
the grep fails on a missing file. Same lockfile-name divergence already listed
for lockfileIncludeTarballUrl.

The derivation itself is present in the merged resolver and covered by aube's
unit tests, so only the aube-branded filename assertion is skipped.
A patchedDependencies key that matches no installed package was silently
ignored. pnpm fails the install (ERR_PNPM_UNUSED_PATCH, no node_modules, no
lockfile written) unless allowUnusedPatches is set, and does so even when the
dead key sits beside keys that do apply. Nub now matches, with the message
text byte-identical to pnpm's.

The gate lives in record_patches_on_graph beside the existing patch-key
conflict gate, which is also where pnpm runs it: verifyPatches is inside the
resolution step, so a warm install whose resolution is skipped does not
re-check. Verified against pnpm 10.15.1 rather than inferred.

allowUnusedPatches downgrades it to a warning. The setting surface was probed
across all seven candidate spellings against real pnpm 10.15.1: it is a
manifest and workspace-YAML setting, and .npmrc is not a home for it at all.
Nub therefore reads it from exactly the homes patchedDependencies uses, which
means the existing pnpm_aube_objects gating gives the brand boundary for
free: a pnpm-incumbent project reads pnpm.allowUnusedPatches, while a
nub-identity project reads the neutral top-level allowUnusedPatches and
ignores the branded one, the same shape allowBuilds already has. pnpm 10's
deprecated allowNonAppliedPatches spelling is accepted, current name winning.

Replaces WARN_AUBE_PATCH_KEY_ALIAS_NAME from the previous commit: the alias
hint now rides inside this error, so an alias-shaped dead key still gets the
drop-in registry-name spelling instead of a generic message.

Note this fails installs that previously succeeded: a typo, a removed
dependency, or a version bump that outran a patch selector now fails on the
next resolving install.

@pullfrog pullfrog Bot left a comment

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.

✅ No new issues found.

Reviewed changes — the one net commit since the prior review (1796dee, "pm: fail the install on an unused patch key, matching pnpm"), which upgrades the alias-name warning from b73a35f6 to the full pnpm verifyPatches gate the prior review explicitly scoped out as a separate change.

  • Generalize dead-key detectionalias_only_patch_keys becomes unused_patch_keys, returning Vec<UnusedPatchKey> (a source_key plus an optional registry_name_spelling for the alias sub-case). It now reports every declared patchedDependencies key that matches no installed package, in declaration order, not just the alias-shaped slice.
  • Fail the install, gated by allowUnusedPatcheswarn_alias_only_patch_keys becomes verify_patches_used, called from record_patches_on_graph at the resolve gate; an unused key raises ERR_AUBE_UNUSED_PATCH unless allowUnusedPatches downgrades it to WARN_AUBE_UNUSED_PATCH. The message is byte-identical to pnpm's ERR_PNPM_UNUSED_PATCH.
  • Read the setting from the same brand-scoped homes as patchedDependencies — new PackageJson::allow_unused_patches and WorkspaceConfig.allow_unused_patches (workspace yaml wins), each inheriting existing brand gating so a nub-identity project reads only the neutral top-level key. pnpm 10's deprecated allowNonAppliedPatches spelling is accepted.
  • Swap the error codesWARN_AUBE_PATCH_KEY_ALIAS_NAME removed, ERR_AUBE_UNUSED_PATCH + WARN_AUBE_UNUSED_PATCH added across aube-codes and error-codes.data.json. Unit + integration tests cover the fail/downgrade split and the deprecated spelling.

The change is coherent and correct. I verified verify_patches_used runs after resolver.resolve at both install call sites (resolve.rs:315, mod.rs:2230), so a warm/frozen install that short-circuits before resolution skips it, matching pnpm and the doc-comment claim. The matched set is built via resolve_package (registry-name rule) and compared against the verbatim declared source keys, so key identity is exact; the alias-replacement slice &source_key[pkg.name.len()..] is UTF-8-safe because a group's source key always begins with its classified name. The removed warning code was introduced earlier in this same PR (b73a35f6) and never shipped, so dropping it is not a stability break, and a grep confirms no dangling references. The prior review's decide_with_floor security-posture note still stands for a maintainer read.

ℹ️ New install-failing gate changes what a previously-passing project does

This is the user-visible blast radius the author flagged: a patchedDependencies key that matches no installed package — a typo, a removed dependency, or a version bump that outran a patch selector — now fails the next resolving install (exit 1, no node_modules, no lockfile) where nub previously ignored it silently. That is the intended pnpm parity, but it means a project that installs cleanly today can start failing after this lands, so it warrants an explicit maintainer sign-off rather than being absorbed implicitly as part of the sync.

Technical details
# Unused-patch-key gate can fail installs that previously succeeded

## Affected sites
- `vendor/aube/crates/aube/src/patches.rs:385,391-449``verify_patches_used` raises `ERR_AUBE_UNUSED_PATCH` at the resolve gate for any declared key matching no installed package.
- `vendor/aube/crates/aube-lockfile/src/patch_groups.rs:285-313``unused_patch_keys` now reports every dead key, not only alias-shaped ones.

## Required outcome
- Confirm the parity is intended to ship in the sync PR: installs with a stale/typo'd `patchedDependencies` key that pass on `main` today will fail after this lands, unless the user sets `allowUnusedPatches`.

## Open questions for the human
- None blocking. Just confirm the install-failing behavior (vs the prior silent-ignore) is acceptable to land as part of the version bump. `allowUnusedPatches` (and the deprecated `allowNonAppliedPatches`) is the documented escape hatch.

Pullfrog  | View workflow run | Using Claude Opus𝕏

…nder nub

aube v1.32 added a test asserting the overlapped and inline lockfile writes
produce byte-identical output. It cannot run under nub for two independent
reasons: it asserts aube-lock.yaml, and the killswitch it toggles is
unreachable here — nub's profile sets env_prefix = None, so
embedder_env("DISABLE_LOCKFILE_WRITE_OVERLAP") is always None and the overlap
is always on, leaving no inline arm to compare against.

The live overlapped path is verified instead: a cold install writes a
pnpm-lock.yaml byte-identical to real pnpm 10.15.1's, with zero time: blocks,
which is what nub's time-stripping delta feeds into that write path to
produce.
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