A round of supply-chain hardening alongside two new CycloneDX scopes and a long-awaited aube install --dry-run.
Added
- Managed hardening config (#935 by @jdx) — Admins can drop a
/etc/aube/managed.toml(and optional additiveAUBE_MANAGED_CONFIG_PATH) that can only make settings stricter than the user/env/project resolution. Each setting now declares amanagedPolicy(max,trueWins,falseWins,managedWins,ranked:…); when a weaker local value is overridden, aube emitsWARN_AUBE_MANAGED_CONFIG_ENFORCED.dangerouslyAllowAllBuildsis resolved through this pipeline too, so a managed config can shut off--dangerously-allow-all-buildsacross a fleet.aube config get/listshow the effective merged values. aube install --dry-run(#927 by @jdx) — Resolve and print what would happen without writingaube-lock.yaml, creatingnode_modules, runningpreinstall, or touching install state. Unlike--lockfile-only, an explicit--frozen-lockfilestill fails when no lockfile exists, while CI-style dry-runs can resolve without one. The two flags are mutually exclusive.aube sbom --exclude-peers(#934 by @jdx) — CycloneDX-only flag that trims components reachable only via peer edges (and drops root direct deps that are peer-only unless they also appear independencies). The BOM recordscdx:npm:package:excludePeers. As a bonus, CycloneDX output now addsexternalReferences(issue-tracker) for the root and each component whenbugsis anhttp(s)URL.- CycloneDX dev-only scoping (#926 by @jdx) — Packages reachable only through devDependency edges (across all workspace importers) are emitted with
scope: "excluded"and thecdx:npm:package:developmentproperty. Anything reachable as a runtime dep in any importer stays unscoped, including cycles and packages linked as dev in one workspace and prod in another. SPDX output is unchanged. aube viewinfers the package name (#925 by @jdx) — Running bareaube viewreadsnamefrom the nearestpackage.jsonand shows registry metadata for it; a missingnamenow produces a clear error rather than a confusing positional failure.
Fixed
- Trust policy enforced on lockfile reuse (#929 by @jdx) — Previously,
aube updatecould write a lockfile and subsequent installs could reuse it (or warm install state) without re-checking trust evidence. Installs that reuseaube-lock.yamlnow walk reachable registry packages, fetch packuments, and runcheck_no_downgradebefore fetch/link. The warm/fast path is skipped entirely whentrust-policy=no-downgradeorparanoid=trueis active (outside offline mode), andrm aube-lock.yamlnow actually triggers a re-resolve instead of being silently restored from.aube-state. - Persist computed tarball integrity (#933 by @jdx) — Registry packages fetched without a lockfile
integrityfield now have SHA-512 SRI derived from the tarball (streaming when possible) and threaded back into the in-memory graph viaapply_computed_integrities, including peer-contextualized entries, before the lockfile is written. - Exact pins skip name-only OSV gate (#923 by @jdx) — Pre-resolve supply-chain checks would block
aube add nx@23.0.0whenever OSV had a name-levelMAL-*hit onnx, even when the pinned version was unaffected. Full semver pins (including vianpm:aliases) now go throughfetch_malicious_advisories_versioned; ranges, dist-tags, and bare names still use the name-only query, and download-count checks remain name-based. Add-time failures now also read "refusing to add" instead of "refusing to install". - Recursive
--no-bail(#928 by @jdx) —aube run -r --no-bailnow matches pnpm: a failing script (or.binfallback) no longer stops the sequential fanout, later matched packages still execute, and the process exits with the first failing code. Default behavior is unchanged.
💚 Sponsor aube
aube is part of jdx.dev — an independent developer-tooling studio run by @jdx, also behind mise. Work on aube is funded entirely by sponsors.
If aube is saving your team install time or CI minutes, please consider sponsoring at jdx.dev. Individual and company sponsorships are what keep the project fast, free, and independent.