@openclaw/fs-safe 0.5.5 → 0.6.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.
Files changed (164) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +16 -10
  3. package/dist/advanced.d.ts +2 -1
  4. package/dist/advanced.d.ts.map +1 -1
  5. package/dist/advanced.js +1 -0
  6. package/dist/archive-crc32.d.ts +2 -0
  7. package/dist/archive-crc32.d.ts.map +1 -0
  8. package/dist/archive-crc32.js +14 -0
  9. package/dist/archive-kind.js +2 -2
  10. package/dist/archive-native.d.ts.map +1 -1
  11. package/dist/archive-native.js +7 -0
  12. package/dist/archive-read.d.ts.map +1 -1
  13. package/dist/archive-read.js +24 -5
  14. package/dist/archive-tar-meta.d.ts.map +1 -1
  15. package/dist/archive-tar-meta.js +53 -6
  16. package/dist/archive-tar-pax.d.ts +8 -0
  17. package/dist/archive-tar-pax.d.ts.map +1 -0
  18. package/dist/archive-tar-pax.js +100 -0
  19. package/dist/archive-tar-runtime.d.ts +1 -0
  20. package/dist/archive-tar-runtime.d.ts.map +1 -1
  21. package/dist/archive-zip-admission.d.ts +7 -0
  22. package/dist/archive-zip-admission.d.ts.map +1 -0
  23. package/dist/archive-zip-admission.js +60 -0
  24. package/dist/archive-zip-count.d.ts +2 -0
  25. package/dist/archive-zip-count.d.ts.map +1 -0
  26. package/dist/archive-zip-count.js +140 -0
  27. package/dist/archive-zip-directory.d.ts +8 -0
  28. package/dist/archive-zip-directory.d.ts.map +1 -0
  29. package/dist/archive-zip-directory.js +224 -0
  30. package/dist/archive-zip-integrity.d.ts.map +1 -1
  31. package/dist/archive-zip-integrity.js +1 -14
  32. package/dist/archive-zip-names.d.ts +12 -0
  33. package/dist/archive-zip-names.d.ts.map +1 -0
  34. package/dist/archive-zip-names.js +99 -0
  35. package/dist/archive-zip-preflight.d.ts +1 -1
  36. package/dist/archive-zip-preflight.d.ts.map +1 -1
  37. package/dist/archive-zip-preflight.js +8 -145
  38. package/dist/archive.d.ts.map +1 -1
  39. package/dist/archive.js +32 -23
  40. package/dist/file-hash.d.ts.map +1 -1
  41. package/dist/file-hash.js +25 -19
  42. package/dist/file-identity.d.ts +1 -0
  43. package/dist/file-identity.d.ts.map +1 -1
  44. package/dist/file-identity.js +10 -0
  45. package/dist/file-lock-sync.d.ts.map +1 -1
  46. package/dist/file-lock-sync.js +19 -7
  47. package/dist/move-path.js +2 -2
  48. package/dist/native-binding.d.ts +3 -0
  49. package/dist/native-binding.d.ts.map +1 -1
  50. package/dist/native-operations.d.ts +4 -1
  51. package/dist/native-operations.d.ts.map +1 -1
  52. package/dist/native-operations.js +24 -8
  53. package/dist/native-pinned-write-windows.d.ts +8 -0
  54. package/dist/native-pinned-write-windows.d.ts.map +1 -0
  55. package/dist/native-pinned-write-windows.js +92 -0
  56. package/dist/native-pinned-write.d.ts.map +1 -1
  57. package/dist/native-pinned-write.js +136 -127
  58. package/dist/native-staged-file.d.ts +24 -0
  59. package/dist/native-staged-file.d.ts.map +1 -0
  60. package/dist/native-staged-file.js +337 -0
  61. package/dist/native.d.ts.map +1 -1
  62. package/dist/native.js +4 -4
  63. package/dist/opened-realpath.d.ts +2 -0
  64. package/dist/opened-realpath.d.ts.map +1 -1
  65. package/dist/opened-realpath.js +12 -7
  66. package/dist/output-sibling.js +3 -3
  67. package/dist/owner-dacl.d.ts.map +1 -1
  68. package/dist/owner-dacl.js +2 -1
  69. package/dist/permission-exec.d.ts +19 -0
  70. package/dist/permission-exec.d.ts.map +1 -1
  71. package/dist/permission-exec.js +57 -11
  72. package/dist/permissions-public.d.ts +1 -1
  73. package/dist/permissions-public.d.ts.map +1 -1
  74. package/dist/permissions-windows.d.ts +3 -0
  75. package/dist/permissions-windows.d.ts.map +1 -1
  76. package/dist/permissions-windows.js +16 -5
  77. package/dist/permissions.d.ts +5 -0
  78. package/dist/permissions.d.ts.map +1 -1
  79. package/dist/pinned-write.d.ts +6 -0
  80. package/dist/pinned-write.d.ts.map +1 -1
  81. package/dist/pinned-write.js +19 -29
  82. package/dist/private-directory.d.ts.map +1 -1
  83. package/dist/private-directory.js +3 -2
  84. package/dist/private-temp-workspace.d.ts.map +1 -1
  85. package/dist/private-temp-workspace.js +23 -15
  86. package/dist/publish-file.d.ts.map +1 -1
  87. package/dist/publish-file.js +2 -2
  88. package/dist/replace-file-descriptor.d.ts +3 -3
  89. package/dist/replace-file-descriptor.d.ts.map +1 -1
  90. package/dist/replace-file-descriptor.js +2 -2
  91. package/dist/root-impl.d.ts.map +1 -1
  92. package/dist/root-impl.js +84 -75
  93. package/dist/root-paths.d.ts +11 -14
  94. package/dist/root-paths.d.ts.map +1 -1
  95. package/dist/root-paths.js +36 -27
  96. package/dist/root-write-verification.d.ts +11 -0
  97. package/dist/root-write-verification.d.ts.map +1 -0
  98. package/dist/root-write-verification.js +91 -0
  99. package/dist/secret-file.d.ts +1 -6
  100. package/dist/secret-file.d.ts.map +1 -1
  101. package/dist/secret-file.js +43 -117
  102. package/dist/secret-read-async.d.ts +1 -1
  103. package/dist/secret-read-async.d.ts.map +1 -1
  104. package/dist/secret-read-async.js +45 -67
  105. package/dist/secret-read-policy.d.ts +13 -0
  106. package/dist/secret-read-policy.d.ts.map +1 -0
  107. package/dist/secret-read-policy.js +28 -0
  108. package/dist/secret.d.ts +2 -1
  109. package/dist/secret.d.ts.map +1 -1
  110. package/dist/secret.js +2 -1
  111. package/dist/secure-file.d.ts.map +1 -1
  112. package/dist/secure-file.js +25 -16
  113. package/dist/sibling-temp.js +1 -1
  114. package/dist/sidecar-lock-acquire.d.ts.map +1 -1
  115. package/dist/sidecar-lock-acquire.js +4 -1
  116. package/dist/staged-directory.d.ts +16 -0
  117. package/dist/staged-directory.d.ts.map +1 -0
  118. package/dist/staged-directory.js +60 -0
  119. package/dist/staged-file-types.d.ts +56 -0
  120. package/dist/staged-file-types.d.ts.map +1 -0
  121. package/dist/staged-file-types.js +1 -0
  122. package/dist/staged-file.d.ts +10 -0
  123. package/dist/staged-file.d.ts.map +1 -0
  124. package/dist/staged-file.js +15 -0
  125. package/dist/strict-file-identity.d.ts +6 -0
  126. package/dist/strict-file-identity.d.ts.map +1 -0
  127. package/dist/strict-file-identity.js +48 -0
  128. package/dist/temp-cleanup.d.ts.map +1 -1
  129. package/dist/temp-cleanup.js +3 -3
  130. package/dist/temp-target.d.ts.map +1 -1
  131. package/dist/temp-target.js +9 -7
  132. package/dist/windows-owner.d.ts +3 -0
  133. package/dist/windows-owner.d.ts.map +1 -1
  134. package/dist/windows-owner.js +10 -2
  135. package/docs/advanced.md +11 -1
  136. package/docs/archive.md +62 -15
  137. package/docs/config.md +7 -0
  138. package/docs/contributing.md +45 -7
  139. package/docs/durability.md +17 -4
  140. package/docs/errors.md +16 -1
  141. package/docs/index.md +3 -1
  142. package/docs/install.md +15 -7
  143. package/docs/migrating-to-0.5.md +7 -7
  144. package/docs/migrating-to-0.6.md +43 -0
  145. package/docs/native-helper.md +15 -5
  146. package/docs/native.md +40 -11
  147. package/docs/path-scope.md +28 -2
  148. package/docs/permissions.md +13 -2
  149. package/docs/root.md +1 -1
  150. package/docs/secret-file.md +8 -0
  151. package/docs/secure-file.md +17 -1
  152. package/docs/security-model.md +15 -1
  153. package/docs/sidecar-lock.md +13 -3
  154. package/docs/staged-file.md +178 -0
  155. package/docs/testing.md +1 -1
  156. package/docs/writing.md +19 -0
  157. package/package.json +16 -9
  158. package/dist/native/darwin-arm64/fs-safe-native.node +0 -0
  159. package/dist/native/darwin-x64/fs-safe-native.node +0 -0
  160. package/dist/native/linux-arm64-gnu/fs-safe-native.node +0 -0
  161. package/dist/native/linux-arm64-musl/fs-safe-native.node +0 -0
  162. package/dist/native/linux-x64-gnu/fs-safe-native.node +0 -0
  163. package/dist/native/linux-x64-musl/fs-safe-native.node +0 -0
  164. package/dist/native/win32-x64-msvc/fs-safe-native.node +0 -0
@@ -0,0 +1,178 @@
1
+ ---
2
+ title: Retained-directory staging
3
+ description: "Prepare and publish one file while retaining its original directory for abort cleanup."
4
+ ---
5
+
6
+ # Retained-directory staging
7
+
8
+ `stageFileInDirectory()` from `@openclaw/fs-safe/advanced` prepares one file in
9
+ an existing directory and keeps that directory open until cleanup or disposal.
10
+ It requires the native binding on Linux or macOS, even in native mode `auto`.
11
+ Native off, an unavailable binding, or a binding without the required mechanism
12
+ fails before file creation. Windows is explicitly unsupported for this API.
13
+ Existing root, output, temp, lock, and durability APIs retain their documented
14
+ platform and fallback contracts.
15
+
16
+ ```ts
17
+ import type { DirectoryReceipt } from "@openclaw/fs-safe/durability";
18
+ import {
19
+ stageFileInDirectory,
20
+ type PublishedFileReceipt,
21
+ } from "@openclaw/fs-safe/advanced";
22
+
23
+ // Call while holding the application's cooperative writer lock. The caller
24
+ // supplies its authorization, manager, snapshot, and fingerprint checks.
25
+ export async function publishReviewedUpdate(options: {
26
+ directory: DirectoryReceipt;
27
+ basename: string;
28
+ bytes: Uint8Array;
29
+ assertAuthorizedAndCurrent(): Promise<void>;
30
+ }): Promise<PublishedFileReceipt> {
31
+ await options.assertAuthorizedAndCurrent();
32
+ await using staged = await stageFileInDirectory({
33
+ directory: options.directory,
34
+ content: options.bytes,
35
+ });
36
+ await options.assertAuthorizedAndCurrent();
37
+ await staged.assertCurrent();
38
+ return await staged.publish(options.basename, { overwrite: true });
39
+ }
40
+ ```
41
+
42
+ `await using` always disposes, including on exceptions. If both the body and
43
+ disposal fail, JavaScript preserves both errors in a `SuppressedError`. A
44
+ successful return means publication was observed and verified, not that a
45
+ separate application transaction committed. Application rollback and recovery
46
+ remain with the caller.
47
+
48
+ ## API
49
+
50
+ ```ts
51
+ function stageFileInDirectory(options: {
52
+ directory: string | DirectoryReceipt;
53
+ content: string | Uint8Array;
54
+ mode?: number;
55
+ }): Promise<StagedFile>;
56
+
57
+ interface StagedFile extends AsyncDisposable {
58
+ readonly receipt: StagedFileReceipt;
59
+ assertCurrent(): Promise<void>;
60
+ publish(basename: string, options: { overwrite: boolean }): Promise<PublishedFileReceipt>;
61
+ cleanup(): Promise<StagedFileCleanupReceipt>;
62
+ }
63
+ ```
64
+
65
+ Strings are UTF-8. `mode` is the requested **published** mode and defaults to
66
+ `0600`; exact final modes, including `000`, are supported. The unpublished file
67
+ stays at `0600` throughout preparation and any awaited application checks.
68
+ After rename succeeds and the published entry passes identity validation, the
69
+ owner applies the requested mode through its retained file descriptor and
70
+ synchronizes the file. No parent is created or chmodded.
71
+ Creation uses an exclusive, no-follow, close-on-exec open of a generated direct
72
+ child name. Writes use that descriptor. Inspection uses non-following metadata
73
+ operations, never a potentially blocking reopen of the leaf.
74
+
75
+ A supplied directory receipt must still match at admission. Its numeric
76
+ identity must be exactly representable; ambiguous identity fails closed.
77
+ Returned receipts are frozen descriptive snapshots, not mutable authority.
78
+ Changing a supplied receipt after admission cannot retarget the lifecycle.
79
+
80
+ `StagedFileReceipt` contains `directory` (`path`, `realPath`, and exact bigint
81
+ `identity.dev`/`identity.ino`), `temporaryBasename`, and the prepared file's
82
+ `identity` (`dev`, `ino`, `size`, `nlink`, `mtimeNs`, `ctimeNs` as bigint;
83
+ `mode`, `uid`, `gid` as numbers). This is a preparation-time snapshot of the
84
+ private stage: its mode is `0600`. Publication does not refresh this snapshot;
85
+ neither its mode nor its timestamps are a final-file fingerprint. No raw
86
+ descriptors are exposed.
87
+
88
+ `assertCurrent()` verifies the original pathname's directory identity and the
89
+ staged name against the retained file. A failed check does not disable cleanup.
90
+ After successful publication there is no staged name to check, so further
91
+ checks or publication reject. Cleanup closes the lifecycle; later checks and
92
+ publication reject before descriptor use. Rejected publication still carries its
93
+ phase, cause, and recorded publication outcome after closure. Concurrent calls
94
+ are serialized in invocation order, including cleanup and disposal. Repeated
95
+ cleanup returns the recorded outcome, or repeats the recorded error, without
96
+ touching descriptors.
97
+
98
+ ## Publication and failure evidence
99
+
100
+ `publish()` requires an explicit boolean `overwrite` and one direct-child
101
+ basename. Empty, dot, dotdot, separators, absolute paths, NUL, control characters,
102
+ drive-relative spellings, and the stage's own name are rejected.
103
+
104
+ With `overwrite: false`, publication is genuine kernel no-replace rename; a
105
+ collision leaves both names unchanged and raises `FsSafeError("already-exists")`.
106
+ The stage may then be cleaned or published under another name. With
107
+ `overwrite: true`, publication is plain atomic replacement. Neither route
108
+ copies. Both source and destination resolve through the retained original
109
+ parent, with checks immediately before rename and after publication.
110
+
111
+ `PublishedFileReceipt` has `status: "published"`, `staged`, `basename`, and
112
+ `overwrite`. Its `staged` field retains the private preparation snapshot, not
113
+ final metadata. Errors from publication carry typed `StagedFileFailureDetails`
114
+ in `FsSafeError.details`, including `phase` and `publication`. Publication is
115
+ `not-published`, `published` (with its receipt), or `indeterminate` (with the
116
+ attempted basename and overwrite policy) if a rename error cannot establish
117
+ whether it committed. The underlying error remains in `cause`.
118
+
119
+ A parent move after the final pre-check cannot divert the rename to a
120
+ replacement parent. It can publish inside the moved original and then fail
121
+ post-validation. Successful rename is recorded before those checks; cleanup
122
+ never deletes or rolls back a published final name. Indeterminate publication
123
+ also preserves names for caller-directed recovery.
124
+
125
+ The same rule applies if applying the published mode, synchronizing, or a later
126
+ check fails: the error reports `published`, and cleanup preserves the final
127
+ name. The file may still have mode `0600` or may already have the requested
128
+ mode, depending on which operation failed. A `published` failure receipt records
129
+ rename success, not successful permission finalization.
130
+
131
+ ## Cleanup guarantee and limits
132
+
133
+ If the temporary basename still names the object created by this lifecycle and
134
+ filesystem removal remains permitted, moving or replacing the actual parent
135
+ (or an ancestor) does not strand the unpublished temp. Cleanup resolves through
136
+ the retained original directory, even after `assertCurrent()` rejects drift.
137
+ Same-name sentinels in the replacement parent are not touched.
138
+
139
+ `StagedFileCleanupReceipt` records `temporaryBasename`, `publication`,
140
+ `resources` (`closed` or `close-failed`), and `status`:
141
+
142
+ | Status | Meaning |
143
+ |---|---|
144
+ | `removed` | The owned recorded name was unlinked through the retained directory. |
145
+ | `name-absent` | That name was absent in the original directory; this does not prove the inode has no other names. |
146
+ | `preserved` | An observed substitute or an indeterminate publication was left alone. |
147
+ | `failed` | Inspection or removal failed. |
148
+ | `not-needed` | Publication was recorded, or preparation failed before creating a file. |
149
+
150
+ Explicit cleanup returns preservation outcomes. Removal or close failures throw
151
+ an `FsSafeError` with the receipt in `details.cleanup` and underlying errors in
152
+ `cause`. Disposal also throws for preservation, so ignoring its return value
153
+ cannot hide incomplete cleanup. Setup failures preserve the original error;
154
+ when cleanup also fails, an aggregate cause retains both failures. Descriptors
155
+ are closed on every cleanup outcome, with no retry through recycled numbers.
156
+
157
+ This is **directory-relative targeting**, not expected-destination-inode/CAS
158
+ publication. Checking an identity before rename does not make rename CAS.
159
+ Likewise, the identity check followed by `unlinkat` is not an atomic conditional
160
+ unlink: an adversary can replace the leaf in that final syscall gap. Observed
161
+ substitutions are preserved, but this API does not guarantee recovery after
162
+ arbitrary child renames, permission revocation, I/O failure, or process death.
163
+ Keep application authorization, manager checks, snapshots, fingerprints,
164
+ cooperative locks, and conditional rollback.
165
+
166
+ Namespace cleanup is not crash durability. Staging retains the native writer's
167
+ file synchronization behavior, and publication synchronizes its directory
168
+ (with the existing `EPERM` exception); cleanup does not promise a durable unlink.
169
+ No successful receipt promises survival across a crash. See [Directory
170
+ durability](durability.md) when an application needs a separate durability proof.
171
+ `pinDirectory().assertCurrent()` and `.sync()` still require a current pathname;
172
+ they do not gain this cleanup authority.
173
+
174
+ ## Related pages
175
+
176
+ - [Advanced composition](advanced.md)
177
+ - [Native architecture](native.md)
178
+ - [Security model](security-model.md)
package/docs/testing.md CHANGED
@@ -17,7 +17,7 @@ The double-underscore prefix is a deliberate "hands off" signal: production code
17
17
  ## When to reach for hooks
18
18
 
19
19
  - Reproduce a TOCTOU race deterministically: simulate a symlink swap between resolve and open, or between write and rename.
20
- - Force guarded JavaScript behavior without removing bundled binaries from your runners.
20
+ - Force guarded JavaScript behavior without removing platform packages from your runners.
21
21
  - Inject latency to test cancellation/timeout paths.
22
22
 
23
23
  If you don't need to inject a race, you don't need hooks — most tests should drive the library through normal calls and assert on observable behavior.
package/docs/writing.md CHANGED
@@ -33,6 +33,10 @@ old-or-new guarantee does not apply to `append()` or `openWritable()`, which
33
33
  write in place, or to lower-level atomic helpers when their explicitly
34
34
  non-atomic permission-error copy fallback is enabled.
35
35
 
36
+ Post-publication verification can still reject after a complete replacement has
37
+ been committed. Rejection does not promise that a successful rename was rolled
38
+ back; the published file or a raced replacement may remain at the destination.
39
+
36
40
  ## Denying mutations
37
41
 
38
42
  All mutation verbs accept `denyMutations?: DenyMutationPolicy`, either as a root default or per-call option:
@@ -64,6 +68,21 @@ await fs.write("notes/today.txt", "hello\n", { encoding: "utf8" });
64
68
 
65
69
  `data` accepts `string | Buffer`. `options` are `{ denyMutations?: DenyMutationPolicy; encoding?: BufferEncoding; mkdir?: boolean; mode?: number; overwrite?: boolean; renameIdentity?: RenameIdentityPolicy }`. `mode` sets the file's POSIX mode. If neither the call nor `RootDefaults` supplies it, a replacement preserves the existing file mode and a new file uses `0o600`. `mkdir` and `overwrite` both default to `true`; set `overwrite: false` for the same no-clobber behavior as `create()`.
66
70
 
71
+ POSIX modes without read permission, including `0o000` and `0o200`, succeed:
72
+ final verification uses a descriptor retained by the writer rather than reopening
73
+ the published file. The requested mode is not relaxed for verification.
74
+ Publication verification compares exact bigint descriptor and pathname identities,
75
+ including large file indexes that cannot be represented by a JavaScript number.
76
+ Later reads still obey OS permissions, and access checks on a pre-existing
77
+ destination are unchanged. The explicit FUSE compatibility policy still requires
78
+ a readable destination to prove matching content when rename changes its identity.
79
+
80
+ When Windows cannot report a pathname's identity, the publication verifier reopens
81
+ the name and compares that descriptor's exact identity with the original retained
82
+ file, without reading bytes. It also rechecks links and root/parent containment.
83
+ This write-specific proof does not relax ordinary reads: unknown pathname metadata
84
+ alone is never proof that the name still refers to the expected file.
85
+
67
86
  ### `fs.create(rel, data, options?)`
68
87
 
69
88
  Don't-clobber variant of `write()`. Throws `already-exists` if the target is there.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/fs-safe",
3
- "version": "0.5.5",
3
+ "version": "0.6.0",
4
4
  "description": "Capability-style filesystem roots for Node.js apps that handle untrusted relative paths.",
5
5
  "keywords": [
6
6
  "filesystem",
@@ -27,7 +27,6 @@
27
27
  "dist/**/*.js",
28
28
  "dist/**/*.d.ts",
29
29
  "dist/**/*.d.ts.map",
30
- "dist/native/**/*.node",
31
30
  "docs/**/*.md",
32
31
  "docs/assets/readme-banner.jpg",
33
32
  "README.md",
@@ -139,6 +138,7 @@
139
138
  "native:test": "cargo test --manifest-path native/Cargo.toml",
140
139
  "pack:check": "pnpm build && node scripts/check-pack.mjs",
141
140
  "public-api:update": "pnpm build && node scripts/check-pack.mjs --update-public-api",
141
+ "package:collect": "node scripts/check-release-packages.mjs --output release-artifacts",
142
142
  "package:smoke": "node scripts/check-release-packages.mjs --allow-host-only --output release-artifacts",
143
143
  "check:changed": "pnpm run check",
144
144
  "release:notes": "node scripts/release-notes.mjs",
@@ -149,25 +149,32 @@
149
149
  "crabbox:warmup": "crabbox warmup"
150
150
  },
151
151
  "optionalDependencies": {
152
+ "@openclaw/fs-safe-darwin-arm64": "0.6.0",
153
+ "@openclaw/fs-safe-darwin-x64": "0.6.0",
154
+ "@openclaw/fs-safe-linux-arm64-gnu": "0.6.0",
155
+ "@openclaw/fs-safe-linux-arm64-musl": "0.6.0",
156
+ "@openclaw/fs-safe-linux-x64-gnu": "0.6.0",
157
+ "@openclaw/fs-safe-linux-x64-musl": "0.6.0",
158
+ "@openclaw/fs-safe-win32-x64-msvc": "0.6.0",
152
159
  "jszip": "^3.10.1",
153
160
  "tar": "7.5.22"
154
161
  },
155
162
  "devDependencies": {
156
- "@emnapi/runtime": "2.0.0-alpha.3",
157
- "@napi-rs/cli": "3.8.2",
158
- "@types/node": "^26.2.0",
159
- "@vitest/coverage-v8": "4.1.10",
163
+ "@emnapi/runtime": "2.0.0-alpha.4",
164
+ "@napi-rs/cli": "3.8.6",
165
+ "@types/node": "^26.3.0",
166
+ "@vitest/coverage-v8": "4.1.11",
160
167
  "fast-check": "^4.9.0",
161
168
  "istanbul-lib-coverage": "3.2.2",
162
169
  "istanbul-lib-report": "3.0.1",
163
170
  "istanbul-reports": "3.2.0",
164
171
  "sigstore": "5.0.0",
165
172
  "typescript": "^7.0.2",
166
- "vite": "8.2.1",
167
- "vitest": "^4.1.10"
173
+ "vite": "8.2.2",
174
+ "vitest": "^4.1.11"
168
175
  },
169
176
  "engines": {
170
177
  "node": ">=22"
171
178
  },
172
- "packageManager": "pnpm@10.34.5"
179
+ "packageManager": "pnpm@11.24.0"
173
180
  }