`hyperdb-bootstrap` fetched `hyperd` from Tableau's Hyper Java API zip, whose
filename embeds an opaque build id (`r07abb490`) that cannot be derived from
the version. Discovering it required scraping the public releases page — and
that scraper had been broken for three-plus releases without anyone noticing,
because its tests ran against a synthetic fixture rather than the live page.
The PyPI `tableauhyperapi` wheels carry the same engine at a fully
constructible URL, and PyPI publishes a sha256 per file:
https://files.pythonhosted.org/packages/py3/t/tableauhyperapi/tableauhyperapi-{version}-py3-none-{wheel_tag}.whl
The bytes are unchanged. The `hyperd` extracted from the macosx_13_0_arm64
wheel is bit-identical to the one the crate downloaded before — sha256
aef5c81970bb4d84d06fb9513d5ffd722526fce779632a0c5f63d87b6450e478, 277,836,448
bytes, Mach-O 64-bit executable arm64. Both report `minos 13.0`, so the wheel
tag is not a raised support floor.
Bumping the pin no longer means downloading four ~80 MB archives and hashing
them by hand; the digests are read off the JSON API and still committed, since
a hash in git attests independently of the host serving the bytes.
Wheel tags are stored per platform in the pin rather than hardcoded in Rust:
they are not stable across releases (arm64 wheels start at 0.0.19484, and a
macOS floor bump would change macosx_13_0_arm64) and a wrong tag 404s
silently, so a change should be a visible pin edit. `build.rs` now requires
one for every supported platform.
`verify` additionally cross-checks each pinned digest against the one PyPI
publishes for that exact wheel filename, so it validates the pinned bytes
rather than merely that the CDN serves something. The npm workflow's
independent pin moves to the wheel URL and its guard grows a wheel-tag
cross-check.
The release strategy is settled: this break lands inside the 1.0.0-rc line as
1.0.0-rc.2, pinned by a `Release-As:` footer on the following commit. The `!`
below marks the break honestly; the footer keeps it from computing 2.0.0.
BREAKING CHANGE: hyperdb-bootstrap no longer has a build id or a
releases-page scraper, because a wheel URL is fully constructible from the
version alone. Removed public API:
- `PinnedRelease::build_id` and `InstalledHyperd::build_id` — use `.version`,
now the only release identifier, plus the new
`PinnedRelease::wheel_tag_for(Platform)` for the per-platform wheel tag.
- `PinnedRelease::version_tag()` — use `.version`. It existed only to join the
version and the build id into `0.0.26479.r96880f6a`; there is no build id
left to join.
- `VersionSource::ScrapeLatest` and the `scrape` module — deleted with no
replacement. With a constructible URL and PyPI-published digests there is
nothing left to discover.
- `Error::Http`, `Error::HttpStatus` and `Error::ScrapeFailed` — all three
existed only to serve the scraper. `Error::MissingWheelTag` is new, because
`url::build_download_url` is now fallible.
- the `--latest` CLI flag — no replacement, it is deleted along with the
scraper it drove. Pass `--version X` or `--version-file PATH` instead.
- the `--build-id` CLI flag — it simply goes away. Wheel URLs need no build
id, so `--version X` on its own is now a complete version source: it
inherits the builtin pin's `[wheel_tag]` values and carries no digests, so
the download is unverified and logs a WARN. Use `--version-file` with a full
pin when you need verified bytes.
- the `regex`, `reqwest` and `rustls` dependencies — no in-process HTTP client
remains, which also retires the rustls crypto-provider workaround.
Motivation
hyperdb-bootstrapfetchedhyperdfrom Tableau's Hyper Java API zip, whosefilename embeds an opaque
build_id(e.g.r07abb490) that cannot be derivedfrom the version. Discovering it meant scraping the public releases page — and
that scraper (
src/scrape.rs, behind--latest) has been broken for three-plusreleases without anyone noticing, because its tests ran against a synthetic
fixture rather than the live page. Two independent defects:
<h3>VERSION [DATE]</h3>, but Docusaurus renders0.0.26479 <!-- -->[September 3 2026], which\s*cannot span;(rc[a-z0-9]+), while every build id since0.0.24457has beenr+ hex.The PyPI
tableauhyperapiwheels carry the same engine behind a fullyconstructible URL, and PyPI publishes a sha256 per file:
So
--latestis deleted, not fixed: with a constructible URL and publisheddigests there is nothing left for it to do.
The bytes are unchanged
The strongest evidence this migration is faithful — the
hyperdextracted fromthe
macosx_13_0_arm64wheel is bit-identical to thehyperdin the Java zipfor the same release, sha256
aef5c81970bb4d84d06fb9513d5ffd722526fce779632a0c5f63d87b6450e478. To be preciseabout what is and isn't established here: that cross-envelope equality was
established upstream of this PR and I did not re-derive it. What I verified
locally is that the wheel path produces exactly that binary:
Same build, different envelope. Note the
--versionline corroborates thisindependently: the wheel's binary self-reports build
r96880f6a, which is exactlythe
build_idthe Java zip carries for0.0.26479(seechore/post-rc-cleanup's8c99d20). It is the same engine build reached by a different filename.This is not a claim that the wheel matches the engine currently on
main(
0.0.26359, buildr07abb490) — that is a different build. The equality issame-release, cross-envelope.
Both binaries report
minos 13.0, so themacosx_13_0wheel tag is not araised support floor — no contributor loses support. Wheels are ~3.6–4.5% smaller
than the Java zips.
Bumping the pin no longer means downloading four ~80 MB archives and hashing them
by hand — the digests come off the JSON API. They are still committed: a hash
in git is an attestation independent of the host serving the bytes.
Breaking changes
Public API removed:
PinnedRelease::build_id,InstalledHyperd::build_id.versionis the only release identifierPinnedRelease::version_tag().versionVersionSource::ScrapeLatest, thescrapemoduleError::Http,Error::HttpStatus,Error::ScrapeFailed--latest,--build-id--version Xalone is now a complete sourceregex,reqwest,rustlsdepsurl::build_download_urlis now fallible (Result<String, Error>); a platformwith no pinned wheel tag is
Error::MissingWheelTagrather than a guess.PinnedRelease::wheel_tag_for(Platform)is new.The install layout is keyed on the version alone:
<dest>/0.0.26479/(was<dest>/0.0.26479.r96880f6a/), andcurrent/VERSIONnow contains just0.0.26479. Nothing in the repo reads that file programmatically.Dropping
reqwest/rustlsalso retires the rustls crypto-provider workaroundthe CHANGELOG records as a past breaking change (
rustls-no-providerplus aOnceLockinstalling ring). Verifiedaws-lc-rsis absent workspace-wide andthat
hyperdb-bootstrapno longer reachesreqwest,rustls, orregexat all.Versioning: breaking, released as
1.0.0-rc.2Decided — no reviewer action needed. The break is now marked honestly and
the version is pinned, which are two independent things:
feat(bootstrap)!:and the migration commit carries aBREAKING CHANGE:footer enumerating every removed item. The break is realand is recorded as such.
chore: release 1.0.0-rc.2, carries aRelease-As: 1.0.0-rc.2footer, which pins the next release inside the1.0.0-rcline.Without that footer the
!would compute 2.0.0: the workspace is already on1.x, andbump-minor-pre-majorinrelease-please-config.jsonis gated onversion.isPreMajor(major < 1), so it does not apply at1.0.0-rc.1.Release-As:wins regardless — release-please'sDefaultVersioningStrategyreturns a
CustomVersionUpdatefrom theRELEASE ASnote before it reads thebreaking-change tally. This is the same mechanism, and the same empty-commit
shape, that produced
1.0.0-rc.1(7bf2dff), and it is whatdocs/GITHUB_OPERATIONS.md→ Pre-releasesdocuments.
Simulated against
release-please@17.11.2(the versionrelease-please-action@v5pins) using its realparseConventionalCommitsandDefaultVersioningStrategy:1.0.0-rc.1→1.0.0-rc.2under a mergecommit and under a squash merge. Dropping the footer from the same input
yields
2.0.0-rc.1, which is the outcome this pin exists to prevent.Why wheel tags live in the pin file
They are deliberately not hardcoded in Rust. They are not guaranteed stable
across releases (arm64 wheels only exist from
0.0.19484; a future macOS floorbump would change
macosx_13_0_arm64), and a wrong tag is a silent 404 on oneplatform only. Keeping them as pin data makes any such change a visible pin edit,
and
build.rsnow fails the build if any supported platform lacks one.(Empirically the four tags are unchanged from
0.0.19484through0.0.26479.)Stronger
verifyhyperdb-bootstrap verifynow cross-checks every pinned digest against the digestPyPI publishes for that exact wheel filename, on top of HEAD-ing the four URLs —
so it validates the exact pinned bytes rather than merely that the CDN serves
something at that path, and it catches a stale
[wheel_tag]explicitly:npm dual pin
npm-build-publish.ymlcarries its own independent pin (this is why0.7.1onceshipped npm with a different engine than crates.io). It is migrated to the wheel
URL,
HYPERD_BUILD_IDis gone, and the matrix gainshyperd-wheel-tag.verify-npm-hyperd-pin.pykeeps its version + digest cross-check and gains awheel-tag cross-check, since the tag is a new drift vector.
Empirically confirmed (not assumed) that the matrix
hyperd-sha256values aredigests of the downloaded archive, not the extracted binary — the step hashes
hyperd-archive.whl— so they are the wheel digests and equal the toml's[sha256].I did not make the workflow read the toml directly. The matrix must be static
YAML, so it would need a
tomllibcall inside the per-platform matrix job, whichruns on a Windows runner under git-bash where
python3may not be onPATH— anuntestable portability risk for no correctness gain over the guard. Recommended
as a follow-up alongside converting the matrix to a
setup-job JSON output.Verification
Run on macOS arm64 (Apple Silicon):
cargo build -p hyperdb-bootstrapandcargo build --workspace— cleancargo test -p hyperdb-bootstrap— 26 lib + 4 integration + 1 doc, 0 failed(up from 12 lib + 2 integration; +16 runnable tests)
cargo test --workspace— 1584 passed, 0 failed, against the freshlydownloaded engine
make test— 1519 passed, 0 failedcargo fmt --all -- --checkandcargo clippy --workspace --all-targets --all-features -- -D warnings— cleannpx markdownlint-cli2— zero new findings; the 5 inAGENTS.md/DEVELOPMENT.mdare the pre-existing MD040 backlog, identical before and afterverify-npm-hyperd-pin.pypasses against the new toml, and fails correctlywhen a wheel tag is perturbed
find-based extraction was replayed against the real wheel entrynames:
HYPER_DIR=hyperd-raw/tableauhyperapi/bin/hyper,hyperdfound,LICENSE*/NOTICE*glob matchesdist-info/extract.rsis unchanged apart from doc comments — its "skip one optionaltop-level directory, then require a
lib/hyperorbin/hyperpair" logic alreadyabsorbs the
tableauhyperapiwrapper. New tests pin that against the real wheelentry names, including the Windows
hyperd.exe+crashdumper.execase.Not verified here
URLs and digests are machine-verified (all four HEAD 200 with matching PyPI
digests), and I downloaded the Windows and Linux wheels to confirm their
bin/hyper/contents (hyperd.exe+crashdumper.exe;hyperd) and digests —but no
hyperdwas run on Linux or Windows.otool -L) andbin/hyper/containsno shared libraries on any of the three wheels I inspected, so the npm
shared-library copy loop finds nothing to copy — as before.
Repeated here as a trailing footer so the version is pinned on the merge commit
too: this repo merges with
merge_commit_message = PR_BODY, so the body belowbecomes the merge commit's body. Same value as the footer on
chore: release 1.0.0-rc.2, so it is redundant rather than conflicting.Release-As: 1.0.0-rc.2