Skip to content

fs-safe 0.16.0

Choose a tag to compare

@github-actions github-actions released this 19 Sep 06:45
· 503 commits to main since this release
v0.16.0
acbb916

Highlights

  • Private files and directories through existing APIs: add private: true to Root mkdir(), ensureRoot(), create(), and createJson(), with verified owner-only permissions and creation-time Windows ACL protection. New /advanced helpers createDirectory(), createDirectorySync(), and createFileSync() create one exclusive entry under an existing trusted parent; the file helper returns an owned, disposable descriptor. (#487, #482)
  • Safer secret and private writes: verify the actual staging permissions before writing content, rejecting filesystems that accept permission changes without enforcing the required private mode. (#491, #493)
  • Atomic buffered file creation: opt into atomic: true on Root.create() or createJson() to keep the destination absent until its content is ready, including without the native addon. Independently select durable: "file" when file-flush failures must propagate. Existing defaults remain unchanged. (#486)
  • Compressed TAR without native installation: extract and read bounded entries from zstd and bzip2 TAR archives through bundled WASM codecs, even with all optional dependencies omitted. The fallback retains the shared Rust TAR parser, full-stream validation, byte limits, and guarded publication, with no runtime interpreter or download. (#488)
  • Windows security operations without the addon: use packaged, readable PowerShell/C# helpers for raw owner/DACL inspection, private-directory creation, and secure-file reads in native auto or off mode when capabilities are unavailable. Private permissions apply at creation, and secure reads inspect the same open handle that supplies the bytes. (#476)

Compatibility and upgrade notes

  • Private creation on macOS requires the matching native helper's ACL-inspection capability; disabled, missing, or older helpers reject before creating parents or stages. Relevant inheritable parent ACLs reject creation, while noninheriting ACLs remain allowed. Existing entries are never repaired or made less restrictive. Nonprivate creation and native-free secret-file writes retain their behavior; see the creation contract for supported modes and platform limits.
  • Native-free atomic: true creation requires hardlinks and rejects unsupported filesystems without publishing partial content. Private Windows file publication also requires hardlinks on the same local filesystem. Streamed creates continue to stage complete content; atomic visibility does not strengthen pathname containment or guarantee crash durability.
  • durable: "file" applies to buffered, streamed, and JSON creates and propagates file-sync errors, including EPERM. Parent-directory synchronization remains best-effort, independently of the selected publication strategy.
  • Windows fallbacks require system PowerShell and permission to run the packaged scripts and .NET Add-Type under normal system policy. They emit a path-free FS_SAFE_NATIVE_FALLBACK warning once per capability per process and add startup and compilation overhead; disallowed execution fails closed. No system policy is bypassed.
  • Native require remains strict, and failures from available native operations never trigger a fallback retry. No-clobber Root.move() still requires native support. ZIP fallback still needs optional jszip, and inspectTarArchive() continues to accept only plain TAR and gzip.
  • Atomic, streamed, and private creation can report cleanup, close, mode, or synchronization errors after a complete file has been published. Preserve the publication and cleanup receipts when handling failures; completed destinations remain in place, and indeterminate outcomes retain names for recovery.

Security and correctness

  • Verify 0600 before secret-file payload writes in native and JavaScript writers. Verify actual native private-file ownership and permissions before payload writes and at publication, rejecting filesystems that accept permission changes without enforcing them; retain explicit final modes and public staging's 0600 guarantees. (#491, #493)
  • Compare exact directory identities before and after durability syncs, retry unknown Windows observations once, and reject rounded or unverifiable caller receipts. Bind numeric metadata to the same observation and preserve private identity authority across receipt mutation, durable creation, publication, and retained staging. (#483)
  • Retain streamed Root.create() authority callbacks and abort signals across producer waits so replacing caller options cannot detach a revoked lease or redirect cancellation; preserve callback receivers and owned-stage cleanup. (#490)
  • Recheck retained parent and staging identities after final publication authority callbacks on JavaScript and native writers, preserving substituted entries before their bytes can be published. Flush native Windows creation through the retained writable descriptor and preserve published destinations after finalization failures.
  • Snapshot Root.move() mutation policy before asynchronous admission so changes to caller-owned deny paths or prefixes cannot change an in-flight move. Recheck native no-clobber source identity, type, and hardlink policy after the final authority callback; live revocation remains available through assertBeforeMutation.
  • Keep asynchronous Root-backed file locks waiting through successive owner handoffs instead of failing with path-mismatch, while retaining identity checks and requiring a fresh exclusive acquisition.
  • Return one unsupported clone-metadata result per input without the native addon on non-macOS platforms in auto and off modes. Preserve input validation, strict require mode, and native-only APFS metadata on macOS. (#489)

Diagnostics and maintenance

  • Address Windows security commands by their built-in module names and restrict discovery to PowerShell's bundled system modules, avoiding broad discovery scans on helper startup. (#484)
  • Clarify that resolveExistingPathsWithinRoot() permits missing paths while resolveStrictExistingPathsWithinRoot() requires existing regular files, and distinguish native beneath mechanisms from the best-effort containment reported by public Root open, read, and writable-open results. (#485)
  • Honor case-insensitive Windows build environment names so configured WASM compilers and archivers remain selected in worker processes; preserve child-only compiler flags without duplicate case variants. (#492)
  • Refresh JavaScript and Rust dependencies, pnpm, CodeQL, and archive/release build toolchains, including current NAPI interoperability fixes; retain Node 22 support and Rust 1.88 compatibility. Includes the Dependabot updates in #481.

Published packages

Package Registry tarball Verified integrity Provenance
@openclaw/fs-safe-linux-x64-gnu@0.16.0 tgz sha512-H644Ko4Jf3gMZTERErwK6yf6ayWW0IkTCmP4VPfX17Kohvi0pV28F11F1FeoUxgxpiVQpaoVopNPBBSrKTnpuw== verified attestation
@openclaw/fs-safe-linux-x64-musl@0.16.0 tgz sha512-ha43qH1ZAfYzZbsqRBwwTSariQxfFvfRnXaYwja9ojRJ9LNJSGTO7MULTMFa4fipU9iTIhz1NYP3Ez2107KbGQ== verified attestation
@openclaw/fs-safe-linux-arm64-gnu@0.16.0 tgz sha512-ziWqlIeft+eQVbtdGxboffiOEqy8RltS67UXT5QIPd+VQjOMmcdi3tV2cyR2dwOsD3mlr13Vw8ldT9GjFIVciA== verified attestation
@openclaw/fs-safe-linux-arm64-musl@0.16.0 tgz sha512-eWeboLCUKDnlMqzAqfj2zQgyogqjL5gudg9l35mRUl3joSmi10i1MU+pAXR6IHlCCy314Txsq4sBF0wWAf7/sw== verified attestation
@openclaw/fs-safe-darwin-x64@0.16.0 tgz sha512-GhaeCtVtZbHaX+O0Zd8Q9wL86SB5ofor6xJB/heV3bDwKFDxRS6lCa55sn1hglzjlpkBQNJqpXCwOiwf+NZABw== verified attestation
@openclaw/fs-safe-darwin-arm64@0.16.0 tgz sha512-DG0FwUHQOEYYNmNJ6voKiIMTSzj8WVlmWkRs3WXDr49zGslI8sVNyGVnDzmk2EYj4kV1WYcib3J5zNlOzfM9hg== verified attestation
@openclaw/fs-safe-win32-x64-msvc@0.16.0 tgz sha512-hSQv6mRpd66364JxFXAyx7rz4G9I9s0q3VbfyKKMntHzPKaj4mPs8HuDuI3NBMjV2AkDo11xMcthXEd9iwEoTg== verified attestation
@openclaw/fs-safe@0.16.0 tgz sha512-jRCVSEfnJQdyAV7LyYOnysV09EQRoQ7KcEysLLhBtzdNVwjYtZApnwwoDDpf38IF2pXIeok0cB679yVUUkAOpg== verified attestation

Release proof: GitHub Actions run.