Repository navigation
fs-safe 0.13.0
Highlights
- Stronger protection against filesystem replacement races: bind Root reads, metadata, writes, moves, and cleanup to exact file and directory identities; use atomic native rename for no-clobber moves.
- Less overhead in guarded writes and archives: avoid repeated path and mutation-policy work on eligible routes, reuse validated archive paths, and size native result buffers to bounded member sizes.
- Safer Windows paths and writes: reject NTFS stream and directory-index aliases before filesystem access, and retain destination handles through compatibility writes and verification.
- New tools for prospective paths: add
resolvePathPrefixSync()andprobePathSuffixAliasesSync()for existing-prefix traversal and bounded observations of missing suffix aliases. - Opt-in bounded temporary-file cleanup: add retained-directory cleanup ownership to
tempFile()and strengthen temporary-workspace admission and permission repair.
Compatibility and upgrade notes
- No-clobber
Root.move()now requires usable native support. Withoverwriteomitted orfalse, native-off mode, missing bindings, or unavailable safe parent/rename support fail withhelper-unavailable; there is no JavaScript check-and-replace fallback. Keep the matching native package installed for these moves. Directory moves still requireoverwrite: true, which retains guarded JavaScript support; use it only when replacement is intended. Post-operation verification can report an error after a rename has completed. - Windows alternate-data-stream and directory-index aliases now reject across guarded APIs before I/O. Supported rooted and extended-drive paths retain their handling, as do released drive-relative forms in trusted-path atomic, store/queue, move, publication, and lock APIs. Existing Root destination restrictions remain distinct; ordinary colon-bearing POSIX names keep their established rules.
- POSIX secure-file ownership checks now use the process's effective user ID and fail closed when required identity facts are unavailable. Public
Statsvalues remain numeric; exact writable-file verification uses private bigint receipts. tempFile({ cleanupSafety: "require-bounded" })is opt-in and requires an existing supplied root plus supported retained-parent cleanup. Unsupported admission fails before child creation."compatible"remains the default; cleanup callbacks and error-suppression behavior are preserved. Bounded cleanup retains the documented POSIX final-entry unlink limitation.- The two new path helpers are observations, not permission to access a path. Prefix resolution is read-only but is not a pinned or consistent snapshot. Suffix probing can create and remove directories under an approved writable parent, returns
undefinedwhen unresolved, and may preserve artifacts whose ownership cannot be verified; its budgets limit work counts and path sizes, not elapsed time.
Root boundaries and mutation performance
- Fence Root content reads, metadata observations, directory entries, and low-level file opens with exact captured-root, parent, and final-path identities. Admit supported native Windows root spellings without relaxing symlink or replacement rejection.
- Apply
denyMutationsand mutation-symlink policy to the actual retained parent used byRoot.write,Root.create,Root.copyIn,Root.openWritable,Root.append, andRoot.mkdir, including Windows buffer fallbacks. Admit missing components before creating them, and re-authorize followed final-link destinations before open, truncation, staging, and publication. - Reuse operation-local policy observations, canonical parent guards, post-create receipts, and immutable suffix offsets for eligible Node.js mutation paths. This avoids repeated resolver work and depth-quadratic segment copies; collisions, callbacks, aliases, ambiguous routes, incomplete identity observations, and final open/publication/cleanup checks retain full admission.
- Bound repeated resolver work during deep missing-parent creation on eligible Windows and POSIX JavaScript paths. Advance only through owned directory-creation receipts, and let
Root.mkdirreuse an exact existing-parent proof for its single missing child. - Reuse an already admitted parent guard for private producer Roots while preserving isolated handoff, including legacy Windows delete-pending and read-only restoration behavior.
- Bind nonrecursive removal to its admitted parent and revalidate native move endpoints and explicit parent-symlink rejection before dispatch. Recheck copied-directory identities after child cleanup so concurrent replacements are preserved.
Credentials, permissions, and temporary files
- Snapshot secure-read, secret-reader, traversal, and borrowed-transfer policies before asynchronous work, including size/link limits, trusted directories, and selected environment values. In-flight admission can no longer be relaxed by changing shared options.
- Preserve single-read pathname and authority accessors on Node.js 22, along with callback receivers, cancellation signals, and progress callbacks across JSON, durable directory/queue, sibling-staging, and borrowed-handle operations. Windows temp admission remains active with platform adapters, and canonical prefixes are checked before inspection.
- Bind secure temporary-directory and synchronous store-directory mode repairs to no-follow descriptors and exact current identities, including concurrent mode changes during the matching-mode fast path.
- Admit temporary-workspace roots and children before use, preserve existing permissions, and bind initialization and cleanup to retained identities. Opt-in bounded temporary-file admission closes descriptors on failure.
- Retain Windows destination descriptors through buffered compatibility-write locking, content verification, mode changes, sync, and final identity checks.
- Validate descriptor-bound macOS clone ACLs before admission and publication, including absent ACLs. Once payload bytes exist, normalization or security failures are terminal
EIOerrors rather than a reason to retry with an ordinary copy.
Archive safety and performance
- Bind physical ZIP entry names and file/directory kinds to decoder metadata before callbacks or member selection, rejecting ambiguous interpretations consistently.
- Stop zstd and bzip2 compressed-input refills after cancellation while preserving decoded-output limits and complete archive validation.
- Reuse canonical archive paths when no components are stripped and avoid temporary ZIP collision collections, retaining validation/filter order and checks of both raw and Unicode identities.
- Reserve native archive result capacity from bounded member-size hints so small ZIP and compressed TAR reads do not allocate the caller's larger byte budget.
Path helpers and reliability
- Add
resolvePathPrefixSync()under@openclaw/fs-safe/advancedto traverse existing path prefixes while retaining the raw missing suffix, preserving dangling aliases and propagating ambiguous resolution failures. - Add
probePathSuffixAliasesSync()under@openclaw/fs-safe/advanced, with fixed path, depth, creation, and observation budgets and conservative identity-checked cleanup. - Sanitize fallback filenames and validate completed sibling callback names before producers run, retaining length bounds and Windows device-name rejection. Reuse Windows namespace admission for unchanged ordinary rooted-drive paths while keeping full checks for relative, normalized, malformed, namespaced, and colon-bearing forms.
- Pin asynchronous relative sidecar-lock paths and roots to their entry-time working directory through acquisition, reclaim, verification, and release. Close synchronous lock descriptors after metadata inspection failures while preserving the original error and unverified sidecar; retry vanished admitted successors under the existing identity checks and budgets.
- Report actionable guarded-write errno diagnostics while preserving error codes, categories, original causes, and already-classified failures.
- Tolerate concurrent guest parent-directory creation only after descriptor-relative no-follow admission; file and symlink competitors remain rejected. Thanks @vincentkoc.
- Show only the moon icon in the docs light-theme picker and only the sun icon in dark mode.
Validation and tooling
- Strengthen exact-identity, rounded-inode, Windows recovery, mutation-policy, and package-consumer regressions, with explicit test-hook provenance and bounded fixture lifetimes. Queue stress fixtures retain and drain outstanding writers before cleanup.
- Separate manual method-audit harnesses from immutable candidate and baseline checkouts, validate dispatch inputs before fan-out, and support Node 22/24 plus rebuild and same-artifact controls. Versioned benchmark receipts bind source, harness, dependencies, artifacts, native addons, and runner metadata; they detect accidental drift and are not a sandbox for hostile code.
- Expand benchmark coverage for filename sanitizers, all 17 profiles, shared mutation admission, temporary-workspace modes, and existing/missing roots at depths 4/8/32. Keep Windows-specific rows and observed-preservation claims distinct from JavaScript operation counts.
- Isolate split-credential proof runners, authenticate official Node archives before checkout, and use private, identity-checked stages and tools. Fixtures remain traversable by both dropped identities while published receipts stay in a separately admitted container; the seven behavioral cases are unchanged.
- Update development tooling to
@napi-rs/cli3.9.1, fast-check 4.10.0, and Vite 8.3.0 with verified registry integrity.
Published packages
| Package | Registry tarball | Verified integrity | Provenance |
|---|---|---|---|
| @openclaw/fs-safe-linux-x64-gnu@0.13.0 | tgz | sha512-tp3yQxmm9HFHCDGPgYsqVmtzPg7LovusfVtBK4Q/DlW4+JJc1NAzT4NfeOcxqYAYbXdHS9jidXNmrZHqXNz2fg== |
verified attestation |
| @openclaw/fs-safe-linux-x64-musl@0.13.0 | tgz | sha512-0S+i258RQh9mGZKIrs+vVGJEwM6fcOlUM7zvGjMEm5IDhb9FxwlI9iZncsBa88Ic4Sxt1hKjKT4L+J3W9/E44w== |
verified attestation |
| @openclaw/fs-safe-linux-arm64-gnu@0.13.0 | tgz | sha512-GAf5q5e65n/CU1JXo7ODbv0B90SUc9JvCwog2ZcQWEYCqumaA4T8qgcBF2GZcDiloNZ0GuUADPppujdDJoxPTg== |
verified attestation |
| @openclaw/fs-safe-linux-arm64-musl@0.13.0 | tgz | sha512-HiU0M8/pl3FCVi625v7fVuxHcgiLPNiQeY7bfEfUrvR4NcWkyjcg8L8jwfDeIm4MSnEjb0+hmL2MyrdRZDGDNg== |
verified attestation |
| @openclaw/fs-safe-darwin-x64@0.13.0 | tgz | sha512-7Gs3BY7/2kOQjJ1fo60SdwA/C1bHMKW6CUC9tJI/samfCRj7Am2PW4y83h3/0P9Otd9qV7KSyxeYJYyMbMN+7Q== |
verified attestation |
| @openclaw/fs-safe-darwin-arm64@0.13.0 | tgz | sha512-/rbWVk5YZcCP2LAfg0yGRie3W5mJuNvBphF8uzk8m4SUTXie20BwYFzeJFsQ+dLAivbosETc000UcCj8hWFS+Q== |
verified attestation |
| @openclaw/fs-safe-win32-x64-msvc@0.13.0 | tgz | sha512-SSCcih/vUV6fR/LU2eTFgzB6DIXH0dftpER4Oglfy+i88oq+HmLlTOJEDRGv2iUkF0+kRpEMEqSUuoOWCY8/ZA== |
verified attestation |
| @openclaw/fs-safe@0.13.0 | tgz | sha512-8dyH9wMH5PFsOZZocY/lb+EYFMVN3+BMaPo0z2a1YwaOrkwrEt6kLvhI2g0X2AAKeq75r99cS1aMvY+Tk3wa6g== |
verified attestation |
Release proof: GitHub Actions run.