Repository navigation
Releases: Lipen/nexus-raw
Releases · Lipen/nexus-raw
Release list
v0.24.0
[0.24.0] - 2026-10-24
Added
--ca-bundle FILE(alsoNXR_CA_BUNDLE) adds a PEM bundle of trust roots for a private CA.
It is native only and conflicts with--tls-insecure.get --range START-END|START-reads one byte span, to a file or stdout.up --prefix PREFIXpublishes only the names under a whole-segment prefix, keeping the relative path.mirror --planis the--dry-runalias.nxr-tui --ca-bundle FILE(alsoNXR_CA_BUNDLE) and--tls-insecureapply one TLS policy to the session.nxr-tui --no-colorand a non-emptyNO_COLORdrop the two semantic colours.- The Node bindings accept
caBundlefor a private CA andprefixesonup. - The Node
getacceptsrange, with the same span rules as the CLI. - The Linux release archives carry
nxr-mountnext tonxr, and the Homebrew formula installs it when present. Nxr::scan_prefixesandNxr::get_rangeexpose the scoped scan and the one-span read to library consumers.Nxr::sibling_digestreads a.sha256marker without a transfer. A malformed marker isMismatch.
Changed
- The repository's terminal output follows one model: results on stdout, failures, warnings and hints on stderr, and colour is decided per stream.
Hints carry commands in backticks,check-docsand the real-Nexus battery stay quiet on success, and the battery keeps a TTY heartbeat without a hardcoded total.
The demo reports its mock scenario count and aligns its--comments. - The local scan refuses a symlink or any other non-regular entry with exit 2 and a hint, instead of silently dropping it from the upload.
Fixed
- The mount evicts cached blocks per inode and counts the released bytes exactly, so the cache budget no longer drifts.
- The mount help and reference state the minimum
--block-kiband--cache-mibvalues. - The
.partsuffix joins the reserved names, and a local.partstaging file is an explicit misuse inupinstead of a silent omission. get --rangerefuses a start past the end and replaces a symlinked output instead of following it.- The
UnsafeNamehint names the regular-file rule, so a symlink refusal no longer points only at the name grammar. - The help hides the
NXR_CA_BUNDLEvalue instead of echoing the path. up --prefixscans only the selected subtrees and validates explicit names path by path, so an unselected symlink no longer refuses the run and the tree is not walked twice.- The scan refuses a symlinked source root for plain
upanddiff, matching the scoped prefix scan. - The mount percent-encodes each path segment, so foreign names with spaces,
?,#,%or unicode resolve correctly. - The mount forgets a node when the kernel drops its last lookup and reports synthetic inodes for unvisited listing entries, so long browsing sessions stay bounded.
- The wasm32 build compiles again: the native prefix helpers are gated, and the gate checks the core for the sandbox target.
- The unreleased
--cache-dirmount experiment was removed before it shipped. The mount stays memory-only.
v0.23.0
[0.23.0] - 2026-10-22
Added
- The Homebrew formula,
Formula/nexus-raw.rb, with this repository as its tap (brew tap lipen/nexus-raw https://github.com/Lipen/nexus-raw).
just brew-formularegenerates it from a release'sSHA256SUMS, andscripts/brew-formula.sh --checkverifies it. nxr-mount(Linux): a read-only FUSE view of a raw repository.
Listings go through the search API, reads are lazy ranged GETs over a bounded block cache, and.sha256markers stay hidden.
Every write answersEROFS.
The binary is a separate crate, sonxrkeeps no FUSE dependency and stays portable.Nxr::read_range, a byte span into memory that skips to the span without buffering the whole object when the server ignoresRange, andNxr::ls_at, a listing of any directory URL: the two core paths the mount is built on.NexusClient::get_range, the transport primitive behindread_range.nxr down <file-url> <dst-dir>, and the Nodedownwith nonamesand nols, download that one artifact with the same marker, resume and digest checks as a directory sync.
The parent directory is the base and the leaf is the name, and an explicit--name,--names-fromor--lskeeps the URL as the directory to enumerate.- The wasm sandbox lists and uploads.
nxr_putPUTs the bytes and the.sha256marker, the proxy forwards PUT with a request-body cap, and both the Node fake and the ServiceWorker fake store it.
Nxr::put_bytesis part of the wasm surface: it is an in-memory POST-free path, not a file operation.
Fixed
- The composite action installs the release named by its tag when
versionis empty, instead of always the latest release. - The mock server refuses an inverted
Rangeand an oversizedContent-Lengthor chunked size instead of panicking, honorsspec.redirect, and lists each repository once in the scoped collection. - The mirror staging lock is held by the creating run, a pre-created symlink at the staging path is replaced instead of followed, and the segmented resume is gated on the object digest.
- An artifact segment with the reserved
.nxrprefix is refused, so local part, segment and cache files can never collide with a repository object. put_bytesvalidates the marker name before the bytes are PUT, and a zero-lengthread_rangestill reports an absent object asNone.up --wait-indexmatches a grouped or repository-root base,service eula --acceptpropagates a 401/403 instead of reporting no gate, andservice statusreads a refused probe asfalse.diff --prefixfilters local-only entries too, andup --if-changed --planuses the if-changed classification.doctorfalls through to the repository HEAD on a 404 status and builds the deep service probes at the origin, andservice assetsno longer slices a multibyte checksum.mirrorandmvfall back to the shared-u,--lscannot be combined with--nameor--names-from, and a clap parse error still carries ahint:line and the NDJSON error object.- The alias URL expansion no longer uses raw pointers, and a broken TOML line no longer echoes an inline password.
- Server-supplied text is escaped in human output, credential-bearing base URLs are no longer echoed, and the 401/403 body read is bounded.
- The TUI drops a repository URL whose origin differs from the configured server.
- The PyPI publish waits for the gate, its action is pinned to a commit, and a new gate rejects any action pinned to a tag.
- The panel and the wasm sandbox bound their targets to configured origins, validate upload names before writing, queue uploads, and ignore stale listing responses.
- The wasm server answers 413 before closing an over-cap body, the page unregisters a stale worker, and the node example kills its mock on exit.
v0.22.1
[0.22.1] - 2026-10-21
Fixed
- The shipped
nxrskill teachescloneand--segments, lists every command that reads the search index, and includesmvin the enumeration contract.
v0.22.0
[0.22.0] - 2026-10-20
Added
down --segments Nsplits each artifact intoNconcurrent closed Range spans, 2..=64.
A finished span survives an interrupted run, so a rerun fetches only the unfinished spans.
The spans assemble into the usual part file, one pass hashes it, and the marker check decides the rename.
The worker budget still caps the total concurrency, and a zero-byte object, an unsplittable one or a server that ignores Range falls back to the single-stream path.
The core exposes the same transfer asNxr::down_with_segments, and the Node bindings acceptsegmentsonNxrDownOpts.nxr clonecopies a whole repository into a local directory: every artifact and marker is verified, an interrupted run resumes, and a local object whose bytes match its remote marker but whose local marker is gone is sealed without fetching the bytes again.
An optional local fact cache (<DIR>/.nxr-state.json,--state,--no-state,--verify) skips re-hashing files whose size, mtime and marker digest still agree.
A missing, corrupt or foreign cache falls back to hashing.
The summary gains the additivesealedcount, and the Node bindings exposeclone()andclonePlan().
v0.21.0
[0.21.0] - 2026-10-19
Added
- The transfer
summarygainsfailures: the same artifacts asfailed, as{"name","code"}objects whose code is the exit class (1 data, 2 misuse, 3 transport).
failedkeeps its legacy strings (a mismatch still carriesname: detail), so the new array is additive for consumers.
The Node bindings mirror the array onNxrSummary. Nxr::audit_filteredandsync::audit::AuditFilter: an audit narrowed by exact names and whole-segment prefixes before any request.- The
retry-after-503mock scenario: the first request per path answers503with aRetry-Afterpause, so the 5xx pause is pinned without changing the plain-503flakycontract.
Changed
- The
putsource type isUint8Arrayinstead ofBuffer.
A NodeBufferis aUint8Array, so existing callers stay compatible, and the shipped declarations no longer need@types/node.
Fixed
- The composite action installs
nxragain: it resolves the release fromgithub.action_repository(the caller's repository was never the action's) and verifies the archive against the publishedSHA256SUMSinstead of a per-archive.sha256asset that the release never uploaded.
The checksum check accepts the Windows binary-mode marker and falls back toshasumwhere GNU coreutils is absent.
A CI job runs the action end to end on Linux, Windows and macOS. get --continuekeeps the partial file when a transfer fails, so the rerun the hint recommends resumes instead of starting from zero.- A resumed download refuses a symlinked or concurrently changed part, validates the
Content-Rangeend and the bytes on disk, and restarts a stale part inside the same attempt, so--retry 1still self-heals. - A
downwhose rename or destination check fails keeps the verified part for the rerun. Retry-Afteris honored on every retryable status, not only429: a restarting Nexus that answers503 Retry-After: 30is waited out instead of retried after half a second.get --segmentsaccepts 2 to 64 spans, runs them under the same worker ceiling as every other transfer, and completes an empty object instead of dividing by zero.
A segment count outside the bounds is misuse (exit 2).- The uploader re-checks the source size per attempt and reads exactly the declared bytes, so a size change between the plan and the send is an I/O error instead of a body that disagrees with
Content-Length. scanrewrites backslashes only on Windows: on Unix a backslash is a filename byte and the grammar rejects it instead of uploading a phantom path.audit --prefixobeys the same whole-segment grammar as every transfer filter, runs before marker and byte requests, andauditedcounts the objects the tree held rather than repeating the finding count.
facts_availablereports whether the index answered, not whether the filter selected anything.mv --jsonwrites a pure NDJSON stream: the plan phase headers are human output.shaexpands-Raliases for relative URLs, keeps an existing local path local, and reports a missing file or a non-http scheme as misuse (exit 2).- The live progress counter counts skipped files in its total.
doctor --deepwithout a URL is refused as misuse instead of silently skipping every server probe and reporting "all checks passed".- The release gate runs the full
just checkset (prek, cargo-deny, Python conformance), CI runs the prek hooks, the docs workflow rebuilds on the files its checkers read, and zensical is pinned. - The Rust example README teaches the current minor and joins the version gate.
v0.20.0
[0.20.0] - 2026-10-18
Added
nxrships a container image:ghcr.io/lipen/nexus-raw:<version>is the static release binary on a distroless base that carries the trust store TLS verification reads, runs asnonroot, and is published forlinux/amd64andlinux/arm64by the release workflow, from the archives that release already built.
ACOPY --from=ghcr.io/lipen/nexus-raw:<version> /nxr /usr/local/bin/nxrputs it in a downstream image.
Fixed
- Enumeration survives a repository bigger than 5000 objects: the search walk was capped at 100 pages of 50 rows, so
ls,down --ls,diff --via searchandauditrefused withcannot enumeratepast that size.
The bound is now per walk at 1000 pages, and a directory listing asks the search API withq=<directory>/, which cuts the pages down to that directory (13 to 61 pages instead of 122 on the measured 6095-object repository) while the client-side whole-segment filter stays the answer.
The property that a directory query never drops a name is versioned, not verified at run time: the stand battery pins it against the pinned Nexus image.
v0.19.1
[0.19.1] - 2026-10-18
Fixed
- The npm platform packages ship an executable
nxr: the artifact hop between the addon job and the publish job flattens file modes, so the staged binary arrived without its exec bit and the published package could not spawn it.
The 0.19.0 platform packages are inert orphans (the main package never shipped at that version), and the publish job now restores the bit and refuses to pack a binary without it.
v0.18.0
[0.18.0] - 2026-10-16
Added
put --stdin: the body streams from stdin as one PUT (printf … | nxr put URL --stdin [--sha]).
The pipe is buffered whole (Content-Length is part of the protocol), the digest rides the same buffer.
-fand--stdinare mutually exclusive, and calling with both (or neither) is refused as a misuse.Nxr::put_bytes(url, body, sha): one-call PUT of an in-memory body, the library surface under--stdin.nxr doctor --jsonand the human report carry a remediation on every failed check:
nextnames the command or configuration to try next (credentials for 401/403, the base URL and
--deepfor a transport refusal, the EULA accept for the 403 write gate).- The Python reference client ships on PyPI as
nexus-raw:pip install nexus-raw, the same
stdlib-onlynxr.pythe conformance suite drives, trusted publishing, no tokens. - The unscoped npm name returns as a bridge:
nexus-rawre-exports@nexus-raw/nxr1:1
(babel-core's bridge pattern), version in lockstep, sorequire('nexus-raw')keeps resolving
to current code. Versions below 0.17.0 are deprecated with the rename message. - The release carries a
llms.txtsnapshot: site URLs rewritten to the raw markdown at the tag,
so an agent pinned to a version reads that version's documentation.
Changed
cargo deny checkjoinsjust checkand CI: RustSec vulnerabilities and yanked crates deny,
licenses allowlist, sources policy. rustls moved to 0.23.46 (four advisories closed by upgrade).- The docs gain a how-to: comparing two servers through
mirror --dry-run, the plan is the delta.
v0.17.0
[0.17.0] - 2026-10-15
Changed
up --wait-indexpolls the search index with exponential backoff instead of a fixed interval: 500ms, then 1s, 2s, 4s, capped at 5s.
A 30s budget costs roughly 8 listing requests instead of roughly 60.
Removed
nxr point --clear <URL>: the--clearflag is gone,nxr point <URL>deletes directly.
The flag-guarded misuse case never had a success path, so the guarded form was a dead branch of the interface.- Documentation advertised manifest-based enumeration that was removed in 0.12.0: the
AGENTS.mddown-source list, the core README example and the CLI README quick start now show the real sources (--name,--names-from,--ls).
The rust example and its tutorial were ported to explicit enumeration, and the example compiles again against the published crate. nxr clean: the command is gone, enumerate and delete withnxr rmitself.
The command guessed versions by path-segment grammar, and a guessed scope is the one thing a destructive command must never do: a channel file namedstableonce passed as a "version".
Retention is a policy, and policies live on the user side: the keep-N recipe builds it fromls,channel getandrmwith explicit enumeration.
The library surface losesNxr::clean_plan,Nxr::clean_execute,Nxr::ls_versions,search_versionsandvalidate_versionwith it, and the npm package loseslsVersions.rm --dry-runandmv --dry-run: the flags are gone, both commands plan by default and delete only with--yes.
Deletion being the default unless flagged was the dialect inversion: a destructive command must demand the explicit go.
The npmrmsurface follows: the promise resolves to the plan by default,confirm: truedeletes, anddryRunis gone fromNxrRmOpts.- The implicit
version.jsonclaim inmirrorandmv: no name is special, the transfer order follows the user's enumeration verbatim.
The explicitup --claim-firstis untouched: an opt-in claim stays a user decision.
v0.16.0
[0.16.0] - 2026-10-15
Added
nxr clean <BASE_URL> [--keep N] [--yes]: retention over whole versions.
The plan names every version outside the newest--keep(dotted-numeric order) with the count of its names.
A plan is the default and deletes nothing.
--yesdeletes the doomed versions through the regularrmmachinery: markers before bytes, per-version atomic.
Channel refs and names outside the recognized versions never enter the plan.
Requires the search API (likeaudit's cross-check): a search-dead server refuses the run.up --wait-index [--index-timeout SECS]: after the run, poll the search index until every uploaded name is visible.
A real server's index lags behind writes by seconds, so a consumer reading through search right afterupsees a stale world.
The wait reportssearch visibility: N/Mand degrades to a warning when the budget (default 30s) expires: the upload itself has succeeded.doctor --deepgains theeulaprobe:GET /service/rest/v1/system/eula, strictly read-only.
accepted: falseis a warning naming the write gate and the accepting command, a 404 is a skip (no gate on this server), a refusal is a skip (admin rights).- The mock scenario
search-lag: the search index serves the empty page for 6s after the first PUT, then a store-backed listing.
The python reference client skip-lists it: its uploads are synchronous by construction.
Changed
- The docker/CI images and the docs site ship a composite GitHub Action in this repository:
uses: <owner>/nexus-raw@v…withcommand,args,versionandauth(a secret, passed through the environment, never argv). cargo binstall nexus-rawresolves the prebuilt release archives through the crate manifest metadata (present since 0.15.0, now documented).