Conversation
Add a preinstall-based npm distribution alongside the existing mise/cargo/curl paths. The root `@endevco/aube` package is tiny (just a preinstall script); at install time it fetches the matching `@endevco/aube-<os>-<arch>` sub-package and hardlinks the three binaries (aube, aubr, aubx) into ./bin. Mirrors the shape of `@jdxcode/mise` — no runtime JS shim, no optionalDependencies sprawl. A new workflow `publish-npm.yml` fires on `release: published` (and `workflow_dispatch` for reruns) and is decoupled from `release-plz.yml` so an npm hiccup never blocks crates.io or the GitHub release. Uses OIDC / Trusted Publishing — no NPM_TOKEN secret to rotate. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Greptile SummaryThis PR adds an npm distribution path for
Confidence Score: 3/5Safe to merge for the install mechanism itself, but two concrete issues — missing --provenance and the unnecessary custom PAT — should be fixed before the first real release. The preinstall architecture is sound and mirrors a proven pattern. However, the --provenance omission directly contradicts a stated design goal, and the custom PAT creates an avoidable operational dependency that will silently break if not configured. npm/scripts/publish.mjs (missing --provenance) and .github/workflows/publish-npm.yml (custom PAT vs built-in token) need attention before the first npm release. Important Files Changed
Sequence DiagramsequenceDiagram
participant GH as GitHub Release Event
participant WF as publish-npm.yml
participant GHR as GitHub Releases
participant NR as npm Registry
GH->>WF: release:published (or workflow_dispatch)
WF->>WF: Resolve tag
WF->>WF: setup-node@v4 (Node 24)
WF->>WF: npm install -g npm@latest
loop For each of 6 platform targets
WF->>GHR: gh release download aube-{tag}-{triple}.tar.gz/.zip
GHR-->>WF: archive
WF->>WF: extract + chmod 0o755
WF->>WF: Stage @endevco/aube-{os}-{cpu}/package.json + bin/
WF->>NR: npm publish @endevco/aube-{os}-{cpu} (OIDC)
end
WF->>WF: Rewrite npm/package.json version
WF->>WF: Copy README.md into npm/
WF->>NR: npm publish @endevco/aube (OIDC)
Note over NR: User runs: npm install -g @endevco/aube
NR-->>NR: Triggers preinstall script
NR->>NR: npm install @endevco/aube-{os}-{arch}@{ver}
NR->>NR: hardlink (or copy) bin/{aube,aubr,aubx} into ./bin/
Reviews (2): Last reviewed commit: "docs(installation): trim redundant npm-p..." | Re-trigger Greptile |
| function npmPublish(stageDir, npmTag, dryRun) { | ||
| const args = ['publish', '--access', 'public', '--tag', npmTag]; | ||
| if (dryRun) args.push('--dry-run'); | ||
| run('npm', args, { cwd: stageDir }); | ||
| } |
There was a problem hiding this comment.
Missing
--provenance flag for provenance-signed publish
The PR description states "the publish is provenance-signed," but npm publish is invoked without --provenance. With npm's Trusted Publishing (OIDC), OIDC auth is used for the token exchange, but the provenance attestation is only attached when --provenance is explicitly passed. Without it, the packages are published without a provenance record even though the OIDC environment is present.
| function npmPublish(stageDir, npmTag, dryRun) { | |
| const args = ['publish', '--access', 'public', '--tag', npmTag]; | |
| if (dryRun) args.push('--dry-run'); | |
| run('npm', args, { cwd: stageDir }); | |
| } | |
| function npmPublish(stageDir, npmTag, dryRun) { | |
| const args = ['publish', '--access', 'public', '--tag', npmTag, '--provenance']; | |
| if (dryRun) args.push('--dry-run'); | |
| run('npm', args, { cwd: stageDir }); | |
| } |
| env: | ||
| GITHUB_TOKEN: ${{ secrets.AUBE_GH_TOKEN }} | ||
| TAG: ${{ steps.tag.outputs.tag }} | ||
| run: node npm/scripts/publish.mjs |
There was a problem hiding this comment.
Custom PAT secret instead of built-in
GITHUB_TOKEN
secrets.AUBE_GH_TOKEN is used to authenticate gh release download, but the job already has contents: read from the built-in GITHUB_TOKEN. The built-in token is always available and requires no manual configuration. Using a custom PAT means:
- A new repo secret (
AUBE_GH_TOKEN) must be created and rotated manually. - If the secret is absent or expired, the workflow fails with a silent empty-string substitution rather than a clear error.
Consider using secrets.GITHUB_TOKEN (the auto-provisioned token) instead:
| env: | |
| GITHUB_TOKEN: ${{ secrets.AUBE_GH_TOKEN }} | |
| TAG: ${{ steps.tag.outputs.tag }} | |
| run: node npm/scripts/publish.mjs | |
| - name: Publish @endevco/aube and platform packages | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| TAG: ${{ steps.tag.outputs.tag }} | |
| run: node npm/scripts/publish.mjs |
Public release assets redirect from /releases/download/<tag>/<asset> to a signed CDN URL — fetch follows the redirect. No GitHub API hit, no rate limit exposure, no GITHUB_TOKEN in the workflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Trusted Publishing only covers the token handshake; the provenance statement requires `npm publish --provenance` explicitly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 180d263. Configure here.
When the child is killed by a signal, close() fires with code=null. process.exit(null) coerces to 0, so npm would record the preinstall as successful even though no binary was fetched. Exit 1 in that case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
aube can now be installed via npm (`npm install -g @endevco/aube`), and Linux binaries have been rebuilt with broader glibc compatibility and a pure-Rust TLS stack — no more OpenSSL system dependency. ## Highlights - **Install from npm** — `npm install -g @endevco/aube` ships native binaries for all six supported platforms (macOS, Linux, Windows × arm64/x64). The multicall shims `aubr` and `aubx` work out of the box. - **Better Linux portability** — Linux targets are now built with `cross`, producing binaries that run on older glibc versions. The switch from OpenSSL to `rustls` removes the system OpenSSL dependency entirely. ## Added - **npm distribution** — aube is now published on npm as `@endevco/aube`. At install time, a `preinstall` script fetches the correct `@endevco/aube-<os>-<arch>` sub-package and hardlinks the three binaries (`aube`, `aubr`, `aubx`) into place. No runtime JS shim — npm's bin wrapper calls the native binary directly. Pre-releases use the `next` dist-tag; stable releases use `latest`. ([#12](#12) by @jdx) ```sh npm install -g @endevco/aube # or try it without installing npx @endevco/aube --version ``` > **Note:** Because install relies on `preinstall`, the `--ignore-scripts` flag and fully offline caches are not supported. Use mise or `cargo install` in those environments. ## Changed - **TLS backend switched to rustls** — HTTP requests now use the pure-Rust `rustls` TLS implementation instead of the system's OpenSSL via `native-tls`. This eliminates the need for OpenSSL headers at build time and removes the OpenSSL runtime dependency on Linux. ([#15](#15) by @jdx) - **Linux builds use `cross`** — Linux release binaries (x86_64 and aarch64) are now compiled inside `cross`'s Docker images, which target an older glibc baseline for broader distribution compatibility. ([#15](#15) by @jdx) ## Fixed - **Per-registry client certificate auth** — The mTLS client certificate path now concatenates cert and key into a single PEM buffer and calls `Identity::from_pem`, which works correctly under rustls. The previous `Identity::from_pkcs8_pem` was a `native-tls`-only API. ([#15](#15) by @jdx) **Full Changelog**: 6587e37...16ded6f <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > This is primarily a release/versioning PR (changelogs, version bumps, and dependency lockfile updates) with no functional code changes shown in the diff, so runtime risk is low. > > **Overview** > Prepares the `v1.0.0-beta.2` release by adding a top-level `CHANGELOG.md` and per-crate changelogs, and bumping the workspace + internal crate versions from `1.0.0-beta.1` to `1.0.0-beta.2`. > > Updates `Cargo.lock` for the release (dependency version/lock refresh) and syncs the reported CLI/docs version (`aube.usage.kdl`, `docs/cli/index.md`, `docs/cli/commands.json`) to `1.0.0-beta.2`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 0e53762. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: release-plz[bot] <release-plz+bot@users.noreply.github.com>

Summary
@endevco/aube; six per-platform subs are@endevco/aube-<os>-<arch>(darwin-arm64, darwin-x64, linux-x64, linux-arm64, win32-x64, win32-arm64).publish-npm.ymltriggers onrelease: published(andworkflow_dispatchfor reruns). Decoupled fromrelease-plz.ymlso an npm hiccup never blocks crates.io or the GitHub release.NPM_TOKENsecret.How it works
At install time,
@endevco/aube'spreinstallscript spawnsnpm install --no-save @endevco/aube-<os>-<arch>@<version>and hardlinks (falling back to copy) the three binaries (aube,aubr,aubx) from the sub-package'sbin/into the root's./bin/. Shape mirrors@jdxcode/mise— no runtime JS shim and nooptionalDependenciessprawl inpackage-lock.json. Note this means--ignore-scriptsand fully offline caches won't work; those users keep the mise/cargo paths.The multicall dispatch from #6 works through npm because the preinstall creates three named files, so
aubrinvoked via npm's bin wrapper seesargv[0]ending inaubrand routes torun.At release time,
npm/scripts/publish.mjsdownloads eachaube-<tag>-<target>.{tar.gz,zip}from the just-published GitHub release, extracts the binaries, stages a platform-scopedpackage.jsonwith correctos/cpu/bin, andnpm publishes each sub-package. Root publishes last so its preinstall can resolve every sub. Auto-picks thenextdist-tag for pre-releases (1.0.0-beta.1→next) andlatestfor stable.DRY_RUN=1,SKIP_ROOT=1, andSKIP_PLATFORMS=1env flags exist for manual recovery.Why OIDC
npm's Trusted Publishing (GA mid-2025) exchanges a short-lived GitHub OIDC token for a one-shot npm publish token. No long-lived secret to rotate or leak, and the publish is provenance-signed. Requires npm ≥ 11.5.1 — the workflow upgrades to
npm@latestbefore publishing to avoid drift with the version Node 24 ships.Pre-merge setup
On npmjs.com/org/endevco → Settings → Trusted Publishers, add an org-level trusted publisher:
endevco/aube.github/workflows/publish-npm.ymlOrg-level config covers all new
@endevco/*packages, so the first release auto-covers root + 6 subs.Limitations / follow-ups
aube(unscoped) is taken on npm by a year-old placeholder (estjs/aube, 1 version, never updated). If you want the unscoped name, file an npm dispute — unrelated to this PR.linux-<arch>; muslc users will hit the glibc binary and fail. Addinglinux-x64-musl/linux-arm64-muslneeds corresponding Rust release targets first.SKIP_PLATFORMS=1(or vice versa) to publish only what hasn't shipped.Test plan
aube,aubr,aubxlocally; staged a fake@endevco/aube-darwin-arm64sub-package undernode_modules/; ran the link logic and confirmed each bin dispatches to the right subcommand viaargv[0]basename (aubr --help→run's help,aubx --help→dlx's help).npm pack --dry-runon the root package — tarball contains onlyinstallArchSpecificPackage.js+package.json(README copied in by publish script at release time).npm pack --dry-runon a hand-staged platform package — containsbin/{aube,aubr,aubx},package.jsonwith correctos/cpu,README.md.1.0.0-beta.Xwithnextdist-tag, thennpm install -g @endevco/aube@nextfrom a clean machine. Runs for real on the next release.🤖 Generated with Claude Code
Note
Medium Risk
Adds a new release-triggered GitHub Actions workflow and
preinstall-driven npm packaging/publishing logic, which can impact release automation and end-user installation behavior if misconfigured.Overview
Adds npm distribution for
aubeby introducing a root@endevco/aubepackage that installs a platform-specific@endevco/aube-<os>-<arch>subpackage atpreinstalltime and links/copies the nativeaube/aubr/aubxbinaries into./bin.Introduces a new
publish-npmGitHub Actions workflow that runs onrelease: published(or manual tag input) and uses npm Trusted Publishing (OIDC) to download release artifacts, stage per-platform npm packages, and publish them before publishing the root package. Documentation is updated to mentionnpm install -g @endevco/aubeas an install option.Reviewed by Cursor Bugbot for commit cf71251. Bugbot is set up for automated code reviews on this repo. Configure here.