@openclaw/fs-safe 0.15.0 → 0.17.0
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/CHANGELOG.md +86 -0
- package/README.md +36 -7
- package/dist/absolute-path.d.ts.map +1 -1
- package/dist/absolute-path.js +2 -8
- package/dist/advanced.d.ts +3 -0
- package/dist/advanced.d.ts.map +1 -1
- package/dist/advanced.js +3 -0
- package/dist/archive-deadline.d.ts.map +1 -1
- package/dist/archive-deadline.js +22 -23
- package/dist/archive-kind.d.ts +0 -1
- package/dist/archive-kind.d.ts.map +1 -1
- package/dist/archive-kind.js +5 -17
- package/dist/archive-merge.d.ts +1 -0
- package/dist/archive-merge.d.ts.map +1 -1
- package/dist/archive-merge.js +4 -4
- package/dist/archive-native.d.ts +1 -0
- package/dist/archive-native.d.ts.map +1 -1
- package/dist/archive-native.js +1 -0
- package/dist/archive-options.d.ts +2 -0
- package/dist/archive-options.d.ts.map +1 -1
- package/dist/archive-parser.wasm +0 -0
- package/dist/archive-read.d.ts.map +1 -1
- package/dist/archive-read.js +6 -7
- package/dist/archive-tar-stream.d.ts +3 -0
- package/dist/archive-tar-stream.d.ts.map +1 -1
- package/dist/archive-tar-stream.js +56 -37
- package/dist/archive-tar-wasm.d.ts +16 -4
- package/dist/archive-tar-wasm.d.ts.map +1 -1
- package/dist/archive-tar-wasm.js +134 -34
- package/dist/archive-zip-count.d.ts.map +1 -1
- package/dist/archive-zip-count.js +21 -1
- package/dist/archive-zip-directory.d.ts.map +1 -1
- package/dist/archive-zip-directory.js +23 -1
- package/dist/archive-zip-loader.d.ts +2 -0
- package/dist/archive-zip-loader.d.ts.map +1 -1
- package/dist/archive-zip-loader.js +7 -0
- package/dist/archive-zip-names.d.ts.map +1 -1
- package/dist/archive-zip-names.js +7 -2
- package/dist/archive.d.ts.map +1 -1
- package/dist/archive.js +14 -9
- package/dist/byte-view.d.ts +3 -0
- package/dist/byte-view.d.ts.map +1 -0
- package/dist/byte-view.js +13 -0
- package/dist/clone-metadata.d.ts +1 -0
- package/dist/clone-metadata.d.ts.map +1 -1
- package/dist/clone-metadata.js +6 -2
- package/dist/create-directory.d.ts +20 -0
- package/dist/create-directory.d.ts.map +1 -0
- package/dist/create-directory.js +130 -0
- package/dist/create-file-async.d.ts +7 -0
- package/dist/create-file-async.d.ts.map +1 -0
- package/dist/create-file-async.js +121 -0
- package/dist/create-file.d.ts +8 -0
- package/dist/create-file.d.ts.map +1 -0
- package/dist/create-file.js +190 -0
- package/dist/create-owned-file.d.ts +8 -0
- package/dist/create-owned-file.d.ts.map +1 -0
- package/dist/create-owned-file.js +16 -0
- package/dist/create.d.ts +4 -0
- package/dist/create.d.ts.map +1 -0
- package/dist/create.js +2 -0
- package/dist/creation-darwin.d.ts +6 -0
- package/dist/creation-darwin.d.ts.map +1 -0
- package/dist/creation-darwin.js +70 -0
- package/dist/creation-file-state.d.ts +19 -0
- package/dist/creation-file-state.d.ts.map +1 -0
- package/dist/creation-file-state.js +118 -0
- package/dist/creation-path.d.ts +21 -0
- package/dist/creation-path.d.ts.map +1 -0
- package/dist/creation-path.js +71 -0
- package/dist/creation-permissions.d.ts +19 -0
- package/dist/creation-permissions.d.ts.map +1 -0
- package/dist/creation-permissions.js +125 -0
- package/dist/directory-durability.d.ts +7 -7
- package/dist/directory-durability.d.ts.map +1 -1
- package/dist/directory-durability.js +22 -80
- package/dist/directory-guard.d.ts +3 -0
- package/dist/directory-guard.d.ts.map +1 -1
- package/dist/directory-mode-node.d.ts +2 -0
- package/dist/directory-mode-node.d.ts.map +1 -1
- package/dist/directory-mode-node.js +8 -0
- package/dist/directory-receipt.d.ts +24 -0
- package/dist/directory-receipt.d.ts.map +1 -0
- package/dist/directory-receipt.js +123 -0
- package/dist/file-cleanup.d.ts +20 -0
- package/dist/file-cleanup.d.ts.map +1 -0
- package/dist/file-cleanup.js +81 -0
- package/dist/file-contents.d.ts +6 -0
- package/dist/file-contents.d.ts.map +1 -0
- package/dist/file-contents.js +40 -0
- package/dist/file-hash.d.ts.map +1 -1
- package/dist/file-hash.js +16 -4
- package/dist/file-lock-sync-root-acquire.d.ts.map +1 -1
- package/dist/file-lock-sync-root-acquire.js +3 -0
- package/dist/file-lock-sync-root-held.d.ts +1 -2
- package/dist/file-lock-sync-root-held.d.ts.map +1 -1
- package/dist/file-lock-sync-root-held.js +7 -5
- package/dist/file-lock-sync-stale-admission.d.ts.map +1 -1
- package/dist/file-lock-sync-stale-admission.js +3 -0
- package/dist/file-lock-sync.d.ts.map +1 -1
- package/dist/file-lock-sync.js +8 -11
- package/dist/file-observation.d.ts +1 -1
- package/dist/file-observation.d.ts.map +1 -1
- package/dist/file-store-boundary.d.ts +2 -6
- package/dist/file-store-boundary.d.ts.map +1 -1
- package/dist/file-store-boundary.js +3 -9
- package/dist/file-store-sync-write.d.ts.map +1 -1
- package/dist/file-store-sync-write.js +2 -5
- package/dist/file-store.js +3 -3
- package/dist/guarded-mkdir.d.ts +1 -0
- package/dist/guarded-mkdir.d.ts.map +1 -1
- package/dist/guarded-mkdir.js +27 -19
- package/dist/install-path.d.ts.map +1 -1
- package/dist/install-path.js +2 -5
- package/dist/json-durable-queue-ownership.d.ts.map +1 -1
- package/dist/json-durable-queue-ownership.js +2 -6
- package/dist/json-durable-queue-paths.d.ts.map +1 -1
- package/dist/json-durable-queue-paths.js +2 -24
- package/dist/json-durable-queue.d.ts.map +1 -1
- package/dist/json-durable-queue.js +10 -9
- package/dist/json.d.ts.map +1 -1
- package/dist/json.js +32 -75
- package/dist/local-roots.d.ts.map +1 -1
- package/dist/local-roots.js +19 -21
- package/dist/move-path-cleanup.d.ts +5 -19
- package/dist/move-path-cleanup.d.ts.map +1 -1
- package/dist/move-path-cleanup.js +57 -21
- package/dist/move-path.d.ts.map +1 -1
- package/dist/move-path.js +63 -40
- package/dist/native-binding.d.ts +11 -1
- package/dist/native-binding.d.ts.map +1 -1
- package/dist/native-fallback-warning.d.ts +4 -0
- package/dist/native-fallback-warning.d.ts.map +1 -0
- package/dist/native-fallback-warning.js +11 -0
- package/dist/native-operations.d.ts +0 -2
- package/dist/native-operations.d.ts.map +1 -1
- package/dist/native-operations.js +0 -24
- package/dist/native-parent-admission.d.ts +2 -0
- package/dist/native-parent-admission.d.ts.map +1 -1
- package/dist/native-parent-admission.js +3 -2
- package/dist/native-pinned-write-windows.d.ts +1 -1
- package/dist/native-pinned-write-windows.d.ts.map +1 -1
- package/dist/native-pinned-write-windows.js +173 -28
- package/dist/native-pinned-write.d.ts.map +1 -1
- package/dist/native-pinned-write.js +19 -3
- package/dist/native-policy-parent-windows.d.ts.map +1 -1
- package/dist/native-policy-parent-windows.js +15 -6
- package/dist/native-staged-file.d.ts +5 -3
- package/dist/native-staged-file.d.ts.map +1 -1
- package/dist/native-staged-file.js +90 -40
- package/dist/native.js +2 -2
- package/dist/opened-realpath.d.ts.map +1 -1
- package/dist/opened-realpath.js +11 -2
- package/dist/owner-dacl.d.ts.map +1 -1
- package/dist/owner-dacl.js +10 -4
- package/dist/path.d.ts.map +1 -1
- package/dist/path.js +2 -1
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +3 -17
- package/dist/pinned-write-input.d.ts +4 -0
- package/dist/pinned-write-input.d.ts.map +1 -0
- package/dist/pinned-write-input.js +35 -0
- package/dist/pinned-write-mode.d.ts +5 -0
- package/dist/pinned-write-mode.d.ts.map +1 -0
- package/dist/pinned-write-mode.js +31 -0
- package/dist/pinned-write-staged.d.ts +6 -0
- package/dist/pinned-write-staged.d.ts.map +1 -0
- package/dist/pinned-write-staged.js +186 -0
- package/dist/pinned-write-types.d.ts +3 -0
- package/dist/pinned-write-types.d.ts.map +1 -1
- package/dist/pinned-write.d.ts.map +1 -1
- package/dist/pinned-write.js +41 -147
- package/dist/private-directory.d.ts.map +1 -1
- package/dist/private-directory.js +18 -4
- package/dist/private-producer-handoff-sync.d.ts +14 -0
- package/dist/private-producer-handoff-sync.d.ts.map +1 -0
- package/dist/private-producer-handoff-sync.js +114 -0
- package/dist/private-producer-handoff.d.ts +22 -4
- package/dist/private-producer-handoff.d.ts.map +1 -1
- package/dist/private-producer-handoff.js +140 -77
- package/dist/publish-copy-stage.d.ts +2 -1
- package/dist/publish-copy-stage.d.ts.map +1 -1
- package/dist/publish-copy-stage.js +16 -7
- package/dist/publish-file.d.ts +2 -2
- package/dist/publish-file.d.ts.map +1 -1
- package/dist/publish-file.js +58 -98
- package/dist/regular-file.d.ts.map +1 -1
- package/dist/regular-file.js +35 -44
- package/dist/replace-file-copy-fallback.d.ts.map +1 -1
- package/dist/replace-file-copy-fallback.js +28 -26
- package/dist/replace-file-copy-source.d.ts.map +1 -1
- package/dist/replace-file-copy-source.js +13 -22
- package/dist/replace-file-descriptor.d.ts.map +1 -1
- package/dist/replace-file-descriptor.js +10 -16
- package/dist/replace-file-temp-owner.d.ts +0 -7
- package/dist/replace-file-temp-owner.d.ts.map +1 -1
- package/dist/replace-file-temp-owner.js +9 -60
- package/dist/replace-file.d.ts.map +1 -1
- package/dist/replace-file.js +9 -13
- package/dist/root-create-input.d.ts +2 -1
- package/dist/root-create-input.d.ts.map +1 -1
- package/dist/root-create-input.js +13 -4
- package/dist/root-directory-creation.d.ts +3 -3
- package/dist/root-directory-creation.d.ts.map +1 -1
- package/dist/root-directory-creation.js +15 -3
- package/dist/root-directory-list.d.ts.map +1 -1
- package/dist/root-directory-list.js +20 -3
- package/dist/root-file-final-admission.d.ts +1 -1
- package/dist/root-file-final-admission.d.ts.map +1 -1
- package/dist/root-file-final-admission.js +5 -2
- package/dist/root-file.d.ts.map +1 -1
- package/dist/root-file.js +3 -2
- package/dist/root-impl.d.ts.map +1 -1
- package/dist/root-impl.js +78 -27
- package/dist/root-move-noreplace.d.ts +2 -0
- package/dist/root-move-noreplace.d.ts.map +1 -1
- package/dist/root-move-noreplace.js +22 -13
- package/dist/root-options.d.ts +12 -4
- package/dist/root-options.d.ts.map +1 -1
- package/dist/root-path-stat.d.ts.map +1 -1
- package/dist/root-path-stat.js +59 -7
- package/dist/root-read-admission.d.ts.map +1 -1
- package/dist/root-read-admission.js +7 -2
- package/dist/root-remove.d.ts.map +1 -1
- package/dist/root-remove.js +15 -1
- package/dist/root-write-publication.js +1 -1
- package/dist/secret-file.d.ts.map +1 -1
- package/dist/secret-file.js +1 -0
- package/dist/secure-file-windows.d.ts +6 -0
- package/dist/secure-file-windows.d.ts.map +1 -1
- package/dist/secure-file-windows.js +34 -117
- package/dist/secure-file.js +2 -2
- package/dist/sidecar-lock-acquire.d.ts.map +1 -1
- package/dist/sidecar-lock-acquire.js +4 -6
- package/dist/sidecar-lock-handle.d.ts +3 -0
- package/dist/sidecar-lock-handle.d.ts.map +1 -1
- package/dist/sidecar-lock-handle.js +6 -0
- package/dist/sidecar-lock-reclaim.d.ts +1 -1
- package/dist/sidecar-lock-reclaim.d.ts.map +1 -1
- package/dist/sidecar-lock-reclaim.js +11 -8
- package/dist/sidecar-lock-root.d.ts.map +1 -1
- package/dist/sidecar-lock-root.js +2 -1
- package/dist/sidecar-lock.d.ts.map +1 -1
- package/dist/sidecar-lock.js +3 -5
- package/dist/staged-directory.d.ts +2 -2
- package/dist/staged-directory.d.ts.map +1 -1
- package/dist/staged-directory.js +6 -6
- package/dist/staged-file-settlement.d.ts +17 -0
- package/dist/staged-file-settlement.d.ts.map +1 -0
- package/dist/staged-file-settlement.js +57 -0
- package/dist/strict-file-identity.d.ts +1 -1
- package/dist/strict-file-identity.d.ts.map +1 -1
- package/dist/strict-file-identity.js +9 -9
- package/dist/symlink-parents.d.ts.map +1 -1
- package/dist/symlink-parents.js +2 -27
- package/dist/temp-workspace-owner.js +4 -4
- package/dist/unicode-path.d.ts.map +1 -1
- package/dist/unicode-path.js +3 -0
- package/dist/walk.d.ts.map +1 -1
- package/dist/walk.js +4 -2
- package/dist/windows-owner.d.ts.map +1 -1
- package/dist/windows-owner.js +2 -1
- package/dist/windows-security-bridge.cs +336 -0
- package/dist/windows-security-bridge.ps1 +15 -0
- package/dist/windows-security-command.d.ts +26 -0
- package/dist/windows-security-command.d.ts.map +1 -0
- package/dist/windows-security-command.js +363 -0
- package/dist/windows-security-facts.d.ts +6 -0
- package/dist/windows-security-facts.d.ts.map +1 -0
- package/dist/windows-security-facts.js +108 -0
- package/dist/write-file-handle.d.ts +7 -0
- package/dist/write-file-handle.d.ts.map +1 -1
- package/dist/write-file-handle.js +23 -0
- package/dist/write-open-flags.d.ts.map +1 -1
- package/dist/write-open-flags.js +1 -8
- package/dist/write-queue.d.ts.map +1 -1
- package/dist/write-queue.js +1 -4
- package/docs/advanced.md +71 -2
- package/docs/archive.md +102 -39
- package/docs/atomic.md +29 -5
- package/docs/config.md +6 -2
- package/docs/contributing.md +48 -4
- package/docs/copy.md +2 -0
- package/docs/creation.md +132 -0
- package/docs/durability.md +59 -0
- package/docs/file-contents.md +68 -0
- package/docs/install.md +31 -7
- package/docs/json.md +5 -4
- package/docs/local-roots.md +2 -0
- package/docs/migrating-to-0.5.md +15 -6
- package/docs/migrating-to-0.6.md +9 -4
- package/docs/mutation-policy-proof.md +5 -3
- package/docs/native-helper.md +22 -9
- package/docs/native.md +47 -15
- package/docs/path.md +4 -4
- package/docs/permissions.md +37 -14
- package/docs/public-api.md +5 -0
- package/docs/quickstart.md +1 -1
- package/docs/reading.md +2 -2
- package/docs/regular-file.md +3 -0
- package/docs/root.md +43 -0
- package/docs/secret-file.md +11 -2
- package/docs/secure-file.md +9 -4
- package/docs/sidecar-lock.md +14 -5
- package/docs/staged-file.md +9 -3
- package/docs/store.md +3 -1
- package/docs/temp.md +4 -1
- package/docs/types.md +18 -2
- package/docs/walk.md +7 -0
- package/docs/writing.md +80 -7
- package/package.json +18 -15
package/docs/writing.md
CHANGED
|
@@ -6,11 +6,11 @@ half-written replacement appears at the destination. Create-only writes
|
|
|
6
6
|
(`create`, `createJson`, and `write` with `overwrite: false`) use sibling-temp
|
|
7
7
|
staging with an atomic no-replace rename only on backends that provide one —
|
|
8
8
|
the native binding, which `require` mode guarantees and `auto` mode uses when
|
|
9
|
-
the binding loads.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
the binding loads. Ordinary buffered creation in the pure-JavaScript fallback
|
|
10
|
+
claims the final name exclusively with `O_EXCL` and writes content in place, so
|
|
11
|
+
a concurrent observer can see the new file before its content is complete.
|
|
12
|
+
Buffered `create` and `createJson` accept `atomic: true` to stage complete content
|
|
13
|
+
on this fallback too. Streamed creation already stages before publication.
|
|
14
14
|
`append` and `openWritable` intentionally modify an opened file in place;
|
|
15
15
|
`move`, `remove`, and `mkdir` mutate directory entries rather than file bytes.
|
|
16
16
|
Each verb applies the boundary checks appropriate to its operation.
|
|
@@ -113,6 +113,14 @@ Native and pure-JavaScript Windows writers honor the option. Replacement writes
|
|
|
113
113
|
sync staged content before rename and the final mode through the retained file
|
|
114
114
|
handle. Directory sync remains best-effort.
|
|
115
115
|
|
|
116
|
+
For `create` and `createJson`, `durable: "file"` requires each file sync to succeed,
|
|
117
|
+
including on `EPERM`; it overrides a disabled Root durability default. Parent
|
|
118
|
+
directory synchronization retains the existing best-effort policy. This also
|
|
119
|
+
applies to streamed creation and is independent of publication strategy. Boolean
|
|
120
|
+
durability options keep their existing behavior, including compatibility paths
|
|
121
|
+
that tolerate `EPERM`. A failed file sync before staged publication prevents
|
|
122
|
+
publication; a failure after publication can leave the complete file present.
|
|
123
|
+
|
|
116
124
|
POSIX modes without read permission, including `0o000` and `0o200`, succeed:
|
|
117
125
|
final verification uses a descriptor retained by the writer rather than reopening
|
|
118
126
|
the published file. The requested mode is not relaxed for verification.
|
|
@@ -146,19 +154,61 @@ claimed exclusively first and content is written afterward, so observers can
|
|
|
146
154
|
briefly see an empty file; failure cleanup removes a claimed file only when its
|
|
147
155
|
identity is unchanged.
|
|
148
156
|
|
|
157
|
+
After a successful create-only write, failure to close its owned file handle
|
|
158
|
+
rejects the operation and leaves the complete file present. Ordinary buffered
|
|
159
|
+
creation in the JavaScript fallback preserves an earlier write or verification
|
|
160
|
+
failure if close also fails. Native, atomic, and streamed creation retain their
|
|
161
|
+
existing publication and cleanup diagnostics.
|
|
162
|
+
|
|
149
163
|
```ts
|
|
150
164
|
try {
|
|
151
165
|
await fs.create("config/seed.json", initial);
|
|
152
166
|
} catch (err) {
|
|
153
|
-
if (err instanceof FsSafeError
|
|
167
|
+
if (!(err instanceof FsSafeError) || err.code !== "already-exists") throw err;
|
|
154
168
|
}
|
|
155
169
|
```
|
|
156
170
|
|
|
171
|
+
### Atomic buffered creation
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
await fs.create("config/seed.json", initial, { atomic: true });
|
|
175
|
+
await fs.createJson("config/settings.json", { enabled: true }, { atomic: true });
|
|
176
|
+
await fs.create("config/flushed.json", initial, { atomic: true, durable: "file" });
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
`atomic: true` keeps the destination absent until all bytes have been written.
|
|
180
|
+
The native backend uses its no-replace rename; the JavaScript fallback hardlinks
|
|
181
|
+
the completed stage and unlinks its temporary name in the same JavaScript turn.
|
|
182
|
+
The fallback requires hardlink support and fails without publishing partial bytes
|
|
183
|
+
when that mechanism is unavailable. Other processes can briefly observe both
|
|
184
|
+
names. Existing and raced entries are preserved, including dangling symlinks;
|
|
185
|
+
ordinary confinement, type, hardlink, and symlink-policy rejections still apply.
|
|
186
|
+
`assertBeforeMutation` retains its live checks through content writes and publication.
|
|
187
|
+
|
|
188
|
+
Omitted or `false` preserves the existing buffered behavior. The option belongs
|
|
189
|
+
to buffered `create` and `createJson`, not replacement writes or Root defaults.
|
|
190
|
+
Streamed creation has no atomic opt-out. `atomic` changes visibility, not the
|
|
191
|
+
existing `durable` file/directory synchronization policy; it does not turn
|
|
192
|
+
best-effort synchronization into a strict crash-durability guarantee or strengthen
|
|
193
|
+
JavaScript pathname containment.
|
|
194
|
+
|
|
195
|
+
Atomic and streamed creates settle owned cleanup and close operations before
|
|
196
|
+
returning. Failed or unverifiable cleanup is reported rather than silently
|
|
197
|
+
discarded. Errors after publication and incomplete-settlement errors carry the
|
|
198
|
+
existing `StagedFileFailureDetails` publication/cleanup receipts where the writer
|
|
199
|
+
can establish them; native disposal can retain them inside a `SuppressedError`
|
|
200
|
+
cause. Preserve those details when handling errors: a rejection can follow
|
|
201
|
+
complete publication, and an indeterminate link or native rename must preserve names for
|
|
202
|
+
recovery. A cleanup or close failure also retains the original operation failure.
|
|
203
|
+
No later verification, mode, or synchronization failure authorizes deleting an
|
|
204
|
+
already published complete destination. See [receipt meanings](staged-file.md).
|
|
205
|
+
|
|
157
206
|
### Streamed creation
|
|
158
207
|
|
|
159
208
|
Pass an `AsyncIterable<Uint8Array>` to `create()` when bytes come from a database,
|
|
160
209
|
network response, or another incremental producer. Buffers are accepted chunks.
|
|
161
|
-
The writer
|
|
210
|
+
The writer borrows `Uint8Array` slices without copying their payloads and counts
|
|
211
|
+
their actual byte bounds. It consumes each chunk completely before requesting the next one; it
|
|
162
212
|
does not collect the full input in memory or expose a writable descriptor.
|
|
163
213
|
|
|
164
214
|
```ts
|
|
@@ -202,6 +252,12 @@ forcibly interrupted, so cancellation waits for its pending work and cleanup to
|
|
|
202
252
|
settle. Do not mutate a yielded chunk until the next pull. Producer errors retain
|
|
203
253
|
their original value when cleanup succeeds.
|
|
204
254
|
|
|
255
|
+
Streamed creation retains the `signal` and `assertBeforeMutation` callback
|
|
256
|
+
selected when the call starts. Replacing or deleting those options during a
|
|
257
|
+
producer wait does not change the in-flight operation. Abort the original signal
|
|
258
|
+
or update the live authority state checked by the original callback to revoke
|
|
259
|
+
it; the callback continues to receive the original options object as `this`.
|
|
260
|
+
|
|
205
261
|
An aborted or failed operation can leave created parent directories. If a
|
|
206
262
|
stage's identity or parent cannot be verified during cleanup, the existing
|
|
207
263
|
guarded cleanup preserves it. After publication, later verification or cleanup
|
|
@@ -268,6 +324,10 @@ await fs.move("incoming/foo.txt", "archive/foo.txt", { overwrite: true });
|
|
|
268
324
|
|
|
269
325
|
Both `from` and `to` are bounded; `..` in either is rejected.
|
|
270
326
|
|
|
327
|
+
Mutation policy is captured at call start; changes to caller-owned denial arrays
|
|
328
|
+
apply to later moves. For live cancellation or revocation, throw from
|
|
329
|
+
`assertBeforeMutation` immediately before dispatch.
|
|
330
|
+
|
|
271
331
|
The default no-clobber mode requires the native helper. It admits both parent
|
|
272
332
|
directory descriptors and performs a descriptor-relative no-replace rename, so
|
|
273
333
|
a competitor that creates the target first is preserved and the source remains
|
|
@@ -407,6 +467,19 @@ an atomic check-and-delete syscall. Use OS isolation for that threat model.
|
|
|
407
467
|
await fs.mkdir("snapshots/2026/05");
|
|
408
468
|
```
|
|
409
469
|
|
|
470
|
+
Pass `{ private: true }` to create missing components with private permissions.
|
|
471
|
+
An existing requested directory must already satisfy that policy; fs-safe does
|
|
472
|
+
not repair it or change existing ancestor permissions. Concurrent creators may
|
|
473
|
+
reuse the winner only after it passes the same checks.
|
|
474
|
+
|
|
475
|
+
Buffered, streamed, and JSON `create` calls also accept `private: true`.
|
|
476
|
+
New POSIX directories default to `0700` and files to `0600`; conflicting
|
|
477
|
+
group/world or privilege bits are rejected before creation. Restrictive
|
|
478
|
+
owner-only file modes remain available through `mode`. On Windows, creation
|
|
479
|
+
uses protected ACLs rather than interpreting POSIX mode bits as access rules.
|
|
480
|
+
This does not change `create`'s no-overwrite behavior or select its durability
|
|
481
|
+
policy. See [creation](creation.md) for supported backends and owned descriptors.
|
|
482
|
+
|
|
410
483
|
### `fs.ensureRoot()`
|
|
411
484
|
|
|
412
485
|
Treats `""` / `"."` as the root itself. Useful when a generic helper computes a relative directory and might end up at the root.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/fs-safe",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "Capability-style filesystem roots for Node.js apps that handle untrusted relative paths.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"filesystem",
|
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
},
|
|
26
26
|
"files": [
|
|
27
27
|
"dist/archive-parser.wasm",
|
|
28
|
+
"dist/windows-security-bridge.cs",
|
|
29
|
+
"dist/windows-security-bridge.ps1",
|
|
28
30
|
"dist/**/*.js",
|
|
29
31
|
"dist/**/*.d.ts",
|
|
30
32
|
"dist/**/*.d.ts.map",
|
|
@@ -144,10 +146,10 @@
|
|
|
144
146
|
"test:bun": "bun node_modules/vitest/vitest.mjs run --config scripts/bun-vitest.config.ts",
|
|
145
147
|
"test:bun:native": "bun scripts/bun-native-proof.mjs && bun node_modules/vitest/vitest.mjs run --config scripts/bun-native-vitest.config.ts",
|
|
146
148
|
"test:coverage": "vitest run --coverage",
|
|
147
|
-
"test:coverage:collect": "pnpm build && vitest run --coverage --coverage.reporter=json --coverage.thresholds.lines=0 --coverage.thresholds.functions=0 --coverage.thresholds.statements=0 --coverage.thresholds.branches=0",
|
|
149
|
+
"test:coverage:collect": "pnpm build && pnpm archive:wasm:allocator-tests && vitest run --coverage --coverage.reporter=json --coverage.thresholds.lines=0 --coverage.thresholds.functions=0 --coverage.thresholds.statements=0 --coverage.thresholds.branches=0",
|
|
148
150
|
"test:coverage:merge": "node scripts/merge-coverage.mjs",
|
|
149
151
|
"test:security": "vitest run test/fs-safe.test.ts test/read-boundary-bypass.test.ts test/write-boundary-bypass.test.ts test/additional-boundary-bypass.test.ts test/adversarial-boundary-payloads.test.ts",
|
|
150
|
-
"check": "pnpm lint:file-size && pnpm lint:fs-boundary && pnpm build && pnpm docs:check && pnpm test && node scripts/check-pack.mjs",
|
|
152
|
+
"check": "pnpm lint:file-size && pnpm lint:fs-boundary && pnpm build && pnpm archive:wasm:allocator-tests && pnpm docs:check && pnpm test && node scripts/check-pack.mjs",
|
|
151
153
|
"docs:check": "node scripts/check-doc-examples.mjs",
|
|
152
154
|
"docs:site": "node scripts/build-docs-site.mjs",
|
|
153
155
|
"native:build": "pnpm --filter @openclaw/fs-safe-native-build build",
|
|
@@ -164,24 +166,25 @@
|
|
|
164
166
|
"crabbox:stop": "crabbox stop",
|
|
165
167
|
"crabbox:warmup": "crabbox warmup",
|
|
166
168
|
"archive:wasm": "node scripts/build-archive-wasm.mjs",
|
|
169
|
+
"archive:wasm:allocator-tests": "node scripts/build-archive-wasm.mjs --allocator-tests",
|
|
167
170
|
"archive:producer-smoke": "node scripts/archive-producer-smoke.mjs"
|
|
168
171
|
},
|
|
169
172
|
"optionalDependencies": {
|
|
170
|
-
"@openclaw/fs-safe-darwin-arm64": "0.
|
|
171
|
-
"@openclaw/fs-safe-darwin-x64": "0.
|
|
172
|
-
"@openclaw/fs-safe-linux-arm64-gnu": "0.
|
|
173
|
-
"@openclaw/fs-safe-linux-arm64-musl": "0.
|
|
174
|
-
"@openclaw/fs-safe-linux-x64-gnu": "0.
|
|
175
|
-
"@openclaw/fs-safe-linux-x64-musl": "0.
|
|
176
|
-
"@openclaw/fs-safe-win32-x64-msvc": "0.
|
|
173
|
+
"@openclaw/fs-safe-darwin-arm64": "0.17.0",
|
|
174
|
+
"@openclaw/fs-safe-darwin-x64": "0.17.0",
|
|
175
|
+
"@openclaw/fs-safe-linux-arm64-gnu": "0.17.0",
|
|
176
|
+
"@openclaw/fs-safe-linux-arm64-musl": "0.17.0",
|
|
177
|
+
"@openclaw/fs-safe-linux-x64-gnu": "0.17.0",
|
|
178
|
+
"@openclaw/fs-safe-linux-x64-musl": "0.17.0",
|
|
179
|
+
"@openclaw/fs-safe-win32-x64-msvc": "0.17.0",
|
|
177
180
|
"jszip": "^3.10.2"
|
|
178
181
|
},
|
|
179
182
|
"devDependencies": {
|
|
180
183
|
"@emnapi/runtime": "2.0.0-alpha.5",
|
|
181
|
-
"@napi-rs/cli": "3.10.
|
|
182
|
-
"@types/node": "^26.
|
|
184
|
+
"@napi-rs/cli": "3.10.3",
|
|
185
|
+
"@types/node": "^26.6.1",
|
|
183
186
|
"@vitest/coverage-v8": "5.0.1",
|
|
184
|
-
"fast-check": "^4.
|
|
187
|
+
"fast-check": "^4.10.1",
|
|
185
188
|
"istanbul-lib-coverage": "3.2.2",
|
|
186
189
|
"istanbul-lib-report": "3.0.1",
|
|
187
190
|
"istanbul-reports": "3.2.0",
|
|
@@ -189,10 +192,10 @@
|
|
|
189
192
|
"tar": "7.5.22",
|
|
190
193
|
"typescript": "^7.0.2",
|
|
191
194
|
"vite": "8.3.0",
|
|
192
|
-
"vitest": "^5.0.
|
|
195
|
+
"vitest": "^5.0.1"
|
|
193
196
|
},
|
|
194
197
|
"engines": {
|
|
195
198
|
"node": ">=22"
|
|
196
199
|
},
|
|
197
|
-
"packageManager": "pnpm@
|
|
200
|
+
"packageManager": "pnpm@12.4.2"
|
|
198
201
|
}
|