@openclaw/openshell-sandbox 2026.9.1 → 2026.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +87 -47
- package/node_modules/@openclaw/fs-safe/CHANGELOG.md +700 -0
- package/node_modules/@openclaw/fs-safe/LICENSE +21 -0
- package/node_modules/@openclaw/fs-safe/README.md +564 -0
- package/node_modules/@openclaw/fs-safe/SECURITY.md +45 -0
- package/node_modules/@openclaw/fs-safe/dist/absolute-path.d.ts +33 -0
- package/node_modules/@openclaw/fs-safe/dist/absolute-path.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/absolute-path.js +307 -0
- package/node_modules/@openclaw/fs-safe/dist/advanced.d.ts +26 -0
- package/node_modules/@openclaw/fs-safe/dist/advanced.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/advanced.js +28 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-crc32.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-crc32.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-crc32.js +14 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-deadline.d.ts +12 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-deadline.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-deadline.js +103 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-entry.d.ts +14 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-entry.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-entry.js +85 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-errors.d.ts +13 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-errors.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-errors.js +23 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-gzip-tail.d.ts +18 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-gzip-tail.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-gzip-tail.js +74 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-input.d.ts +19 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-input.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-input.js +92 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-kind.d.ts +9 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-kind.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-kind.js +82 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-limits.d.ts +57 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-limits.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-limits.js +131 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-merge.d.ts +18 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-merge.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-merge.js +157 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-native.d.ts +20 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-native.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-native.js +107 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-options.d.ts +21 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-options.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-options.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-parser-errors.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-parser-errors.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-parser-errors.js +12 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-parser.wasm +0 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-plan.d.ts +20 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-plan.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-plan.js +55 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-policy.d.ts +22 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-policy.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-policy.js +38 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-read.d.ts +6 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-read.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-read.js +225 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-staging.d.ts +31 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-staging.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-staging.js +250 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar-inspect.d.ts +7 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar-inspect.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar-inspect.js +59 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar-stream.d.ts +18 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar-stream.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar-stream.js +95 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar-wasm.d.ts +18 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar-wasm.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar-wasm.js +99 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar.d.ts +19 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar.js +21 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-admission.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-admission.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-admission.js +60 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-count.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-count.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-count.js +140 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-directory.d.ts +15 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-directory.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-directory.js +228 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-entry.d.ts +21 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-entry.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-entry.js +27 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-integrity.d.ts +5 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-integrity.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-integrity.js +41 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-names.d.ts +12 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-names.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-names.js +100 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-preflight.d.ts +7 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-preflight.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-preflight.js +44 -0
- package/node_modules/@openclaw/fs-safe/dist/archive.d.ts +15 -0
- package/node_modules/@openclaw/fs-safe/dist/archive.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive.js +275 -0
- package/node_modules/@openclaw/fs-safe/dist/async-lock.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/async-lock.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/async-lock.js +17 -0
- package/node_modules/@openclaw/fs-safe/dist/atomic.d.ts +5 -0
- package/node_modules/@openclaw/fs-safe/dist/atomic.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/atomic.js +4 -0
- package/node_modules/@openclaw/fs-safe/dist/bounded-read-stream.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/bounded-read-stream.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/bounded-read-stream.js +21 -0
- package/node_modules/@openclaw/fs-safe/dist/bounded-read.d.ts +14 -0
- package/node_modules/@openclaw/fs-safe/dist/bounded-read.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/bounded-read.js +106 -0
- package/node_modules/@openclaw/fs-safe/dist/byte-budget.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/byte-budget.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/byte-budget.js +9 -0
- package/node_modules/@openclaw/fs-safe/dist/config.d.ts +3 -0
- package/node_modules/@openclaw/fs-safe/dist/config.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/config.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/containment.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/containment.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/containment.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/deny-mutations.d.ts +12 -0
- package/node_modules/@openclaw/fs-safe/dist/deny-mutations.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/deny-mutations.js +69 -0
- package/node_modules/@openclaw/fs-safe/dist/device-path.d.ts +15 -0
- package/node_modules/@openclaw/fs-safe/dist/device-path.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/device-path.js +137 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-durability.d.ts +44 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-durability.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-durability.js +299 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-guard.d.ts +31 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-guard.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-guard.js +82 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-mode-node.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-mode-node.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-mode-node.js +93 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-mode-owner.d.ts +21 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-mode-owner.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-mode-owner.js +78 -0
- package/node_modules/@openclaw/fs-safe/dist/durability.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/durability.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/durability.js +3 -0
- package/node_modules/@openclaw/fs-safe/dist/error-detail.d.ts +3 -0
- package/node_modules/@openclaw/fs-safe/dist/error-detail.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/error-detail.js +10 -0
- package/node_modules/@openclaw/fs-safe/dist/errors.d.ts +14 -0
- package/node_modules/@openclaw/fs-safe/dist/errors.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/errors.js +26 -0
- package/node_modules/@openclaw/fs-safe/dist/file-hash.d.ts +10 -0
- package/node_modules/@openclaw/fs-safe/dist/file-hash.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/file-hash.js +73 -0
- package/node_modules/@openclaw/fs-safe/dist/file-identity.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/file-identity.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/file-identity.js +34 -0
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync.d.ts +35 -0
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync.js +349 -0
- package/node_modules/@openclaw/fs-safe/dist/file-lock.d.ts +24 -0
- package/node_modules/@openclaw/fs-safe/dist/file-lock.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/file-lock.js +46 -0
- package/node_modules/@openclaw/fs-safe/dist/file-observation.d.ts +9 -0
- package/node_modules/@openclaw/fs-safe/dist/file-observation.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/file-observation.js +22 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-boundary.d.ts +33 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-boundary.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-boundary.js +189 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-limit.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-limit.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-limit.js +8 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-prune.d.ts +12 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-prune.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-prune.js +95 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-sync-write.d.ts +9 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-sync-write.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-sync-write.js +127 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store.d.ts +62 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store.js +357 -0
- package/node_modules/@openclaw/fs-safe/dist/file-sync.d.ts +5 -0
- package/node_modules/@openclaw/fs-safe/dist/file-sync.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/file-sync.js +19 -0
- package/node_modules/@openclaw/fs-safe/dist/filename.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/filename.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/filename.js +91 -0
- package/node_modules/@openclaw/fs-safe/dist/fs.d.ts +13 -0
- package/node_modules/@openclaw/fs-safe/dist/fs.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/fs.js +30 -0
- package/node_modules/@openclaw/fs-safe/dist/guarded-mkdir.d.ts +14 -0
- package/node_modules/@openclaw/fs-safe/dist/guarded-mkdir.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/guarded-mkdir.js +87 -0
- package/node_modules/@openclaw/fs-safe/dist/guarded-mutation.d.ts +37 -0
- package/node_modules/@openclaw/fs-safe/dist/guarded-mutation.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/guarded-mutation.js +82 -0
- package/node_modules/@openclaw/fs-safe/dist/home-dir.d.ts +12 -0
- package/node_modules/@openclaw/fs-safe/dist/home-dir.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/home-dir.js +84 -0
- package/node_modules/@openclaw/fs-safe/dist/index.d.ts +7 -0
- package/node_modules/@openclaw/fs-safe/dist/index.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/index.js +5 -0
- package/node_modules/@openclaw/fs-safe/dist/install-path.d.ts +20 -0
- package/node_modules/@openclaw/fs-safe/dist/install-path.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/install-path.js +94 -0
- package/node_modules/@openclaw/fs-safe/dist/json-document-store.d.ts +35 -0
- package/node_modules/@openclaw/fs-safe/dist/json-document-store.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/json-document-store.js +97 -0
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue-directory.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue-directory.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue-directory.js +20 -0
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue-ownership.d.ts +17 -0
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue-ownership.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue-ownership.js +292 -0
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue.d.ts +46 -0
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue.js +383 -0
- package/node_modules/@openclaw/fs-safe/dist/json-store.d.ts +9 -0
- package/node_modules/@openclaw/fs-safe/dist/json-store.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/json-store.js +12 -0
- package/node_modules/@openclaw/fs-safe/dist/json-stringify.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/json-stringify.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/json-stringify.js +7 -0
- package/node_modules/@openclaw/fs-safe/dist/json.d.ts +50 -0
- package/node_modules/@openclaw/fs-safe/dist/json.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/json.js +343 -0
- package/node_modules/@openclaw/fs-safe/dist/local-file-access.d.ts +9 -0
- package/node_modules/@openclaw/fs-safe/dist/local-file-access.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/local-file-access.js +87 -0
- package/node_modules/@openclaw/fs-safe/dist/local-roots.d.ts +26 -0
- package/node_modules/@openclaw/fs-safe/dist/local-roots.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/local-roots.js +135 -0
- package/node_modules/@openclaw/fs-safe/dist/lock-config.d.ts +10 -0
- package/node_modules/@openclaw/fs-safe/dist/lock-config.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/lock-config.js +12 -0
- package/node_modules/@openclaw/fs-safe/dist/move-path-cleanup.d.ts +43 -0
- package/node_modules/@openclaw/fs-safe/dist/move-path-cleanup.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/move-path-cleanup.js +161 -0
- package/node_modules/@openclaw/fs-safe/dist/move-path.d.ts +21 -0
- package/node_modules/@openclaw/fs-safe/dist/move-path.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/move-path.js +334 -0
- package/node_modules/@openclaw/fs-safe/dist/native-binding.d.ts +93 -0
- package/node_modules/@openclaw/fs-safe/dist/native-binding.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/native-binding.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/native-config.d.ts +17 -0
- package/node_modules/@openclaw/fs-safe/dist/native-config.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/native-config.js +71 -0
- package/node_modules/@openclaw/fs-safe/dist/native-operations.d.ts +21 -0
- package/node_modules/@openclaw/fs-safe/dist/native-operations.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/native-operations.js +132 -0
- package/node_modules/@openclaw/fs-safe/dist/native-pinned-write-windows.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/native-pinned-write-windows.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/native-pinned-write-windows.js +96 -0
- package/node_modules/@openclaw/fs-safe/dist/native-pinned-write.d.ts +5 -0
- package/node_modules/@openclaw/fs-safe/dist/native-pinned-write.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/native-pinned-write.js +161 -0
- package/node_modules/@openclaw/fs-safe/dist/native-staged-file.d.ts +31 -0
- package/node_modules/@openclaw/fs-safe/dist/native-staged-file.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/native-staged-file.js +362 -0
- package/node_modules/@openclaw/fs-safe/dist/native.d.ts +14 -0
- package/node_modules/@openclaw/fs-safe/dist/native.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/native.js +204 -0
- package/node_modules/@openclaw/fs-safe/dist/opened-file-failure.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/opened-file-failure.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/opened-file-failure.js +45 -0
- package/node_modules/@openclaw/fs-safe/dist/opened-realpath.d.ts +16 -0
- package/node_modules/@openclaw/fs-safe/dist/opened-realpath.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/opened-realpath.js +92 -0
- package/node_modules/@openclaw/fs-safe/dist/output.d.ts +15 -0
- package/node_modules/@openclaw/fs-safe/dist/output.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/output.js +123 -0
- package/node_modules/@openclaw/fs-safe/dist/owner-dacl.d.ts +31 -0
- package/node_modules/@openclaw/fs-safe/dist/owner-dacl.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/owner-dacl.js +28 -0
- package/node_modules/@openclaw/fs-safe/dist/path-policy.d.ts +25 -0
- package/node_modules/@openclaw/fs-safe/dist/path-policy.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/path-policy.js +44 -0
- package/node_modules/@openclaw/fs-safe/dist/path.d.ts +21 -0
- package/node_modules/@openclaw/fs-safe/dist/path.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/path.js +136 -0
- package/node_modules/@openclaw/fs-safe/dist/permission-exec.d.ts +25 -0
- package/node_modules/@openclaw/fs-safe/dist/permission-exec.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/permission-exec.js +74 -0
- package/node_modules/@openclaw/fs-safe/dist/permissions-public.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/permissions-public.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/permissions-public.js +3 -0
- package/node_modules/@openclaw/fs-safe/dist/permissions-windows.d.ts +59 -0
- package/node_modules/@openclaw/fs-safe/dist/permissions-windows.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/permissions-windows.js +296 -0
- package/node_modules/@openclaw/fs-safe/dist/permissions.d.ts +60 -0
- package/node_modules/@openclaw/fs-safe/dist/permissions.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/permissions.js +125 -0
- package/node_modules/@openclaw/fs-safe/dist/pinned-open.d.ts +24 -0
- package/node_modules/@openclaw/fs-safe/dist/pinned-open.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/pinned-open.js +74 -0
- package/node_modules/@openclaw/fs-safe/dist/pinned-operation.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/pinned-operation.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/pinned-operation.js +35 -0
- package/node_modules/@openclaw/fs-safe/dist/pinned-write.d.ts +36 -0
- package/node_modules/@openclaw/fs-safe/dist/pinned-write.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/pinned-write.js +252 -0
- package/node_modules/@openclaw/fs-safe/dist/private-directory.d.ts +5 -0
- package/node_modules/@openclaw/fs-safe/dist/private-directory.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/private-directory.js +14 -0
- package/node_modules/@openclaw/fs-safe/dist/private-temp-workspace.d.ts +45 -0
- package/node_modules/@openclaw/fs-safe/dist/private-temp-workspace.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/private-temp-workspace.js +299 -0
- package/node_modules/@openclaw/fs-safe/dist/publish-file-failure.d.ts +28 -0
- package/node_modules/@openclaw/fs-safe/dist/publish-file-failure.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/publish-file-failure.js +22 -0
- package/node_modules/@openclaw/fs-safe/dist/publish-file.d.ts +21 -0
- package/node_modules/@openclaw/fs-safe/dist/publish-file.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/publish-file.js +366 -0
- package/node_modules/@openclaw/fs-safe/dist/read-open-flags.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/read-open-flags.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/read-open-flags.js +13 -0
- package/node_modules/@openclaw/fs-safe/dist/read-opened-file.d.ts +21 -0
- package/node_modules/@openclaw/fs-safe/dist/read-opened-file.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/read-opened-file.js +18 -0
- package/node_modules/@openclaw/fs-safe/dist/regular-file.d.ts +38 -0
- package/node_modules/@openclaw/fs-safe/dist/regular-file.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/regular-file.js +391 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-directory.d.ts +7 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-directory.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-directory.js +42 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-fallback.d.ts +39 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-fallback.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-fallback.js +331 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-source.d.ts +21 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-source.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-source.js +107 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-descriptor.d.ts +51 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-descriptor.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-descriptor.js +161 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-rename-policy.d.ts +7 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-rename-policy.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-rename-policy.js +30 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-temp-owner.d.ts +53 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-temp-owner.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-temp-owner.js +376 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file.d.ts +58 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file.js +329 -0
- package/node_modules/@openclaw/fs-safe/dist/root-context.d.ts +38 -0
- package/node_modules/@openclaw/fs-safe/dist/root-context.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-context.js +141 -0
- package/node_modules/@openclaw/fs-safe/dist/root-errors.d.ts +12 -0
- package/node_modules/@openclaw/fs-safe/dist/root-errors.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-errors.js +75 -0
- package/node_modules/@openclaw/fs-safe/dist/root-file.d.ts +45 -0
- package/node_modules/@openclaw/fs-safe/dist/root-file.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-file.js +120 -0
- package/node_modules/@openclaw/fs-safe/dist/root-impl.d.ts +163 -0
- package/node_modules/@openclaw/fs-safe/dist/root-impl.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-impl.js +1230 -0
- package/node_modules/@openclaw/fs-safe/dist/root-path-existing.d.ts +3 -0
- package/node_modules/@openclaw/fs-safe/dist/root-path-existing.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-path-existing.js +68 -0
- package/node_modules/@openclaw/fs-safe/dist/root-path-symlink.d.ts +7 -0
- package/node_modules/@openclaw/fs-safe/dist/root-path-symlink.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-path-symlink.js +35 -0
- package/node_modules/@openclaw/fs-safe/dist/root-path.d.ts +40 -0
- package/node_modules/@openclaw/fs-safe/dist/root-path.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-path.js +481 -0
- package/node_modules/@openclaw/fs-safe/dist/root-paths.d.ts +89 -0
- package/node_modules/@openclaw/fs-safe/dist/root-paths.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-paths.js +381 -0
- package/node_modules/@openclaw/fs-safe/dist/root-walk.d.ts +41 -0
- package/node_modules/@openclaw/fs-safe/dist/root-walk.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-walk.js +133 -0
- package/node_modules/@openclaw/fs-safe/dist/root-write-mode.d.ts +6 -0
- package/node_modules/@openclaw/fs-safe/dist/root-write-mode.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-write-mode.js +61 -0
- package/node_modules/@openclaw/fs-safe/dist/root-write-verification.d.ts +12 -0
- package/node_modules/@openclaw/fs-safe/dist/root-write-verification.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-write-verification.js +97 -0
- package/node_modules/@openclaw/fs-safe/dist/root.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/root.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/safe-path-segment.d.ts +12 -0
- package/node_modules/@openclaw/fs-safe/dist/safe-path-segment.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/safe-path-segment.js +75 -0
- package/node_modules/@openclaw/fs-safe/dist/secret-file.d.ts +25 -0
- package/node_modules/@openclaw/fs-safe/dist/secret-file.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/secret-file.js +329 -0
- package/node_modules/@openclaw/fs-safe/dist/secret-read-async.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/secret-read-async.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/secret-read-async.js +73 -0
- package/node_modules/@openclaw/fs-safe/dist/secret-read-policy.d.ts +17 -0
- package/node_modules/@openclaw/fs-safe/dist/secret-read-policy.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/secret-read-policy.js +40 -0
- package/node_modules/@openclaw/fs-safe/dist/secret.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/secret.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/secret.js +3 -0
- package/node_modules/@openclaw/fs-safe/dist/secure-file.d.ts +32 -0
- package/node_modules/@openclaw/fs-safe/dist/secure-file.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/secure-file.js +182 -0
- package/node_modules/@openclaw/fs-safe/dist/secure-temp-dir.d.ts +27 -0
- package/node_modules/@openclaw/fs-safe/dist/secure-temp-dir.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/secure-temp-dir.js +160 -0
- package/node_modules/@openclaw/fs-safe/dist/sibling-staged-file.d.ts +15 -0
- package/node_modules/@openclaw/fs-safe/dist/sibling-staged-file.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/sibling-staged-file.js +143 -0
- package/node_modules/@openclaw/fs-safe/dist/sibling-temp.d.ts +27 -0
- package/node_modules/@openclaw/fs-safe/dist/sibling-temp.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/sibling-temp.js +95 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-acquire.d.ts +31 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-acquire.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-acquire.js +336 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-handle.d.ts +24 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-handle.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-handle.js +42 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-policy.d.ts +14 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-policy.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-policy.js +71 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.d.ts +63 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.js +305 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-root.d.ts +3 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-root.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-root.js +76 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-types.d.ts +63 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-types.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-types.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock.d.ts +14 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock.js +265 -0
- package/node_modules/@openclaw/fs-safe/dist/staged-directory.d.ts +16 -0
- package/node_modules/@openclaw/fs-safe/dist/staged-directory.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/staged-directory.js +60 -0
- package/node_modules/@openclaw/fs-safe/dist/staged-file-types.d.ts +56 -0
- package/node_modules/@openclaw/fs-safe/dist/staged-file-types.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/staged-file-types.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/store.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/store.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/store.js +3 -0
- package/node_modules/@openclaw/fs-safe/dist/strict-file-identity.d.ts +6 -0
- package/node_modules/@openclaw/fs-safe/dist/strict-file-identity.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/strict-file-identity.js +51 -0
- package/node_modules/@openclaw/fs-safe/dist/string-coerce.d.ts +5 -0
- package/node_modules/@openclaw/fs-safe/dist/string-coerce.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/string-coerce.js +16 -0
- package/node_modules/@openclaw/fs-safe/dist/suppressed-error.d.ts +6 -0
- package/node_modules/@openclaw/fs-safe/dist/suppressed-error.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/suppressed-error.js +15 -0
- package/node_modules/@openclaw/fs-safe/dist/symlink-parents.d.ts +12 -0
- package/node_modules/@openclaw/fs-safe/dist/symlink-parents.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/symlink-parents.js +78 -0
- package/node_modules/@openclaw/fs-safe/dist/temp-cleanup.d.ts +14 -0
- package/node_modules/@openclaw/fs-safe/dist/temp-cleanup.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/temp-cleanup.js +87 -0
- package/node_modules/@openclaw/fs-safe/dist/temp-target.d.ts +28 -0
- package/node_modules/@openclaw/fs-safe/dist/temp-target.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/temp-target.js +137 -0
- package/node_modules/@openclaw/fs-safe/dist/temp-workspace-owner.d.ts +23 -0
- package/node_modules/@openclaw/fs-safe/dist/temp-workspace-owner.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/temp-workspace-owner.js +320 -0
- package/node_modules/@openclaw/fs-safe/dist/temp.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/temp.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/temp.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/test-hooks.d.ts +25 -0
- package/node_modules/@openclaw/fs-safe/dist/test-hooks.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/test-hooks.js +13 -0
- package/node_modules/@openclaw/fs-safe/dist/text-atomic.d.ts +14 -0
- package/node_modules/@openclaw/fs-safe/dist/text-atomic.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/text-atomic.js +14 -0
- package/node_modules/@openclaw/fs-safe/dist/timing.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/timing.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/timing.js +40 -0
- package/node_modules/@openclaw/fs-safe/dist/trash.d.ts +5 -0
- package/node_modules/@openclaw/fs-safe/dist/trash.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/trash.js +171 -0
- package/node_modules/@openclaw/fs-safe/dist/types.d.ts +23 -0
- package/node_modules/@openclaw/fs-safe/dist/types.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/types.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/walk.d.ts +37 -0
- package/node_modules/@openclaw/fs-safe/dist/walk.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/walk.js +207 -0
- package/node_modules/@openclaw/fs-safe/dist/windows-command.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/windows-command.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/windows-command.js +34 -0
- package/node_modules/@openclaw/fs-safe/dist/windows-owner.d.ts +32 -0
- package/node_modules/@openclaw/fs-safe/dist/windows-owner.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/windows-owner.js +126 -0
- package/node_modules/@openclaw/fs-safe/dist/write-open-flags.d.ts +5 -0
- package/node_modules/@openclaw/fs-safe/dist/write-open-flags.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/write-open-flags.js +35 -0
- package/node_modules/@openclaw/fs-safe/dist/write-queue.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/write-queue.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/write-queue.js +18 -0
- package/node_modules/@openclaw/fs-safe/docs/advanced.md +153 -0
- package/node_modules/@openclaw/fs-safe/docs/archive.md +658 -0
- package/node_modules/@openclaw/fs-safe/docs/assets/readme-banner.jpg +0 -0
- package/node_modules/@openclaw/fs-safe/docs/atomic.md +334 -0
- package/node_modules/@openclaw/fs-safe/docs/config.md +131 -0
- package/node_modules/@openclaw/fs-safe/docs/contributing.md +180 -0
- package/node_modules/@openclaw/fs-safe/docs/durability.md +313 -0
- package/node_modules/@openclaw/fs-safe/docs/errors.md +232 -0
- package/node_modules/@openclaw/fs-safe/docs/file-store.md +258 -0
- package/node_modules/@openclaw/fs-safe/docs/filename.md +96 -0
- package/node_modules/@openclaw/fs-safe/docs/index.md +84 -0
- package/node_modules/@openclaw/fs-safe/docs/install-path.md +170 -0
- package/node_modules/@openclaw/fs-safe/docs/install.md +163 -0
- package/node_modules/@openclaw/fs-safe/docs/json-store.md +221 -0
- package/node_modules/@openclaw/fs-safe/docs/json.md +213 -0
- package/node_modules/@openclaw/fs-safe/docs/local-roots.md +141 -0
- package/node_modules/@openclaw/fs-safe/docs/migrating-to-0.5.md +196 -0
- package/node_modules/@openclaw/fs-safe/docs/migrating-to-0.6.md +43 -0
- package/node_modules/@openclaw/fs-safe/docs/native-helper.md +118 -0
- package/node_modules/@openclaw/fs-safe/docs/native.md +196 -0
- package/node_modules/@openclaw/fs-safe/docs/output.md +139 -0
- package/node_modules/@openclaw/fs-safe/docs/path-scope.md +159 -0
- package/node_modules/@openclaw/fs-safe/docs/path.md +208 -0
- package/node_modules/@openclaw/fs-safe/docs/permissions.md +200 -0
- package/node_modules/@openclaw/fs-safe/docs/private-file-store.md +54 -0
- package/node_modules/@openclaw/fs-safe/docs/public-api.md +112 -0
- package/node_modules/@openclaw/fs-safe/docs/quickstart.md +154 -0
- package/node_modules/@openclaw/fs-safe/docs/reading.md +183 -0
- package/node_modules/@openclaw/fs-safe/docs/regular-file.md +190 -0
- package/node_modules/@openclaw/fs-safe/docs/root.md +266 -0
- package/node_modules/@openclaw/fs-safe/docs/secret-file.md +273 -0
- package/node_modules/@openclaw/fs-safe/docs/secure-file.md +100 -0
- package/node_modules/@openclaw/fs-safe/docs/security-model.md +188 -0
- package/node_modules/@openclaw/fs-safe/docs/sidecar-lock.md +439 -0
- package/node_modules/@openclaw/fs-safe/docs/staged-file.md +182 -0
- package/node_modules/@openclaw/fs-safe/docs/store.md +94 -0
- package/node_modules/@openclaw/fs-safe/docs/temp.md +476 -0
- package/node_modules/@openclaw/fs-safe/docs/test-hooks.md +96 -0
- package/node_modules/@openclaw/fs-safe/docs/testing.md +189 -0
- package/node_modules/@openclaw/fs-safe/docs/timing.md +121 -0
- package/node_modules/@openclaw/fs-safe/docs/types.md +188 -0
- package/node_modules/@openclaw/fs-safe/docs/walk.md +128 -0
- package/node_modules/@openclaw/fs-safe/docs/writing.md +347 -0
- package/node_modules/@openclaw/fs-safe/package.json +187 -0
- package/node_modules/@openclaw/fs-safe-darwin-arm64/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-darwin-arm64/package.json +29 -0
- package/node_modules/@openclaw/fs-safe-darwin-x64/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-darwin-x64/package.json +29 -0
- package/node_modules/@openclaw/fs-safe-linux-arm64-gnu/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-arm64-gnu/package.json +32 -0
- package/node_modules/@openclaw/fs-safe-linux-arm64-musl/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-arm64-musl/package.json +32 -0
- package/node_modules/@openclaw/fs-safe-linux-x64-gnu/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-x64-gnu/package.json +32 -0
- package/node_modules/@openclaw/fs-safe-linux-x64-musl/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-x64-musl/package.json +32 -0
- package/node_modules/@openclaw/fs-safe-win32-x64-msvc/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-win32-x64-msvc/package.json +29 -0
- package/node_modules/core-util-is/LICENSE +19 -0
- package/node_modules/core-util-is/README.md +3 -0
- package/node_modules/core-util-is/lib/util.js +107 -0
- package/node_modules/core-util-is/package.json +38 -0
- package/node_modules/immediate/LICENSE.txt +20 -0
- package/node_modules/immediate/README.md +93 -0
- package/node_modules/immediate/dist/immediate.js +75 -0
- package/node_modules/immediate/dist/immediate.min.js +1 -0
- package/node_modules/immediate/lib/browser.js +69 -0
- package/node_modules/immediate/lib/index.js +73 -0
- package/node_modules/immediate/package.json +42 -0
- package/node_modules/inherits/LICENSE +16 -0
- package/node_modules/inherits/README.md +42 -0
- package/node_modules/inherits/inherits.js +9 -0
- package/node_modules/inherits/inherits_browser.js +27 -0
- package/node_modules/inherits/package.json +29 -0
- package/node_modules/isarray/.npmignore +1 -0
- package/node_modules/isarray/.travis.yml +4 -0
- package/node_modules/isarray/Makefile +6 -0
- package/node_modules/isarray/README.md +60 -0
- package/node_modules/isarray/component.json +19 -0
- package/node_modules/isarray/index.js +5 -0
- package/node_modules/isarray/package.json +45 -0
- package/node_modules/isarray/test.js +20 -0
- package/node_modules/jszip/.codeclimate.yml +16 -0
- package/node_modules/jszip/.editorconfig +8 -0
- package/node_modules/jszip/.eslintrc.js +43 -0
- package/node_modules/jszip/.github/workflows/pr.yaml +58 -0
- package/node_modules/jszip/.jekyll-metadata +0 -0
- package/node_modules/jszip/.travis.yml +17 -0
- package/node_modules/jszip/CHANGES.md +204 -0
- package/node_modules/jszip/LICENSE.markdown +651 -0
- package/node_modules/jszip/README.markdown +33 -0
- package/node_modules/jszip/deps.js +37 -0
- package/node_modules/jszip/dist/jszip.js +11577 -0
- package/node_modules/jszip/dist/jszip.min.js +13 -0
- package/node_modules/jszip/graph.svg +601 -0
- package/node_modules/jszip/index.d.ts +330 -0
- package/node_modules/jszip/lib/base64.js +106 -0
- package/node_modules/jszip/lib/compressedObject.js +74 -0
- package/node_modules/jszip/lib/compressions.js +14 -0
- package/node_modules/jszip/lib/crc32.js +77 -0
- package/node_modules/jszip/lib/defaults.js +11 -0
- package/node_modules/jszip/lib/external.js +18 -0
- package/node_modules/jszip/lib/flate.js +85 -0
- package/node_modules/jszip/lib/generate/ZipFileWorker.js +539 -0
- package/node_modules/jszip/lib/generate/index.js +57 -0
- package/node_modules/jszip/lib/index.js +55 -0
- package/node_modules/jszip/lib/license_header.js +11 -0
- package/node_modules/jszip/lib/load.js +88 -0
- package/node_modules/jszip/lib/nodejs/NodejsStreamInputAdapter.js +74 -0
- package/node_modules/jszip/lib/nodejs/NodejsStreamOutputAdapter.js +42 -0
- package/node_modules/jszip/lib/nodejsUtils.js +57 -0
- package/node_modules/jszip/lib/object.js +384 -0
- package/node_modules/jszip/lib/readable-stream-browser.js +10 -0
- package/node_modules/jszip/lib/reader/ArrayReader.js +57 -0
- package/node_modules/jszip/lib/reader/DataReader.js +116 -0
- package/node_modules/jszip/lib/reader/NodeBufferReader.js +19 -0
- package/node_modules/jszip/lib/reader/StringReader.js +38 -0
- package/node_modules/jszip/lib/reader/Uint8ArrayReader.js +22 -0
- package/node_modules/jszip/lib/reader/readerFor.js +28 -0
- package/node_modules/jszip/lib/signature.js +7 -0
- package/node_modules/jszip/lib/stream/ConvertWorker.js +26 -0
- package/node_modules/jszip/lib/stream/Crc32Probe.js +24 -0
- package/node_modules/jszip/lib/stream/DataLengthProbe.js +29 -0
- package/node_modules/jszip/lib/stream/DataWorker.js +116 -0
- package/node_modules/jszip/lib/stream/GenericWorker.js +263 -0
- package/node_modules/jszip/lib/stream/StreamHelper.js +214 -0
- package/node_modules/jszip/lib/support.js +38 -0
- package/node_modules/jszip/lib/utf8.js +275 -0
- package/node_modules/jszip/lib/utils.js +501 -0
- package/node_modules/jszip/lib/zipEntries.js +261 -0
- package/node_modules/jszip/lib/zipEntry.js +293 -0
- package/node_modules/jszip/lib/zipObject.js +133 -0
- package/node_modules/jszip/package.json +67 -0
- package/node_modules/jszip/sponsors.md +21 -0
- package/node_modules/jszip/tsconfig.json +101 -0
- package/node_modules/jszip/vendor/FileSaver.js +247 -0
- package/node_modules/lie/README.md +62 -0
- package/node_modules/lie/dist/lie.js +350 -0
- package/node_modules/lie/dist/lie.min.js +1 -0
- package/node_modules/lie/dist/lie.polyfill.js +358 -0
- package/node_modules/lie/dist/lie.polyfill.min.js +1 -0
- package/node_modules/lie/lib/browser.js +273 -0
- package/node_modules/lie/lib/index.js +298 -0
- package/node_modules/lie/license.md +7 -0
- package/node_modules/lie/lie.d.ts +244 -0
- package/node_modules/lie/package.json +69 -0
- package/node_modules/lie/polyfill.js +4 -0
- package/node_modules/pako/CHANGELOG.md +164 -0
- package/node_modules/pako/LICENSE +21 -0
- package/node_modules/pako/README.md +191 -0
- package/node_modules/pako/dist/pako.js +6818 -0
- package/node_modules/pako/dist/pako.min.js +1 -0
- package/node_modules/pako/dist/pako_deflate.js +3997 -0
- package/node_modules/pako/dist/pako_deflate.min.js +1 -0
- package/node_modules/pako/dist/pako_inflate.js +3300 -0
- package/node_modules/pako/dist/pako_inflate.min.js +1 -0
- package/node_modules/pako/index.js +14 -0
- package/node_modules/pako/lib/deflate.js +400 -0
- package/node_modules/pako/lib/inflate.js +423 -0
- package/node_modules/pako/lib/utils/common.js +105 -0
- package/node_modules/pako/lib/utils/strings.js +187 -0
- package/node_modules/pako/lib/zlib/README +59 -0
- package/node_modules/pako/lib/zlib/adler32.js +51 -0
- package/node_modules/pako/lib/zlib/constants.js +68 -0
- package/node_modules/pako/lib/zlib/crc32.js +59 -0
- package/node_modules/pako/lib/zlib/deflate.js +1874 -0
- package/node_modules/pako/lib/zlib/gzheader.js +58 -0
- package/node_modules/pako/lib/zlib/inffast.js +345 -0
- package/node_modules/pako/lib/zlib/inflate.js +1556 -0
- package/node_modules/pako/lib/zlib/inftrees.js +343 -0
- package/node_modules/pako/lib/zlib/messages.js +32 -0
- package/node_modules/pako/lib/zlib/trees.js +1222 -0
- package/node_modules/pako/lib/zlib/zstream.js +47 -0
- package/node_modules/pako/package.json +44 -0
- package/node_modules/process-nextick-args/index.js +45 -0
- package/node_modules/process-nextick-args/license.md +19 -0
- package/node_modules/process-nextick-args/package.json +25 -0
- package/node_modules/process-nextick-args/readme.md +18 -0
- package/node_modules/readable-stream/.travis.yml +34 -0
- package/node_modules/readable-stream/CONTRIBUTING.md +38 -0
- package/node_modules/readable-stream/GOVERNANCE.md +136 -0
- package/node_modules/readable-stream/LICENSE +47 -0
- package/node_modules/readable-stream/README.md +58 -0
- package/node_modules/readable-stream/doc/wg-meetings/2015-01-30.md +60 -0
- package/node_modules/readable-stream/duplex-browser.js +1 -0
- package/node_modules/readable-stream/duplex.js +1 -0
- package/node_modules/readable-stream/lib/_stream_duplex.js +131 -0
- package/node_modules/readable-stream/lib/_stream_passthrough.js +47 -0
- package/node_modules/readable-stream/lib/_stream_readable.js +1019 -0
- package/node_modules/readable-stream/lib/_stream_transform.js +214 -0
- package/node_modules/readable-stream/lib/_stream_writable.js +685 -0
- package/node_modules/readable-stream/lib/internal/streams/BufferList.js +78 -0
- package/node_modules/readable-stream/lib/internal/streams/destroy.js +84 -0
- package/node_modules/readable-stream/lib/internal/streams/stream-browser.js +1 -0
- package/node_modules/readable-stream/lib/internal/streams/stream.js +1 -0
- package/node_modules/readable-stream/package.json +52 -0
- package/node_modules/readable-stream/passthrough.js +1 -0
- package/node_modules/readable-stream/readable-browser.js +7 -0
- package/node_modules/readable-stream/readable.js +19 -0
- package/node_modules/readable-stream/transform.js +1 -0
- package/node_modules/readable-stream/writable-browser.js +1 -0
- package/node_modules/readable-stream/writable.js +8 -0
- package/node_modules/safe-buffer/LICENSE +21 -0
- package/node_modules/safe-buffer/README.md +584 -0
- package/node_modules/safe-buffer/index.d.ts +187 -0
- package/node_modules/safe-buffer/index.js +62 -0
- package/node_modules/safe-buffer/package.json +37 -0
- package/node_modules/setimmediate/LICENSE.txt +20 -0
- package/node_modules/setimmediate/package.json +30 -0
- package/node_modules/setimmediate/setImmediate.js +186 -0
- package/node_modules/string_decoder/.travis.yml +50 -0
- package/node_modules/string_decoder/LICENSE +48 -0
- package/node_modules/string_decoder/README.md +47 -0
- package/node_modules/string_decoder/lib/string_decoder.js +296 -0
- package/node_modules/string_decoder/package.json +31 -0
- package/node_modules/util-deprecate/History.md +16 -0
- package/node_modules/util-deprecate/LICENSE +24 -0
- package/node_modules/util-deprecate/README.md +53 -0
- package/node_modules/util-deprecate/browser.js +67 -0
- package/node_modules/util-deprecate/node.js +6 -0
- package/node_modules/util-deprecate/package.json +27 -0
- package/package.json +6 -4
- /package/node_modules/{p-limit/node_modules/yocto-queue → yocto-queue}/index.d.ts +0 -0
- /package/node_modules/{p-limit/node_modules/yocto-queue → yocto-queue}/index.js +0 -0
- /package/node_modules/{p-limit/node_modules/yocto-queue → yocto-queue}/license +0 -0
- /package/node_modules/{p-limit/node_modules/yocto-queue → yocto-queue}/package.json +0 -0
- /package/node_modules/{p-limit/node_modules/yocto-queue → yocto-queue}/readme.md +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 openclaw
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,564 @@
|
|
|
1
|
+
# 🛡️ @openclaw/fs-safe
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@openclaw/fs-safe)
|
|
6
|
+
[](https://github.com/openclaw/fs-safe/actions/workflows/ci.yml)
|
|
7
|
+
[](https://nodejs.org)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
[](https://fs-safe.io)
|
|
10
|
+
|
|
11
|
+
Capability-style filesystem roots for Node.js apps that handle untrusted relative paths.
|
|
12
|
+
|
|
13
|
+
Think Go's `os.Root` / `OpenInRoot` or Rust's [`cap-std`](https://github.com/bytecodealliance/cap-std), but for Node. Hand `root()` a trusted directory and you get back a handle whose every method resolves relative paths against it and defends against `..`, symlink swaps, hardlink aliases, and TOCTOU rename races. The exact containment strength is reported per mechanism: Linux native opens are kernel-atomic; macOS, Windows, and JavaScript paths are best-effort.
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { root } from "@openclaw/fs-safe";
|
|
17
|
+
|
|
18
|
+
const fs = await root("/safe/workspace");
|
|
19
|
+
await fs.write("notes/today.txt", "hello\n"); // ok
|
|
20
|
+
await fs.write("../escape.txt", "x"); // throws FsSafeError("outside-workspace")
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
That's the whole pitch. `root()` is the product; the rest of the package — JSON stores, atomic writes, secret files, archive extraction, temp workspaces — is supporting cast for the same boundary.
|
|
24
|
+
|
|
25
|
+
Full docs and reference at **[fs-safe.io](https://fs-safe.io)**.
|
|
26
|
+
|
|
27
|
+
## Contents
|
|
28
|
+
|
|
29
|
+
[Why this exists](#why-this-exists) · [Not a sandbox](#not-a-sandbox) · [Install](#install) · [0.6 migration](docs/migrating-to-0.6.md) · [Python migration](#migrating-from-the-python-helper) · [Quick start](#quick-start) · [Reading](#reading) · [Subpaths](#subpaths) · [Failure semantics](#failure-semantics-in-the-name) · [Directory durability](#directory-durability) · [Atomic writes](#atomic-writes) · [External outputs](#external-outputs) · [Stores](#stores) · [Secure absolute reads](#secure-absolute-file-reads) · [Walking](#directory-walking) · [Archive extraction](#archive-extraction) · [Path scopes](#advanced-path-scopes) · [Errors](#errors) · [Safety model](#safety-model) · [Limitations](#limitations)
|
|
30
|
+
|
|
31
|
+
## Why this exists
|
|
32
|
+
|
|
33
|
+
Most Node code that has to touch caller-controlled paths reaches for:
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
path.resolve(root, input).startsWith(root)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
That validates a *string*. It does not pin the file you opened, defend against a symlink retarget between check and use, reject hardlinked aliases of out-of-tree inodes, or verify that a write landed where you intended after a rename. The pieces to do those things exist scattered across the ecosystem — [`write-file-atomic`](https://www.npmjs.com/package/write-file-atomic) for atomic writes, `tar` / `jszip` for archive extraction, various `safefs`-style convenience wrappers — but none of them give you one root handle with traversal-resistant semantics across every operation.
|
|
40
|
+
|
|
41
|
+
The same idea has landed in other languages. Go [added `os.Root` and `OpenInRoot`](https://go.dev/blog/osroot); Rust has had [`cap-std`](https://github.com/bytecodealliance/cap-std) for years. Node's `fs` is path-string-oriented and exposes flags like `O_NOFOLLOW` but not an ergonomic "operate inside this root" API. `fs-safe` fills that gap.
|
|
42
|
+
|
|
43
|
+
| | Root boundary | Atomic writes | Symlink/hardlink defense | TOCTOU resistance | Archive extraction |
|
|
44
|
+
|---|---|---|---|---|---|
|
|
45
|
+
| `path.resolve().startsWith()` | string check only | – | – | – | – |
|
|
46
|
+
| [`write-file-atomic`](https://www.npmjs.com/package/write-file-atomic) | – | ✓ | – | – | – |
|
|
47
|
+
| Go [`os.Root`](https://go.dev/blog/osroot) / Rust [`cap-std`](https://github.com/bytecodealliance/cap-std) | ✓ | platform | ✓ | ✓ | – |
|
|
48
|
+
| **`@openclaw/fs-safe`** | **✓** | **✓** | **✓** | **Linux atomic; others best-effort** | **✓ (ZIP/TAR; native zstd/bzip2)** |
|
|
49
|
+
|
|
50
|
+
## Not a sandbox
|
|
51
|
+
|
|
52
|
+
This is a **library-level guardrail**, not OS-level isolation. It does not replace containers, seccomp, AppArmor, or filesystem permissions. It is for code that already runs with the privileges of its workspace and wants to stop trivial path tricks from escaping it. If your threat model is a hostile process, you need OS isolation; if your threat model is "an agent, plugin, upload handler, or CLI will eventually be tricked into writing somewhere it shouldn't," `fs-safe` catches that. The [security model](docs/security-model.md) describes the exact Linux, macOS, Windows, and JavaScript fallback guarantees and race boundaries.
|
|
53
|
+
|
|
54
|
+
## Install
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
pnpm add @openclaw/fs-safe
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Node 22 or newer. Core root/path/json/temp helpers avoid framework dependencies. With all optional dependencies omitted, public subpaths remain safe to import and non-archive fallback-capable operations work in `auto` or `off`. Native-only features remain unavailable, and operations needing the binding in `require` mode fail with `helper-unavailable`. TAR/gzip fallback uses the bundled WASM build of the same Rust parser as native and works with optional dependencies omitted. ZIP fallback still needs optional `jszip`. See the [0.6 migration guide](docs/migrating-to-0.6.md).
|
|
61
|
+
|
|
62
|
+
The package installs one prebuilt native binding for the current supported target. It
|
|
63
|
+
supplies fd-relative and atomic no-replace primitives that Node does not expose
|
|
64
|
+
directly. Configure the lazy loader before first use when you need a strict
|
|
65
|
+
environment policy:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { configureFsSafeNative } from "@openclaw/fs-safe";
|
|
69
|
+
|
|
70
|
+
configureFsSafeNative({ mode: "auto" }); // default: native when available
|
|
71
|
+
configureFsSafeNative({ mode: "off" }); // guarded JavaScript only
|
|
72
|
+
configureFsSafeNative({ mode: "require" }); // fail closed if the binding is unavailable
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Native mode performs `write()`, `create()`, and `copyIn()` parent creation and
|
|
76
|
+
publication relative to pinned directory descriptors, including atomic
|
|
77
|
+
replacement. The JavaScript path selected by `off`, or by `auto` when no
|
|
78
|
+
binding can load, is explicitly best-effort: a same-privilege peer that can
|
|
79
|
+
replace a writable parent between its identity check and Node's pathname
|
|
80
|
+
mutation can redirect that mutation outside the root before the post-check
|
|
81
|
+
reports the escape. Use `require` when hostile concurrent mutation is in scope.
|
|
82
|
+
|
|
83
|
+
Equivalent env var: `FS_SAFE_NATIVE_MODE=auto|off|require`. The seven bindings
|
|
84
|
+
ship as exact-version optional packages filtered by OS, CPU, and Linux libc, so
|
|
85
|
+
a normal install receives only its matching binary. There are no postinstall
|
|
86
|
+
steps, runtime downloads, or consumer Rust builds. On a platform without a
|
|
87
|
+
published binding, or when optional dependencies are omitted, `auto` silently retains lexical and canonical root
|
|
88
|
+
checks, no-follow opens, guarded temp+rename writes, and post-write identity
|
|
89
|
+
verification. See the [native
|
|
90
|
+
helper policy](docs/native-helper.md) for the exact boundary and deployment
|
|
91
|
+
tradeoff, and [native architecture](docs/native.md) for the platform mechanisms
|
|
92
|
+
and policy ownership model.
|
|
93
|
+
|
|
94
|
+
Open results report the mechanism's containment class as `"kernel-atomic"` or
|
|
95
|
+
`"best-effort"`. Linux native `openBeneath()` is kernel-atomic; macOS, Windows,
|
|
96
|
+
and guarded JavaScript results are best-effort. See the [security model](docs/security-model.md#containment-guarantees-by-platform) before using that fact in higher-level policy.
|
|
97
|
+
|
|
98
|
+
## Migrating from the Python helper
|
|
99
|
+
|
|
100
|
+
Version 0.5 replaces the persistent Python worker with prebuilt native
|
|
101
|
+
bindings. The modes map directly: `configureFsSafePython({ mode: "auto" })`
|
|
102
|
+
becomes `configureFsSafeNative({ mode: "auto" })`, and likewise for `off` and
|
|
103
|
+
`require`. Replace `FS_SAFE_PYTHON_MODE` with `FS_SAFE_NATIVE_MODE`; remove
|
|
104
|
+
`pythonPath`, `FS_SAFE_PYTHON`, and interpreter provisioning because the native
|
|
105
|
+
loader does not spawn Python.
|
|
106
|
+
|
|
107
|
+
Version 0.5 retains the old function and documented `FS_SAFE_PYTHON*`
|
|
108
|
+
and OpenClaw Python environment names emit one `FS_SAFE_PYTHON_DEPRECATED`
|
|
109
|
+
warning and map the old mode to its native equivalent. They are migration
|
|
110
|
+
bridges for shipped 0.4 consumers, not an alternate helper contract. Update
|
|
111
|
+
startup configuration as part of the 0.5 upgrade rather than relying on the
|
|
112
|
+
warning path. Follow the [0.5 migration checklist](docs/migrating-to-0.5.md).
|
|
113
|
+
|
|
114
|
+
## Quick start
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
import { root } from "@openclaw/fs-safe";
|
|
118
|
+
|
|
119
|
+
const fs = await root("/safe/workspace", {
|
|
120
|
+
hardlinks: "reject",
|
|
121
|
+
symlinks: "reject",
|
|
122
|
+
mkdir: true,
|
|
123
|
+
mode: 0o600,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
await fs.write("notes/today.txt", "hello\n");
|
|
127
|
+
const text = await fs.readText("notes/today.txt");
|
|
128
|
+
const config = await fs.readJson("config.json");
|
|
129
|
+
await fs.copyIn("uploads/upload.png", "/tmp/upload.png");
|
|
130
|
+
await fs.move("notes/today.txt", "notes/archive/today.txt", { overwrite: true });
|
|
131
|
+
await fs.remove("notes/archive/today.txt");
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`root()` takes the trusted directory; relative paths in subsequent calls are resolved against it. Defaults you pass to `root()` apply to every call below; per-call options override them.
|
|
135
|
+
|
|
136
|
+
When you need metadata or a `FileHandle`:
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
const { buffer, realPath, stat } = await fs.read("notes/today.txt");
|
|
140
|
+
const opened = await fs.open("notes/today.txt");
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
`create()` is the don't-clobber variant of `write()` and throws `already-exists` when the target already exists:
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
await fs.create("notes/README.md", "seed\n"); // throws if it already exists
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
`write()` replaces file contents by default; pass `{ overwrite: false }` or use `create()` when an existing file should be an error. `move()` defaults to no clobber because it can otherwise delete an unrelated target while also consuming the source. Pass `{ overwrite: true }` when replacing the target is intended.
|
|
150
|
+
|
|
151
|
+
Use `ensureRoot()` when a computed relative directory target resolves to the root itself (`""` or `"."`) and you want the operation to be accepted. `root()` still requires the trusted root directory to already exist.
|
|
152
|
+
|
|
153
|
+
## Reading
|
|
154
|
+
|
|
155
|
+
Pick the narrowest read shape that gives you what you need:
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
await fs.readJson("config.json"); // parsed value; validate it at your boundary
|
|
159
|
+
await fs.readText("notes/today.txt");
|
|
160
|
+
await fs.readBytes("image.png");
|
|
161
|
+
await fs.read("notes/today.txt"); // { buffer, realPath, stat }
|
|
162
|
+
const opened = await fs.open("large.log"); // FileHandle for streaming
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
For streams, use `open()` and the returned `FileHandle`:
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
await using opened = await fs.open("large.log");
|
|
169
|
+
{
|
|
170
|
+
const stream = opened.handle.createReadStream();
|
|
171
|
+
// consume stream
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Root reads default to `DEFAULT_ROOT_MAX_BYTES` (16 MiB). Pass a larger `maxBytes`
|
|
176
|
+
for expected large reads, or `Number.POSITIVE_INFINITY` when the caller has a
|
|
177
|
+
separate size budget.
|
|
178
|
+
|
|
179
|
+
`reader()` returns a callback that reads absolute or relative paths through the same root boundary. It is useful for APIs that accept a `(path) => Promise<Buffer>` loader. For roots configured through a directory symlink or Windows junction, absolute inputs may use either the configured spelling or the canonical real path. Absolute paths outside the root are rejected with `outside-workspace`. `readAbsolute()` has the same absolute-path behavior directly.
|
|
180
|
+
|
|
181
|
+
When you need a writable `FileHandle`, use `openWritable()` and prefer `await using` for cleanup:
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
await using opened = await fs.openWritable("logs/current.log", { writeMode: "append" });
|
|
185
|
+
{
|
|
186
|
+
await opened.handle.appendFile("line\n");
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
`nonBlockingRead` remains as a compatibility hint in `RootDefaults`. Safe read/open operations already use nonblocking descriptor opens where the platform supports them so a raced FIFO cannot pin a worker; filesystem safety policy remains explicit through `hardlinks`, `symlinks`, and `denyMutations`.
|
|
191
|
+
|
|
192
|
+
On POSIX, `openWritable()` also uses nonblocking admission for existing targets
|
|
193
|
+
so a no-reader FIFO cannot stall validation. Ordinary regular-file write
|
|
194
|
+
semantics are unchanged; see [writing](docs/writing.md#openwritable-for-streaming).
|
|
195
|
+
|
|
196
|
+
```ts
|
|
197
|
+
const locked = await root("/srv/workspace", {
|
|
198
|
+
denyMutations: {
|
|
199
|
+
paths: ["/srv/workspace/.env"],
|
|
200
|
+
prefixes: ["/srv/workspace/.ssh"],
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
await locked.write(".env", "token"); // FsSafeError code "denied-path"
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
`stat()`, `exists()`, and `list()` are boundary-checked, but they cannot pin a later operation to the same filesystem object. Use `read()`, `open()`, `write()`, `create()`, `copyIn()`, `move()`, or `remove()` for operation-local identity checks, and inspect `containment` when the platform distinction matters.
|
|
208
|
+
|
|
209
|
+
## Subpaths
|
|
210
|
+
|
|
211
|
+
The main entry point collects the common root, config, output, lock, native-mode,
|
|
212
|
+
and error exports. Prefer focused subpaths when a consumer needs a narrower
|
|
213
|
+
contract. Low-level helpers that OpenClaw needs to compose higher-level APIs are grouped under
|
|
214
|
+
`@openclaw/fs-safe/advanced` instead of being separate public leaf contracts.
|
|
215
|
+
|
|
216
|
+
| Subpath | Contents |
|
|
217
|
+
|---|---|
|
|
218
|
+
| `@openclaw/fs-safe/root` | `root()`, `Root`, `RootDefaults`, and root-bounded walking with pruning/error markers |
|
|
219
|
+
| `@openclaw/fs-safe/config` | process-global native helper and lock defaults |
|
|
220
|
+
| `@openclaw/fs-safe/path` | canonical path checks: `isPathInside`, `safeRealpathSync`, `isNotFoundPathError`, `isSymlinkOpenError` |
|
|
221
|
+
| `@openclaw/fs-safe/json` | `tryReadJson`, `readJson`, `readJsonIfExists`, `writeJson`, sync variants |
|
|
222
|
+
| `@openclaw/fs-safe/output` | `writeExternalFileWithinRoot` for external libraries that need a temp output path |
|
|
223
|
+
| `@openclaw/fs-safe/store` | `fileStore`, `fileStoreSync`, and `jsonStore` |
|
|
224
|
+
| `@openclaw/fs-safe/secret` | sync/async strict and try-style secret reads, atomic replace, and create-only secret writes |
|
|
225
|
+
| `@openclaw/fs-safe/atomic` | `replaceFileAtomic`, `replaceFileAtomicSync`, `replaceDirectoryAtomic`, `movePathWithCopyFallback` |
|
|
226
|
+
| `@openclaw/fs-safe/durability` | pinned directory identities, strict directory sync, durable nested-directory creation, exclusive publication, streaming SHA-256, provenance receipts, and sync-failure policy |
|
|
227
|
+
| `@openclaw/fs-safe/temp` | `tempWorkspace`, `tempWorkspaceSync`, `withTempWorkspace`, `resolveSecureTempRoot` |
|
|
228
|
+
| `@openclaw/fs-safe/secure-file` | fd-pinned absolute file reads with owner, mode, ACL, trusted-dir, size, and timeout checks |
|
|
229
|
+
| `@openclaw/fs-safe/file-lock` | async/sync sidecar locks, root-bounded sidecars, ownership verification, and stale policy |
|
|
230
|
+
| `@openclaw/fs-safe/permissions` | POSIX mode and Windows ACL inspection, raw owner/ACE facts, private-directory creation, and remediation helpers |
|
|
231
|
+
| `@openclaw/fs-safe/walk` | budget-bounded directory walking with symlink policy, filters, and truncation accounting; not root-bounded |
|
|
232
|
+
| `@openclaw/fs-safe/archive` | policy-driven ZIP/TAR extraction, clamp/filter policy, metadata/path-depth limits, native gzip/zstd/bzip2, and bounded entry reads |
|
|
233
|
+
| `@openclaw/fs-safe/advanced` | lower-level composition helpers such as path scopes, root-file open, bounded descriptor reads, install paths, filename sanitizing, temp-file targets, sibling-temp writes, local-root readers, regular-file helpers, `pathExists`, and `withTimeout`; less stable than focused public subpaths |
|
|
234
|
+
| `@openclaw/fs-safe/errors` | `FsSafeError`, closed codes/categories, causes, and operation-specific details receipts |
|
|
235
|
+
| `@openclaw/fs-safe/types` | shared types: `DirEntry`, `PathStat`, … |
|
|
236
|
+
| `@openclaw/fs-safe/test-hooks` | hooks the test suite uses to inject races; registration requires `NODE_ENV=test` or `VITEST=true` |
|
|
237
|
+
|
|
238
|
+
## Failure semantics in the name
|
|
239
|
+
|
|
240
|
+
When two helpers behave differently on the same input, the difference is in the name, not the docs.
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
import { readJson, tryReadJson } from "@openclaw/fs-safe/json";
|
|
244
|
+
|
|
245
|
+
await tryReadJson("./config.json"); // returns null on missing or invalid
|
|
246
|
+
await readJson("./manifest.json"); // throws on missing or invalid
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
For one-off structured reads under a trusted root, `readRootJsonObjectSync()`
|
|
250
|
+
performs the root-bounded open and JSON object validation in one step. Use
|
|
251
|
+
`readRootStructuredFileSync()` when the parser lives outside fs-safe, such as
|
|
252
|
+
JSON5-backed plugin manifests.
|
|
253
|
+
|
|
254
|
+
## Directory durability
|
|
255
|
+
|
|
256
|
+
```ts
|
|
257
|
+
import { ensureDurableDirectory, pinDirectory } from "@openclaw/fs-safe/durability";
|
|
258
|
+
|
|
259
|
+
const receipt = await ensureDurableDirectory({
|
|
260
|
+
directoryPath: "/srv/backups/sqlite",
|
|
261
|
+
mode: 0o700,
|
|
262
|
+
});
|
|
263
|
+
const pinned = await pinDirectory(receipt);
|
|
264
|
+
try {
|
|
265
|
+
await publishSnapshot();
|
|
266
|
+
const outcome = await pinned.sync();
|
|
267
|
+
// `unsupported` is explicit on platforms without directory flushing.
|
|
268
|
+
console.log(outcome.status);
|
|
269
|
+
} finally {
|
|
270
|
+
await pinned.close();
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
The durability subpath pins a directory descriptor to its pathname identity,
|
|
275
|
+
detects symlink/FIFO/replacement races, and synchronizes every new parent edge
|
|
276
|
+
when creating a nested directory. Strict sync propagates real I/O failures and
|
|
277
|
+
reports known Windows directory-flush limitations explicitly. Separate
|
|
278
|
+
best-effort helpers preserve operations that do not promise crash durability.
|
|
279
|
+
|
|
280
|
+
`publishFileExclusive()` adds no-clobber hardlink/copy/rename strategies and a
|
|
281
|
+
typed post-creation receipt. Its `onSyncFailure` policy defaults to
|
|
282
|
+
`"rollback"`; backup writers can choose `"preserve"` to keep a complete target
|
|
283
|
+
when parent-directory sync fails, then inspect `details.directorySync` and
|
|
284
|
+
retry or record the weaker durability state.
|
|
285
|
+
|
|
286
|
+
See [Directory durability](docs/durability.md) for the receipt, pin lifecycle,
|
|
287
|
+
publication policy, creation callback, and platform contract.
|
|
288
|
+
|
|
289
|
+
## Atomic writes
|
|
290
|
+
|
|
291
|
+
For preparation that must survive a parent rename until abort cleanup, use
|
|
292
|
+
[`stageFileInDirectory()`](docs/staged-file.md) from `advanced`. It retains the
|
|
293
|
+
original directory on Linux/macOS and requires native support for this operation.
|
|
294
|
+
It offers atomic replace/no-replace publication, not expected-inode replacement
|
|
295
|
+
or a crash-durability promise; application checks and coordination remain yours.
|
|
296
|
+
|
|
297
|
+
`replaceFileAtomic()` writes a sibling temp file, applies its exact mode through the still-open descriptor, optionally fsyncs it, and renames it over the destination. It never follows the published destination path to set file permissions. Mode preservation, pinned-destination hardlink rejection, rename retry / copy fallback on `EPERM`, bounded original-content restoration after a torn fallback, parent-directory fsync, and a `beforeRename` hook for backup or observer flows are all opt-in. `movePathWithCopyFallback()` stages cross-device moves before commit and removes only the copied source entries, so concurrent source additions or replacements are preserved. Its optional synchronous `assertBeforeMutation` hook rechecks caller authority before renames and each source removal; `onDestinationPublished` reports an exact bigint destination identity before later checks or cleanup can fail. See [mutation authority and publication receipts](docs/atomic.md#mutation-authority-and-publication-receipts).
|
|
298
|
+
|
|
299
|
+
```ts
|
|
300
|
+
import { replaceFileAtomic } from "@openclaw/fs-safe/atomic";
|
|
301
|
+
|
|
302
|
+
await replaceFileAtomic({
|
|
303
|
+
filePath: "/safe/workspace/state.json",
|
|
304
|
+
content: JSON.stringify(state, null, 2),
|
|
305
|
+
mode: 0o600,
|
|
306
|
+
syncTempFile: true,
|
|
307
|
+
syncParentDir: true,
|
|
308
|
+
});
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
`replaceFileAtomicSync()` covers the synchronous case with the same options shape. Both accept an injectable `fileSystem` for tests. Async adapters use `chmod()` on the `FileHandle` returned by their required `open()` operation; custom sync adapters using `mode` or `preserveExistingMode` provide the optional descriptor-bound `fchmodSync` operation.
|
|
312
|
+
|
|
313
|
+
## External outputs
|
|
314
|
+
|
|
315
|
+
Use `writeExternalFileWithinRoot()` when a browser download, renderer, media
|
|
316
|
+
tool, or native library needs an absolute path to write to:
|
|
317
|
+
|
|
318
|
+
```ts
|
|
319
|
+
import { writeExternalFileWithinRoot } from "@openclaw/fs-safe/output";
|
|
320
|
+
|
|
321
|
+
await writeExternalFileWithinRoot({
|
|
322
|
+
rootDir: "/safe/workspace/downloads",
|
|
323
|
+
path: "reports/today.pdf",
|
|
324
|
+
staging: "sibling",
|
|
325
|
+
write: async (filePath) => {
|
|
326
|
+
await download.saveAs(filePath);
|
|
327
|
+
},
|
|
328
|
+
});
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
The callback receives a staged path, not the final destination. The default
|
|
332
|
+
`"workspace"` mode uses private temp storage plus `Root.copyIn()` for
|
|
333
|
+
cross-device-tolerant finalization. `"sibling"` stages in the target directory,
|
|
334
|
+
fsyncs the completed file, and atomically renames it over the target. Choose it
|
|
335
|
+
when the destination directory is itself the writable boundary and atomic
|
|
336
|
+
replacement matters.
|
|
337
|
+
|
|
338
|
+
Use it when the final filename is known before the external writer runs. If the
|
|
339
|
+
filename depends on sniffing the produced bytes, write to a private temp
|
|
340
|
+
workspace first, then finalize through the normal root APIs after validation.
|
|
341
|
+
|
|
342
|
+
## Stores
|
|
343
|
+
|
|
344
|
+
Use `fileStore().json()` for small state files that need explicit fallback
|
|
345
|
+
reads, atomic writes, and optional sidecar locking around read-modify-write
|
|
346
|
+
updates:
|
|
347
|
+
|
|
348
|
+
```ts
|
|
349
|
+
import { fileStore } from "@openclaw/fs-safe/store";
|
|
350
|
+
|
|
351
|
+
const files = fileStore({ rootDir: "/safe/workspace/state", private: true });
|
|
352
|
+
const store = files.json("settings.json", { lock: true });
|
|
353
|
+
|
|
354
|
+
await store.updateOr({ enabled: false }, (current) => ({ ...current, enabled: true }));
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
`jsonStore({ filePath })` is the absolute-path convenience wrapper for the same
|
|
358
|
+
primitive.
|
|
359
|
+
|
|
360
|
+
Use `update()` when missing state is part of your model; use `updateOr()` for
|
|
361
|
+
the common merge-into-defaults case. Standalone helpers use options bags
|
|
362
|
+
because they do not carry a bound root and often need multiple authority, path,
|
|
363
|
+
and policy knobs.
|
|
364
|
+
|
|
365
|
+
Sidecar locks fail closed on stale holders by default. Opt-in `remove-if-unchanged`
|
|
366
|
+
recovery requires caller approval and serializes snapshot verification and unlink
|
|
367
|
+
with an exclusive reclaim guard so a replacement lock cannot be deleted; see the
|
|
368
|
+
[file lock docs](docs/sidecar-lock.md).
|
|
369
|
+
|
|
370
|
+
Use `fileStore()` for cache/blob/media-style directories where callers
|
|
371
|
+
need safe relative paths, size limits, atomic replacement, stream writes, and
|
|
372
|
+
TTL cleanup behind one root. Pass `private: true` for credentials, auth
|
|
373
|
+
profiles, tokens, and per-agent private state; private mode keeps the same
|
|
374
|
+
store shape while routing writes through the secret-file atomic path.
|
|
375
|
+
|
|
376
|
+
```ts
|
|
377
|
+
import { fileStore } from "@openclaw/fs-safe/store";
|
|
378
|
+
|
|
379
|
+
const media = fileStore({
|
|
380
|
+
rootDir: "/safe/workspace/media",
|
|
381
|
+
maxBytes: 5 * 1024 * 1024,
|
|
382
|
+
mode: 0o600,
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
await media.write("inbound/photo.jpg", bytes);
|
|
386
|
+
await media.writeJson("state/photo.json", { id: "photo" });
|
|
387
|
+
const cached = await media.readJsonIfExists("state/photo.json");
|
|
388
|
+
const opened = await media.open("inbound/photo.jpg");
|
|
389
|
+
await media.pruneExpired({ ttlMs: 10 * 60 * 1000, recursive: true });
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
The `store` subpath also includes durable JSON queue helpers for the common
|
|
393
|
+
"one JSON file per work item" pattern: atomic entry writes, pending-entry loads,
|
|
394
|
+
acknowledgement via `.delivered` markers, failed-entry moves, and stale temp
|
|
395
|
+
cleanup. Retry, dedupe, and transport semantics stay with the caller.
|
|
396
|
+
|
|
397
|
+
`tempWorkspace()` exposes `write()`, `writeText()`, `writeJson()`, `copyIn()`, and `read()` for
|
|
398
|
+
single-file scratch workflows without hand-rolled path joins, plus a `store: FileStore` view of
|
|
399
|
+
the workspace dir for the richer cases (`writeStream`, `readJsonIfExists`, `store.json<T>(rel)`).
|
|
400
|
+
Compatible creation and cleanup remain available without native support.
|
|
401
|
+
Set `cleanupSafety: "require-bounded"` to require collision-safe quarantine and
|
|
402
|
+
descriptor-bounded recursive cleanup before creating a child. See the
|
|
403
|
+
[temp workspace contract](docs/temp.md).
|
|
404
|
+
Linux bounded cleanup requires the exact `openat2`/`RESOLVE_NO_XDEV` capability
|
|
405
|
+
at runtime; compatible mode falls back when unavailable, while `require-bounded`
|
|
406
|
+
rejects before child creation.
|
|
407
|
+
|
|
408
|
+
`tempFile()` is the smaller one-file temp helper. It is intentionally an
|
|
409
|
+
advanced primitive: use `tempWorkspace()` for the stable temp surface and reach
|
|
410
|
+
for `tempFile()` only when you need a raw file target.
|
|
411
|
+
|
|
412
|
+
```ts
|
|
413
|
+
import { tempFile } from "@openclaw/fs-safe/advanced";
|
|
414
|
+
|
|
415
|
+
await using target = await tempFile({ prefix: "download", fileName: "payload.bin" });
|
|
416
|
+
await fs.promises.writeFile(target.path, bytes);
|
|
417
|
+
const checksumPath = target.file("payload.sha256");
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
## Secure absolute file reads
|
|
421
|
+
|
|
422
|
+
Use `readSecureFile()` when the caller gives you an absolute credential path
|
|
423
|
+
instead of a root-relative workspace path. It opens the file first, validates the
|
|
424
|
+
same handle it will read from, checks trusted directories, owner, POSIX mode or
|
|
425
|
+
Windows ACLs, hardlink count, size, and optional timeout, then reads through the
|
|
426
|
+
pinned handle.
|
|
427
|
+
|
|
428
|
+
```ts
|
|
429
|
+
import { readSecureFile } from "@openclaw/fs-safe/secure-file";
|
|
430
|
+
|
|
431
|
+
const { buffer } = await readSecureFile({
|
|
432
|
+
filePath: "/var/lib/app/token",
|
|
433
|
+
label: "auth token",
|
|
434
|
+
trust: { trustedDirs: ["/var/lib/app"] },
|
|
435
|
+
io: { maxBytes: 16 * 1024, timeoutMs: 5_000 },
|
|
436
|
+
});
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
Use `permissions: { allowInsecure: true }` only for migration or explicit local-development
|
|
440
|
+
flows where a warning is preferable to refusing the file.
|
|
441
|
+
|
|
442
|
+
## Directory walking
|
|
443
|
+
|
|
444
|
+
`walkDirectory()` and `walkDirectorySync()` replace ad-hoc recursive
|
|
445
|
+
`readdir()` loops with entry and depth budgets, a symlink policy, and stable
|
|
446
|
+
relative paths.
|
|
447
|
+
|
|
448
|
+
```ts
|
|
449
|
+
import { walkDirectory } from "@openclaw/fs-safe/walk";
|
|
450
|
+
|
|
451
|
+
const scan = await walkDirectory("/safe/workspace", {
|
|
452
|
+
maxDepth: 4,
|
|
453
|
+
maxEntries: 10_000,
|
|
454
|
+
symlinks: "skip",
|
|
455
|
+
include: (entry) => entry.kind === "file",
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
for (const file of scan.entries) {
|
|
459
|
+
console.log(file.relativePath);
|
|
460
|
+
}
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
Check `scan.truncated` before treating the result as complete, and `scan.failedDirs` to tell an incomplete scan (a directory that could not be read) from an empty one before pruning state from the listing.
|
|
464
|
+
|
|
465
|
+
For caller-controlled paths, `Root.walk()` is the root-bounded async iterator.
|
|
466
|
+
It supports entry/depth budgets, in-root symlink following, cancellation, and a
|
|
467
|
+
truncation marker (or typed error) when a budget is reached. Its `entryFilter`
|
|
468
|
+
can return `"skip-subtree"` to prune a directory, and
|
|
469
|
+
`onDirectoryError: "skip-and-report"` yields typed `"directory-error"` markers
|
|
470
|
+
while preserving entries from readable subtrees.
|
|
471
|
+
|
|
472
|
+
## Archive extraction
|
|
473
|
+
|
|
474
|
+
`extractArchive()` handles ZIP and TAR behind one API, with traversal checks, blocked-link-type rejection, and entry-count and byte budgets.
|
|
475
|
+
|
|
476
|
+
```ts
|
|
477
|
+
import { extractArchive, resolveArchiveKind } from "@openclaw/fs-safe/archive";
|
|
478
|
+
|
|
479
|
+
const kind = resolveArchiveKind(uploadPath);
|
|
480
|
+
if (!kind) throw new Error(`unsupported archive: ${uploadPath}`);
|
|
481
|
+
|
|
482
|
+
await extractArchive({
|
|
483
|
+
archivePath: uploadPath,
|
|
484
|
+
destDir: "/safe/workspace/plugin",
|
|
485
|
+
kind,
|
|
486
|
+
timeoutMs: 15_000,
|
|
487
|
+
limits: {
|
|
488
|
+
maxArchiveBytes: 256 * 1024 * 1024,
|
|
489
|
+
maxEntries: 50_000,
|
|
490
|
+
maxExtractedBytes: 512 * 1024 * 1024,
|
|
491
|
+
maxEntryBytes: 256 * 1024 * 1024,
|
|
492
|
+
maxEntryPathComponents: 64,
|
|
493
|
+
},
|
|
494
|
+
});
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
Extraction stages into a private directory and merges through the same safe-open boundary used by direct writes, so a symlinked entry can't trick the merge into following an out-of-tree path.
|
|
498
|
+
|
|
499
|
+
## Advanced path scopes
|
|
500
|
+
|
|
501
|
+
For code that already has a trusted absolute path and wants lower-level boundary
|
|
502
|
+
validation without going through `root()`:
|
|
503
|
+
|
|
504
|
+
```ts
|
|
505
|
+
import { pathScope } from "@openclaw/fs-safe/advanced";
|
|
506
|
+
|
|
507
|
+
const uploads = pathScope("/safe/uploads", { label: "uploads directory" });
|
|
508
|
+
const files = await uploads.files(["photo.jpg"]);
|
|
509
|
+
const target = await uploads.writable("report.pdf");
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
## Errors
|
|
513
|
+
|
|
514
|
+
Every failure surfaces as an `FsSafeError` with a closed `code` union you can branch on:
|
|
515
|
+
|
|
516
|
+
```ts
|
|
517
|
+
import { FsSafeError } from "@openclaw/fs-safe/errors";
|
|
518
|
+
|
|
519
|
+
try {
|
|
520
|
+
await fs.write("../escape.txt", "x");
|
|
521
|
+
} catch (err) {
|
|
522
|
+
if (err instanceof FsSafeError && err.code === "outside-workspace") {
|
|
523
|
+
// handle
|
|
524
|
+
}
|
|
525
|
+
throw err;
|
|
526
|
+
}
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
Codes are grouped by category:
|
|
530
|
+
|
|
531
|
+
```ts
|
|
532
|
+
if (err instanceof FsSafeError) {
|
|
533
|
+
if (err.category === "policy") {
|
|
534
|
+
// Unsafe caller input or filesystem state rejected by a safety policy.
|
|
535
|
+
} else {
|
|
536
|
+
// Routine filesystem outcome or runtime/environment problem.
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
Routine filesystem outcomes such as `not-found`, `not-empty`, and
|
|
542
|
+
`not-removable`, plus runtime failures such as `read-failed`, are operational;
|
|
543
|
+
they do not indicate that a filesystem
|
|
544
|
+
boundary policy was violated.
|
|
545
|
+
|
|
546
|
+
Current `FsSafeErrorCode` values are `already-exists`, `denied-path`, `device-path`, `hardlink`, `helper-failed`, `helper-unavailable`, `invalid-path`, `insecure-permissions`, `not-empty`, `not-file`, `not-found`, `not-owned`, `not-removable`, `outside-workspace`, `path-alias`, `path-mismatch`, `permission-unverified`, `read-failed`, `secret-exists`, `store-reentrant-update`, `symlink`, `timeout`, `too-large`, and `unsupported-platform`.
|
|
547
|
+
|
|
548
|
+
## Safety model
|
|
549
|
+
|
|
550
|
+
- root-bounded APIs resolve paths against a configured root and reject canonical escapes
|
|
551
|
+
- reads reject known unsafe device paths, open with `O_NOFOLLOW` where available, then verify fd identity matches the path identity before returning the buffer or handle
|
|
552
|
+
- create-only writes, sidecar acquisition, and exclusive publication prefer fd-relative native primitives, with verified guarded JavaScript fallbacks
|
|
553
|
+
- `remove`, `mkdir`, `move`, `stat`, and `list` retain guarded JavaScript implementations with pre/post identity checks
|
|
554
|
+
- archive extraction stages into a private directory and merges through the same boundary checks used by direct writes
|
|
555
|
+
|
|
556
|
+
## Limitations
|
|
557
|
+
|
|
558
|
+
- Windows native opens are handle-relative and reject reparse points; operations without native wiring use the guarded Node implementation.
|
|
559
|
+
- Hardlink rejection depends on platform metadata. Treat it as defense-in-depth, not authorization.
|
|
560
|
+
- `fs-safe` does not validate file contents or archive payload semantics beyond filesystem safety constraints. Schemas, signatures, and authorization belong in the layer above.
|
|
561
|
+
|
|
562
|
+
## License
|
|
563
|
+
|
|
564
|
+
MIT.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
If you believe you found a security issue in `@openclaw/fs-safe`, report it
|
|
4
|
+
privately.
|
|
5
|
+
|
|
6
|
+
## Reporting
|
|
7
|
+
|
|
8
|
+
Open a private report through
|
|
9
|
+
[GitHub Security Advisories](https://github.com/openclaw/fs-safe/security/advisories/new)
|
|
10
|
+
or email `security@openclaw.ai`.
|
|
11
|
+
|
|
12
|
+
Include:
|
|
13
|
+
|
|
14
|
+
1. affected version or commit
|
|
15
|
+
2. Node.js version, operating system, filesystem, and mount details
|
|
16
|
+
3. minimal reproduction
|
|
17
|
+
4. demonstrated impact
|
|
18
|
+
5. suggested remediation, if known
|
|
19
|
+
|
|
20
|
+
Do not open a public issue until maintainers have coordinated disclosure.
|
|
21
|
+
|
|
22
|
+
## Scope
|
|
23
|
+
|
|
24
|
+
Security issues in scope generally include:
|
|
25
|
+
|
|
26
|
+
- traversal or root-confinement bypasses
|
|
27
|
+
- symlink, hardlink, rename, or identity-swap races that cross a documented
|
|
28
|
+
filesystem boundary
|
|
29
|
+
- archive extraction outside the intended destination
|
|
30
|
+
- unsafe secret-file, permission, ownership, or temporary-file behavior
|
|
31
|
+
- package or release-pipeline compromise affecting the published package
|
|
32
|
+
|
|
33
|
+
Reports must demonstrate a concrete boundary bypass or impact. Applications
|
|
34
|
+
remain responsible for operating-system isolation, authorization, and choosing
|
|
35
|
+
trusted root directories unless this package documents and fails to enforce a
|
|
36
|
+
specific invariant.
|
|
37
|
+
|
|
38
|
+
## Operational Guidance
|
|
39
|
+
|
|
40
|
+
- Keep `@openclaw/fs-safe`, Node.js, and optional archive dependencies current.
|
|
41
|
+
- Treat pathnames and archive contents as untrusted.
|
|
42
|
+
- Use OS-level sandboxing when the threat model includes a hostile process.
|
|
43
|
+
- Pin and review dependency updates before publishing.
|
|
44
|
+
|
|
45
|
+
There is currently no paid bug bounty program.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { FsSafeError, type FsSafeErrorCode } from "./errors.js";
|
|
2
|
+
export type AbsolutePathSymlinkPolicy = "reject" | "follow";
|
|
3
|
+
export type ResolvedAbsolutePath = {
|
|
4
|
+
path: string;
|
|
5
|
+
canonicalPath: string;
|
|
6
|
+
};
|
|
7
|
+
export type ResolvedWritableAbsolutePath = ResolvedAbsolutePath & {
|
|
8
|
+
parentDir: string;
|
|
9
|
+
parentExists: boolean;
|
|
10
|
+
};
|
|
11
|
+
export type EnsureAbsoluteDirectoryOptions = {
|
|
12
|
+
scopeLabel?: string;
|
|
13
|
+
mode?: number;
|
|
14
|
+
};
|
|
15
|
+
export type EnsureAbsoluteDirectoryResult = {
|
|
16
|
+
ok: true;
|
|
17
|
+
path: string;
|
|
18
|
+
} | {
|
|
19
|
+
ok: false;
|
|
20
|
+
code: FsSafeErrorCode;
|
|
21
|
+
error: FsSafeError;
|
|
22
|
+
};
|
|
23
|
+
export declare function assertAbsolutePathInput(filePath: string): string;
|
|
24
|
+
export declare function findExistingAncestor(filePath: string): Promise<string | null>;
|
|
25
|
+
export declare function ensureAbsoluteDirectory(dirPath: string, options?: EnsureAbsoluteDirectoryOptions): Promise<EnsureAbsoluteDirectoryResult>;
|
|
26
|
+
export declare function canonicalPathFromExistingAncestor(filePath: string): Promise<string>;
|
|
27
|
+
export declare function resolveAbsolutePathForRead(filePath: string, options?: {
|
|
28
|
+
symlinks?: AbsolutePathSymlinkPolicy;
|
|
29
|
+
}): Promise<ResolvedAbsolutePath>;
|
|
30
|
+
export declare function resolveAbsolutePathForWrite(filePath: string, options?: {
|
|
31
|
+
symlinks?: AbsolutePathSymlinkPolicy;
|
|
32
|
+
}): Promise<ResolvedWritableAbsolutePath>;
|
|
33
|
+
//# sourceMappingURL=absolute-path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"absolute-path.d.ts","sourceRoot":"","sources":["../src/absolute-path.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAIhE,MAAM,MAAM,yBAAyB,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAU5D,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG,oBAAoB,GAAG;IAChE,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,6BAA6B,GACrC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC1B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,eAAe,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,CAAC;AAmL7D,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAWhE;AAED,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAEnF;AAuBD,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,8BAAmC,GAC3C,OAAO,CAAC,6BAA6B,CAAC,CA+ExC;AAED,wBAAsB,iCAAiC,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAazF;AAED,wBAAsB,0BAA0B,CAC9C,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,yBAAyB,CAAA;CAAO,GACrD,OAAO,CAAC,oBAAoB,CAAC,CAgB/B;AAED,wBAAsB,2BAA2B,CAC/C,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,yBAAyB,CAAA;CAAO,GACrD,OAAO,CAAC,4BAA4B,CAAC,CA2BvC"}
|