Repository navigation
fs-safe 0.11.0
Highlights
- Faster archive-heavy workloads: reduce repeated ZIP admission, batch native ZIP metadata reads, and reuse TAR parser input and admitted payload ranges. Archive extraction and inspection also benefit from larger reusable staging and transfer buffers.
- More capable filesystem roots: iterate one directory with
Root.entries(), remove trees with bounded or explicitly unlimitedRoot.remove(), and create complete files from async byte streams withRoot.create(). - Reuse handles for copying, overwriting, and hashing: add
copyFileHandle(),overwriteFileHandle(), andsha256FileSync()while preserving caller-owned descriptors and file positions. - Faster Windows permissions and copying: inspect inherited ACLs without PowerShell startup when the native binding is available, reduce copy allocations, and preserve large zero-filled ranges in empty destination files.
- Safer publication and private files: tighten hardlink, inode, permission, archive-destination, and lock validation; add private producer workspaces for callback writes and fix staging of long Unicode filenames.
Compatibility and upgrade notes
readSecureFile()now rejects hardlinked inputs and rechecks the opened file after reading. Synchronous store publication rejects substituted or unverifiable file identities, including opaque Windows identities.- Invalid lock stale thresholds and compromise-check intervals now reject before acquisition. Asynchronous compromise checks no longer overlap or turn overflowing timer values into rapid polling loops.
- Inherited atomic-replacement modes include only ordinary rwx bits from an existing non-symlink regular file. JavaScript raw sidecars are created with mode
0o600, so a permissive umask cannot expose their payloads. - Bun gains additional POSIX path support through the existing Rust binding, including with JIT disabled. Native-off policy remains explicit; addon-free limitations are documented. Node.js remains supported from version 22.
Directory and file workflows
- Add guarded, nonrecursive
Root.entries()with child-symlink reporting, cancellation, entry limits, and bounded sorted-name collection. Traversal and link policy remain with the caller. - Extend
Root.remove()with recursive traversal, entry/depth budgets, sorted or filesystem order, cancellation, and missing-target handling. Callers may explicitly choose unlimited recursive-removal budgets; exact directory/leaf identity checks remain in place, andforcecontinues sibling cleanup when a child directory disappears. - Add a
Root.create()overload for async byte iterables. Input consumption is bounded, cancellation settles pending work, and completed contents are published exclusively through the existing guarded writer. - Add
copyFileHandle()for bounded regular-file transfers andoverwriteFileHandle()for in-place replacement with prefix-only rollback preparation, growth-before-overwrite ordering, and a once-only synchronous pre-write admission callback. Both preserve caller ownership and cursors. - Add
sha256FileSync()for bounded hashing of pathnames and borrowed descriptors, with exact pathname admission and no native-binding requirement. - Add exact directory-identity observations and synchronous assertions for caller-owned staging and recovery, retaining bigint precision, optional canonical-path checks, and final-symlink rejection even with trailing separators.
- Add
probePathCaseInsensitiveSync()for local ASCII-case observations, with a read-only option, owned temporary probes, and an explicit unknown result instead of operating-system guesses. - Add opt-in
producerIsolation: "private-directory"to sibling callback writes and external sibling outputs. Cleanup ownership is established before the producer runs, allowing partial failures to be cleaned without changing existing defaults or publication checks.
Archive and path performance
- Avoid repeating physical ZIP admission during JavaScript member reads. Reduce filename-validation allocations across both backends, and group native ZIP metadata reads into bounded buffers while retaining complete record, CRC, limit, and cancellation checks.
- Copy each JavaScript TAR WASM input window once across member events. Read selected plain-TAR payloads directly from the fully admitted private snapshot instead of parsing it a second time.
- Batch private archive-input staging through reusable buffers capped at 512 KiB. Match file-backed JavaScript gzip output to the 64 KiB WASM input window for faster extraction and TAR inspection; retain short-I/O handling, framing validation, bounded growth probes, and settled cancellation.
- Reduce repeated POSIX path-scoping and Root work, reuse checked store keys, and avoid redundant name normalization. Root exclusion, canonical spelling, Unicode byte limits, collision rules, home expansion, and live filesystem identity checks are preserved.
- Complete short gzip-header reads before classifying staged archives, preventing valid gzip files from being mistaken for TAR.
- Fit callback staging names using their original UTF-8 length as well as NFC/NFD lengths. Valid destination names whose normalization is shorter no longer fail with
ENAMETOOLONGwhen a staging prefix is added; the final target spelling is preserved.
Copy performance and filesystem fidelity
- Batch large borrowed-handle and JavaScript Root transfers through reusable 512 KiB buffers, retaining byte limits, cancellation, and per-write authority checks. Small byte budgets also bound scratch allocation and the overflow probe.
- Batch atomic copy-fallback restore snapshots and synchronous source reads into reusable buffers, reducing reads and full-buffer copies while preserving restore budgets, short reads, identity checks, original modes, and rollback behavior.
- Share portable directory-copy workers across sibling directories, with bounded deferred completion, joined cancellation, and bottom-up timestamp restoration. Preserve fractional timestamps, including pre-1970 dates on Unix, to the precision supported by Node and the destination filesystem.
- Add Linux ZFS directory cloning through the bounded reflink traversal, with independent destinations, metadata preservation, and no byte-copy fallback when cloning is required. XFS clones now preserve user extended attributes on read-only files and directories, along with their modes and ACLs.
- Preserve large zero-filled ranges without allocating them during native Linux automatic directory byte copies and native Windows byte copies into empty files. Exact lengths, contents, cancellation settlement, and existing-target overwrite behavior remain intact.
- Confirm EOF when Linux copy offload initially reports zero bytes, so automatic copying reads available data instead of publishing an empty file.
- Size Windows native copy buffers to small inputs, reuse directory-enumeration buffers, and start ReFS workers as file jobs arrive. Report disk-full and sharing failures as
ENOSPCandEBUSY; worker-start failures join admitted workers before returning instead of panicking across the native boundary.
Permissions, compatibility, and tooling
- Inspect complete inherited local Windows ACLs through the native descriptor reader when available, preserving SID classification, explicit test injections, .NET normalization, and structured fallback diagnostics. Classify canonical SID facts directly without a redundant account lookup, retaining fail-closed behavior when discovery is unavailable.
- Retain the admitted archive destination's exact bigint identity through publication, rejecting replacements introduced by entry filters or concurrent actors before files can be published into them.
- Support Bun POSIX resolution for restrictive permissions, literal backslashes, sockets, and symlink/parent traversal. Preserve raw path components in absolute recursive-mkdir inputs to fix relative publication and queue writes on Bun for Windows.
- Export the caller-launched Python guest filesystem program and shared no-replace rename fragment through
@openclaw/fs-safe/guest. The Linux/macOS protocol validates basenames before filesystem operations and uses short independent staging names for long-basename writes and cross-device moves. - Support standalone
@pnpm/exein consumer smoke and lifecycle tests while retaining the declared pnpm version and isolated consumer configuration. Strengthen exact-inode durability checks and batch independent native ACL test observations. - Expand method benchmarks to 557 representative workloads across Linux, macOS, and Windows, with native/JavaScript modes, equal-concurrency copy comparisons, large collections, contention, and explicit platform exclusions. Verify returned data and digests, initialize private Windows fixture ACLs, apply synchronous iteration reductions consistently, and handle expected synchronous rejections during timed calls as well as warmup.
Published packages
| Package | Registry tarball | Verified integrity | Provenance |
|---|---|---|---|
| @openclaw/fs-safe-linux-x64-gnu@0.11.0 | tgz | sha512-xZOV+EFnRW83R6UHQfuj87M7+4KZRFceCtCrJh5kOedbUaBuAzcIjmMuBWCXQcaUzKDhNQA+b5L6sIxgKQWHfw== |
verified attestation |
| @openclaw/fs-safe-linux-x64-musl@0.11.0 | tgz | sha512-7zITC0ajQdejv5XbM3RgsGEfu+ZoAiUlLV2T711xgrhGYcfPLRHEipjX9ulTLqApcf+EX2PjAv+ZcOTodvfN9A== |
verified attestation |
| @openclaw/fs-safe-linux-arm64-gnu@0.11.0 | tgz | sha512-YxHKHiCiCZUuKmebofoGvjj2zN6YTYskpsPfBjGJmPn7blJmsoHnWX3bF3B2b3RUQcxtS2vJ0m73PDTlx3FvDQ== |
verified attestation |
| @openclaw/fs-safe-linux-arm64-musl@0.11.0 | tgz | sha512-w6JxYF1WsLMBhdJgEVTSRboCwKKcAoCmnnAkF1Uw+CltoBfvE+pROQzbPBlLFRmjnKB5kDIiu7To8UcXxQeMUw== |
verified attestation |
| @openclaw/fs-safe-darwin-x64@0.11.0 | tgz | sha512-ofIIFNoHvh4bJQ50vkUFnSCXkITLtkQ9dP81h95rVrDX7pFINZn8Q3hciMHsGwIjcNZTzG3AuHBJ03fBNVB+Nw== |
verified attestation |
| @openclaw/fs-safe-darwin-arm64@0.11.0 | tgz | sha512-bvQLY3q4Sumw+2V3KHhMiuOMEptvR7fEQQ7ewivRE77skxM/t05+UeQ0px23wONMmh2VR8AqB1vAV9ORaAVC9g== |
verified attestation |
| @openclaw/fs-safe-win32-x64-msvc@0.11.0 | tgz | sha512-K75zyBetramBNGjgT/GMuFWvyWaF+th1s5zYTYXllFD907dSW3VOub82VAwbuiJHNnJ4VeknFDTdjnhgVj5xiw== |
verified attestation |
| @openclaw/fs-safe@0.11.0 | tgz | sha512-peGqt1p6b/93Xvqo8V5ZvrL9NdNX6VjzrcnDuo0o+Y+UfeuFvxcF64qSarsHwyJ24s2gEjE9Vl76A3vtFR8WTg== |
verified attestation |
Release proof: GitHub Actions run.