@openclaw/fs-safe 0.15.0 → 0.16.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 +38 -0
- package/README.md +28 -6
- package/dist/advanced.d.ts +1 -0
- package/dist/advanced.d.ts.map +1 -1
- package/dist/advanced.js +1 -0
- 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-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.d.ts.map +1 -1
- package/dist/archive.js +5 -6
- 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 +7 -0
- package/dist/creation-darwin.d.ts.map +1 -0
- package/dist/creation-darwin.js +79 -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 +1 -1
- 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 +127 -0
- package/dist/file-cleanup.d.ts +19 -0
- package/dist/file-cleanup.d.ts.map +1 -0
- package/dist/file-cleanup.js +78 -0
- 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/guarded-mkdir.d.ts +1 -0
- package/dist/guarded-mkdir.d.ts.map +1 -1
- package/dist/guarded-mkdir.js +36 -7
- package/dist/move-path.js +1 -1
- 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 +3 -2
- package/dist/native-staged-file.d.ts.map +1 -1
- package/dist/native-staged-file.js +86 -39
- package/dist/owner-dacl.d.ts.map +1 -1
- package/dist/owner-dacl.js +10 -4
- 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 +25 -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 +24 -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 +187 -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 +35 -145
- 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.map +1 -1
- package/dist/publish-file.js +2 -2
- 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 +3 -54
- 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-impl.d.ts.map +1 -1
- package/dist/root-impl.js +28 -7
- 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-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-root.d.ts.map +1 -1
- package/dist/sidecar-lock-root.js +2 -1
- 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/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/docs/advanced.md +3 -1
- package/docs/archive.md +61 -37
- package/docs/config.md +6 -2
- package/docs/contributing.md +44 -4
- package/docs/copy.md +2 -0
- package/docs/creation.md +128 -0
- package/docs/durability.md +24 -0
- package/docs/install.md +31 -7
- package/docs/migrating-to-0.5.md +15 -6
- package/docs/migrating-to-0.6.md +9 -4
- package/docs/native-helper.md +22 -9
- package/docs/native.md +38 -7
- package/docs/permissions.md +37 -14
- package/docs/root.md +34 -0
- package/docs/secret-file.md +11 -2
- package/docs/secure-file.md +9 -4
- package/docs/sidecar-lock.md +5 -4
- package/docs/staged-file.md +5 -0
- package/docs/writing.md +71 -5
- package/package.json +18 -15
package/docs/native.md
CHANGED
|
@@ -17,7 +17,7 @@ guarded JavaScript path. Native loading is lazy; installs do not compile Rust,
|
|
|
17
17
|
run postinstall code, or fetch binaries at runtime. Seven exact-version optional
|
|
18
18
|
packages are filtered by OS, CPU, and Linux libc, so an installation receives
|
|
19
19
|
only its matching prebuilt binding.
|
|
20
|
-
Native-only formats
|
|
20
|
+
Native-only formats fail explicitly
|
|
21
21
|
instead of substituting a weaker implementation.
|
|
22
22
|
|
|
23
23
|
## The beneath model
|
|
@@ -115,6 +115,17 @@ the guarded Node staging/publication boundary. ZIP behavior is unchanged.
|
|
|
115
115
|
`maxMetaEntryBytes` bounds bodies before allocation; unsupported global/old
|
|
116
116
|
metadata and sparse forms fail closed. See [bounded local PAX support](archive.md#bounded-local-pax-support).
|
|
117
117
|
|
|
118
|
+
The bundled module also compiles the same zstd and bzip2 codec implementations
|
|
119
|
+
used by native. In `off` or missing-native `auto`, those decoders feed the shared
|
|
120
|
+
TAR parser through fixed 64 KiB windows in one import-free WASM session with a
|
|
121
|
+
256 MiB linear-memory ceiling. Gzip retains Node's built-in decoder. Complete
|
|
122
|
+
container and TAR admission precedes policy evaluation and guarded publication;
|
|
123
|
+
concatenated compressed members and zstd skippable frames are consumed through
|
|
124
|
+
physical EOF. No runtime command, interpreter, download, or consumer compilation
|
|
125
|
+
is needed for these archive routes. `require` stays strict, and available native
|
|
126
|
+
operation failures do not retry through WASM. Public `inspectTarArchive()` still
|
|
127
|
+
accepts only plain TAR/gzip; ZIP fallback still requires optional JSZip.
|
|
128
|
+
|
|
118
129
|
Every raw pass receives only TypeScript's resolved `maxEntries`,
|
|
119
130
|
`maxMetaEntryBytes`, and `maxDecodedBytes`. Shared resolution caps metadata and
|
|
120
131
|
decoded byte fields at JavaScript's safe-integer maximum and entry counts at
|
|
@@ -172,12 +183,26 @@ not bypass the byte limit.
|
|
|
172
183
|
does not load the binding. Use asynchronous `sha256File()` for native hashing
|
|
173
184
|
and cancellation that can respond while JavaScript callbacks run.
|
|
174
185
|
|
|
175
|
-
Features without a safe
|
|
176
|
-
`Root.move()
|
|
186
|
+
Features without a safe fallback, including no-clobber
|
|
187
|
+
`Root.move()` and
|
|
177
188
|
[retained-directory staging](staged-file.md), fail with `helper-unavailable`
|
|
178
189
|
when native support is absent or off. Staging is currently Linux/macOS only and
|
|
179
190
|
rejects Windows with `unsupported-platform`.
|
|
180
191
|
|
|
192
|
+
Windows raw owner/DACL inspection, private-directory creation, and secure-file
|
|
193
|
+
descriptor inspection can use a package-shipped, readable `.ps1` driver and
|
|
194
|
+
adjacent `.cs` source in `auto` or `off` mode when their binding or capability is
|
|
195
|
+
unavailable. System Windows PowerShell runs the fixed driver with `-File`;
|
|
196
|
+
paths remain data, with no runtime-generated helper script or encoded launcher.
|
|
197
|
+
The [Windows security fallback prerequisites](install.md#windows-security-fallback)
|
|
198
|
+
apply, and unsupported or disallowed command execution fails closed. This route
|
|
199
|
+
preserves raw ACL facts, private DACLs at creation, and descriptor-bound secure
|
|
200
|
+
reads, and emits a path-free `FS_SAFE_NATIVE_FALLBACK` warning once per capability
|
|
201
|
+
per process. Each call adds PowerShell startup and compilation overhead.
|
|
202
|
+
`require` rejects missing capabilities without a command, and an available native operation's
|
|
203
|
+
failure never triggers this fallback. See [Permissions](permissions.md) and
|
|
204
|
+
[Secure file reads](secure-file.md) for error and platform contracts.
|
|
205
|
+
|
|
181
206
|
The staged-file owner also serves POSIX native pinned writes, including streaming.
|
|
182
207
|
Unpublished files remain at `0600`; requested modes are applied through the
|
|
183
208
|
owned file descriptor only after rename and published-entry identity validation.
|
|
@@ -219,15 +244,21 @@ rejection, archive filters/limits/modes, exclusive target creation, source and
|
|
|
219
244
|
target identity fencing, publication cleanup receipts, and secret/lock policy
|
|
220
245
|
remain TypeScript-owned. What changes is the syscall strength or availability:
|
|
221
246
|
|
|
247
|
+
The table compares underlying mechanisms. On Node, public `Root.open()`,
|
|
248
|
+
`Root.read()`, and `Root.openWritable()` use guarded Node file opens and report
|
|
249
|
+
`containment: "best-effort"` in every native mode. `require` checks availability
|
|
250
|
+
when an operation requests native support; it does not upgrade those results.
|
|
251
|
+
See [Root containment guarantees](security-model.md#containment-guarantees-by-platform).
|
|
252
|
+
|
|
222
253
|
| Capability | Native path | Guarded JavaScript path |
|
|
223
254
|
|---|---|---|
|
|
224
|
-
| Root
|
|
255
|
+
| Native beneath opens and Root mutations | Descriptor-relative beneath operations. Pinned writes create parents and publish both replacement and no-replace targets relative to open directory descriptors. No-clobber `Root.move()` admits both parents and uses the native no-replace rename. Native `openBeneath()` reports `kernel-atomic` on Linux and `best-effort` on macOS and Windows. macOS uses `O_RESOLVE_BENEATH` when available plus an `F_GETPATH` detector, while Windows rejects reparse traversal in the object-manager call. | Reports `best-effort`: component-wise alias checks, no-follow opens where Node exposes them, private temp/rename, and post-operation identity verification. No-clobber `Root.move()` is unsupported because a check followed by a replacing rename is unsafe. A same-privilege peer can replace a writable parent after a guard assertion but before Node resolves another pathname mutation; the mutation may land outside the intended root before the post-check detects it. |
|
|
225
256
|
| ZIP/TAR/gzip | Rust streaming decode and fd-relative output creation. | Optional JSZip or bundled WASM TAR into guarded private staging, then the same guarded merge policy. |
|
|
226
|
-
| Zstd/bzip2 TAR |
|
|
257
|
+
| Zstd/bzip2 TAR | Rust streaming decode and fd-relative output creation. | Bundled WASM codecs feed the shared Rust TAR parser, then guarded private staging and the same merge policy; no optional codec dependency. |
|
|
227
258
|
| Publication copy | Clone, Linux `copy_file_range`, async native SHA-256. | Exclusive `wx` byte loop and Node SHA-256 with the same content/identity fences. |
|
|
228
259
|
| `rename-noreplace` | Atomic platform no-replace rename. | Unsupported; no emulation by check-then-rename. |
|
|
229
|
-
| Windows DACL read | Direct `GetSecurityInfo`; the public facts API exposes ordered basic allow/deny ACE SIDs, masks, and decoded flags without trust policy. Secure-file reads query the borrowed open descriptor and compare its 32-bit volume serial and 64-bit file-index projection with Node's bigint receipt. |
|
|
230
|
-
| Windows private directory | Creation-time protected DACL. |
|
|
260
|
+
| Windows DACL read | Direct `GetSecurityInfo`; the public facts API exposes ordered basic allow/deny ACE SIDs, masks, and decoded flags without trust policy. Secure-file reads query the borrowed open descriptor and compare its 32-bit volume serial and 64-bit file-index projection with Node's bigint receipt. | The packaged PowerShell/C# bridge preserves raw facts and inspects the borrowed descriptor for secure reads, with the same Node identity comparison; its command failures reject. Structured .NET pathname reporting retains its separate compatibility query. |
|
|
261
|
+
| Windows private directory | Creation-time protected DACL. | The packaged PowerShell/C# bridge applies the protected DACL at creation and retains exact handles through identity validation and failure cleanup. Command failures reject. |
|
|
231
262
|
|
|
232
263
|
Use `off` in CI to keep the fallback contract exercised. Use `require` when a
|
|
233
264
|
deployment depends on the stronger mechanism or a native-only feature; do not
|
package/docs/permissions.md
CHANGED
|
@@ -42,7 +42,7 @@ POSIX remediation strings shell-quote paths with whitespace or metacharacters
|
|
|
42
42
|
and protect option-like paths with `--`, so they can be presented as commands
|
|
43
43
|
without letting the inspected pathname add shell syntax.
|
|
44
44
|
|
|
45
|
-
`inspectPathPermissions()` follows symlink targets for the effective mode but tells you whether the original path was a symlink. On POSIX it reports owner/group/world bits. On Windows it delegates to the ACL helpers below and also reports `ownerSid` plus `ownerTrusted` when ownership can be verified. `ownerTrusted` is true only for a local volume owned by the current user, LocalSystem, or built-in Administrators; remote filesystems fail closed. This remains a pathname reporting API with the fallbacks described below. `readSecureFile()`
|
|
45
|
+
`inspectPathPermissions()` follows symlink targets for the effective mode but tells you whether the original path was a symlink. On POSIX it reports owner/group/world bits. On Windows it delegates to the ACL helpers below and also reports `ownerSid` plus `ownerTrusted` when ownership can be verified. `ownerTrusted` is true only for a local volume owned by the current user, LocalSystem, or built-in Administrators; remote filesystems fail closed. This remains a pathname reporting API with the fallbacks described below. `readSecureFile()` obtains descriptor-bound owner/DACL facts for the exact handle it reads, using native support or the packaged PowerShell/C# bridge in `auto` and `off` modes.
|
|
46
46
|
|
|
47
47
|
## Advanced Windows ACL helpers
|
|
48
48
|
|
|
@@ -69,9 +69,10 @@ resolveWindowsUserPrincipal(env);
|
|
|
69
69
|
```
|
|
70
70
|
|
|
71
71
|
The fallback Windows inspector reads the owner and DACL together through one
|
|
72
|
-
built-in Windows PowerShell/.NET query.
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
built-in Windows PowerShell/.NET query. The query addresses its JSON command by
|
|
73
|
+
module name and limits module discovery to PowerShell's bundled system modules.
|
|
74
|
+
It returns canonical SIDs and numeric access masks, so Unicode paths and account
|
|
75
|
+
names do not pass through lossy console display text. `inspectWindowsAcl()` uses native descriptor facts for
|
|
75
76
|
complete local ACLs with nonzero inherited ACEs (or empty/null DACLs) when the
|
|
76
77
|
optional Windows binding is available. It applies
|
|
77
78
|
the same classifier to native facts and the fallback query, returning canonical
|
|
@@ -171,10 +172,12 @@ Object-specific and other ACE layouts are not guessed: they are omitted,
|
|
|
171
172
|
`complete` becomes false, and their numeric types appear in
|
|
172
173
|
`unsupportedAceTypes`, allowing a security-sensitive caller to fail closed.
|
|
173
174
|
Non-Windows systems return `{ status: "unsupported-platform", platform }`.
|
|
174
|
-
Windows
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
175
|
+
Windows prefers the native binding. In native `auto` or `off` mode, a missing
|
|
176
|
+
binding or capability uses the packaged PowerShell/C# bridge with
|
|
177
|
+
the same raw ACE projection. Native `require` rejects either absence with
|
|
178
|
+
`FsSafeError("helper-unavailable")` and starts no command. An available native
|
|
179
|
+
query's failure is terminal. The existing coarse `inspectPathPermissions()` API
|
|
180
|
+
still owns its compatibility fallback and trust classification.
|
|
178
181
|
|
|
179
182
|
## Private directories
|
|
180
183
|
|
|
@@ -188,10 +191,11 @@ await createPrivateDirectory(sqliteDirectory);
|
|
|
188
191
|
await openSqlite(path.join(sqliteDirectory, "sessions.sqlite"));
|
|
189
192
|
```
|
|
190
193
|
|
|
191
|
-
On Windows
|
|
194
|
+
On Windows, this creates the directory and applies a
|
|
192
195
|
protected owner + LocalSystem + Administrators full-control DACL directly with
|
|
193
|
-
an atomic security descriptor
|
|
194
|
-
|
|
196
|
+
an atomic security descriptor. The native route launches no command. When its
|
|
197
|
+
binding or capability is unavailable, native `auto` and `off` modes use the
|
|
198
|
+
packaged PowerShell/C# bridge. Both routes retain the parent and exact created-directory handles
|
|
195
199
|
through ACL and final pathname validation. If validation fails, it attempts only
|
|
196
200
|
nonrecursive deletion through the created handle, preserving any pathname
|
|
197
201
|
replacement. If cleanup also fails, the error retains the original failure and
|
|
@@ -216,13 +220,32 @@ also rejects explicit `.` and `..` components, including spellings such as
|
|
|
216
220
|
`.\private` and `parent\..\private`, as a compatibility restriction. Simple
|
|
217
221
|
relative names without these components remain supported.
|
|
218
222
|
|
|
219
|
-
This API is Windows-only
|
|
220
|
-
|
|
221
|
-
|
|
223
|
+
This API is Windows-only; it fails closed with `FsSafeError("helper-unavailable")`
|
|
224
|
+
on other platforms. Native `require` also fails if the binding or capability is
|
|
225
|
+
missing and never starts a command. An available native operation's failure is
|
|
226
|
+
terminal. POSIX callers should create private
|
|
222
227
|
directories through their existing trusted-root creation policy rather than a
|
|
223
228
|
pathname-only compatibility shim. Existing Windows permission inspection still
|
|
224
229
|
retains its structured .NET compatibility fallback.
|
|
225
230
|
|
|
231
|
+
The raw owner/DACL and private-directory fallbacks each emit one path-free
|
|
232
|
+
`FS_SAFE_NATIVE_FALLBACK` warning per process. PowerShell startup and C#
|
|
233
|
+
compilation add overhead to each call; install the native package for frequent
|
|
234
|
+
operations. These routes run the package's readable, fixed scripts under normal
|
|
235
|
+
system PowerShell policy; see the [Windows security fallback prerequisites](install.md#windows-security-fallback).
|
|
236
|
+
If command support is unavailable, disallowed, or fails, the operation rejects.
|
|
237
|
+
Private-directory creation never falls back to inherited permissions.
|
|
238
|
+
The asynchronous creation command has a 30-second deadline. After a timeout or
|
|
239
|
+
transport failure, fs-safe requests termination and waits at most one further
|
|
240
|
+
second before rejecting and closing its output pipes. The error distinguishes
|
|
241
|
+
observed process exit from an unconfirmed termination attempt. If the OS refuses
|
|
242
|
+
termination, the command can still create the directory after rejection. An
|
|
243
|
+
already-created object retains its protected DACL, but pathname validation and
|
|
244
|
+
owned-handle cleanup may not finish. An error therefore does not prove the
|
|
245
|
+
pathname is absent; a retry can report `EEXIST`. Before retrying or using the
|
|
246
|
+
pathname, establish that the earlier operation stopped and verify any existing
|
|
247
|
+
directory's security. The library does not attempt pathname-based cleanup.
|
|
248
|
+
|
|
226
249
|
Use `createIcaclsResetCommand()` when you need a structured command and argv pair. Use `formatIcaclsResetCommand()` when you only need a remediation string for a user-facing message.
|
|
227
250
|
|
|
228
251
|
## Types
|
package/docs/root.md
CHANGED
|
@@ -130,8 +130,32 @@ fs.mkdir(rel, options?) // mkdir -p (creates missing parents)
|
|
|
130
130
|
fs.ensureRoot(options?) // accepts "" / "." as the root itself
|
|
131
131
|
```
|
|
132
132
|
|
|
133
|
+
`mkdir`, `ensureRoot`, `create`, and `createJson` accept `private: true`.
|
|
134
|
+
Missing directories are created with private permissions, and an existing
|
|
135
|
+
requested directory must already be private. Existing ancestors are not
|
|
136
|
+
chmodded or assigned new ACLs. Private files use owner-only POSIX permissions
|
|
137
|
+
or a protected Windows DACL granting access to the current user, System, and
|
|
138
|
+
Administrators. On macOS, private directories and files must also have no ACL;
|
|
139
|
+
creation rejects relevant inheritable parent ACLs, while noninheriting parent
|
|
140
|
+
ACLs remain allowed. A native helper with `inspectDarwinAcl` is required. Native
|
|
141
|
+
`off`, a missing helper, or an older helper without that capability rejects with
|
|
142
|
+
`helper-unavailable` before creating parents or stages. See [creation](creation.md)
|
|
143
|
+
for platform support, synchronous leaf creation, and failure handling.
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
await fs.mkdir("private-data", { private: true });
|
|
147
|
+
await fs.create("private-data/credential", "synthetic credential", { private: true });
|
|
148
|
+
```
|
|
149
|
+
|
|
133
150
|
`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`).
|
|
134
151
|
|
|
152
|
+
Buffered `create` and `createJson` also accept `atomic?: boolean`. With `true`,
|
|
153
|
+
complete content is staged before exclusive publication even in native-off mode;
|
|
154
|
+
the fallback requires hardlinks. Omitted or `false` keeps the existing buffered
|
|
155
|
+
publication behavior. Streamed creates always stage complete content. The flag
|
|
156
|
+
does not change `durable` or promise stronger containment or crash durability.
|
|
157
|
+
See [atomic creation and settlement](writing.md#atomic-buffered-creation).
|
|
158
|
+
|
|
135
159
|
`create` also accepts `AsyncIterable<Uint8Array>` with `RootCreateStreamOptions`:
|
|
136
160
|
the same path, authority, mode, and durability options, plus `maxBytes` and
|
|
137
161
|
`signal`, without `encoding` or `renameIdentity`. It consumes one chunk at a
|
|
@@ -152,6 +176,11 @@ and parent-directory fsync calls. Use it only for reconstructible data: a crash
|
|
|
152
176
|
may lose the write or leave the previous file. See [Writing](writing.md#write-options)
|
|
153
177
|
for platform details.
|
|
154
178
|
|
|
179
|
+
`create` and `createJson` additionally accept `durable: "file"` to require file
|
|
180
|
+
synchronization, including propagating `EPERM`. Parent-directory synchronization
|
|
181
|
+
retains its existing best-effort behavior. This option applies to buffered and
|
|
182
|
+
streamed creation and does not select a publication strategy.
|
|
183
|
+
|
|
155
184
|
`copyIn` accepts a `RootCopySource`: a trusted absolute source path or a file
|
|
156
185
|
within another Root. The guarded form supplies `root` with only its `open` and
|
|
157
186
|
`stat` read capabilities, plus `relativePath`:
|
|
@@ -300,6 +329,11 @@ the caller, which must check authority before its own later writes.
|
|
|
300
329
|
|
|
301
330
|
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.
|
|
302
331
|
|
|
332
|
+
`move()` snapshots its merged default and per-call mutation policy before
|
|
333
|
+
asynchronous preparation. Later changes to the original policy objects or arrays
|
|
334
|
+
apply to subsequent calls. Use `assertBeforeMutation` for live revocation of an
|
|
335
|
+
in-flight move.
|
|
336
|
+
|
|
303
337
|
For writes, creates, streams, and copies, parent creation admits the prospective
|
|
304
338
|
file and each missing directory before creating that directory, including on the
|
|
305
339
|
Windows native route. An exact deny on an existing parent does not prevent using
|
package/docs/secret-file.md
CHANGED
|
@@ -133,6 +133,15 @@ startWebhookVerifier(signingKey);
|
|
|
133
133
|
|
|
134
134
|
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.
|
|
135
135
|
|
|
136
|
+
On POSIX, both native and JavaScript writers verify actual `0o600` permission
|
|
137
|
+
bits through the retained descriptor before writing content. A filesystem that
|
|
138
|
+
reports successful chmod without enforcing those bits fails with
|
|
139
|
+
`insecure-permissions` before any payload is written, including when an explicit
|
|
140
|
+
`dirMode` permits other users to traverse the parent. The requested final `mode`
|
|
141
|
+
is still applied after content writes, including restrictive and special-bit
|
|
142
|
+
overrides. This mode-bit check does not require native ACL inspection; JavaScript
|
|
143
|
+
secret writes remain available on macOS.
|
|
144
|
+
|
|
136
145
|
Concurrent writes to distinct leaves may share creation of a missing parent.
|
|
137
146
|
After a parent-creation race, the helper re-inspects the entry and requires a
|
|
138
147
|
non-symlink directory, then revalidates root/parent guards, containment, and
|
|
@@ -270,9 +279,9 @@ await withTimeout(
|
|
|
270
279
|
|
|
271
280
|
## Threat model notes
|
|
272
281
|
|
|
273
|
-
-
|
|
282
|
+
- On POSIX, the default `0600` file and `0700` directory modes restrict group and other access. They do not protect against processes with the same UID, root, attackers who can read process memory, or access granted by additional ACL entries.
|
|
274
283
|
- Validation failures are tripwires, not authorization. Investigate before clearing a rejected credential file.
|
|
275
|
-
-
|
|
284
|
+
- On POSIX, a file that still reports a mode other than `0600` after initialization is rejected with `insecure-permissions` before payload is written. Matching mode reports alone cannot prove that an arbitrary filesystem actually enforces those permissions.
|
|
276
285
|
|
|
277
286
|
## See also
|
|
278
287
|
|
package/docs/secure-file.md
CHANGED
|
@@ -27,9 +27,13 @@ The helper:
|
|
|
27
27
|
- enforces `maxBytes` before and after reading
|
|
28
28
|
- closes the handle on success, error, and timeout
|
|
29
29
|
|
|
30
|
-
On POSIX, unsafe permissions mean group/world writable, and group/world readable unless `permissions.allowReadableByOthers` is true. On Windows, the helper queries owner, DACL, and locality from the same open descriptor that supplies the bytes.
|
|
30
|
+
On POSIX, unsafe permissions mean group/world writable, and group/world readable unless `permissions.allowReadableByOthers` is true. On Windows, the helper queries owner, DACL, and locality from the same open descriptor that supplies the bytes. Both native and system-command queries return the 32-bit volume serial and 64-bit file-index projection used by Node, which must equal Node's bigint descriptor receipt before its ACL facts are trusted. This avoids JavaScript number rounding but does not represent the full 128-bit file identity available on ReFS. Only the current user, LocalSystem, and built-in Administrators are trusted owner classes.
|
|
31
31
|
|
|
32
|
-
Windows secure reads
|
|
32
|
+
Windows secure reads prefer the matching optional native package. In native `auto` or `off` mode, a missing binding or descriptor-inspection capability uses a packaged, readable PowerShell script and adjacent C# source to inspect the borrowed file handle. This route requires the [Windows security fallback prerequisites](install.md#windows-security-fallback), including permission to run the scripts under normal system policy. The command does not read file contents or reopen the pathname. Successful inspection waits for the child to exit and its output pipes to close. This emits a path-free `FS_SAFE_NATIVE_FALLBACK` warning once per process for secure reads and adds PowerShell startup and compilation overhead to each inspection.
|
|
33
|
+
|
|
34
|
+
Descriptor commands have a 30-second deadline. After a timeout or transport failure, fs-safe requests termination, waits at most one further second, and then rejects even if process exit or pipe closure remains unconfirmed. It closes its own output pipes and reports the observed exit separately from the termination attempt in the error cause. If the OS refuses termination, the child may retain its independently inherited Windows handle; closing the caller's descriptor cannot retarget that handle. No file bytes are returned from a failed inspection.
|
|
35
|
+
|
|
36
|
+
Native `require` still rejects a missing binding or capability with `permission-unverified`, without starting a command. An available native helper's failure is terminal. On either route, fd-to-handle conversion failure, denied `READ_CONTROL`, a remote handle, incomplete descriptor, unsupported ACE form, or unavailable command support rejects with `permission-unverified` before content is read. A malformed or different handle identity rejects with `path-mismatch`. The standalone reporting APIs in [`permissions`](permissions.md) retain their documented pathname fallbacks. `permissions.allowInsecure` remains the explicit escape hatch and bypasses the ACL query.
|
|
33
37
|
|
|
34
38
|
Descriptor, pathname, and realpath identity checks use bigint stats internally to avoid JavaScript number rounding. 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.
|
|
35
39
|
|
|
@@ -92,13 +96,14 @@ On an actual Windows process with effective `platform: "win32"`, `inject.env` an
|
|
|
92
96
|
| `timeout` | `timeoutMs` elapsed while reading. |
|
|
93
97
|
|
|
94
98
|
Windows descriptor-inspection failures are operational `permission-unverified`
|
|
95
|
-
errors and refuse the read. The original native exception is retained as
|
|
99
|
+
errors and refuse the read. The original native or descriptor-command exception is retained as
|
|
96
100
|
`cause`; treat causes as restricted local diagnostic data. No pathname or ACL
|
|
97
101
|
content is copied into the display message. Test adapters that simulate Windows
|
|
98
102
|
on another operating system retain the standalone pathname inspector's
|
|
99
103
|
structured command diagnostics (`ownerError`, `command`, `durationMs`,
|
|
100
104
|
`timedOut`, `exitCode`, `signal`, and bounded escaped `stderr`). Actual Windows
|
|
101
|
-
secure reads
|
|
105
|
+
secure reads never invoke the injected pathname inspector: their optional
|
|
106
|
+
command route inspects the borrowed descriptor instead. No retries are performed.
|
|
102
107
|
|
|
103
108
|
## See also
|
|
104
109
|
|
package/docs/sidecar-lock.md
CHANGED
|
@@ -295,10 +295,11 @@ Discarding an acquisition observation is not proof that the pathname is absent:
|
|
|
295
295
|
another owner may already have created the next record. Every discarded
|
|
296
296
|
observation consumes the normal retry/deadline budget and requires fresh
|
|
297
297
|
exclusive creation. It supplies no release, reclaim, or held-lock authority.
|
|
298
|
-
If that successor disappears during the recovery metadata probe,
|
|
299
|
-
may discard the probe only with an operation-local receipt for an
|
|
300
|
-
regular file with one link
|
|
301
|
-
|
|
298
|
+
If that successor disappears or is replaced during the recovery metadata probe,
|
|
299
|
+
the waiter may discard the probe only with an operation-local receipt for an
|
|
300
|
+
admitted regular file with one link. Replacement also requires a single exact
|
|
301
|
+
observation of a different regular file with one link. Current Root and canonical
|
|
302
|
+
ancestor checks must still pass. A generic metadata error does not permit this retry, and public
|
|
302
303
|
`Root.stat()` still rejects a file that changes during observation.
|
|
303
304
|
Generic `Root.open()` and held-owner/reclaim reads still reject failed opens.
|
|
304
305
|
Moving an already-matched pinned descriptor without unlinking it, unknown or
|
package/docs/staged-file.md
CHANGED
|
@@ -65,6 +65,11 @@ interface StagedFile extends AsyncDisposable {
|
|
|
65
65
|
Strings are UTF-8. `mode` is the requested **published** mode and defaults to
|
|
66
66
|
`0600`; exact final modes, including `000`, are supported. The unpublished file
|
|
67
67
|
stays at `0600` throughout preparation and any awaited application checks.
|
|
68
|
+
The retained descriptor's actual mode is checked before writing payload bytes,
|
|
69
|
+
by `assertCurrent()`, and before publication; a successful but ineffective
|
|
70
|
+
`chmod` fails with `insecure-permissions`. Final mode verification after
|
|
71
|
+
publication can fail with a `published` receipt while preserving the completed
|
|
72
|
+
file. These are POSIX mode checks, not ACL or ownership admission.
|
|
68
73
|
After rename succeeds and the published entry passes identity validation, the
|
|
69
74
|
owner applies the requested mode through its retained file descriptor. Content
|
|
70
75
|
was synchronized during preparation; publication always synchronizes the parent.
|
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.
|
|
@@ -154,6 +162,41 @@ try {
|
|
|
154
162
|
}
|
|
155
163
|
```
|
|
156
164
|
|
|
165
|
+
### Atomic buffered creation
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
await fs.create("config/seed.json", initial, { atomic: true });
|
|
169
|
+
await fs.createJson("config/settings.json", { enabled: true }, { atomic: true });
|
|
170
|
+
await fs.create("config/flushed.json", initial, { atomic: true, durable: "file" });
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
`atomic: true` keeps the destination absent until all bytes have been written.
|
|
174
|
+
The native backend uses its no-replace rename; the JavaScript fallback hardlinks
|
|
175
|
+
the completed stage and unlinks its temporary name in the same JavaScript turn.
|
|
176
|
+
The fallback requires hardlink support and fails without publishing partial bytes
|
|
177
|
+
when that mechanism is unavailable. Other processes can briefly observe both
|
|
178
|
+
names. Existing and raced entries are preserved, including dangling symlinks;
|
|
179
|
+
ordinary confinement, type, hardlink, and symlink-policy rejections still apply.
|
|
180
|
+
`assertBeforeMutation` retains its live checks through content writes and publication.
|
|
181
|
+
|
|
182
|
+
Omitted or `false` preserves the existing buffered behavior. The option belongs
|
|
183
|
+
to buffered `create` and `createJson`, not replacement writes or Root defaults.
|
|
184
|
+
Streamed creation has no atomic opt-out. `atomic` changes visibility, not the
|
|
185
|
+
existing `durable` file/directory synchronization policy; it does not turn
|
|
186
|
+
best-effort synchronization into a strict crash-durability guarantee or strengthen
|
|
187
|
+
JavaScript pathname containment.
|
|
188
|
+
|
|
189
|
+
Atomic and streamed creates settle owned cleanup and close operations before
|
|
190
|
+
returning. Failed or unverifiable cleanup is reported rather than silently
|
|
191
|
+
discarded. Errors after publication and incomplete-settlement errors carry the
|
|
192
|
+
existing `StagedFileFailureDetails` publication/cleanup receipts where the writer
|
|
193
|
+
can establish them; native disposal can retain them inside a `SuppressedError`
|
|
194
|
+
cause. Preserve those details when handling errors: a rejection can follow
|
|
195
|
+
complete publication, and an indeterminate link or native rename must preserve names for
|
|
196
|
+
recovery. A cleanup or close failure also retains the original operation failure.
|
|
197
|
+
No later verification, mode, or synchronization failure authorizes deleting an
|
|
198
|
+
already published complete destination. See [receipt meanings](staged-file.md).
|
|
199
|
+
|
|
157
200
|
### Streamed creation
|
|
158
201
|
|
|
159
202
|
Pass an `AsyncIterable<Uint8Array>` to `create()` when bytes come from a database,
|
|
@@ -202,6 +245,12 @@ forcibly interrupted, so cancellation waits for its pending work and cleanup to
|
|
|
202
245
|
settle. Do not mutate a yielded chunk until the next pull. Producer errors retain
|
|
203
246
|
their original value when cleanup succeeds.
|
|
204
247
|
|
|
248
|
+
Streamed creation retains the `signal` and `assertBeforeMutation` callback
|
|
249
|
+
selected when the call starts. Replacing or deleting those options during a
|
|
250
|
+
producer wait does not change the in-flight operation. Abort the original signal
|
|
251
|
+
or update the live authority state checked by the original callback to revoke
|
|
252
|
+
it; the callback continues to receive the original options object as `this`.
|
|
253
|
+
|
|
205
254
|
An aborted or failed operation can leave created parent directories. If a
|
|
206
255
|
stage's identity or parent cannot be verified during cleanup, the existing
|
|
207
256
|
guarded cleanup preserves it. After publication, later verification or cleanup
|
|
@@ -268,6 +317,10 @@ await fs.move("incoming/foo.txt", "archive/foo.txt", { overwrite: true });
|
|
|
268
317
|
|
|
269
318
|
Both `from` and `to` are bounded; `..` in either is rejected.
|
|
270
319
|
|
|
320
|
+
Mutation policy is captured at call start; changes to caller-owned denial arrays
|
|
321
|
+
apply to later moves. For live cancellation or revocation, throw from
|
|
322
|
+
`assertBeforeMutation` immediately before dispatch.
|
|
323
|
+
|
|
271
324
|
The default no-clobber mode requires the native helper. It admits both parent
|
|
272
325
|
directory descriptors and performs a descriptor-relative no-replace rename, so
|
|
273
326
|
a competitor that creates the target first is preserved and the source remains
|
|
@@ -407,6 +460,19 @@ an atomic check-and-delete syscall. Use OS isolation for that threat model.
|
|
|
407
460
|
await fs.mkdir("snapshots/2026/05");
|
|
408
461
|
```
|
|
409
462
|
|
|
463
|
+
Pass `{ private: true }` to create missing components with private permissions.
|
|
464
|
+
An existing requested directory must already satisfy that policy; fs-safe does
|
|
465
|
+
not repair it or change existing ancestor permissions. Concurrent creators may
|
|
466
|
+
reuse the winner only after it passes the same checks.
|
|
467
|
+
|
|
468
|
+
Buffered, streamed, and JSON `create` calls also accept `private: true`.
|
|
469
|
+
New POSIX directories default to `0700` and files to `0600`; conflicting
|
|
470
|
+
group/world or privilege bits are rejected before creation. Restrictive
|
|
471
|
+
owner-only file modes remain available through `mode`. On Windows, creation
|
|
472
|
+
uses protected ACLs rather than interpreting POSIX mode bits as access rules.
|
|
473
|
+
This does not change `create`'s no-overwrite behavior or select its durability
|
|
474
|
+
policy. See [creation](creation.md) for supported backends and owned descriptors.
|
|
475
|
+
|
|
410
476
|
### `fs.ensureRoot()`
|
|
411
477
|
|
|
412
478
|
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.16.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.16.0",
|
|
174
|
+
"@openclaw/fs-safe-darwin-x64": "0.16.0",
|
|
175
|
+
"@openclaw/fs-safe-linux-arm64-gnu": "0.16.0",
|
|
176
|
+
"@openclaw/fs-safe-linux-arm64-musl": "0.16.0",
|
|
177
|
+
"@openclaw/fs-safe-linux-x64-gnu": "0.16.0",
|
|
178
|
+
"@openclaw/fs-safe-linux-x64-musl": "0.16.0",
|
|
179
|
+
"@openclaw/fs-safe-win32-x64-msvc": "0.16.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
|
}
|