@openclaw/openshell-sandbox 2026.9.2 → 2026.9.4
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/openclaw.plugin.json +1 -0
- package/package.json +7 -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,266 @@
|
|
|
1
|
+
# root()
|
|
2
|
+
|
|
3
|
+
`root()` is the primary entry point. It takes a trusted directory and returns a capability-style `Root` handle whose methods accept relative paths and refuse to escape the directory.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { root } from "@openclaw/fs-safe";
|
|
7
|
+
|
|
8
|
+
const fs = await root("/srv/workspace", {
|
|
9
|
+
hardlinks: "reject",
|
|
10
|
+
symlinks: "reject",
|
|
11
|
+
mkdir: true,
|
|
12
|
+
});
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Signature
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
function root(rootDir: string, defaults?: RootDefaults): Promise<Root>;
|
|
19
|
+
|
|
20
|
+
type RootDefaults = {
|
|
21
|
+
durable?: boolean; // fsync write/create/writeJson/createJson/append; default true
|
|
22
|
+
hardlinks?: "reject" | "allow"; // refuse files with nlink > 1 on read; defaults to "reject"
|
|
23
|
+
denyMutations?: DenyMutationPolicy; // absolute paths/prefixes mutation methods may not change
|
|
24
|
+
maxBytes?: number; // refuse reads larger than this many bytes; defaults to 16 MiB
|
|
25
|
+
mkdir?: boolean; // create missing parent dirs on write/openWritable/append; default true
|
|
26
|
+
mode?: number; // file mode applied to new writes; per-call override available
|
|
27
|
+
nonBlockingRead?: boolean; // compatibility hint; safe opens are already nonblocking where supported
|
|
28
|
+
renameIdentity?: "strict" | "verify-content-with-lock"; // default "strict"
|
|
29
|
+
symlinks?: "reject" | "follow-within-root"; // policy when a path component is a symlink
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
type DenyMutationPolicy = {
|
|
33
|
+
paths?: readonly string[];
|
|
34
|
+
prefixes?: readonly string[];
|
|
35
|
+
};
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`root()` resolves the directory through the real filesystem. A symlinked input becomes the canonical path; a non-existent root throws `FsSafeError` with code `not-found`, and malformed or non-directory roots throw `invalid-path`.
|
|
39
|
+
|
|
40
|
+
`defaults` apply to every method on the returned handle. Per-call options on individual methods override the defaults for that call only, except `denyMutations`: root and per-call deny entries are merged so a call cannot clear a root-level deny.
|
|
41
|
+
|
|
42
|
+
Every `maxBytes` value must be a non-negative safe integer or positive `Infinity`. Zero is an active zero-byte cap; `Infinity` explicitly disables the cap. An omitted or explicitly `undefined` per-call value preserves the configured Root default instead of clearing it.
|
|
43
|
+
|
|
44
|
+
## The `Root` interface
|
|
45
|
+
|
|
46
|
+
Every method on the returned handle accepts paths relative to the root and rejects anything that would escape it.
|
|
47
|
+
|
|
48
|
+
### Reads
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
fs.read(rel, options?) // { buffer, containment, realPath, stat }
|
|
52
|
+
fs.readBytes(rel, options?) // Buffer
|
|
53
|
+
fs.readText(rel, options?) // string
|
|
54
|
+
fs.readJson<T>(rel, options?) // parsed T
|
|
55
|
+
fs.open(rel, options?) // { handle, containment, realPath, stat, [Symbol.asyncDispose] }
|
|
56
|
+
fs.readAbsolute(absPath, options?) // ReadResult; absPath must already be inside the root
|
|
57
|
+
fs.reader(options?) // (path) => Promise<Buffer>; useful for loader APIs
|
|
58
|
+
fs.walk(rel, options) // root-bounded AsyncIterable<{ relativePath, kind, size }>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`walk()` is the incremental, root-bounded recursive scan. It supports entry and
|
|
62
|
+
depth budgets, cancellation, and `symlinkPolicy: "skip" |
|
|
63
|
+
"follow-within-root"`. Budget exhaustion yields a `"truncated"` marker by
|
|
64
|
+
default or throws `FsSafeError("too-large")` with `limitBehavior: "throw"`.
|
|
65
|
+
Use `entryFilter(entry)` to return `"include"`, `"skip"`, or
|
|
66
|
+
`"skip-subtree"`. `"skip"` omits the current entry but still descends into a
|
|
67
|
+
directory; `"skip-subtree"` omits a directory and all of its descendants.
|
|
68
|
+
Directory reads remain fail-fast by default. With
|
|
69
|
+
`onDirectoryError: "skip-and-report"`, the iterator instead yields
|
|
70
|
+
`{ relativePath, kind: "directory-error", size: 0, error }` and continues with
|
|
71
|
+
the remaining tree.
|
|
72
|
+
See [Directory walking](walk.md) for the pure-Node guarantees and the contrast
|
|
73
|
+
with the standalone best-effort walkers.
|
|
74
|
+
|
|
75
|
+
`open()` returns a Node `FileHandle` for streaming. Prefer `await using` for cleanup:
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
await using opened = await fs.open("large.log");
|
|
79
|
+
{
|
|
80
|
+
for await (const chunk of opened.handle.createReadStream()) {
|
|
81
|
+
process.stdout.write(chunk);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
`open()`, `read()`, and `openWritable()` results include
|
|
87
|
+
`containment: "best-effort"`. The field reports the mechanism used; see the
|
|
88
|
+
[security model](security-model.md#containment-guarantees-by-platform).
|
|
89
|
+
|
|
90
|
+
The read methods also accept an absolute spelling that already resolves inside
|
|
91
|
+
the root. `readAbsolute()` and `reader()` make that intent explicit and accept
|
|
92
|
+
both the configured root spelling and its canonical real path when the Root was
|
|
93
|
+
created through a directory symlink or Windows junction. An absolute path
|
|
94
|
+
outside the root is still rejected.
|
|
95
|
+
|
|
96
|
+
### Writes
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
fs.write(rel, data, options?) // overwrite-ok atomic write
|
|
100
|
+
fs.create(rel, data, options?) // throws "already-exists" if target exists
|
|
101
|
+
fs.writeJson(rel, value, options?) // JSON.stringify + atomic write
|
|
102
|
+
fs.createJson(rel, value, options?) // create() variant of writeJson
|
|
103
|
+
fs.append(rel, data, options?) // append text/buffer; syncs before close by default
|
|
104
|
+
fs.copyIn(rel, sourceAbsPath, options?) // copy from outside the root, atomically, with size cap
|
|
105
|
+
fs.openWritable(rel, options?) // FileHandle for streaming writes; supports await using
|
|
106
|
+
fs.move(from, to, options?) // rename within the root; defaults to no clobber
|
|
107
|
+
fs.remove(rel, options?) // unlink file or rmdir empty directory
|
|
108
|
+
fs.mkdir(rel, options?) // mkdir -p (creates missing parents)
|
|
109
|
+
fs.ensureRoot(options?) // accepts "" / "." as the root itself
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`write`, `create`, `append`, `writeJson`, and `createJson` accept `mode?: number`; use `0o600` for credentials and other private state. `writeJson` also accepts the same options as `JSON.stringify` plus `trailingNewline?: boolean` (defaults `true` so the file ends in `\n`).
|
|
113
|
+
|
|
114
|
+
These five methods also accept `durable?: boolean`: the per-call value overrides
|
|
115
|
+
`Root.defaults.durable`, which defaults to `true` when omitted. An explicitly
|
|
116
|
+
`undefined` per-call value preserves the root default. `durable: false` keeps
|
|
117
|
+
the existing publication behavior, modes, and identity checks but skips file
|
|
118
|
+
and parent-directory fsync calls. Use it only for reconstructible data: a crash
|
|
119
|
+
may lose the write or leave the previous file. See [Writing](writing.md#write-options)
|
|
120
|
+
for platform details.
|
|
121
|
+
|
|
122
|
+
`copyIn` is a one-shot ingest from a trusted absolute source path: it streams the source through the boundary, atomically renames into the root, and respects `maxBytes`.
|
|
123
|
+
|
|
124
|
+
Root operations that choose a new destination reject a leading Windows
|
|
125
|
+
drive-relative spelling such as `C:name` on every platform. This applies to
|
|
126
|
+
`write`, `create`, `append`, `openWritable`, `mkdir`, `copyIn`, and the
|
|
127
|
+
destination argument of `move`. In particular, `copyIn(path.basename(source),
|
|
128
|
+
source)` can reject a legal POSIX basename such as `c:photo.png`; callers that
|
|
129
|
+
derive portable destination names from host files must sanitize or map that
|
|
130
|
+
basename first.
|
|
131
|
+
|
|
132
|
+
`openWritable` opens a writable file with options `mode?: number` and `writeMode?: "replace" | "append" | "update"`. `replace` truncates existing files and is the default; `update` keeps existing contents. Use it for streaming output. Prefer `await using` for cleanup.
|
|
133
|
+
|
|
134
|
+
All mutation methods accept `denyMutations?: { paths?: string[]; prefixes?: string[] }`. Entries must be absolute paths. `paths` blocks those exact paths; `prefixes` blocks those paths and their descendants. fs-safe preserves path strings exactly and canonicalizes through existing ancestors before comparing, so a symlinked ancestor to a denied location is still denied. Denied mutations throw `FsSafeError` with code `denied-path`. Use this for caller-specific sensitive paths, not as a replacement for the root boundary, symlink, or hardlink checks.
|
|
135
|
+
|
|
136
|
+
### Inspection (advisory)
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
fs.exists(rel) // boolean
|
|
140
|
+
fs.stat(rel) // PathStat
|
|
141
|
+
fs.list(rel) // string[]
|
|
142
|
+
fs.list(rel, { withFileTypes }) // DirEntry[]
|
|
143
|
+
fs.resolve(rel) // absolute path inside the root, after canonicalization
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
These do not pin a later operation. They are safe to expose to UIs and decision points; for the actual read or write, use the verb methods so the operation pins identity at the point of use.
|
|
147
|
+
|
|
148
|
+
`resolve()` is the exception to the existing-object rule: because it selects a
|
|
149
|
+
location for later use, it rejects a leading drive-relative spelling. Reads,
|
|
150
|
+
`stat`, `exists`, `list`, `walk`, `remove`, and the source argument of `move`
|
|
151
|
+
accept an existing POSIX filename such as `c:notes.txt`. For `move`, only the
|
|
152
|
+
new destination name is subject to the portable guard.
|
|
153
|
+
|
|
154
|
+
## Native helper mode
|
|
155
|
+
|
|
156
|
+
Create-only writes prefer the platform native helper for fd-relative opens and
|
|
157
|
+
atomic no-replace rename. Operations without native wiring retain their guarded
|
|
158
|
+
JavaScript implementations.
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
import { configureFsSafeNative } from "@openclaw/fs-safe/config";
|
|
162
|
+
|
|
163
|
+
configureFsSafeNative({ mode: "off" }); // guarded JavaScript path
|
|
164
|
+
configureFsSafeNative({ mode: "require" }); // fail if the binding is unavailable
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
`auto` is the default. Configure the mode before creating roots. See the
|
|
168
|
+
[native helper policy](native-helper.md) for supported platforms, the native
|
|
169
|
+
surface, and the precise fallback boundary.
|
|
170
|
+
|
|
171
|
+
### Properties
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
fs.rootDir // the directory you passed in
|
|
175
|
+
fs.rootReal // its canonical real path (after symlink resolution)
|
|
176
|
+
fs.rootWithSep // rootReal with a trailing separator, for prefix comparisons
|
|
177
|
+
fs.defaults // the RootDefaults you passed
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Failure semantics
|
|
181
|
+
|
|
182
|
+
Boundary and policy failures throw `FsSafeError` with a `code`. Parsing callbacks
|
|
183
|
+
and underlying filesystem operations can also surface `SyntaxError` or native
|
|
184
|
+
`NodeJS.ErrnoException` values. Branch on `err.code`, not message text, after
|
|
185
|
+
checking `err instanceof FsSafeError`. Common fs-safe codes:
|
|
186
|
+
|
|
187
|
+
| Code | When it fires |
|
|
188
|
+
|---|---|
|
|
189
|
+
| `invalid-path` | The input path is malformed, including embedded NUL bytes. Portable relative-path helpers and `FileStore` keys reject drive-relative segments; Root destination and resolution operations reject a leading drive-relative spelling such as `C:name`. |
|
|
190
|
+
| `outside-workspace` | The input resolves outside the root, or contains a `..` segment that would escape it. |
|
|
191
|
+
| `not-found` | The target does not exist (or its parent does not, with `mkdir: false`). |
|
|
192
|
+
| `not-file` | A read or copy targeted a non-regular file (directory, FIFO, socket, …). |
|
|
193
|
+
| `device-path` | A read/open target is a known unsafe device or process-fd path. |
|
|
194
|
+
| `already-exists` | `create()` or `move()` without `overwrite` hit an existing target. |
|
|
195
|
+
| `denied-path` | A mutation target matched `denyMutations.paths` or `denyMutations.prefixes`. |
|
|
196
|
+
| `symlink` | A path component is a symlink, and the call's `symlinks` policy is `reject`. |
|
|
197
|
+
| `hardlink` | The target's `nlink > 1` and `hardlinks` policy is `reject`. |
|
|
198
|
+
| `path-mismatch` | Post-open identity check failed — the opened fd does not match the resolved path. |
|
|
199
|
+
| `too-large` | Read exceeded `maxBytes`. |
|
|
200
|
+
|
|
201
|
+
Full list in the [Errors](errors.md) reference.
|
|
202
|
+
|
|
203
|
+
## Defaults vs per-call options
|
|
204
|
+
|
|
205
|
+
Defaults reduce repetition; per-call options handle exceptions:
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
const fs = await root("/srv/workspace", {
|
|
209
|
+
symlinks: "reject",
|
|
210
|
+
hardlinks: "reject",
|
|
211
|
+
mkdir: true,
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// Default: symlinks rejected.
|
|
215
|
+
await fs.readText("config.toml");
|
|
216
|
+
|
|
217
|
+
// One specific path needs to follow a symlink that lands inside the root.
|
|
218
|
+
await fs.readText("links/current.log", { symlinks: "follow-within-root" });
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Text helpers default to UTF-8. Pass `encoding` per call to `readText`, `readJson`, `write`, `create`, or `append` when you need another encoding.
|
|
222
|
+
|
|
223
|
+
## Common patterns
|
|
224
|
+
|
|
225
|
+
### Read-only loader
|
|
226
|
+
|
|
227
|
+
```ts
|
|
228
|
+
const fs = await root("/srv/workspace", { symlinks: "reject", hardlinks: "reject" });
|
|
229
|
+
const load = fs.reader();
|
|
230
|
+
const a = await load("notes/today.txt"); // relative
|
|
231
|
+
const b = await load("/srv/workspace/state.bin"); // absolute, but inside the root
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
`fs.reader()` returns a `(path) => Promise<Buffer>` callback. Useful when wiring `fs-safe` into APIs that accept a generic loader function. Absolute paths outside the root are rejected with `outside-workspace`.
|
|
235
|
+
|
|
236
|
+
### "Touch only if missing" seeding
|
|
237
|
+
|
|
238
|
+
```ts
|
|
239
|
+
try {
|
|
240
|
+
await fs.create("config/seed.json", initialJson);
|
|
241
|
+
} catch (err) {
|
|
242
|
+
if (err instanceof FsSafeError && err.code === "already-exists") {
|
|
243
|
+
// existing config wins
|
|
244
|
+
} else {
|
|
245
|
+
throw err;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Replace + verify
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
await fs.write("state.json", JSON.stringify(state, null, 2));
|
|
254
|
+
const echoed = await fs.readJson<State>("state.json");
|
|
255
|
+
assertDeepEqual(echoed, state);
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
`write` is atomic, so the file is either old or new — never half-written. Re-reading lets you detect a parallel writer, if one exists.
|
|
259
|
+
|
|
260
|
+
## See also
|
|
261
|
+
|
|
262
|
+
- [Reading](reading.md) — read variants in depth, plus stream patterns.
|
|
263
|
+
- [Writing](writing.md) — write/create/move/remove in depth.
|
|
264
|
+
- [pathScope()](path-scope.md) — the same boundary semantics over an absolute path you already trust.
|
|
265
|
+
- [Atomic writes](atomic.md) — the lower-level helpers used by `fs.write`.
|
|
266
|
+
- [Errors](errors.md) — the closed code union you'll be catching.
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
# Secret files
|
|
2
|
+
|
|
3
|
+
Helpers for reading and writing credentials. Files are written at mode `0o600`, dirs at `0o700`, with a maximum read size to avoid OOM on bogus input.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import {
|
|
7
|
+
createSecretFileAtomic,
|
|
8
|
+
readSecretFile,
|
|
9
|
+
readSecretFileSync,
|
|
10
|
+
tryReadSecretFile,
|
|
11
|
+
tryReadSecretFileSync,
|
|
12
|
+
writeSecretFileAtomic,
|
|
13
|
+
DEFAULT_SECRET_FILE_MAX_BYTES,
|
|
14
|
+
PRIVATE_SECRET_DIR_MODE,
|
|
15
|
+
PRIVATE_SECRET_FILE_MODE,
|
|
16
|
+
} from "@openclaw/fs-safe/secret";
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## When to use these vs `writeJson`
|
|
20
|
+
|
|
21
|
+
| Use these when | Use `writeJson` when |
|
|
22
|
+
|---|---|
|
|
23
|
+
| The file is a credential (token, key, password). | The file is application state. |
|
|
24
|
+
| You want the parent directory created at `0o700` if missing. | You don't care about the parent directory mode. |
|
|
25
|
+
| You want a hard size cap on reads (to defend against bogus input). | You're reading bounded JSON state. |
|
|
26
|
+
| Mode `0o600` and the private parent policy are mandatory. | Standalone `writeJson` also defaults to `0o600`, but it does not enforce the secret-directory ownership and permission policy. |
|
|
27
|
+
|
|
28
|
+
## Constants
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
DEFAULT_SECRET_FILE_MAX_BYTES = 16 * 1024; // 16 KiB
|
|
32
|
+
PRIVATE_SECRET_DIR_MODE = 0o700;
|
|
33
|
+
PRIVATE_SECRET_FILE_MODE = 0o600;
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The 16 KiB cap is intentionally aggressive — credentials should be small. If you need bigger, pass `maxBytes` explicitly.
|
|
37
|
+
|
|
38
|
+
## Reading
|
|
39
|
+
|
|
40
|
+
### `tryReadSecretFileSync(filePath, label, options?)`
|
|
41
|
+
|
|
42
|
+
The missing-is-optional reader. It returns the trimmed secret string, or
|
|
43
|
+
`undefined` when the `filePath` argument is absent/blank or the target does not
|
|
44
|
+
exist. An existing empty file is invalid and throws, as do unreadable,
|
|
45
|
+
oversized, symlink, hardlink, and other validation failures.
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import { tryReadSecretFileSync } from "@openclaw/fs-safe/secret";
|
|
49
|
+
|
|
50
|
+
const token = tryReadSecretFileSync("/var/lib/app/auth.token", "auth token");
|
|
51
|
+
if (token) {
|
|
52
|
+
useToken(token);
|
|
53
|
+
} else {
|
|
54
|
+
await reauthenticate();
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### `readSecretFileSync(filePath, label, options?)`
|
|
59
|
+
|
|
60
|
+
Strict reader. Throws `FsSafeError` when the file is missing, too large, empty, unreadable, or rejected by the validation checks. Use when failing loudly is the right call:
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
const token = readSecretFileSync("/var/lib/app/auth.token", "auth token");
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Read options
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
type SecretFileReadOptions = {
|
|
70
|
+
maxBytes?: number; // default DEFAULT_SECRET_FILE_MAX_BYTES (16 KiB)
|
|
71
|
+
rejectSymlink?: boolean; // default false
|
|
72
|
+
rejectHardlinks?: boolean; // default true
|
|
73
|
+
};
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`maxBytes` must be a non-negative safe integer or positive `Infinity`; zero is an active cap, `Infinity` disables it, and omitted or explicitly `undefined` values preserve the 16 KiB default.
|
|
77
|
+
|
|
78
|
+
The reader trims the file content and rejects empty results. Symlink paths are
|
|
79
|
+
followed and pinned by default; set `rejectSymlink: true` when the pathname
|
|
80
|
+
itself must not be an alias. Hardlinks are rejected by default so another
|
|
81
|
+
in-tree name cannot alias the credential; pass `rejectHardlinks: false` only
|
|
82
|
+
when you explicitly trust that layout.
|
|
83
|
+
|
|
84
|
+
These readers do not enforce ownership or mode bits on an existing file. Their
|
|
85
|
+
read contract covers pinned identity, file type, link policy, and byte bounds;
|
|
86
|
+
the `0o600` guarantee belongs to the write helpers below. Use
|
|
87
|
+
[`readSecureFile`](secure-file.md) when reading an externally managed
|
|
88
|
+
credential must also fail on broad permissions or unexpected ownership.
|
|
89
|
+
|
|
90
|
+
`readSecretFile()` and `tryReadSecretFile()` are asynchronous counterparts with
|
|
91
|
+
the same pinned-handle validation, byte cap, trimming, error codes, and strict
|
|
92
|
+
versus missing-is-undefined naming semantics.
|
|
93
|
+
|
|
94
|
+
Both readers reject known unsafe device and process-fd paths with `device-path`
|
|
95
|
+
before inspection, and check the resolved target before opening it. This includes
|
|
96
|
+
Windows reserved device names and ignored-space aliases such as `nul .txt`.
|
|
97
|
+
Optional readers propagate this error instead of treating the secret as missing.
|
|
98
|
+
|
|
99
|
+
Both sync and async readers compare lossless bigint identities from the preview,
|
|
100
|
+
opened descriptor, resolved target, and current input path before reading. POSIX
|
|
101
|
+
opens are nonblocking, so a raced FIFO is rejected by descriptor type instead of
|
|
102
|
+
waiting for a writer. An
|
|
103
|
+
allowed symlink must still point to the opened file. On Windows, a zero device
|
|
104
|
+
or inode is unverified: that inspection is retried once without reopening the
|
|
105
|
+
file, preserving known identity components and link checks. Definite mismatches
|
|
106
|
+
and persistent ambiguity fail with `path-mismatch`; optional reads do not treat
|
|
107
|
+
these failures as missing files.
|
|
108
|
+
|
|
109
|
+
If an already validated descriptor fails while reading, both readers throw an
|
|
110
|
+
operational `FsSafeError` with `code: "read-failed"`; inspect `cause` for the
|
|
111
|
+
underlying Node filesystem code such as `EIO`.
|
|
112
|
+
|
|
113
|
+
Use the async strict reader when a service cannot start safely without the
|
|
114
|
+
credential:
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
import { readSecretFile } from "@openclaw/fs-safe/secret";
|
|
118
|
+
|
|
119
|
+
const signingKey = await readSecretFile(
|
|
120
|
+
"/var/lib/app/keys/webhook-signing.key",
|
|
121
|
+
"webhook signing key",
|
|
122
|
+
{ maxBytes: 8 * 1024, rejectSymlink: true },
|
|
123
|
+
);
|
|
124
|
+
startWebhookVerifier(signingKey);
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Writing
|
|
128
|
+
|
|
129
|
+
### `writeSecretFileAtomic(params)`
|
|
130
|
+
|
|
131
|
+
Async. Creates the parent directory at `dirMode` (default `0o700`) if missing, writes content to a sibling temp file, finalizes `mode` (default `0o600`) through an owned descriptor after content writes, and atomically renames over the destination. Publication verification checks the final file identity and mode.
|
|
132
|
+
|
|
133
|
+
Concurrent writes to distinct leaves may share creation of a missing parent.
|
|
134
|
+
After a parent-creation race, the helper re-inspects the entry and requires a
|
|
135
|
+
non-symlink directory, then revalidates root/parent guards, containment, and
|
|
136
|
+
the requested directory mode before writing either leaf.
|
|
137
|
+
|
|
138
|
+
Publication verification borrows the writer's still-open descriptor to check
|
|
139
|
+
the exact file identity, regular-file and link policy, requested POSIX mode,
|
|
140
|
+
and root/parent ancestry before the writer closes it. All `0o7777` mode bits
|
|
141
|
+
must match, including explicitly requested special bits; unexpected special
|
|
142
|
+
bits are rejected. POSIX mode overrides such as `0o000` and `0o200` do not
|
|
143
|
+
require read permission or a readonly reopen, and verification does not widen
|
|
144
|
+
the final mode. Windows retains pathname-identity verification without enforcing
|
|
145
|
+
POSIX mode bits; its native writer checks the reopened descriptor against the
|
|
146
|
+
original lossless file identity before changing the final mode.
|
|
147
|
+
|
|
148
|
+
Failed JavaScript fallback writes attempt cleanup while retaining the original
|
|
149
|
+
descriptor and only after checking parent and file identities. Native cleanup
|
|
150
|
+
also compares lossless parent and file identities. Unverifiable paths are left
|
|
151
|
+
for caller-managed cleanup, and cleanup failures do not replace the original
|
|
152
|
+
write error. These are best-effort identity checks followed by name-based
|
|
153
|
+
removal, not atomic conditional unlink. A publication-verification failure
|
|
154
|
+
after a completed write does not authorize deleting the published file.
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
import { writeSecretFileAtomic } from "@openclaw/fs-safe/secret";
|
|
158
|
+
|
|
159
|
+
await writeSecretFileAtomic({
|
|
160
|
+
rootDir: "/var/lib/app",
|
|
161
|
+
filePath: "/var/lib/app/auth.token",
|
|
162
|
+
content: token,
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Parameters
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
type WriteSecretFileParams = {
|
|
170
|
+
rootDir: string; // trusted root directory (created at dirMode if missing)
|
|
171
|
+
filePath: string; // absolute path; must be inside rootDir
|
|
172
|
+
content: string | Uint8Array;
|
|
173
|
+
mode?: number; // file mode for the new file (default PRIVATE_SECRET_FILE_MODE = 0o600)
|
|
174
|
+
dirMode?: number; // mode for the root and intermediate dirs (default PRIVATE_SECRET_DIR_MODE = 0o700)
|
|
175
|
+
};
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
The full POSIX directory mode is asserted on each component along the path: `rootDir`, then any intermediate dirs, then the parent. Existing directories, including another creator's `EEXIST` winner, must already match `dirMode` exactly or the write fails with `insecure-permissions`; they are never chmod-repaired. An explicitly requested directory mode such as `0o2750` preserves its setgid bit. Audit and adjust existing secret directories yourself. The admitted directory guards are retained through traversal and the final writer/lock handoff; a fresh pathname lookup cannot silently authorize a replacement. The caller must still trust the selected root and its owners; matching permission bits alone do not establish that trust.
|
|
179
|
+
|
|
180
|
+
Directory admission and its retained guards use lossless bigint identities, including through private locks and native writes. On Windows, an unknown zero device or inode gets one reinspection that retains known components; a definite mismatch or persistent ambiguity fails with `path-mismatch` rather than authorizing a replacement.
|
|
181
|
+
|
|
182
|
+
Both mode options must resolve to integers between `0o0000` and `0o7777`; invalid values fail with `invalid-path` before directory creation or file publication. Windows validates the options but does not enforce POSIX permission bits.
|
|
183
|
+
|
|
184
|
+
After this operation wins directory creation, initialization uses a pinned descriptor bound to the admitted identity and effective user, with ancestor checks before chmod. It does not chmod the caller's pathname. Creation and descriptor admission are separate operations, not an atomic create-and-pin guarantee. A raced directory that has not reached its requested mode yet is rejected rather than repaired; callers may retry after its creator finishes initialization.
|
|
185
|
+
|
|
186
|
+
Initialization fails closed if the platform cannot safely pin a created directory. In particular, a non-root macOS process cannot pin a new `000` directory produced by `umask(0o777)`; the write fails without repairing that directory or writing a secret. Restrictive masks retaining owner search permission remain usable. Linux x64/arm64 can use the guarded `O_PATH`/procfs descriptor route where available. There is no unguarded pathname-chmod fallback, and a failure may leave a created directory for caller-managed cleanup.
|
|
187
|
+
|
|
188
|
+
### `createSecretFileAtomic(params)`
|
|
189
|
+
|
|
190
|
+
This create-only sibling has the same directory, mode, pinned-write, and
|
|
191
|
+
post-write verification policy. Final materialization uses exclusive create;
|
|
192
|
+
if anything already occupies the target path it throws
|
|
193
|
+
`FsSafeError("secret-exists")` without modifying that entry. Use the distinct
|
|
194
|
+
name when first-writer-wins is part of the credential protocol.
|
|
195
|
+
|
|
196
|
+
Distinct leaves can share missing-parent creation without a `secret-exists`
|
|
197
|
+
error. Concurrent creates at the same leaf still have exactly one winner;
|
|
198
|
+
the loser receives `secret-exists` and leaves the winner's bytes intact.
|
|
199
|
+
|
|
200
|
+
For example, two onboarding requests may race to install the first refresh
|
|
201
|
+
token. Exactly one should win, and the loser must not overwrite it:
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
import { FsSafeError } from "@openclaw/fs-safe/errors";
|
|
205
|
+
import { createSecretFileAtomic } from "@openclaw/fs-safe/secret";
|
|
206
|
+
|
|
207
|
+
try {
|
|
208
|
+
await createSecretFileAtomic({
|
|
209
|
+
rootDir: "/var/lib/app/credentials",
|
|
210
|
+
filePath: "/var/lib/app/credentials/provider.refresh-token",
|
|
211
|
+
content: refreshToken,
|
|
212
|
+
});
|
|
213
|
+
} catch (error) {
|
|
214
|
+
if (!(error instanceof FsSafeError) || error.code !== "secret-exists") throw error;
|
|
215
|
+
// Another initializer won. Read and validate the installed credential.
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
For more permissive credentials, override `mode`:
|
|
220
|
+
|
|
221
|
+
```ts
|
|
222
|
+
await writeSecretFileAtomic({
|
|
223
|
+
rootDir: "/var/lib/app",
|
|
224
|
+
filePath: "/var/lib/app/readonly.token",
|
|
225
|
+
content: token,
|
|
226
|
+
mode: 0o400, // tighter than the default
|
|
227
|
+
});
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## Common patterns
|
|
231
|
+
|
|
232
|
+
### Load on boot, reauthenticate on miss
|
|
233
|
+
|
|
234
|
+
```ts
|
|
235
|
+
const token = tryReadSecretFileSync("/var/lib/app/auth.token", "auth token");
|
|
236
|
+
if (!token) await runOauthFlow();
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Refresh and persist a token
|
|
240
|
+
|
|
241
|
+
```ts
|
|
242
|
+
const fresh = await refreshToken(currentRefresh);
|
|
243
|
+
await writeSecretFileAtomic({
|
|
244
|
+
rootDir: "/var/lib/app",
|
|
245
|
+
filePath: "/var/lib/app/auth.token",
|
|
246
|
+
content: JSON.stringify(fresh),
|
|
247
|
+
});
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Compose with `withTimeout`
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
import { withTimeout } from "@openclaw/fs-safe/advanced";
|
|
254
|
+
|
|
255
|
+
await withTimeout(
|
|
256
|
+
writeSecretFileAtomic({ rootDir, filePath, content }),
|
|
257
|
+
5_000,
|
|
258
|
+
"persist auth token",
|
|
259
|
+
);
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## Threat model notes
|
|
263
|
+
|
|
264
|
+
- These helpers protect the secret file from **other processes with the same UID** that respect filesystem permissions. They do not defend against root or against attackers who can read process memory.
|
|
265
|
+
- Validation failures are tripwires, not authorization. Investigate before clearing a rejected credential file.
|
|
266
|
+
- If the destination directory is on a tmpfs that does not honor mode bits, the helpers will set the mode bits but the OS may ignore them. Audit your platform.
|
|
267
|
+
|
|
268
|
+
## See also
|
|
269
|
+
|
|
270
|
+
- [JSON files](json.md) — `writeJson` accepts `mode: 0o600` for non-secret JSON state.
|
|
271
|
+
- [Atomic writes](atomic.md) — the lower-level `replaceFileAtomic` used by these helpers.
|
|
272
|
+
- [Private file-store mode](private-file-store.md) — root-bounded JSON+text stores using secret-file write policy.
|
|
273
|
+
- [Migrating to 0.5](migrating-to-0.5.md) — strict/try reads and create-only adoption checklist.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Secure file reads
|
|
2
|
+
|
|
3
|
+
`readSecureFile()` is for absolute file paths that should be treated like credentials or other sensitive local inputs. It is stricter than `fs.readFile()` and different from `root().read()`: the file path is absolute, but the read is still fd-pinned and permission-checked before bytes are returned.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { readSecureFile } from "@openclaw/fs-safe/secure-file";
|
|
7
|
+
|
|
8
|
+
const { buffer, realPath, permissions } = await readSecureFile({
|
|
9
|
+
filePath: "/var/lib/app/auth.token",
|
|
10
|
+
label: "auth token",
|
|
11
|
+
trust: { trustedDirs: ["/var/lib/app"] },
|
|
12
|
+
io: { maxBytes: 16 * 1024, timeoutMs: 5_000 },
|
|
13
|
+
});
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Checks
|
|
17
|
+
|
|
18
|
+
The helper:
|
|
19
|
+
|
|
20
|
+
- requires a local absolute path and rejects UNC/network paths by default
|
|
21
|
+
- rejects every non-regular preview and, by default, symlink paths
|
|
22
|
+
- opens POSIX paths no-follow and nonblocking before reading, then verifies the opened fd still matches the path and realpath; a FIFO swap cannot block before `timeoutMs` owns the byte read
|
|
23
|
+
- optionally requires the real path to live under one of `trust.trustedDirs`
|
|
24
|
+
- rejects hard-to-verify or unsafe permissions unless `permissions.allowInsecure` is set
|
|
25
|
+
- rejects files owned by another POSIX uid
|
|
26
|
+
- enforces `maxBytes` before and after reading
|
|
27
|
+
- closes the handle on success, error, and timeout
|
|
28
|
+
|
|
29
|
+
On POSIX, unsafe permissions mean group/world writable, and group/world readable unless `permissions.allowReadableByOthers` is true. On Windows, the helper uses the ACL inspection helpers from [`permissions`](permissions.md) and refuses the read if ACLs cannot be verified.
|
|
30
|
+
|
|
31
|
+
Descriptor, pathname, and realpath identity checks use lossless bigint stats internally. The returned `stat` remains a normal Node `Stats` object with numeric fields. A zero Windows device or inode is unverified, never a match: the helper re-inspects that identity once using the same descriptor or pathname, then rejects persistent ambiguity with `path-mismatch`. A definite mismatch rejects immediately; retries retain known identity components and still enforce symlink policy.
|
|
32
|
+
|
|
33
|
+
## Options
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
type SecureFileReadOptions = {
|
|
37
|
+
filePath: string;
|
|
38
|
+
label?: string;
|
|
39
|
+
trust?: {
|
|
40
|
+
trustedDirs?: string[];
|
|
41
|
+
allowSymlink?: boolean;
|
|
42
|
+
allowNetworkPath?: boolean;
|
|
43
|
+
};
|
|
44
|
+
permissions?: {
|
|
45
|
+
allowInsecure?: boolean;
|
|
46
|
+
allowReadableByOthers?: boolean;
|
|
47
|
+
};
|
|
48
|
+
inject?: {
|
|
49
|
+
platform?: NodeJS.Platform;
|
|
50
|
+
env?: NodeJS.ProcessEnv;
|
|
51
|
+
exec?: PermissionExec;
|
|
52
|
+
};
|
|
53
|
+
io?: {
|
|
54
|
+
maxBytes?: number;
|
|
55
|
+
timeoutMs?: number;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
`io.maxBytes` must be a non-negative safe integer or positive `Infinity`; zero is an active cap and `Infinity` disables the cap. Invalid limits reject before filesystem admission.
|
|
61
|
+
|
|
62
|
+
`permissions.allowInsecure` is a migration escape hatch. Prefer fixing permissions and using [`formatPermissionRemediation`](permissions.md) to show the user what to run. `trust.allowNetworkPath` is off by default because UNC paths are remote authority, not local filesystem input. `inject` is for tests and platform adapters; production callers usually leave it unset.
|
|
63
|
+
|
|
64
|
+
`permissions.allowInsecure` bypasses only permission checks. Neither it nor `inject.platform` changes filesystem identity verification, which always uses the actual process platform. `trust.allowSymlink` permits an alias but still requires its target and realpath to match the opened descriptor.
|
|
65
|
+
|
|
66
|
+
## Errors
|
|
67
|
+
|
|
68
|
+
`readSecureFile()` throws `FsSafeError` with codes such as:
|
|
69
|
+
|
|
70
|
+
| Code | Meaning |
|
|
71
|
+
|---|---|
|
|
72
|
+
| `invalid-path` | `filePath` was not a local absolute path. |
|
|
73
|
+
| `not-found` | The path could not be stat'd before open. |
|
|
74
|
+
| `not-file` | The opened target is not a regular file. |
|
|
75
|
+
| `symlink` | The path is a symlink and `trust.allowSymlink` is false. |
|
|
76
|
+
| `path-mismatch` | The path or realpath changed between open and verification, or filesystem identity could not be verified after bounded re-inspection. |
|
|
77
|
+
| `outside-workspace` | `realPath` is outside `trust.trustedDirs`. |
|
|
78
|
+
| `permission-unverified` | Required mode/ACL checks could not be completed. |
|
|
79
|
+
| `insecure-permissions` | Mode bits or ACLs grant broader access than allowed. |
|
|
80
|
+
| `not-owned` | POSIX owner uid is not the current process uid. |
|
|
81
|
+
| `too-large` | File size or bytes read exceeded `maxBytes`. |
|
|
82
|
+
| `timeout` | `timeoutMs` elapsed while reading. |
|
|
83
|
+
|
|
84
|
+
Windows inspection failures remain operational `permission-unverified` errors
|
|
85
|
+
and still refuse the read. Their message includes the underlying reason when
|
|
86
|
+
available. `details` includes `ownerError` for owner-query failures and, when
|
|
87
|
+
command diagnostics are available, `command`, `durationMs`, `timedOut`,
|
|
88
|
+
`exitCode`, `signal`, and `stderr`. Reasons and stderr are control-character
|
|
89
|
+
escaped and limited to 400 characters each (including a truncation marker).
|
|
90
|
+
No stdout or target file contents are copied into these display diagnostics.
|
|
91
|
+
The original inspection exception is retained as `cause`; built-in command
|
|
92
|
+
errors also retain their original execFile exception in the cause chain.
|
|
93
|
+
Treat causes as restricted local diagnostic data. No retries are performed,
|
|
94
|
+
and verification order and rejection conditions are unchanged.
|
|
95
|
+
|
|
96
|
+
## See also
|
|
97
|
+
|
|
98
|
+
- [Permissions](permissions.md) — standalone POSIX mode and Windows ACL checks.
|
|
99
|
+
- [Secret files](secret-file.md) — mode-0600 credential read/write helpers.
|
|
100
|
+
- [Reading](reading.md) — root-bounded relative reads.
|