@openclaw/fs-safe 0.7.2 → 0.8.1

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.
Files changed (159) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/README.md +5 -1
  3. package/dist/absolute-path.d.ts.map +1 -1
  4. package/dist/absolute-path.js +9 -10
  5. package/dist/archive-merge.d.ts +18 -0
  6. package/dist/archive-merge.d.ts.map +1 -0
  7. package/dist/archive-merge.js +157 -0
  8. package/dist/archive-native.d.ts.map +1 -1
  9. package/dist/archive-native.js +25 -5
  10. package/dist/archive-policy.d.ts +1 -1
  11. package/dist/archive-policy.d.ts.map +1 -1
  12. package/dist/archive-policy.js +1 -1
  13. package/dist/archive-read.d.ts.map +1 -1
  14. package/dist/archive-read.js +3 -2
  15. package/dist/archive-staging.d.ts +13 -8
  16. package/dist/archive-staging.d.ts.map +1 -1
  17. package/dist/archive-staging.js +44 -192
  18. package/dist/archive-tar-meta.d.ts.map +1 -1
  19. package/dist/archive-tar-meta.js +9 -5
  20. package/dist/archive-tar-runtime.d.ts +1 -0
  21. package/dist/archive-tar-runtime.d.ts.map +1 -1
  22. package/dist/archive-zip-admission.d.ts +2 -1
  23. package/dist/archive-zip-admission.d.ts.map +1 -1
  24. package/dist/archive-zip-admission.js +2 -2
  25. package/dist/archive-zip-directory.d.ts +8 -1
  26. package/dist/archive-zip-directory.d.ts.map +1 -1
  27. package/dist/archive-zip-directory.js +6 -2
  28. package/dist/archive-zip-entry.d.ts +1 -1
  29. package/dist/archive-zip-entry.d.ts.map +1 -1
  30. package/dist/archive-zip-names.d.ts +1 -1
  31. package/dist/archive-zip-names.d.ts.map +1 -1
  32. package/dist/archive-zip-names.js +1 -0
  33. package/dist/archive.d.ts.map +1 -1
  34. package/dist/archive.js +17 -25
  35. package/dist/directory-guard.d.ts +17 -5
  36. package/dist/directory-guard.d.ts.map +1 -1
  37. package/dist/directory-guard.js +8 -6
  38. package/dist/directory-mode-node.d.ts +8 -0
  39. package/dist/directory-mode-node.d.ts.map +1 -0
  40. package/dist/directory-mode-node.js +93 -0
  41. package/dist/directory-mode-owner.d.ts +21 -0
  42. package/dist/directory-mode-owner.d.ts.map +1 -0
  43. package/dist/directory-mode-owner.js +73 -0
  44. package/dist/file-observation.d.ts +1 -1
  45. package/dist/file-observation.d.ts.map +1 -1
  46. package/dist/file-store-boundary.d.ts +2 -0
  47. package/dist/file-store-boundary.d.ts.map +1 -1
  48. package/dist/file-store-boundary.js +13 -0
  49. package/dist/file-store.d.ts.map +1 -1
  50. package/dist/file-store.js +8 -11
  51. package/dist/filename.d.ts +6 -0
  52. package/dist/filename.d.ts.map +1 -1
  53. package/dist/filename.js +36 -0
  54. package/dist/guarded-mkdir.d.ts +2 -0
  55. package/dist/guarded-mkdir.d.ts.map +1 -1
  56. package/dist/guarded-mkdir.js +2 -2
  57. package/dist/guarded-mutation.d.ts +2 -2
  58. package/dist/guarded-mutation.d.ts.map +1 -1
  59. package/dist/json-document-store.d.ts +3 -0
  60. package/dist/json-document-store.d.ts.map +1 -1
  61. package/dist/json-document-store.js +2 -0
  62. package/dist/json-durable-queue-ownership.d.ts +3 -1
  63. package/dist/json-durable-queue-ownership.d.ts.map +1 -1
  64. package/dist/json-durable-queue-ownership.js +7 -4
  65. package/dist/json-durable-queue.d.ts.map +1 -1
  66. package/dist/json-durable-queue.js +25 -28
  67. package/dist/local-roots.d.ts.map +1 -1
  68. package/dist/local-roots.js +18 -56
  69. package/dist/move-path-cleanup.d.ts +43 -0
  70. package/dist/move-path-cleanup.d.ts.map +1 -0
  71. package/dist/move-path-cleanup.js +159 -0
  72. package/dist/move-path.d.ts.map +1 -1
  73. package/dist/move-path.js +30 -84
  74. package/dist/native-operations.d.ts +2 -4
  75. package/dist/native-operations.d.ts.map +1 -1
  76. package/dist/native-operations.js +7 -9
  77. package/dist/native-pinned-write-windows.d.ts +2 -2
  78. package/dist/native-pinned-write-windows.d.ts.map +1 -1
  79. package/dist/native-pinned-write-windows.js +5 -5
  80. package/dist/native-pinned-write.d.ts.map +1 -1
  81. package/dist/native-pinned-write.js +14 -4
  82. package/dist/native-staged-file.d.ts +2 -2
  83. package/dist/native-staged-file.d.ts.map +1 -1
  84. package/dist/opened-file-failure.d.ts +1 -0
  85. package/dist/opened-file-failure.d.ts.map +1 -1
  86. package/dist/opened-file-failure.js +4 -0
  87. package/dist/output-sibling.d.ts.map +1 -1
  88. package/dist/output-sibling.js +9 -3
  89. package/dist/pinned-write.d.ts +2 -2
  90. package/dist/pinned-write.d.ts.map +1 -1
  91. package/dist/pinned-write.js +32 -13
  92. package/dist/publish-file.d.ts.map +1 -1
  93. package/dist/publish-file.js +7 -3
  94. package/dist/regular-file.d.ts +1 -1
  95. package/dist/regular-file.d.ts.map +1 -1
  96. package/dist/regular-file.js +35 -6
  97. package/dist/replace-file-descriptor.d.ts +9 -1
  98. package/dist/replace-file-descriptor.d.ts.map +1 -1
  99. package/dist/replace-file-descriptor.js +58 -10
  100. package/dist/replace-file-temp-owner.d.ts +7 -0
  101. package/dist/replace-file-temp-owner.d.ts.map +1 -1
  102. package/dist/replace-file-temp-owner.js +29 -0
  103. package/dist/replace-file.d.ts +1 -0
  104. package/dist/replace-file.d.ts.map +1 -1
  105. package/dist/replace-file.js +12 -38
  106. package/dist/root-context.d.ts +4 -0
  107. package/dist/root-context.d.ts.map +1 -1
  108. package/dist/root-context.js +19 -0
  109. package/dist/root-impl.d.ts +43 -0
  110. package/dist/root-impl.d.ts.map +1 -1
  111. package/dist/root-impl.js +13 -11
  112. package/dist/root-path-symlink.d.ts +6 -2
  113. package/dist/root-path-symlink.d.ts.map +1 -1
  114. package/dist/root-path-symlink.js +7 -6
  115. package/dist/root-path.d.ts +1 -0
  116. package/dist/root-path.d.ts.map +1 -1
  117. package/dist/root-path.js +6 -2
  118. package/dist/root-walk.d.ts.map +1 -1
  119. package/dist/root-walk.js +4 -0
  120. package/dist/root-write-verification.d.ts +3 -2
  121. package/dist/root-write-verification.d.ts.map +1 -1
  122. package/dist/root-write-verification.js +6 -0
  123. package/dist/secret-file.d.ts +9 -0
  124. package/dist/secret-file.d.ts.map +1 -1
  125. package/dist/secret-file.js +136 -74
  126. package/dist/sibling-temp.d.ts.map +1 -1
  127. package/dist/sibling-temp.js +9 -3
  128. package/dist/sidecar-lock-acquire.d.ts +1 -0
  129. package/dist/sidecar-lock-acquire.d.ts.map +1 -1
  130. package/dist/sidecar-lock-acquire.js +24 -5
  131. package/dist/sidecar-lock-reclaim.d.ts.map +1 -1
  132. package/dist/sidecar-lock-reclaim.js +6 -4
  133. package/dist/sidecar-lock-types.d.ts +7 -0
  134. package/dist/sidecar-lock-types.d.ts.map +1 -1
  135. package/dist/sidecar-lock.d.ts +2 -0
  136. package/dist/sidecar-lock.d.ts.map +1 -1
  137. package/dist/sidecar-lock.js +44 -3
  138. package/dist/write-open-flags.d.ts +5 -0
  139. package/dist/write-open-flags.d.ts.map +1 -0
  140. package/dist/write-open-flags.js +35 -0
  141. package/docs/advanced.md +1 -1
  142. package/docs/archive.md +56 -7
  143. package/docs/atomic.md +8 -2
  144. package/docs/contributing.md +13 -0
  145. package/docs/durability.md +3 -2
  146. package/docs/errors.md +3 -1
  147. package/docs/file-store.md +38 -8
  148. package/docs/local-roots.md +4 -3
  149. package/docs/output.md +4 -1
  150. package/docs/private-file-store.md +11 -2
  151. package/docs/reading.md +3 -1
  152. package/docs/regular-file.md +16 -2
  153. package/docs/root.md +4 -2
  154. package/docs/secret-file.md +37 -2
  155. package/docs/sidecar-lock.md +33 -5
  156. package/docs/store.md +5 -1
  157. package/docs/temp.md +19 -1
  158. package/docs/writing.md +24 -3
  159. package/package.json +14 -10
package/docs/writing.md CHANGED
@@ -1,8 +1,16 @@
1
1
  # Writing
2
2
 
3
3
  The `Root` handle exposes a tight set of mutation verbs. Replacement writes
4
- (`write`, `create`, `writeJson`, `createJson`, and `copyIn`) publish with a
5
- sibling-temp commit so no half-written replacement appears at the destination.
4
+ (`write`, `writeJson`, and `copyIn`) publish with a sibling-temp commit so no
5
+ half-written replacement appears at the destination. Create-only writes
6
+ (`create`, `createJson`, and `write` with `overwrite: false`) use sibling-temp
7
+ staging with an atomic no-replace rename only on backends that provide one —
8
+ the native binding, which `require` mode guarantees and `auto` mode uses when
9
+ the binding loads. The pure-JavaScript fallback has no atomic no-clobber
10
+ rename and does not stage: it claims the final name exclusively with `O_EXCL`
11
+ and writes content in place, so a concurrent observer can see the new file
12
+ before its content is complete. Use `require` mode when that visibility window
13
+ matters.
6
14
  `append` and `openWritable` intentionally modify an opened file in place;
7
15
  `move`, `remove`, and `mkdir` mutate directory entries rather than file bytes.
8
16
  Each verb applies the boundary checks appropriate to its operation.
@@ -91,7 +99,13 @@ alone is never proof that the name still refers to the expected file.
91
99
  Don't-clobber variant of `write()`. Throws `already-exists` if the target is there.
92
100
  Create-only preflight preserves boundary, alias, hardlink, and type checks without
93
101
  opening an existing target to inherit its mode; a fresh file uses the requested
94
- mode or the normal new-file default.
102
+ mode or the normal new-file default. When the native binding is in use
103
+ (`require` mode, or `auto` mode with a successfully loaded binding), content is
104
+ staged privately and published with an atomic no-replace rename, so the name
105
+ never appears before its bytes. In the pure-JavaScript fallback the name is
106
+ claimed exclusively first and content is written afterward, so observers can
107
+ briefly see an empty file; failure cleanup removes a claimed file only when its
108
+ identity is unchanged.
95
109
 
96
110
  ```ts
97
111
  try {
@@ -207,6 +221,13 @@ destination — there is no atomic-rename step. If you need both streaming and
207
221
  atomicity, write to a sibling temp yourself and rename when done; the
208
222
  [`atomic`](atomic.md) helpers can do this for you.
209
223
 
224
+ On POSIX, existing-target opens use `O_NONBLOCK` as an admission safeguard so
225
+ a no-reader FIFO cannot stall regular-file validation. This does not change
226
+ ordinary regular-file write semantics. `replace` and `update` remain write-only
227
+ opens, including for mode `0o200` files; replacement truncation happens only
228
+ after type, identity, and boundary checks pass. Rejected existing paths are
229
+ never cleanup-owned or unlinked.
230
+
210
231
  ## Write defaults vs per-call options
211
232
 
212
233
  Set `mkdir: true` once on `root()`; pass text encodings per call when needed:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/fs-safe",
3
- "version": "0.7.2",
3
+ "version": "0.8.1",
4
4
  "description": "Capability-style filesystem roots for Node.js apps that handle untrusted relative paths.",
5
5
  "keywords": [
6
6
  "filesystem",
@@ -93,6 +93,10 @@
93
93
  "types": "./dist/temp.d.ts",
94
94
  "default": "./dist/temp.js"
95
95
  },
96
+ "./secure-temp-root": {
97
+ "types": "./dist/secure-temp-dir.d.ts",
98
+ "default": "./dist/secure-temp-dir.js"
99
+ },
96
100
  "./atomic": {
97
101
  "types": "./dist/atomic.d.ts",
98
102
  "default": "./dist/atomic.js"
@@ -149,20 +153,20 @@
149
153
  "crabbox:warmup": "crabbox warmup"
150
154
  },
151
155
  "optionalDependencies": {
152
- "@openclaw/fs-safe-darwin-arm64": "0.7.2",
153
- "@openclaw/fs-safe-darwin-x64": "0.7.2",
154
- "@openclaw/fs-safe-linux-arm64-gnu": "0.7.2",
155
- "@openclaw/fs-safe-linux-arm64-musl": "0.7.2",
156
- "@openclaw/fs-safe-linux-x64-gnu": "0.7.2",
157
- "@openclaw/fs-safe-linux-x64-musl": "0.7.2",
158
- "@openclaw/fs-safe-win32-x64-msvc": "0.7.2",
156
+ "@openclaw/fs-safe-darwin-arm64": "0.8.1",
157
+ "@openclaw/fs-safe-darwin-x64": "0.8.1",
158
+ "@openclaw/fs-safe-linux-arm64-gnu": "0.8.1",
159
+ "@openclaw/fs-safe-linux-arm64-musl": "0.8.1",
160
+ "@openclaw/fs-safe-linux-x64-gnu": "0.8.1",
161
+ "@openclaw/fs-safe-linux-x64-musl": "0.8.1",
162
+ "@openclaw/fs-safe-win32-x64-msvc": "0.8.1",
159
163
  "jszip": "^3.10.1",
160
164
  "tar": "7.5.22"
161
165
  },
162
166
  "devDependencies": {
163
167
  "@emnapi/runtime": "2.0.0-alpha.4",
164
168
  "@napi-rs/cli": "3.8.6",
165
- "@types/node": "^26.4.0",
169
+ "@types/node": "^26.4.1",
166
170
  "@vitest/coverage-v8": "4.1.11",
167
171
  "fast-check": "^4.9.0",
168
172
  "istanbul-lib-coverage": "3.2.2",
@@ -176,5 +180,5 @@
176
180
  "engines": {
177
181
  "node": ">=22"
178
182
  },
179
- "packageManager": "pnpm@11.24.0"
183
+ "packageManager": "pnpm@11.25.0"
180
184
  }