@openclaw/matrix 2026.10.5-beta.4 → 2026.10.10-beta.2

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 (313) hide show
  1. package/dist/.setup/{approval-handler.runtime-rxLn8CbP.mjs → approval-handler.runtime-CsqMdj7h.mjs} +9 -9
  2. package/dist/.setup/{approval-reactions-DhB6gNPU.mjs → approval-reactions-D2pEUrFS.mjs} +1 -1
  3. package/dist/.setup/{channel-BcwGspPw.mjs → channel-Dw4_imdd.mjs} +132 -111
  4. package/dist/.setup/{channel.runtime-CUc6rbu1.mjs → channel.runtime-2EEtIlyu.mjs} +6 -6
  5. package/dist/.setup/{channel.setup-CwuYD_CT.mjs → channel.setup-Be8TYKMA.mjs} +8 -3
  6. package/dist/.setup/{cli-mbL9jCro.mjs → cli-CEmWh7wh.mjs} +99 -37
  7. package/dist/.setup/{cli-metadata-6MOGuyHq.mjs → cli-metadata-CBLGwJT6.mjs} +1 -1
  8. package/dist/.setup/{client-BlTvpEWC.mjs → client-BKiiI29H.mjs} +3 -3
  9. package/dist/.setup/{client-vPPbaxNp.mjs → client-C4Gibhzl.mjs} +94 -120
  10. package/dist/.setup/{client-bootstrap-D05xy1HB.mjs → client-bootstrap-kOIDV4z_.mjs} +3 -3
  11. package/dist/.setup/{create-client-CroC4BVc.mjs → create-client-BS8UYx6N.mjs} +23 -15
  12. package/dist/.setup/{credentials-Bf9PQ7xs.mjs → credentials-CPnJZaZB.mjs} +3 -5
  13. package/dist/.setup/{credentials-read-CqRiEAQa.mjs → credentials-read-D2ULV55A.mjs} +12 -4
  14. package/dist/.setup/{crypto-runtime-CpJ0b7vY.mjs → crypto-runtime-D8yY7kjD.mjs} +168 -290
  15. package/dist/.setup/crypto-state-store-D4wrCvFs.mjs +185 -0
  16. package/dist/.setup/crypto-store-ownership-Z_Y5WRKr.mjs +174 -0
  17. package/dist/.setup/crypto-unsafe-state-doctor-C8szCYmf.mjs +54 -0
  18. package/dist/.setup/{directory-live-B1WbfSHo.mjs → directory-live-BpSz-FQB.mjs} +1 -1
  19. package/dist/.setup/{draft-stream-Bdrh7dRt.mjs → draft-stream-DYf0th1n.mjs} +1 -1
  20. package/dist/.setup/{exec-approvals-BgNWWJg1.mjs → exec-approvals-DaM-5OA5.mjs} +33 -43
  21. package/dist/.setup/{file-sync-store-BdKx_gMi.mjs → file-sync-store-CUH8EAJq.mjs} +3 -3
  22. package/dist/.setup/idb-persistence-BHTYPRe_.mjs +233 -0
  23. package/dist/.setup/idb-persistence-lock-Bh3ZLIsE.mjs +14 -0
  24. package/dist/.setup/{messages-B1CZqU8u.mjs → messages-_XHVg3do.mjs} +3 -18
  25. package/dist/.setup/{monitor-Dk_fQL1k.mjs → monitor-DRUSJ_Ev.mjs} +31 -39
  26. package/dist/.setup/{onboarding-CrSexor_.mjs → onboarding-CK9Ksgio.mjs} +3 -3
  27. package/dist/.setup/{outbound-LR3SqPIq.mjs → outbound-D5Z_4FBg.mjs} +28 -36
  28. package/dist/.setup/{profile-update-C7bjaGR6.mjs → profile-update--Pf3jCXD.mjs} +2 -2
  29. package/dist/.setup/{reaction-events-CTSvOlXO.mjs → reaction-events-BG9spedG.mjs} +6 -6
  30. package/dist/.setup/{resolve-targets-BVVbbvP6.mjs → resolve-targets-BJ5sIKeM.mjs} +1 -1
  31. package/dist/.setup/{retired-state-DW5pLH05.mjs → retired-state-DOCruzWd.mjs} +10 -10
  32. package/dist/.setup/{room-info-9Uqlpt1V.mjs → room-info-BE7bbX_c.mjs} +3 -3
  33. package/dist/.setup/runtime-setter-api-i2MOXoT3.mjs +2 -0
  34. package/dist/.setup/{sdk-Cfc6m7fY.mjs → sdk-ByU8So5S.mjs} +242 -139
  35. package/dist/.setup/secret-contract-DxyzKSzf.mjs +90 -0
  36. package/dist/.setup/secret-contract-api-Dukgvike.mjs +2 -0
  37. package/dist/.setup/{send-LCOuTVc1.mjs → send-BprM-Wmx.mjs} +19 -42
  38. package/dist/.setup/{setup-bootstrap-CV-hHBXu.mjs → setup-bootstrap-DmznRqYe.mjs} +2 -6
  39. package/dist/.setup/{setup-core-CKnNTfgD.mjs → setup-core-DcCk1_Tv.mjs} +4 -7
  40. package/dist/.setup/setup-plugin-api-BU6UGksW.mjs +2 -0
  41. package/dist/.setup/{startup-verification-CgfUb4yJ.mjs → startup-verification-UU8DUvi4.mjs} +5 -13
  42. package/dist/.setup/state-layout-walk-BQMgMykU.mjs +27 -0
  43. package/dist/.setup/{storage-DkC6bHgA.mjs → storage-l8V0XsGM.mjs} +7 -166
  44. package/dist/.setup/{subagent-hooks-D8jyeQsO.mjs → subagent-hooks-CSY4iwa_.mjs} +7 -6
  45. package/dist/.setup/{sync-cache-state-D4G-fi3t.mjs → sync-cache-state-Cnm4TCEI.mjs} +1 -1
  46. package/dist/.setup/thread-bindings-rrwQAS6R.mjs +620 -0
  47. package/dist/.setup/{thread-bindings-shared-CbsFNbAY.mjs → thread-bindings-shared-CPjUA0Ib.mjs} +26 -5
  48. package/dist/.setup/{tool-actions-DAp6_XSJ.mjs → tool-actions-DBrk6Yei.mjs} +9 -11
  49. package/dist/.setup/{verification-B3VswneT.mjs → verification--qUbmRd-.mjs} +2 -2
  50. package/dist/api.js +6 -6
  51. package/dist/auth-presence.js +16 -2
  52. package/dist/channel-plugin-api.js +1 -2
  53. package/dist/cli-metadata.js +1 -2
  54. package/dist/contract-api.js +2 -2
  55. package/dist/doctor-contract-api.js +20 -27
  56. package/dist/index.js +38 -12
  57. package/dist/plugin-entry.handlers.runtime.js +32 -5
  58. package/dist/runtime-api.js +3 -3
  59. package/dist/runtime-setter-api.js +1 -2
  60. package/dist/secret-contract-api.js +1 -2
  61. package/dist/session-binding-contract-api.js +1 -1
  62. package/dist/setup-entry.js +3 -3
  63. package/dist/setup-plugin-api.js +1 -2
  64. package/dist/subagent-hooks-api.js +1 -1
  65. package/dist/thread-binding-api.js +1 -2
  66. package/dist/thread-bindings-runtime.js +1 -2
  67. package/node_modules/@openclaw/fs-safe/CHANGELOG.md +148 -0
  68. package/node_modules/@openclaw/fs-safe/README.md +20 -4
  69. package/node_modules/@openclaw/fs-safe/dist/advanced.d.ts +2 -1
  70. package/node_modules/@openclaw/fs-safe/dist/advanced.js +1 -0
  71. package/node_modules/@openclaw/fs-safe/dist/archive-merge.js +28 -3
  72. package/node_modules/@openclaw/fs-safe/dist/archive-parser.wasm +0 -0
  73. package/node_modules/@openclaw/fs-safe/dist/archive-read.js +11 -5
  74. package/node_modules/@openclaw/fs-safe/dist/archive-zip-loader.js +4 -2
  75. package/node_modules/@openclaw/fs-safe/dist/archive.js +2 -2
  76. package/node_modules/@openclaw/fs-safe/dist/atomic-io.js +2 -2
  77. package/node_modules/@openclaw/fs-safe/dist/bounded-read.d.ts +1 -0
  78. package/node_modules/@openclaw/fs-safe/dist/bounded-read.js +9 -2
  79. package/node_modules/@openclaw/fs-safe/dist/clone-metadata.d.ts +2 -0
  80. package/node_modules/@openclaw/fs-safe/dist/clone-metadata.js +2 -1
  81. package/node_modules/@openclaw/fs-safe/dist/config.d.ts +6 -0
  82. package/node_modules/@openclaw/fs-safe/dist/config.js +5 -0
  83. package/node_modules/@openclaw/fs-safe/dist/copy-file-input.d.ts +3 -1
  84. package/node_modules/@openclaw/fs-safe/dist/copy-file-input.js +8 -7
  85. package/node_modules/@openclaw/fs-safe/dist/copy-link.d.ts +26 -0
  86. package/node_modules/@openclaw/fs-safe/dist/copy-link.js +170 -0
  87. package/node_modules/@openclaw/fs-safe/dist/copy-metadata.d.ts +9 -0
  88. package/node_modules/@openclaw/fs-safe/dist/copy-metadata.js +39 -0
  89. package/node_modules/@openclaw/fs-safe/dist/copy-path-admission.js +11 -2
  90. package/node_modules/@openclaw/fs-safe/dist/copy-root-file-sync.d.ts +2 -4
  91. package/node_modules/@openclaw/fs-safe/dist/copy-root-file-sync.js +4 -2
  92. package/node_modules/@openclaw/fs-safe/dist/copy-tree-portable.js +3 -6
  93. package/node_modules/@openclaw/fs-safe/dist/copy.js +3 -3
  94. package/node_modules/@openclaw/fs-safe/dist/create.js +1 -1
  95. package/node_modules/@openclaw/fs-safe/dist/creation-boundary.js +7 -4
  96. package/node_modules/@openclaw/fs-safe/dist/darwin-acl.d.ts +12 -0
  97. package/node_modules/@openclaw/fs-safe/dist/darwin-acl.js +29 -0
  98. package/node_modules/@openclaw/fs-safe/dist/directory-durability.d.ts +7 -4
  99. package/node_modules/@openclaw/fs-safe/dist/directory-guard.js +20 -5
  100. package/node_modules/@openclaw/fs-safe/dist/directory-mode-node.d.ts +3 -0
  101. package/node_modules/@openclaw/fs-safe/dist/directory-mode-node.js +27 -2
  102. package/node_modules/@openclaw/fs-safe/dist/directory-receipt.d.ts +7 -7
  103. package/node_modules/@openclaw/fs-safe/dist/directory-receipt.js +9 -4
  104. package/node_modules/@openclaw/fs-safe/dist/durability.d.ts +2 -1
  105. package/node_modules/@openclaw/fs-safe/dist/entry-publication.js +2 -2
  106. package/node_modules/@openclaw/fs-safe/dist/exact-identity.d.ts +17 -0
  107. package/node_modules/@openclaw/fs-safe/dist/exact-identity.js +29 -0
  108. package/node_modules/@openclaw/fs-safe/dist/file-handle-transfer.js +4 -2
  109. package/node_modules/@openclaw/fs-safe/dist/file-hash.d.ts +1 -1
  110. package/node_modules/@openclaw/fs-safe/dist/file-hash.js +11 -9
  111. package/node_modules/@openclaw/fs-safe/dist/file-identity.d.ts +7 -1
  112. package/node_modules/@openclaw/fs-safe/dist/file-identity.js +27 -5
  113. package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-admission.js +1 -2
  114. package/node_modules/@openclaw/fs-safe/dist/file-lock-sync.js +8 -1
  115. package/node_modules/@openclaw/fs-safe/dist/file-lock.d.ts +1 -0
  116. package/node_modules/@openclaw/fs-safe/dist/file-lock.js +1 -0
  117. package/node_modules/@openclaw/fs-safe/dist/file-write-lease.d.ts +9 -0
  118. package/node_modules/@openclaw/fs-safe/dist/file-write-lease.js +42 -0
  119. package/node_modules/@openclaw/fs-safe/dist/guarded-mkdir.d.ts +1 -0
  120. package/node_modules/@openclaw/fs-safe/dist/guarded-mkdir.js +22 -15
  121. package/node_modules/@openclaw/fs-safe/dist/guest-native-python.js +3 -0
  122. package/node_modules/@openclaw/fs-safe/dist/hardlink-fallback.d.ts +1 -0
  123. package/node_modules/@openclaw/fs-safe/dist/hardlink-fallback.js +5 -0
  124. package/node_modules/@openclaw/fs-safe/dist/index.d.ts +1 -0
  125. package/node_modules/@openclaw/fs-safe/dist/index.js +1 -0
  126. package/node_modules/@openclaw/fs-safe/dist/json-durable-queue-ownership.js +16 -3
  127. package/node_modules/@openclaw/fs-safe/dist/local-file-descriptor.js +24 -13
  128. package/node_modules/@openclaw/fs-safe/dist/native-binding.d.ts +85 -18
  129. package/node_modules/@openclaw/fs-safe/dist/native-config.d.ts +5 -0
  130. package/node_modules/@openclaw/fs-safe/dist/native-config.js +11 -0
  131. package/node_modules/@openclaw/fs-safe/dist/native-directory-observation.js +6 -4
  132. package/node_modules/@openclaw/fs-safe/dist/native-fallback-warning.d.ts +2 -1
  133. package/node_modules/@openclaw/fs-safe/dist/native-fallback-warning.js +26 -2
  134. package/node_modules/@openclaw/fs-safe/dist/native-guidance.d.ts +3 -0
  135. package/node_modules/@openclaw/fs-safe/dist/native-guidance.js +21 -0
  136. package/node_modules/@openclaw/fs-safe/dist/native-move-fallback.d.ts +1 -1
  137. package/node_modules/@openclaw/fs-safe/dist/native-move-fallback.js +2 -0
  138. package/node_modules/@openclaw/fs-safe/dist/native-operations.js +8 -6
  139. package/node_modules/@openclaw/fs-safe/dist/native-parent-admission.d.ts +44 -4
  140. package/node_modules/@openclaw/fs-safe/dist/native-parent-admission.js +85 -15
  141. package/node_modules/@openclaw/fs-safe/dist/native-pinned-write-windows.d.ts +3 -3
  142. package/node_modules/@openclaw/fs-safe/dist/native-pinned-write-windows.js +33 -6
  143. package/node_modules/@openclaw/fs-safe/dist/native-pinned-write.d.ts +4 -1
  144. package/node_modules/@openclaw/fs-safe/dist/native-pinned-write.js +22 -3
  145. package/node_modules/@openclaw/fs-safe/dist/native-policy-directory-observation.js +4 -3
  146. package/node_modules/@openclaw/fs-safe/dist/native-policy-parent.d.ts +1 -1
  147. package/node_modules/@openclaw/fs-safe/dist/native-policy-parent.js +3 -0
  148. package/node_modules/@openclaw/fs-safe/dist/native-staged-file-metadata.d.ts +3 -0
  149. package/node_modules/@openclaw/fs-safe/dist/native-staged-file-metadata.js +16 -0
  150. package/node_modules/@openclaw/fs-safe/dist/native-staged-file.d.ts +1 -1
  151. package/node_modules/@openclaw/fs-safe/dist/native-staged-file.js +15 -5
  152. package/node_modules/@openclaw/fs-safe/dist/native-stat-identity.d.ts +3 -0
  153. package/node_modules/@openclaw/fs-safe/dist/native-stat-identity.js +7 -0
  154. package/node_modules/@openclaw/fs-safe/dist/native-status.d.ts +17 -0
  155. package/node_modules/@openclaw/fs-safe/dist/native-status.js +30 -0
  156. package/node_modules/@openclaw/fs-safe/dist/native.d.ts +31 -4
  157. package/node_modules/@openclaw/fs-safe/dist/native.js +107 -9
  158. package/node_modules/@openclaw/fs-safe/dist/opened-realpath.js +9 -1
  159. package/node_modules/@openclaw/fs-safe/dist/overwrite-file-handle.js +4 -1
  160. package/node_modules/@openclaw/fs-safe/dist/owner-dacl-batch.js +1 -1
  161. package/node_modules/@openclaw/fs-safe/dist/owner-dacl.js +1 -1
  162. package/node_modules/@openclaw/fs-safe/dist/permission-exec.js +9 -1
  163. package/node_modules/@openclaw/fs-safe/dist/permissions-public.d.ts +1 -0
  164. package/node_modules/@openclaw/fs-safe/dist/permissions-public.js +1 -0
  165. package/node_modules/@openclaw/fs-safe/dist/permissions-windows.js +83 -47
  166. package/node_modules/@openclaw/fs-safe/dist/pinned-open.d.ts +2 -0
  167. package/node_modules/@openclaw/fs-safe/dist/pinned-open.js +8 -3
  168. package/node_modules/@openclaw/fs-safe/dist/pinned-write-input.js +13 -0
  169. package/node_modules/@openclaw/fs-safe/dist/pinned-write-staged.js +10 -8
  170. package/node_modules/@openclaw/fs-safe/dist/pinned-write-types.d.ts +2 -1
  171. package/node_modules/@openclaw/fs-safe/dist/pinned-write.js +7 -5
  172. package/node_modules/@openclaw/fs-safe/dist/pipe.d.ts +9 -0
  173. package/node_modules/@openclaw/fs-safe/dist/pipe.js +26 -0
  174. package/node_modules/@openclaw/fs-safe/dist/private-directory.js +1 -1
  175. package/node_modules/@openclaw/fs-safe/dist/private-producer-handoff.js +2 -5
  176. package/node_modules/@openclaw/fs-safe/dist/private-temp-workspace.d.ts +3 -2
  177. package/node_modules/@openclaw/fs-safe/dist/private-temp-workspace.js +38 -10
  178. package/node_modules/@openclaw/fs-safe/dist/publish-copy-stage.js +92 -10
  179. package/node_modules/@openclaw/fs-safe/dist/publish-file-failure.d.ts +3 -0
  180. package/node_modules/@openclaw/fs-safe/dist/publish-file-failure.js +3 -0
  181. package/node_modules/@openclaw/fs-safe/dist/publish-file.d.ts +5 -3
  182. package/node_modules/@openclaw/fs-safe/dist/publish-file.js +26 -20
  183. package/node_modules/@openclaw/fs-safe/dist/read-opened-file.d.ts +2 -0
  184. package/node_modules/@openclaw/fs-safe/dist/read-opened-file.js +3 -4
  185. package/node_modules/@openclaw/fs-safe/dist/realpath.js +32 -0
  186. package/node_modules/@openclaw/fs-safe/dist/regular-file.d.ts +4 -0
  187. package/node_modules/@openclaw/fs-safe/dist/regular-file.js +11 -15
  188. package/node_modules/@openclaw/fs-safe/dist/replace-file-descriptor.js +3 -2
  189. package/node_modules/@openclaw/fs-safe/dist/root-copy.d.ts +18 -0
  190. package/node_modules/@openclaw/fs-safe/dist/root-copy.js +128 -0
  191. package/node_modules/@openclaw/fs-safe/dist/root-create-native.d.ts +8 -13
  192. package/node_modules/@openclaw/fs-safe/dist/root-create-native.js +252 -27
  193. package/node_modules/@openclaw/fs-safe/dist/root-directory-creation.js +5 -1
  194. package/node_modules/@openclaw/fs-safe/dist/root-directory-list-types.d.ts +11 -8
  195. package/node_modules/@openclaw/fs-safe/dist/root-directory-list.js +35 -13
  196. package/node_modules/@openclaw/fs-safe/dist/root-file-open-batch-sync.d.ts +8 -0
  197. package/node_modules/@openclaw/fs-safe/dist/root-file-open-batch-sync.js +108 -0
  198. package/node_modules/@openclaw/fs-safe/dist/root-file.d.ts +7 -0
  199. package/node_modules/@openclaw/fs-safe/dist/root-file.js +15 -0
  200. package/node_modules/@openclaw/fs-safe/dist/root-impl.d.ts +2 -0
  201. package/node_modules/@openclaw/fs-safe/dist/root-impl.js +154 -175
  202. package/node_modules/@openclaw/fs-safe/dist/root-mkdir-native.d.ts +2 -0
  203. package/node_modules/@openclaw/fs-safe/dist/root-mkdir-native.js +239 -0
  204. package/node_modules/@openclaw/fs-safe/dist/root-move-noreplace.js +37 -15
  205. package/node_modules/@openclaw/fs-safe/dist/root-native-creation-path.d.ts +32 -0
  206. package/node_modules/@openclaw/fs-safe/dist/root-native-creation-path.js +56 -0
  207. package/node_modules/@openclaw/fs-safe/dist/root-options.d.ts +2 -0
  208. package/node_modules/@openclaw/fs-safe/dist/root-public-types.d.ts +1 -0
  209. package/node_modules/@openclaw/fs-safe/dist/root-remove-native.js +95 -16
  210. package/node_modules/@openclaw/fs-safe/dist/root-remove.js +6 -4
  211. package/node_modules/@openclaw/fs-safe/dist/root-walk.js +23 -19
  212. package/node_modules/@openclaw/fs-safe/dist/root-write-admission.js +8 -6
  213. package/node_modules/@openclaw/fs-safe/dist/root-write-publication.js +5 -1
  214. package/node_modules/@openclaw/fs-safe/dist/secure-file-windows.js +3 -1
  215. package/node_modules/@openclaw/fs-safe/dist/secure-file.d.ts +2 -0
  216. package/node_modules/@openclaw/fs-safe/dist/secure-file.js +10 -4
  217. package/node_modules/@openclaw/fs-safe/dist/sibling-staged-file.js +1 -1
  218. package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.js +2 -2
  219. package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-retained.js +1 -1
  220. package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-target.js +8 -1
  221. package/node_modules/@openclaw/fs-safe/dist/staged-directory.d.ts +13 -0
  222. package/node_modules/@openclaw/fs-safe/dist/staged-directory.js +29 -0
  223. package/node_modules/@openclaw/fs-safe/dist/temp-workspace-child-admission.js +5 -3
  224. package/node_modules/@openclaw/fs-safe/dist/temp-workspace-descriptor.d.ts +8 -0
  225. package/node_modules/@openclaw/fs-safe/dist/temp-workspace-descriptor.js +13 -2
  226. package/node_modules/@openclaw/fs-safe/dist/temp-workspace-owner.js +71 -3
  227. package/node_modules/@openclaw/fs-safe/dist/temp-workspace-ownership.d.ts +2 -1
  228. package/node_modules/@openclaw/fs-safe/dist/temp-workspace-ownership.js +22 -0
  229. package/node_modules/@openclaw/fs-safe/dist/temp-workspace-types.d.ts +3 -0
  230. package/node_modules/@openclaw/fs-safe/dist/test-hooks.d.ts +1 -0
  231. package/node_modules/@openclaw/fs-safe/dist/test-hooks.js +1 -0
  232. package/node_modules/@openclaw/fs-safe/dist/trash.js +2 -2
  233. package/node_modules/@openclaw/fs-safe/dist/types.d.ts +4 -0
  234. package/node_modules/@openclaw/fs-safe/dist/watch-native.js +2 -2
  235. package/node_modules/@openclaw/fs-safe/dist/windows-appcontainer.d.ts +5 -0
  236. package/node_modules/@openclaw/fs-safe/dist/windows-appcontainer.js +39 -0
  237. package/node_modules/@openclaw/fs-safe/dist/windows-owner.d.ts +1 -0
  238. package/node_modules/@openclaw/fs-safe/dist/windows-owner.js +25 -36
  239. package/node_modules/@openclaw/fs-safe/dist/windows-security-command.js +24 -5
  240. package/node_modules/@openclaw/fs-safe/dist/windows-security-facts.d.ts +2 -1
  241. package/node_modules/@openclaw/fs-safe/dist/windows-security-facts.js +4 -0
  242. package/node_modules/@openclaw/fs-safe/dist/windows-security-helper.d.ts +2 -0
  243. package/node_modules/@openclaw/fs-safe/dist/windows-security-helper.exe +0 -0
  244. package/node_modules/@openclaw/fs-safe/dist/windows-security-helper.js +7 -0
  245. package/node_modules/@openclaw/fs-safe/dist/windows-test-hooks.d.ts +16 -0
  246. package/node_modules/@openclaw/fs-safe/dist/windows-test-hooks.js +51 -0
  247. package/node_modules/@openclaw/fs-safe/dist/write-file-handle.d.ts +1 -0
  248. package/node_modules/@openclaw/fs-safe/dist/write-file-handle.js +12 -10
  249. package/node_modules/@openclaw/fs-safe/docs/advanced.md +2 -1
  250. package/node_modules/@openclaw/fs-safe/docs/archive.md +16 -0
  251. package/node_modules/@openclaw/fs-safe/docs/config.md +71 -1
  252. package/node_modules/@openclaw/fs-safe/docs/contributing.md +45 -5
  253. package/node_modules/@openclaw/fs-safe/docs/copy.md +45 -5
  254. package/node_modules/@openclaw/fs-safe/docs/durability.md +34 -7
  255. package/node_modules/@openclaw/fs-safe/docs/errors.md +8 -0
  256. package/node_modules/@openclaw/fs-safe/docs/guest.md +2 -0
  257. package/node_modules/@openclaw/fs-safe/docs/install.md +47 -27
  258. package/node_modules/@openclaw/fs-safe/docs/migrating-to-0.5.md +6 -6
  259. package/node_modules/@openclaw/fs-safe/docs/migrating-to-0.6.md +1 -1
  260. package/node_modules/@openclaw/fs-safe/docs/native-helper.md +79 -6
  261. package/node_modules/@openclaw/fs-safe/docs/native.md +279 -8
  262. package/node_modules/@openclaw/fs-safe/docs/permissions.md +64 -15
  263. package/node_modules/@openclaw/fs-safe/docs/pipe.md +81 -0
  264. package/node_modules/@openclaw/fs-safe/docs/platform-capabilities.md +63 -0
  265. package/node_modules/@openclaw/fs-safe/docs/public-api.md +10 -0
  266. package/node_modules/@openclaw/fs-safe/docs/queue-link-free-design.md +237 -0
  267. package/node_modules/@openclaw/fs-safe/docs/quickstart.md +23 -3
  268. package/node_modules/@openclaw/fs-safe/docs/reading.md +56 -2
  269. package/node_modules/@openclaw/fs-safe/docs/regular-file.md +2 -0
  270. package/node_modules/@openclaw/fs-safe/docs/secret-file.md +5 -5
  271. package/node_modules/@openclaw/fs-safe/docs/secure-file.md +1 -1
  272. package/node_modules/@openclaw/fs-safe/docs/security-model.md +35 -0
  273. package/node_modules/@openclaw/fs-safe/docs/sidecar-lock.md +31 -13
  274. package/node_modules/@openclaw/fs-safe/docs/staged-file.md +18 -0
  275. package/node_modules/@openclaw/fs-safe/docs/store.md +15 -0
  276. package/node_modules/@openclaw/fs-safe/docs/temp.md +39 -0
  277. package/node_modules/@openclaw/fs-safe/docs/testing.md +13 -0
  278. package/node_modules/@openclaw/fs-safe/docs/types.md +51 -81
  279. package/node_modules/@openclaw/fs-safe/docs/walk.md +4 -1
  280. package/node_modules/@openclaw/fs-safe/docs/watch.md +3 -2
  281. package/node_modules/@openclaw/fs-safe/docs/writing.md +121 -14
  282. package/node_modules/@openclaw/fs-safe/package.json +21 -12
  283. package/node_modules/@openclaw/fs-safe-darwin-arm64/fs-safe-native.node +0 -0
  284. package/node_modules/@openclaw/fs-safe-darwin-arm64/package.json +1 -1
  285. package/node_modules/@openclaw/fs-safe-darwin-x64/fs-safe-native.node +0 -0
  286. package/node_modules/@openclaw/fs-safe-darwin-x64/package.json +1 -1
  287. package/node_modules/@openclaw/fs-safe-freebsd-arm64/fs-safe-native.node +0 -0
  288. package/node_modules/@openclaw/fs-safe-freebsd-arm64/package.json +29 -0
  289. package/node_modules/@openclaw/fs-safe-freebsd-x64/fs-safe-native.node +0 -0
  290. package/node_modules/@openclaw/fs-safe-freebsd-x64/package.json +29 -0
  291. package/node_modules/@openclaw/fs-safe-linux-arm64-gnu/fs-safe-native.node +0 -0
  292. package/node_modules/@openclaw/fs-safe-linux-arm64-gnu/package.json +1 -1
  293. package/node_modules/@openclaw/fs-safe-linux-arm64-musl/fs-safe-native.node +0 -0
  294. package/node_modules/@openclaw/fs-safe-linux-arm64-musl/package.json +1 -1
  295. package/node_modules/@openclaw/fs-safe-linux-x64-gnu/fs-safe-native.node +0 -0
  296. package/node_modules/@openclaw/fs-safe-linux-x64-gnu/package.json +1 -1
  297. package/node_modules/@openclaw/fs-safe-linux-x64-musl/fs-safe-native.node +0 -0
  298. package/node_modules/@openclaw/fs-safe-linux-x64-musl/package.json +1 -1
  299. package/node_modules/@openclaw/fs-safe-win32-arm64-msvc/fs-safe-native.node +0 -0
  300. package/node_modules/@openclaw/fs-safe-win32-arm64-msvc/package.json +29 -0
  301. package/node_modules/@openclaw/fs-safe-win32-x64-msvc/fs-safe-native.node +0 -0
  302. package/node_modules/@openclaw/fs-safe-win32-x64-msvc/package.json +1 -1
  303. package/node_modules/typebox/build/value/clean/from_object.mjs +1 -1
  304. package/node_modules/typebox/package.json +1 -1
  305. package/openclaw.plugin.json +3 -0
  306. package/package.json +7 -6
  307. package/dist/.setup/runtime-setter-api-DtxDAM-x.mjs +0 -3
  308. package/dist/.setup/secret-contract-DSBRvhdZ.mjs +0 -95
  309. package/dist/.setup/secret-contract-api-DzEJ-X7n.mjs +0 -3
  310. package/dist/.setup/setup-plugin-api-BDAYk1a5.mjs +0 -3
  311. package/dist/.setup/thread-bindings-CT4P-OSZ.mjs +0 -365
  312. package/node_modules/@openclaw/fs-safe/dist/windows-security-bridge.cs +0 -336
  313. package/node_modules/@openclaw/fs-safe/dist/windows-security-bridge.ps1 +0 -90
@@ -81,6 +81,9 @@ export interface NativeOwnedTreeRemovalResult {
81
81
  errorCode?: string;
82
82
  errorMessage?: string;
83
83
  }
84
+ export interface NativeEmptyTreeRemovalResult extends Omit<NativeOwnedTreeRemovalResult, "outcome"> {
85
+ outcome?: "removed" | "preserved" | "not-empty";
86
+ }
84
87
  export interface NativeRootRemovalEntry {
85
88
  dev: bigint;
86
89
  ino: bigint;
@@ -101,6 +104,7 @@ export interface NativeWindowsAccessControlEntry {
101
104
  export interface NativeWindowsSecurityFacts {
102
105
  ownerSid: string;
103
106
  currentUserSid: string;
107
+ currentAppContainerSid?: string | null;
104
108
  ownerClass: string;
105
109
  worldWritable: boolean;
106
110
  groupWritable: boolean;
@@ -124,6 +128,8 @@ export interface NativeWindowsDirectoryReceipt {
124
128
  }
125
129
  export interface NativeDarwinAclFacts {
126
130
  state: "absent" | "empty" | "present";
131
+ inheritsToFiles?: boolean;
132
+ inheritsToDirectories?: boolean;
127
133
  }
128
134
  type NativeTwoPathArgs = [
129
135
  sourceRootFd: number,
@@ -132,6 +138,37 @@ type NativeTwoPathArgs = [
132
138
  targetRelPath: string
133
139
  ];
134
140
  export interface NativeBinding {
141
+ readCopyMetadata?(fd: number): Buffer;
142
+ restoreCopyMetadata?(fd: number, snapshot: Buffer): void;
143
+ restoreCopyFileTimes?(fd: number, atimeNs: bigint, mtimeNs: bigint): void;
144
+ copyLinkExclusive?(sourceParent: number, sourceName: string, parent: number, name: string, dev: bigint, ino: bigint, preserveMetadata: boolean, mode: number): {
145
+ dev: bigint;
146
+ ino: bigint;
147
+ };
148
+ publishCopyLink?(parent: number, name: string, destination: string, dev: bigint, ino: bigint): void;
149
+ removeCopyLink?(parent: number, name: string, dev: bigint, ino: bigint): void;
150
+ createCopySymlink?(parent: number, name: string, target: Buffer, mode: number, atimeNs?: bigint, mtimeNs?: bigint): {
151
+ dev: bigint;
152
+ ino: bigint;
153
+ errorCode?: string;
154
+ errorMessage?: string;
155
+ };
156
+ tryAcquireWriteLease?(fd: number): boolean;
157
+ isFileWriteLeaseHeld?(fd: number): boolean;
158
+ releaseFileWriteLease?(fd: number): void;
159
+ holdWindowsSharingLock?(path: string): {
160
+ close(): void;
161
+ };
162
+ setWindowsFileAttributes?(path: string, attrs: {
163
+ readOnly?: boolean;
164
+ hidden?: boolean;
165
+ system?: boolean;
166
+ }): void;
167
+ readWindowsFileExtents?(path: string): {
168
+ vcn: bigint;
169
+ lcn: bigint;
170
+ clusters: bigint;
171
+ }[];
135
172
  rootRemovalStat?(parent: number, name: string): NativeRootRemovalEntry;
136
173
  rootRemovalUnlink?(parent: number, name: string, dev: bigint, ino: bigint, directory: boolean): void;
137
174
  openRootRemovalDirectory?(parent: number, name: string, dev: bigint, ino: bigint): NativeRootRemovalDirectory;
@@ -169,6 +206,11 @@ export interface NativeBinding {
169
206
  };
170
207
  /** Internal: consumes only a descriptor returned by this binding. */
171
208
  closeOwnedFd(fd: number): void;
209
+ createPipe?(): {
210
+ reader: number;
211
+ writer: number;
212
+ atomicCloseOnExec: boolean;
213
+ };
172
214
  /** Internal Darwin-only synchronous inspection; the caller retains its fd. */
173
215
  inspectDarwinAcl?(fd: number, inheritanceTarget?: "file" | "directory"): NativeDarwinAclFacts;
174
216
  /** POSIX system canonicalization; confinement and identity policy stay with callers. */
@@ -176,6 +218,10 @@ export interface NativeBinding {
176
218
  path?: string;
177
219
  errno?: number;
178
220
  };
221
+ /** Internal Windows normalized name resolution after a denied DOS-name query. */
222
+ resolveWindowsCanonicalPath?(path: string): string | null;
223
+ /** Internal immutable primary-token membership, cached across Workers. */
224
+ isWindowsAppContainer?(): boolean;
179
225
  /** Internal: exact directory identity and canonical path from one no-follow handle. */
180
226
  observeDirectory?(path: string): NativeDirectoryObservation;
181
227
  /** Internal POSIX-only exact name/descriptor observation; the caller retains its fd. */
@@ -183,66 +229,87 @@ export interface NativeBinding {
183
229
  /** Linux/Windows byte transfer; callers retain both admitted descriptors until settlement. */
184
230
  copyFileContents?(sourceFd: number, targetFd: number, signal?: AbortSignal): Promise<void>;
185
231
  /** Internal: same private, immutable input ownership as the ZIP buffer reader. */
186
- openTarBufferNative(buffer: Buffer, kind: string, limits: TarMeterLimits, signal?: AbortSignal): Promise<{
232
+ openTarBufferNative?(buffer: Buffer, kind: string, limits: TarMeterLimits, signal?: AbortSignal): Promise<{
187
233
  readonly entries: NativeArchiveEntry[];
188
234
  readEntry(index: number, maxBytes: number, signal?: AbortSignal): Promise<Buffer>;
189
235
  }>;
190
236
  /** Internal: input remains private, unpooled and immutable until the reader is released. */
191
- openZipBufferNative(buffer: Buffer, limits: TarMeterLimits, signal?: AbortSignal): Promise<{
237
+ openZipBufferNative?(buffer: Buffer, limits: TarMeterLimits, signal?: AbortSignal): Promise<{
192
238
  readonly entries: NativeArchiveEntry[];
193
239
  readEntry(index: number, maxBytes: number, signal?: AbortSignal): Promise<Buffer>;
194
240
  }>;
195
- readCloneFileMetadata(paths: string[]): Promise<(Buffer | null)[]>;
196
- probeTreeClone(parentFd: number): "apfs" | "btrfs" | "refs" | "xfs" | "zfs" | null;
197
- cloneTree(sourceFd: number | null, parentFd: number, basename: string, concurrency: number, signal?: AbortSignal): Promise<void>;
241
+ readCloneFileMetadata?(paths: string[]): Promise<(Buffer | null)[]>;
242
+ probeTreeClone?(parentFd: number): "apfs" | "btrfs" | "refs" | "xfs" | "zfs" | null;
243
+ cloneTree?(sourceFd: number | null, parentFd: number, basename: string, concurrency: number, signal?: AbortSignal): Promise<void>;
198
244
  openStagedSymlink?(parentFd: number, basename: string): number;
199
245
  stagedSymlinkTarget?(parentFd: number, basename: string, linkFd: number): string;
200
246
  stagedSymlinkMatches?(parentFd: number, basename: string, linkFd: number): boolean;
201
247
  publishStagedSymlink?(parentFd: number, basename: string, linkFd: number, destination: string): void;
202
248
  removeStagedSymlink?(parentFd: number, basename: string, linkFd: number): "removed" | "name-absent" | "preserved";
203
249
  createStagedFile?(parentFd: number, basename: string): number;
250
+ stagedFileMetadata?(parentFd: number, basename: string, fd: number): {
251
+ mode: bigint;
252
+ nlink: bigint;
253
+ } | null;
204
254
  stagedFileMatches?(parentFd: number, basename: string, fileFd: number): boolean;
255
+ stagedDirectoryMatches?(fd: number, path: string, dev: bigint, ino: bigint): boolean;
205
256
  removeStagedFile?(parentFd: number, basename: string, fileFd: number): "removed" | "name-absent" | "preserved";
206
257
  copyFileExclusive?(sourceFd: number, parentFd: number, basename: string, clone: CopyCloneMode, maxBytes: number | undefined, signal: AbortSignal | undefined): Promise<NativeFileCopyResult>;
207
258
  copyFileExclusiveSync?(sourceFd: number, parentFd: number, basename: string, clone: CopyCloneMode, maxBytes: number | undefined): NativeFileCopyResult;
208
- cloneFileExclusive(sourceFd: number, targetRootFd: number, targetRelPath: string): number;
209
- copyFileRangeExclusive(sourceFd: number, targetRootFd: number, targetRelPath: string): Promise<NativeCopyResult>;
210
- createPrivateDirectory(path: string): void;
259
+ cloneFileExclusive?(sourceFd: number, targetRootFd: number, targetRelPath: string): number;
260
+ copyFileRangeExclusive?(sourceFd: number, targetRootFd: number, targetRelPath: string): Promise<NativeCopyResult>;
261
+ createPrivateDirectory?(path: string): void;
211
262
  /** Internal Windows creation receipts use full FILE_ID_INFO, never Node's projection. */
212
263
  inspectWindowsDirectory?(path: string, requirePrivate: boolean): NativeWindowsDirectoryReceipt;
213
264
  createPrivateDirectoryWithParentIdentity?(path: string, expectedParentIdentity: string): NativeWindowsDirectoryReceipt;
214
265
  /** Protects an already-private borrowed Node file; descriptor ownership stays with Node. */
215
266
  protectPrivateWindowsFile?(fd: number, path: string, expectedParentIdentity: string): NativeWindowsDirectoryReceipt;
216
267
  verifyPrivateWindowsFile?(fd: number, path: string, expectedFileIdentity: string, expectedParentIdentity: string, expectedLinks: number): void;
217
- extractArchiveNative(path: string, kind: string, rootFd: number, plan: NativeArchivePlanEntry[], limits: TarMeterLimits, signal: AbortSignal): Promise<void>;
218
- fstatIdentity(fd: number): NativeFileIdentity;
219
- inspectArchiveNative(path: string, kind: string, limits: TarMeterLimits, signal: AbortSignal): Promise<NativeArchiveEntry[]>;
220
- linkBeneath(...args: NativeTwoPathArgs): void;
268
+ extractArchiveNative?(path: string, kind: string, rootFd: number, plan: NativeArchivePlanEntry[], limits: TarMeterLimits, signal: AbortSignal): Promise<void>;
269
+ fstatIdentity?(fd: number): NativeFileIdentity;
270
+ inspectArchiveNative?(path: string, kind: string, limits: TarMeterLimits, signal: AbortSignal): Promise<NativeArchiveEntry[]>;
271
+ linkBeneath?(...args: NativeTwoPathArgs): void;
221
272
  /** Direct-child mkdir; true is receipt provenance only, never cleanup ownership. */
222
273
  mkdirChildBeneath?(parentFd: number, basename: string, mode: number): boolean;
223
274
  mkdirOpenChildBeneath?(parentFd: number, basename: string, mode: number, flags: number): {
224
275
  fd: number;
225
276
  created: boolean;
226
277
  };
227
- mkdirBeneath(rootFd: number, relPath: string, mode: number): void;
228
- openBeneath(rootFd: number, relPath: string, flags: number): NativeOpenBeneathResult;
229
- readOwnerAndDacl(path: string): NativeWindowsSecurityFacts;
278
+ createTempDirectoryBeneath?(parentFd: number, basename: string): {
279
+ fd: number;
280
+ searchOnly: boolean;
281
+ };
282
+ verifyRootDirectory?(pathname: string, dev: bigint, ino: bigint): null | {
283
+ errorCode?: string;
284
+ errorMessage?: string;
285
+ errorErrno?: number;
286
+ closeErrorCode?: string;
287
+ closeErrorMessage?: string;
288
+ closeErrorErrno?: number;
289
+ fallbackFd?: number;
290
+ };
291
+ mkdirBeneath?(rootFd: number, relPath: string, mode: number): void;
292
+ openBeneath?(rootFd: number, relPath: string, flags: number): NativeOpenBeneathResult;
293
+ openPublicationMetadata?(parentFd: number, basename: string): number;
294
+ readOwnerAndDacl?(path: string): NativeWindowsSecurityFacts;
230
295
  /** Internal Windows-only inspection of the exact borrowed Node descriptor. */
231
296
  inspectWindowsSecureFileHandle?(fd: number): NativeWindowsDescriptorSecurityFacts;
232
297
  ownedTreeRemovalAvailable?(parentFd: number): boolean;
298
+ tryRemoveEmptyOwnedTree?(parentFd: number, basename: string, directoryFd: number): NativeEmptyTreeRemovalResult;
233
299
  removeOwnedTree?(parentFd: number, basename: string, directoryFd: number): Promise<NativeOwnedTreeRemovalResult>;
234
300
  removeOwnedTreeSync?(parentFd: number, basename: string, directoryFd: number): NativeOwnedTreeRemovalResult;
235
301
  /** Local filesystem admission for one-way cooperative entry publication. */
236
302
  retainWindowsEntryPublication?(sourcePath: string, name: string, sourceDev: bigint, sourceIno: bigint, targetPath: string, targetName: string, targetDev: bigint, targetIno: bigint, dev: bigint, ino: bigint, kind: "file" | "directory" | "symlink"): NativeWindowsEntryPublication;
237
303
  entryPublicationFilesystem?(parentFd: number): string;
238
304
  publishRetainedEntryNoReplace?(sourceParentFd: number, sourceBasename: string, sourceFd: number, targetParentFd: number, targetBasename: string): NativePublicationTransition;
239
- renameNoReplace(...args: NativeTwoPathArgs): void;
305
+ renameNoReplace?(...args: NativeTwoPathArgs): void;
240
306
  /** Linux auto-mode fallback through already-admitted direct-child parents. */
241
307
  moveNoReplaceFallback?(...args: [...paths: NativeTwoPathArgs, expectedSourceDev: bigint, expectedSourceIno: bigint]): void;
242
308
  /** Identity-fenced retained-directory rename capability. */
243
309
  renameNoReplaceWithIdentity?(...args: [...paths: NativeTwoPathArgs, expectedSourceDev: bigint, expectedSourceIno: bigint]): void;
244
- renameReplace(...args: NativeTwoPathArgs): void;
245
- sha256File(fd: number, maxBytes?: number, signal?: AbortSignal): Promise<NativeFileHash>;
310
+ renameReplace?(...args: NativeTwoPathArgs): void;
311
+ sha256File?(fd: number, maxBytes?: number, signal?: AbortSignal, ownsPosition?: boolean): Promise<NativeFileHash>;
246
312
  }
313
+ export type CapableNativeBinding<K extends keyof NativeBinding> = NativeBinding & Required<Pick<NativeBinding, K>>;
247
314
  export declare function captureNativeFdClose(binding: NativeBinding): (fd: number) => void;
248
315
  export {};
@@ -4,5 +4,10 @@ export type FsSafeNativeConfig = {
4
4
  };
5
5
  export declare function configureFsSafeNative(config: Partial<FsSafeNativeConfig>): void;
6
6
  export declare function getFsSafeNativeConfig(): FsSafeNativeConfig;
7
+ /** Internal provenance; keep the public configuration shape unchanged. */
8
+ export declare function getNativeModeSetting(): {
9
+ mode: FsSafeNativeMode;
10
+ source: "programmatic configuration" | "FS_SAFE_NATIVE_MODE" | "OPENCLAW_FS_SAFE_NATIVE_MODE" | "default";
11
+ };
7
12
  export declare function isFsSafeNativeRequired(): boolean;
8
13
  export declare function __resetFsSafeNativeConfigForTest(): void;
@@ -26,6 +26,17 @@ export function getFsSafeNativeConfig() {
26
26
  "auto",
27
27
  };
28
28
  }
29
+ /** Internal provenance; keep the public configuration shape unchanged. */
30
+ export function getNativeModeSetting() {
31
+ if (overrideConfig.mode !== undefined)
32
+ return { mode: overrideConfig.mode, source: "programmatic configuration" };
33
+ for (const source of ["FS_SAFE_NATIVE_MODE", "OPENCLAW_FS_SAFE_NATIVE_MODE"]) {
34
+ const mode = parseMode(process.env[source]);
35
+ if (mode !== undefined)
36
+ return { mode, source };
37
+ }
38
+ return { mode: "auto", source: "default" };
39
+ }
29
40
  export function isFsSafeNativeRequired() {
30
41
  return (overrideConfig.mode ??
31
42
  parseMode(process.env.FS_SAFE_NATIVE_MODE) ??
@@ -2,23 +2,25 @@ import path from "node:path";
2
2
  import { FsSafeError } from "./errors.js";
3
3
  import { getNativeBinding } from "./native.js";
4
4
  import { inspectFileIdentitySync } from "./strict-file-identity.js";
5
+ import { isNativeStatIdentity, statIdentityFromNative } from "./native-stat-identity.js";
5
6
  export function getNativeDirectoryObservationBackend(enabled = true) {
6
7
  if (!enabled)
7
8
  return undefined;
8
- const binding = getNativeBinding();
9
+ const binding = getNativeBinding("observeDirectory");
9
10
  return binding && typeof binding.observeDirectory === "function"
10
11
  ? binding
11
12
  : undefined;
12
13
  }
13
14
  function validateNativeDirectoryObservation(observation) {
14
- if (!observation || typeof observation.dev !== "bigint" || observation.dev < 0n ||
15
- typeof observation.ino !== "bigint" || observation.ino < 0n ||
15
+ if (!observation || !isNativeStatIdentity(observation.dev) ||
16
+ !isNativeStatIdentity(observation.ino) ||
16
17
  typeof observation.realPath !== "string" ||
17
18
  observation.realPath.includes("\0") ||
18
19
  (!path.isAbsolute(observation.realPath) && !path.win32.isAbsolute(observation.realPath))) {
19
20
  throw new FsSafeError("path-mismatch", "native directory observation is invalid");
20
21
  }
21
- return observation;
22
+ const dev = statIdentityFromNative(observation.dev), ino = statIdentityFromNative(observation.ino);
23
+ return dev === observation.dev && ino === observation.ino ? observation : { ...observation, dev, ino };
22
24
  }
23
25
  /** Exact identity, type, and canonical path captured from one retained handle. */
24
26
  export function inspectNativeDirectoryObservation(backend, pathname, expected, platform = process.platform) {
@@ -1,3 +1,4 @@
1
+ import { type NativeBinding } from "./native.js";
1
2
  /** Warn once per capability, without including caller paths or native error text. */
2
- export declare function warnNativeFallback(feature: string, limitation: string): void;
3
+ export declare function warnNativeFallback(feature: string, limitation: string, ...capabilities: (keyof NativeBinding)[]): void;
3
4
  export declare function __resetNativeFallbackWarningsForTest(): void;
@@ -1,10 +1,34 @@
1
+ import { getNativeFallbackDiagnostic } from "./native.js";
2
+ import { getNativeModeSetting } from "./native-config.js";
3
+ import { nativeGuidance } from "./native-guidance.js";
1
4
  const warnedFeatures = new Set();
5
+ function fallbackReason(capabilities) {
6
+ const diagnostic = getNativeFallbackDiagnostic(...capabilities);
7
+ const expected = diagnostic.packageName === undefined
8
+ ? `No native package is published for ${diagnostic.target}.`
9
+ : `Expected ${diagnostic.packageName}@${diagnostic.packageVersion}.`;
10
+ const guidance = nativeGuidance(diagnostic.reason, getNativeModeSetting().source);
11
+ switch (diagnostic.reason) {
12
+ case "disabled":
13
+ return `native support is disabled by ${diagnostic.source} (disabled). ${expected} ${guidance}`;
14
+ case "unsupported-target":
15
+ return `the target ${diagnostic.target} is unsupported (unsupported-target). ${expected} ${guidance}`;
16
+ case "package-missing":
17
+ return `the selected native package could not be resolved (package-missing). ${expected} ${guidance}`;
18
+ case "load-failed":
19
+ return `the native package could not be loaded (load-failed: ${diagnostic.code}). ${expected} ${guidance}`;
20
+ case "capability-missing":
21
+ return `the native package lacks requested functions (capability-missing: ${diagnostic.capabilities.join(", ")}). ${expected} ${guidance}`;
22
+ default:
23
+ return `the requested native operation is unavailable (${diagnostic.reason}). ${expected}`;
24
+ }
25
+ }
2
26
  /** Warn once per capability, without including caller paths or native error text. */
3
- export function warnNativeFallback(feature, limitation) {
27
+ export function warnNativeFallback(feature, limitation, ...capabilities) {
4
28
  if (warnedFeatures.has(feature))
5
29
  return;
6
30
  warnedFeatures.add(feature);
7
- process.emitWarning(`${feature} is using its portable fallback because native support is unavailable or disabled. ${limitation}`, { code: "FS_SAFE_NATIVE_FALLBACK", type: "FsSafeWarning" });
31
+ process.emitWarning(`${feature} is using its portable fallback because ${fallbackReason(capabilities)} ${limitation}`, { code: "FS_SAFE_NATIVE_FALLBACK", type: "FsSafeWarning" });
8
32
  }
9
33
  export function __resetNativeFallbackWarningsForTest() {
10
34
  warnedFeatures.clear();
@@ -0,0 +1,3 @@
1
+ import type { getNativeModeSetting } from "./native-config.js";
2
+ /** Shared, path-free next steps for status reports and fallback warnings. */
3
+ export declare function nativeGuidance(reason: string, modeSource: ReturnType<typeof getNativeModeSetting>["source"]): string | undefined;
@@ -0,0 +1,21 @@
1
+ /** Shared, path-free next steps for status reports and fallback warnings. */
2
+ export function nativeGuidance(reason, modeSource) {
3
+ switch (reason) {
4
+ case "disabled": {
5
+ const enable = modeSource === "programmatic configuration"
6
+ ? 'call configureFsSafeNative({ mode: "auto" }) or configureFsSafeNative({ mode: "require" })'
7
+ : `set ${modeSource}=auto or ${modeSource}=require`;
8
+ return `If native loading is intended, ${enable}; keep intentional off settings.`;
9
+ }
10
+ case "unsupported-target":
11
+ return "Portable mode is expected on this target.";
12
+ case "package-missing":
13
+ return "Reinstall with optional dependencies included: npm --include=optional, or pnpm without --no-optional / optional=false. Check the lockfile and registry mirror.";
14
+ case "load-failed":
15
+ return "Check Node architecture, Linux libc compatibility, package dependencies, and OS code-integrity policy. Reinstalling identical bytes may not help.";
16
+ case "capability-missing":
17
+ return "Use matching fs-safe and platform-package versions; some targets intentionally provide only a subset of capabilities.";
18
+ default:
19
+ return undefined;
20
+ }
21
+ }
@@ -1,3 +1,3 @@
1
1
  import type { BigIntStats } from "node:fs";
2
2
  import type { NativeBinding } from "./native-binding.js";
3
- export declare function nativeMoveNoReplace(binding: NativeBinding, paths: Parameters<NativeBinding["renameNoReplace"]>, expected: BigIntStats | undefined, allowFallback: boolean, operation?: string): "link-unlink" | undefined;
3
+ export declare function nativeMoveNoReplace(binding: NativeBinding, paths: Parameters<NonNullable<NativeBinding["renameNoReplace"]>>, expected: BigIntStats | undefined, allowFallback: boolean, operation?: string): "link-unlink" | undefined;
@@ -1,4 +1,5 @@
1
1
  import { FsSafeError } from "./errors.js";
2
+ import { assertNativeCapabilities } from "./native.js";
2
3
  import { cachedNoReplaceUnavailable, noReplaceUnavailable, rememberNoReplaceUnavailable, } from "./native-noreplace.js";
3
4
  function fallbackError(error, operation) {
4
5
  const code = error?.code;
@@ -24,6 +25,7 @@ function fallbackError(error, operation) {
24
25
  return error;
25
26
  }
26
27
  export function nativeMoveNoReplace(binding, paths, expected, allowFallback, operation = "move") {
28
+ assertNativeCapabilities(binding, "renameNoReplace");
27
29
  const [sourceFd, source, targetFd, target] = paths;
28
30
  let unavailable = cachedNoReplaceUnavailable(binding, sourceFd, operation);
29
31
  if (!unavailable) {
@@ -1,5 +1,4 @@
1
1
  import fsSync, {} from "node:fs";
2
- import fs from "node:fs/promises";
3
2
  import path from "node:path";
4
3
  import { sameFileIdentityForCleanup } from "./file-identity.js";
5
4
  import { getNativeBinding } from "./native.js";
@@ -32,21 +31,21 @@ export function removeNativeCreatedFileIfStillPinned(params) {
32
31
  }
33
32
  }
34
33
  export async function createNativeExclusiveFile(targetPath, mode) {
35
- const binding = getNativeBinding();
34
+ const binding = getNativeBinding("openBeneath");
36
35
  if (!binding) {
37
36
  return undefined;
38
37
  }
39
38
  const closeFd = captureNativeFdClose(binding);
40
39
  const parentPath = path.dirname(targetPath);
41
40
  const basename = path.basename(targetPath);
42
- const parent = await fs.open(parentPath, fsSync.constants.O_RDONLY |
41
+ const parentFd = fsSync.openSync(parentPath, fsSync.constants.O_RDONLY |
43
42
  (typeof fsSync.constants.O_DIRECTORY === "number" ? fsSync.constants.O_DIRECTORY : 0));
44
43
  let fd;
45
44
  let created;
46
45
  try {
47
46
  let opened;
48
47
  try {
49
- opened = binding.openBeneath(parent.fd, basename, nativeOpenFlags(fsSync.constants.O_WRONLY | fsSync.constants.O_CREAT | fsSync.constants.O_EXCL));
48
+ opened = binding.openBeneath(parentFd, basename, nativeOpenFlags(fsSync.constants.O_WRONLY | fsSync.constants.O_CREAT | fsSync.constants.O_EXCL));
50
49
  }
51
50
  catch (error) {
52
51
  // The parent open above and every post-create operation remain untagged.
@@ -94,7 +93,7 @@ export async function createNativeExclusiveFile(targetPath, mode) {
94
93
  }
95
94
  removeNativeCreatedFileIfStillPinned({
96
95
  parentPath,
97
- parentFd: parent.fd,
96
+ parentFd,
98
97
  basename,
99
98
  created,
100
99
  });
@@ -102,6 +101,9 @@ export async function createNativeExclusiveFile(targetPath, mode) {
102
101
  throw error;
103
102
  }
104
103
  finally {
105
- await parent.close().catch(() => undefined);
104
+ try {
105
+ fsSync.closeSync(parentFd);
106
+ }
107
+ catch { /* Preserve the creation outcome. */ }
106
108
  }
107
109
  }
@@ -1,15 +1,20 @@
1
1
  import { type BigIntStats, type Stats } from "node:fs";
2
2
  import type { FileHandle } from "node:fs/promises";
3
- import type { FileIdentityStat } from "./file-identity.js";
4
- import type { NativeBinding } from "./native.js";
3
+ import { type FileIdentityStat } from "./file-identity.js";
4
+ import { type NativeBinding } from "./native.js";
5
5
  import { describeStagedDirectory } from "./staged-directory.js";
6
6
  type RootIdentity = Pick<FileIdentityStat, "dev" | "ino">;
7
+ type NativeRootHandle = {
8
+ readonly fd: number;
9
+ close(): Promise<void>;
10
+ [Symbol.asyncDispose](): Promise<void>;
11
+ };
7
12
  export type NativeRootAdmission = {
8
13
  directoryFlags?: number;
9
14
  exactRoot: boolean;
10
15
  reportCloseErrors?: boolean;
11
16
  operation: string;
12
- root: FileHandle;
17
+ root: NativeRootHandle;
13
18
  rootPath: string;
14
19
  };
15
20
  export type NativeParentAdmission = {
@@ -23,6 +28,41 @@ export type NativeParentAdmission = {
23
28
  stagedDirectory?: ReturnType<typeof describeStagedDirectory>;
24
29
  };
25
30
  export declare function sameNativeIdentity(left: RootIdentity, right: RootIdentity): boolean;
31
+ /** Short native mutations need a retained descriptor, not a Node FileHandle. */
32
+ export declare function openExactNativeRootSync(binding: NativeBinding, params: {
33
+ rootPath: string;
34
+ rootIdentity: {
35
+ dev: bigint;
36
+ ino: bigint;
37
+ };
38
+ }): {
39
+ fd: number;
40
+ stat: BigIntStats;
41
+ close(): void;
42
+ [Symbol.dispose](): void;
43
+ };
44
+ export declare function openExactNativeRootAdmissionSync(binding: NativeBinding, params: {
45
+ rootPath: string;
46
+ rootIdentity: {
47
+ dev: bigint;
48
+ ino: bigint;
49
+ };
50
+ operation: string;
51
+ reportCloseErrors?: boolean;
52
+ }): {
53
+ directoryFlags: number;
54
+ exactRoot: boolean;
55
+ reportCloseErrors: boolean | undefined;
56
+ operation: string;
57
+ root: {
58
+ fd: number;
59
+ stat: BigIntStats;
60
+ close(): void;
61
+ [Symbol.dispose](): void;
62
+ };
63
+ rootPath: string;
64
+ };
65
+ export declare function borrowNativeRootParent(admission: ReturnType<typeof openExactNativeRootAdmissionSync>): NativeParentAdmission;
26
66
  export declare function openNativeRootAdmission(binding: NativeBinding, params: {
27
67
  rootPath: string;
28
68
  rootIdentity?: RootIdentity;
@@ -32,5 +72,5 @@ export declare function openNativeRootAdmission(binding: NativeBinding, params:
32
72
  }): Promise<NativeRootAdmission>;
33
73
  export declare function openNativeParentAdmission(binding: NativeBinding, rootAdmission: Omit<NativeRootAdmission, "root"> & {
34
74
  root: Pick<FileHandle, "fd">;
35
- }, relativeParentPath: string, observation?: "native-directory"): Promise<NativeParentAdmission>;
75
+ }, relativeParentPath: string, observation?: "native-directory" | "native-publication"): Promise<NativeParentAdmission>;
36
76
  export {};
@@ -1,18 +1,20 @@
1
1
  import fsSync, {} from "node:fs";
2
- import fs from "node:fs/promises";
3
2
  import path from "node:path";
4
- import { inspectDirectoryIdentity, inspectDirectoryIdentitySync } from "./directory-guard.js";
3
+ import { assertSyncDirectoryGuard, inspectDirectoryIdentity, inspectDirectoryIdentitySync } from "./directory-guard.js";
5
4
  import { nodeDirectorySearchOnlyFlags } from "./directory-mode-node.js";
6
5
  import { inspectNativeDirectoryObservation } from "./native-directory-observation.js";
7
6
  import { FsSafeError } from "./errors.js";
7
+ import { hasSafeFileIdentity } from "./file-identity.js";
8
+ import { assertNativeCapabilities } from "./native.js";
8
9
  import { captureNativeFdClose } from "./native-binding.js";
9
10
  import { realpathSync } from "./realpath.js";
10
- import { describeStagedDirectory, exactIdentityMatches } from "./staged-directory.js";
11
+ import { describeNativeStagedDirectory, describePolicyStagedDirectory, describeStagedDirectory, exactIdentityMatches } from "./staged-directory.js";
11
12
  import { inspectFileIdentitySync } from "./strict-file-identity.js";
12
13
  import { createSuppressedError } from "./suppressed-error.js";
13
14
  import { assertNoWindowsPathAlias, pathForWindowsFilesystem } from "./windows-path-alias.js";
14
15
  export function sameNativeIdentity(left, right) {
15
- return left.dev === right.dev && left.ino === right.ino;
16
+ return hasSafeFileIdentity(left) && hasSafeFileIdentity(right) &&
17
+ BigInt(left.dev) === BigInt(right.dev) && BigInt(left.ino) === BigInt(right.ino);
16
18
  }
17
19
  function unavailable(message) {
18
20
  return new FsSafeError("helper-unavailable", message);
@@ -22,13 +24,67 @@ function assertParentAdmissionAvailable(binding) {
22
24
  throw unavailable("native parent directory admission is unavailable");
23
25
  }
24
26
  captureNativeFdClose(binding);
27
+ assertNativeCapabilities(binding, "openBeneath");
28
+ }
29
+ /** Short native mutations need a retained descriptor, not a Node FileHandle. */
30
+ export function openExactNativeRootSync(binding, params) {
31
+ assertParentAdmissionAvailable(binding);
32
+ assertNoWindowsPathAlias(params.rootPath, "filesystem", "native root uses a Windows filesystem namespace alias");
33
+ const flags = (nodeDirectorySearchOnlyFlags()?.flags ?? fsSync.constants.O_RDONLY) |
34
+ (fsSync.constants.O_DIRECTORY ?? 0);
35
+ const fd = fsSync.openSync(pathForWindowsFilesystem(params.rootPath), flags);
36
+ let held = true;
37
+ const close = () => {
38
+ if (!held)
39
+ return;
40
+ held = false;
41
+ fsSync.closeSync(fd);
42
+ };
43
+ try {
44
+ const stat = inspectFileIdentitySync(() => fsSync.fstatSync(fd, { bigint: true }), params.rootIdentity);
45
+ if (!stat.isDirectory())
46
+ throw new FsSafeError("path-mismatch", "native root is not a directory");
47
+ return { fd, stat, close, [Symbol.dispose]: close };
48
+ }
49
+ catch (error) {
50
+ try {
51
+ close();
52
+ }
53
+ catch (closeError) {
54
+ throw createSuppressedError(closeError, error, "native root admission and close failed");
55
+ }
56
+ throw error;
57
+ }
58
+ }
59
+ export function openExactNativeRootAdmissionSync(binding, params) {
60
+ return {
61
+ directoryFlags: (nodeDirectorySearchOnlyFlags()?.flags ?? fsSync.constants.O_RDONLY) | (fsSync.constants.O_DIRECTORY ?? 0),
62
+ exactRoot: true,
63
+ reportCloseErrors: params.reportCloseErrors,
64
+ operation: params.operation,
65
+ root: openExactNativeRootSync(binding, params),
66
+ rootPath: params.rootPath,
67
+ };
68
+ }
69
+ export function borrowNativeRootParent(admission) {
70
+ const guard = { dir: admission.rootPath, realPath: admission.rootPath, stat: admission.root.stat };
71
+ assertSyncDirectoryGuard(guard);
72
+ return { fd: admission.root.fd, guard, close() { } };
25
73
  }
26
74
  export async function openNativeRootAdmission(binding, params) {
27
75
  assertParentAdmissionAvailable(binding);
28
76
  const directoryFlags = (params.searchOnly ? nodeDirectorySearchOnlyFlags()?.flags ?? fsSync.constants.O_RDONLY : fsSync.constants.O_RDONLY) |
29
77
  (fsSync.constants.O_DIRECTORY ?? 0);
30
78
  assertNoWindowsPathAlias(params.rootPath, "filesystem", "native root uses a Windows filesystem namespace alias");
31
- const root = await fs.open(pathForWindowsFilesystem(params.rootPath), directoryFlags);
79
+ let fd = fsSync.openSync(pathForWindowsFilesystem(params.rootPath), directoryFlags);
80
+ const close = async () => {
81
+ if (fd < 0)
82
+ return;
83
+ const owned = fd;
84
+ fd = -1;
85
+ fsSync.closeSync(owned);
86
+ };
87
+ const root = { get fd() { return fd; }, close, [Symbol.asyncDispose]: close };
32
88
  try {
33
89
  const exactRoot = typeof params.rootIdentity?.dev === "bigint" &&
34
90
  typeof params.rootIdentity.ino === "bigint";
@@ -38,10 +94,7 @@ export async function openNativeRootAdmission(binding, params) {
38
94
  rootMatches = true;
39
95
  }
40
96
  else if (process.platform === "win32") {
41
- if (typeof binding.fstatIdentity !== "function") {
42
- throw unavailable("native root directory identity checks are unavailable");
43
- }
44
- const identity = binding.fstatIdentity(root.fd);
97
+ const identity = fsSync.fstatSync(root.fd, { bigint: true });
45
98
  rootMatches = !params.rootIdentity || sameNativeIdentity(params.rootIdentity, identity);
46
99
  }
47
100
  else {
@@ -87,7 +140,8 @@ export async function openNativeParentAdmission(binding, rootAdmission, relative
87
140
  const parentInput = relativeParentPath
88
141
  ? path.join(rootAdmission.rootPath, ...relativeParentPath.split("/"))
89
142
  : rootAdmission.rootPath;
90
- if (observation === "native-directory" && process.platform === "win32" && rootAdmission.exactRoot &&
143
+ if ((observation === "native-directory" || observation === "native-publication") &&
144
+ process.platform === "win32" && rootAdmission.exactRoot &&
91
145
  typeof binding.observeDirectory === "function") {
92
146
  const stat = inspectFileIdentitySync(() => fsSync.fstatSync(parentFd, { bigint: true }));
93
147
  let observed;
@@ -110,17 +164,33 @@ export async function openNativeParentAdmission(binding, rootAdmission, relative
110
164
  }
111
165
  const parentPath = realpathSync.native(pathForWindowsFilesystem(parentInput));
112
166
  assertNoWindowsPathAlias(parentPath, "filesystem", "native parent uses a Windows filesystem namespace alias");
167
+ if (observation === "native-publication" && process.platform !== "win32" && rootAdmission.exactRoot) {
168
+ const captured = describeNativeStagedDirectory(binding, parentFd, parentPath);
169
+ return {
170
+ fd: parentFd,
171
+ close: () => closeFd(parentFd),
172
+ guard: { dir: parentPath, realPath: parentPath, stat: captured.stat },
173
+ stagedDirectory: captured.directory,
174
+ };
175
+ }
176
+ if (observation === "native-directory" && process.platform !== "win32" && rootAdmission.exactRoot) {
177
+ const captured = describePolicyStagedDirectory(parentFd, parentPath, binding);
178
+ captured.disposeObservation?.();
179
+ return {
180
+ fd: parentFd,
181
+ close: () => closeFd(parentFd),
182
+ guard: { dir: parentPath, realPath: parentPath, stat: captured.stat },
183
+ stagedDirectory: captured.directory,
184
+ };
185
+ }
113
186
  const stagedDirectory = process.platform === "win32"
114
187
  ? undefined
115
188
  : describeStagedDirectory(parentFd, parentPath);
116
189
  const parentPathStat = rootAdmission.exactRoot
117
190
  ? await inspectDirectoryIdentity(parentPath, inspectFileIdentitySync(() => fsSync.fstatSync(parentFd, { bigint: true })))
118
- : fsSync.lstatSync(pathForWindowsFilesystem(parentPath));
191
+ : fsSync.lstatSync(pathForWindowsFilesystem(parentPath), { bigint: true });
119
192
  if (process.platform === "win32" && !rootAdmission.exactRoot) {
120
- if (typeof binding.fstatIdentity !== "function") {
121
- throw unavailable("native parent directory identity checks are unavailable");
122
- }
123
- const parentIdentity = binding.fstatIdentity(parentFd);
193
+ const parentIdentity = fsSync.fstatSync(parentFd, { bigint: true });
124
194
  if (parentPathStat.isSymbolicLink() || !sameNativeIdentity(parentPathStat, parentIdentity)) {
125
195
  throw new FsSafeError("path-mismatch", `${rootAdmission.operation} parent changed during resolution`);
126
196
  }
@@ -1,6 +1,6 @@
1
- import type { FileHandle } from "node:fs/promises";
1
+ import type { NativeRootAdmission } from "./native-parent-admission.js";
2
2
  import { type AnyAsyncDirectoryGuard } from "./directory-guard.js";
3
3
  import type { FileIdentityStat } from "./file-identity.js";
4
- import type { NativeBinding } from "./native.js";
4
+ import { type NativeBinding } from "./native.js";
5
5
  import type { PinnedWriteParams } from "./pinned-write-types.js";
6
- export declare function runPinnedWriteWindows(binding: NativeBinding, params: PinnedWriteParams, root: FileHandle, parentFd: number, parentGuard: AnyAsyncDirectoryGuard): Promise<FileIdentityStat>;
6
+ export declare function runPinnedWriteWindows(binding: NativeBinding, params: PinnedWriteParams, root: NativeRootAdmission["root"], parentFd: number, parentGuard: AnyAsyncDirectoryGuard): Promise<FileIdentityStat>;