Skip to content

v5.2.3

Choose a tag to compare

@github-actions github-actions released this 19 Aug 02:55
· 266 commits to main since this release
e92fef1

Blob durability — dangling references and in-flight readers

Two related fixes close windows where a committed record could point at blob bytes that were no longer on disk.

  • A transient replication save could leave a record referencing a missing, PENDING, or incomplete blob file. When the same record is later re-delivered by a base copy, Harper now repairs that existing file in place rather than writing a new orphan the duplicate-skipped record would never reference. The repair is fail-atomic — it holds the blob lock, writes and verifies a sibling temp file, flushes, and renames over the target — so a failed repair leaves the referenced file byte-for-byte unchanged. The orphan sweeper respects active repair locks. Adds the shared blob-header classifier and the replication.blobGapReconnectMs config key consumed by harper-pro (#2177).
  • Superseded blob files were unlinked on a fixed 500 ms timer with nothing checking whether a reader still needed the bytes. Because a blob file is opened lazily by path at stream()/bytes() time, a reader that resolved a record just before a concurrent write could open a file that was already gone — on the HTTP path that ENOENT lands after response headers are committed, reaching the client as a truncated body while every signal reports success. The delay is now configurable via storage.blobRetention and defaults to 2s, and reclamation is reference-aware so an in-flight reader can take a retention hold (#2145).

Deploy — by reference, with a durable credential

harper deploy gains two opt-ins that together let an app be deployed from its git repository instead of an uploaded payload:

  • by_ref=true (or ref=<committish>) resolves the app's GitHub owner/repo and commit from the local working copy (or from GitHub Actions env) and deploys git+https://github.com/<owner>/<repo>.git#<sha>. Everything that could move is resolved client-side to a SHA — including an explicit ref=, locally first and then via git ls-remote — so cluster peers, which resolve the package independently, cannot diverge on a moved tag. An unpinnable ref fails closed rather than being sent as a name the cluster would resolve for itself, and an attached credential is pinned to the package host (#1850).
  • setup=true is a guided, client-side credential provisioning flow — what harper login is for auth, but for deploy tokens. It fetches the cluster's public key, sources a token (a fine-grained PAT, your gh session, or an npm token), seals it locally into an enc:v1: envelope, and stores only ciphertext in the component-scoped secret tier. The plaintext never leaves the machine; the cluster decrypts in memory only at deploy/rollback time (#1851).

package_component streams instead of base64

package_component returned the whole component tarball as a base64 string inside the JSON envelope, peaking at roughly 4.7× the archive size resident in a shared (on Fabric, multi-tenant) Harper process, and hard-failing with ERR_STRING_TOO_LONG once the base64 result exceeded V8's string cap. The operation now streams the archive; project-resolution failures other than ENOENT are rethrown instead of being swallowed (#2152, #2150).

Dependency pinning for load-bearing modules

A caret range does not bind the version that reaches a running node: harper-pro, a rebuilt container, or a plain npm install of published harper could resolve a newer native or encoder dependency with no Harper PR and no human merge. The load-bearing ranges — rocksdb-js, the encoder/iterator modules whose object identity crosses its boundary, structon, and the optional native addons — are now pinned to the versions the lockfile already resolved. No installed dependency moves; only the allowed resolution narrows. Docker smoke additionally requires the root msgpackr and @harperfast/extended-iterable specs to be byte-equal to rocksdb-js's requirements and rejects a nested copy (#2179). A follow-up aligned the structon pin with the lockfile after it broke npm ci on main (#2196).

Also in this release

A report-mode review-coverage CI check that surfaces cross-model review counts and a stale Human-Review-Need: footer without blocking (#2183); an integration-test helper refactor (#1904); and non-major dependency updates (#2131, #2189, #2190).

Full Changelog: v5.2.2...v5.2.3