@openclaw/fs-safe 0.2.6 → 0.3.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 (56) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +21 -7
  3. package/dist/archive-deadline.d.ts +9 -0
  4. package/dist/archive-deadline.d.ts.map +1 -0
  5. package/dist/archive-deadline.js +67 -0
  6. package/dist/archive-file-io.d.ts +9 -0
  7. package/dist/archive-file-io.d.ts.map +1 -0
  8. package/dist/archive-file-io.js +11 -0
  9. package/dist/archive-staging.d.ts.map +1 -1
  10. package/dist/archive-staging.js +43 -3
  11. package/dist/archive.d.ts.map +1 -1
  12. package/dist/archive.js +213 -105
  13. package/dist/deny-mutations.d.ts +11 -0
  14. package/dist/deny-mutations.d.ts.map +1 -0
  15. package/dist/deny-mutations.js +102 -0
  16. package/dist/errors.d.ts +1 -1
  17. package/dist/errors.d.ts.map +1 -1
  18. package/dist/index.d.ts +1 -1
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/json-durable-queue.d.ts.map +1 -1
  21. package/dist/json-durable-queue.js +5 -0
  22. package/dist/json.d.ts.map +1 -1
  23. package/dist/json.js +51 -4
  24. package/dist/opened-realpath.d.ts +3 -0
  25. package/dist/opened-realpath.d.ts.map +1 -0
  26. package/dist/opened-realpath.js +79 -0
  27. package/dist/output.d.ts.map +1 -1
  28. package/dist/output.js +1 -0
  29. package/dist/pinned-write.js +3 -9
  30. package/dist/read-opened-file.d.ts +18 -0
  31. package/dist/read-opened-file.d.ts.map +1 -0
  32. package/dist/read-opened-file.js +15 -0
  33. package/dist/regular-file.d.ts.map +1 -1
  34. package/dist/regular-file.js +23 -3
  35. package/dist/root-impl.d.ts +18 -15
  36. package/dist/root-impl.d.ts.map +1 -1
  37. package/dist/root-impl.js +60 -100
  38. package/dist/root-paths.d.ts.map +1 -1
  39. package/dist/root-paths.js +16 -5
  40. package/dist/root.d.ts +1 -1
  41. package/dist/root.d.ts.map +1 -1
  42. package/dist/secret-file.d.ts +1 -0
  43. package/dist/secret-file.d.ts.map +1 -1
  44. package/dist/secret-file.js +23 -3
  45. package/dist/sidecar-lock.d.ts.map +1 -1
  46. package/dist/sidecar-lock.js +9 -3
  47. package/dist/symlink-parents.js +2 -2
  48. package/docs/errors.md +2 -0
  49. package/docs/python-helper.md +3 -3
  50. package/docs/root.md +19 -9
  51. package/docs/secret-file.md +3 -2
  52. package/docs/security-model.md +4 -0
  53. package/docs/timing.md +1 -1
  54. package/docs/types.md +21 -9
  55. package/docs/writing.md +19 -1
  56. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.0 - 2026-05-21
4
+
5
+ ### Features
6
+
7
+ - Add opt-in `denyMutations` policies with exact `paths` and subtree `prefixes` so callers can protect application-sensitive files from root write, copy, move, remove, mkdir, and writable-open operations. (#20; thanks @amknight)
8
+
9
+ ### Security and Correctness
10
+
11
+ - Retry async JSON reads (`readJson`, `readJsonIfExists`, `tryReadJson`) up to five attempts with 50ms exponential backoff when the file is rotated mid-read by an atomic rename, and tag the underlying race as `FsSafeError("path-mismatch")` so callers can distinguish transient swaps from corruption. (#19; thanks @yetval)
12
+
13
+ ## 0.2.7 - 2026-05-20
14
+
15
+ ### Security and Correctness
16
+
17
+ - Restore best-effort Node write fallbacks when the Python helper is disabled or unavailable, preserving the `mode: "off"` contract while documenting the weaker POSIX same-UID race resistance compared with fd-relative helper commits.
18
+ - Harden DeepSec-reported archive staging and input pinning, secret and queue hardlink rejection, absolute output file validation, sidecar lock read failures, ClawSweeper dispatch trust checks, and scoped path defaults.
19
+
3
20
  ## 0.2.6 - 2026-05-17
4
21
 
5
22
  ### Security and Correctness
package/README.md CHANGED
@@ -66,15 +66,18 @@ before first use when you need a strict environment policy:
66
66
  import { configureFsSafePython } from "@openclaw/fs-safe";
67
67
 
68
68
  configureFsSafePython({ mode: "auto" }); // default: use helper, fall back if unavailable
69
- configureFsSafePython({ mode: "off" }); // never spawn Python; writes that need it fail closed
69
+ configureFsSafePython({ mode: "off" }); // never spawn Python; use best-effort Node fallbacks
70
70
  configureFsSafePython({ mode: "require" }); // fail closed if helper cannot start
71
71
  ```
72
72
 
73
73
  Equivalent env vars: `FS_SAFE_PYTHON_MODE=auto|off|require` and
74
- `FS_SAFE_PYTHON=/path/to/python3`. On POSIX, disabling or losing the helper now
75
- fails closed for root write paths that require fd-relative parent commits.
76
- Windows already uses the Node fallback path. See the
77
- [Python helper policy](docs/python-helper.md) for deployment guidance.
74
+ `FS_SAFE_PYTHON=/path/to/python3`. Without Python, `fs-safe` keeps lexical and
75
+ canonical root checks, no-follow opens, atomic temp+rename writes, and
76
+ post-write identity verification. What you lose is the strongest POSIX
77
+ fd-relative protection against a same-process-user racer swapping parent
78
+ directories between validation and mutation. Windows already uses the Node
79
+ fallback path. See the [Python helper policy](docs/python-helper.md) for
80
+ deployment guidance.
78
81
 
79
82
  ## Quick start
80
83
 
@@ -152,7 +155,18 @@ await using opened = await fs.openWritable("logs/current.log", { writeMode: "app
152
155
  }
153
156
  ```
154
157
 
155
- `nonBlockingRead` is the only I/O scheduling knob in `RootDefaults`; it applies to read/open operations because it changes how file descriptors are opened. Filesystem safety policy remains explicit through `hardlinks` and `symlinks`.
158
+ `nonBlockingRead` is the only I/O scheduling knob in `RootDefaults`; it applies to read/open operations because it changes how file descriptors are opened. Filesystem safety policy remains explicit through `hardlinks`, `symlinks`, and `denyMutations`.
159
+
160
+ ```ts
161
+ const locked = await root("/srv/workspace", {
162
+ denyMutations: {
163
+ paths: ["/srv/workspace/.env"],
164
+ prefixes: ["/srv/workspace/.ssh"],
165
+ },
166
+ });
167
+
168
+ await locked.write(".env", "token"); // FsSafeError code "denied-path"
169
+ ```
156
170
 
157
171
  `stat()`, `exists()`, and `list()` are boundary-checked, but they cannot pin a later operation to the same filesystem object. Use `read()`, `open()`, `write()`, `create()`, `copyIn()`, `move()`, or `remove()` for operations that must be race-resistant at the point of use.
158
172
 
@@ -432,7 +446,7 @@ Current `FsSafeErrorCode` values are `already-exists`, `hardlink`, `helper-faile
432
446
  - root-bounded APIs resolve paths against a configured root and reject canonical escapes
433
447
  - reads open with `O_NOFOLLOW` where available, then verify fd identity matches the path identity before returning the buffer or handle
434
448
  - writes use pinned parent-directory helpers and atomic replacement on POSIX, with verified post-write identity
435
- - `remove`, `mkdir`, `move`, `stat`, `list`, and parent-fd writes use one persistent fd-relative Python helper on POSIX; security-sensitive writes fail closed when that helper is disabled or unavailable
449
+ - `remove`, `mkdir`, `move`, `stat`, `list`, and parent-fd writes use one persistent fd-relative Python helper on POSIX, with Node fallbacks when the helper is disabled or unavailable
436
450
  - archive extraction stages into a private directory and merges through the same boundary checks used by direct writes
437
451
 
438
452
  ## Limitations
@@ -0,0 +1,9 @@
1
+ export type ExtractionDeadline = {
2
+ signal: AbortSignal;
3
+ check: () => void;
4
+ dispose: () => void;
5
+ };
6
+ export declare function createPipelineTimeoutError(err: unknown, deadline: ExtractionDeadline): unknown;
7
+ export declare function waitForDeadline<T>(promise: Promise<T>, deadline: ExtractionDeadline): Promise<T>;
8
+ export declare function withExtractionDeadline<T>(timeoutMs: number, label: string, run: (deadline: ExtractionDeadline) => Promise<T>): Promise<T>;
9
+ //# sourceMappingURL=archive-deadline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive-deadline.d.ts","sourceRoot":"","sources":["../src/archive-deadline.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAWF,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,kBAAkB,GAC3B,OAAO,CAST;AAED,wBAAsB,eAAe,CAAC,CAAC,EACrC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,QAAQ,EAAE,kBAAkB,GAC3B,OAAO,CAAC,CAAC,CAAC,CAgBZ;AA4BD,wBAAsB,sBAAsB,CAAC,CAAC,EAC5C,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,OAAO,CAAC,CAAC,CAAC,GAChD,OAAO,CAAC,CAAC,CAAC,CAQZ"}
@@ -0,0 +1,67 @@
1
+ function signalReason(signal, fallback) {
2
+ const reason = signal.reason;
3
+ return reason instanceof Error ? reason : fallback ?? new Error(String(reason));
4
+ }
5
+ function deadlineReason(deadline) {
6
+ return signalReason(deadline.signal);
7
+ }
8
+ export function createPipelineTimeoutError(err, deadline) {
9
+ if (deadline.signal.aborted &&
10
+ err instanceof Error &&
11
+ (err.name === "AbortError" || err.message === "The operation was aborted")) {
12
+ return deadlineReason(deadline);
13
+ }
14
+ return err;
15
+ }
16
+ export async function waitForDeadline(promise, deadline) {
17
+ deadline.check();
18
+ if (deadline.signal.aborted) {
19
+ throw deadlineReason(deadline);
20
+ }
21
+ return await Promise.race([
22
+ promise,
23
+ new Promise((_, reject) => {
24
+ const abort = () => reject(deadlineReason(deadline));
25
+ deadline.signal.addEventListener("abort", abort, { once: true });
26
+ const cleanup = () => {
27
+ deadline.signal.removeEventListener("abort", abort);
28
+ };
29
+ promise.then(cleanup, cleanup);
30
+ }),
31
+ ]);
32
+ }
33
+ function createExtractionDeadline(timeoutMs, label) {
34
+ const controller = new AbortController();
35
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
36
+ return {
37
+ signal: controller.signal,
38
+ check: () => undefined,
39
+ dispose: () => undefined,
40
+ };
41
+ }
42
+ const timeoutError = new Error(`${label} timed out after ${timeoutMs}ms`);
43
+ const timeoutId = setTimeout(() => {
44
+ controller.abort(timeoutError);
45
+ }, timeoutMs);
46
+ return {
47
+ signal: controller.signal,
48
+ check: () => {
49
+ if (controller.signal.aborted) {
50
+ throw signalReason(controller.signal, timeoutError);
51
+ }
52
+ },
53
+ dispose: () => {
54
+ clearTimeout(timeoutId);
55
+ },
56
+ };
57
+ }
58
+ export async function withExtractionDeadline(timeoutMs, label, run) {
59
+ const deadline = createExtractionDeadline(timeoutMs, label);
60
+ try {
61
+ deadline.check();
62
+ return await waitForDeadline(run(deadline), deadline);
63
+ }
64
+ finally {
65
+ deadline.dispose();
66
+ }
67
+ }
@@ -0,0 +1,9 @@
1
+ import type { FileHandle } from "node:fs/promises";
2
+ import type { ExtractionDeadline } from "./archive-deadline.js";
3
+ export declare function writeFileHandleFully(params: {
4
+ handle: FileHandle;
5
+ buffer: Buffer;
6
+ bytes: number;
7
+ deadline: ExtractionDeadline;
8
+ }): Promise<void>;
9
+ //# sourceMappingURL=archive-file-io.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive-file-io.d.ts","sourceRoot":"","sources":["../src/archive-file-io.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IACjD,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,kBAAkB,CAAC;CAC9B,GAAG,OAAO,CAAC,IAAI,CAAC,CAchB"}
@@ -0,0 +1,11 @@
1
+ export async function writeFileHandleFully(params) {
2
+ let offset = 0;
3
+ while (offset < params.bytes) {
4
+ params.deadline.check();
5
+ const { bytesWritten } = await params.handle.write(params.buffer, offset, params.bytes - offset);
6
+ if (bytesWritten <= 0) {
7
+ throw new Error("archive staging write made no progress");
8
+ }
9
+ offset += bytesWritten;
10
+ }
11
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"archive-staging.d.ts","sourceRoot":"","sources":["../src/archive-staging.ts"],"names":[],"mappings":"AAiBA,MAAM,MAAM,wBAAwB,GAChC,2BAA2B,GAC3B,qBAAqB,GACrB,+BAA+B,CAAC;AAEpC,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,IAAI,EAAE,wBAAwB,CAAC;gBAEnB,IAAI,EAAE,wBAAwB,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAKpF;AAkCD,wBAAsB,4BAA4B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA4BnF;AA6CD,wBAAsB,wBAAwB,CAAC,MAAM,EAAE;IACrD,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;CACtB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmChB;AAiGD,wBAAsB,4BAA4B,CAAC,CAAC,EAAE,MAAM,EAAE;IAC5D,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,GAAG,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;CACzC,GAAG,OAAO,CAAC,CAAC,CAAC,CAkBb;AAED,wBAAsB,iCAAiC,CAAC,MAAM,EAAE;IAC9D,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;CAC5B,GAAG,OAAO,CAAC,IAAI,CAAC,CAyEhB;AAED,wBAAgB,kCAAkC,CAAC,YAAY,EAAE,MAAM,GAAG,oBAAoB,CAE7F"}
1
+ {"version":3,"file":"archive-staging.d.ts","sourceRoot":"","sources":["../src/archive-staging.ts"],"names":[],"mappings":"AAiBA,MAAM,MAAM,wBAAwB,GAChC,2BAA2B,GAC3B,qBAAqB,GACrB,+BAA+B,CAAC;AAEpC,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,IAAI,EAAE,wBAAwB,CAAC;gBAEnB,IAAI,EAAE,wBAAwB,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAKpF;AAkCD,wBAAsB,4BAA4B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA4BnF;AA6CD,wBAAsB,wBAAwB,CAAC,MAAM,EAAE;IACrD,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;CACtB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmChB;AAyHD,wBAAsB,4BAA4B,CAAC,CAAC,EAAE,MAAM,EAAE;IAC5D,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,GAAG,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;CACzC,GAAG,OAAO,CAAC,CAAC,CAAC,CA6Bb;AAED,wBAAsB,iCAAiC,CAAC,MAAM,EAAE;IAC9D,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;CAC5B,GAAG,OAAO,CAAC,IAAI,CAAC,CAgFhB;AAED,wBAAgB,kCAAkC,CAAC,YAAY,EAAE,MAAM,GAAG,oBAAoB,CAE7F"}
@@ -195,6 +195,16 @@ async function assertExtractedFileHasNoHardlinkAlias(params) {
195
195
  }
196
196
  async function removeExtractedDestinationFile(params) {
197
197
  const destinationPath = path.join(params.destinationRealDir, params.relPath);
198
+ let stat;
199
+ try {
200
+ stat = await fs.lstat(destinationPath);
201
+ }
202
+ catch {
203
+ return;
204
+ }
205
+ if (!stat.isFile()) {
206
+ return;
207
+ }
198
208
  let resolved;
199
209
  try {
200
210
  resolved = await fs.realpath(destinationPath);
@@ -205,7 +215,19 @@ async function removeExtractedDestinationFile(params) {
205
215
  if (!isPathInside(params.destinationRealDir, resolved)) {
206
216
  return;
207
217
  }
208
- await fs.rm(destinationPath, { force: true }).catch(() => undefined);
218
+ const targetRoot = await root(params.destinationRealDir);
219
+ await targetRoot.remove(params.relPath).catch(() => undefined);
220
+ }
221
+ function assertSafeArchiveStagingPrefix(prefix) {
222
+ if (!prefix ||
223
+ prefix === "." ||
224
+ prefix === ".." ||
225
+ prefix.includes("/") ||
226
+ prefix.includes("\\") ||
227
+ path.basename(prefix) !== prefix) {
228
+ throw new Error("archive staging prefix must be a single path segment");
229
+ }
230
+ return prefix;
209
231
  }
210
232
  export async function withStagedArchiveDestination(params) {
211
233
  const stagingRoot = resolveSecureTempRoot({
@@ -216,20 +238,34 @@ export async function withStagedArchiveDestination(params) {
216
238
  if (isPathInside(params.destinationRealDir, stagingRoot)) {
217
239
  throw new Error(`archive staging root must be outside destination: ${stagingRoot}`);
218
240
  }
219
- const stagingDir = await fs.mkdtemp(path.join(stagingRoot, params.stagingDirPrefix ?? "fs-safe-archive-"));
241
+ const stagingPrefix = assertSafeArchiveStagingPrefix(params.stagingDirPrefix ?? "fs-safe-archive-");
242
+ const stagingDir = await fs.mkdtemp(path.join(stagingRoot, stagingPrefix));
243
+ const stagingGuard = await createDirectoryIdentityGuard(stagingDir);
220
244
  try {
221
245
  await fs.chmod(stagingDir, ARCHIVE_STAGING_MODE).catch(() => undefined);
246
+ await assertDirectoryIdentityGuard(stagingGuard);
222
247
  return await params.run(stagingDir);
223
248
  }
224
249
  finally {
225
- await fs.rm(stagingDir, { recursive: true, force: true }).catch(() => undefined);
250
+ try {
251
+ await assertDirectoryIdentityGuard(stagingGuard);
252
+ await fs.rm(stagingDir, { recursive: true, force: true }).catch(() => undefined);
253
+ }
254
+ catch {
255
+ // The staging path identity changed; deleting by name could target data
256
+ // outside the private temp tree, so fail closed and leave it for OS cleanup.
257
+ }
226
258
  }
227
259
  }
228
260
  export async function mergeExtractedTreeIntoDestination(params) {
229
261
  const targetRoot = await root(params.destinationRealDir);
262
+ const sourceRootGuard = await createDirectoryIdentityGuard(params.sourceDir);
263
+ const sourceRootReal = sourceRootGuard.realPath;
230
264
  const walk = async (currentSourceDir) => {
265
+ await assertDirectoryIdentityGuard(sourceRootGuard);
231
266
  const entries = await fs.readdir(currentSourceDir, { withFileTypes: true });
232
267
  for (const entry of entries) {
268
+ await assertDirectoryIdentityGuard(sourceRootGuard);
233
269
  const sourcePath = path.join(currentSourceDir, entry.name);
234
270
  const relPath = path.relative(params.sourceDir, sourcePath);
235
271
  const originalPath = relPath.split(path.sep).join("/");
@@ -238,6 +274,10 @@ export async function mergeExtractedTreeIntoDestination(params) {
238
274
  if (sourceStat.isSymbolicLink()) {
239
275
  throw symlinkTraversalError(originalPath);
240
276
  }
277
+ const sourceReal = await fs.realpath(sourcePath);
278
+ if (!isPathInside(sourceRootReal, sourceReal)) {
279
+ throw symlinkTraversalError(originalPath);
280
+ }
241
281
  if (sourceStat.isDirectory()) {
242
282
  await prepareArchiveOutputPath({
243
283
  destinationDir: params.destinationDir,
@@ -1 +1 @@
1
- {"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../src/archive.ts"],"names":[],"mappings":"AAWA,OAAO,EAOL,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAgBzE,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC,CAAC;AAEF,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,wBAAwB,EACxB,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC/F,OAAO,EACL,wBAAwB,EACxB,iBAAiB,EACjB,6BAA6B,EAC7B,mBAAmB,EACnB,2BAA2B,EAC3B,uBAAuB,EACvB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAE,KAAK,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAC3F,OAAO,EACL,kCAAkC,EAClC,iCAAiC,EACjC,4BAA4B,EAC5B,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,8BAA8B,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrF,OAAO,EACL,2BAA2B,EAC3B,iCAAiC,EACjC,KAAK,mBAAmB,GACzB,MAAM,4BAA4B,CAAC;AA8MpC,wBAAsB,cAAc,CAAC,MAAM,EAAE;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyEhB"}
1
+ {"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../src/archive.ts"],"names":[],"mappings":"AAkBA,OAAO,EAOL,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAiBzE,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC,CAAC;AAEF,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,wBAAwB,EACxB,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC/F,OAAO,EACL,wBAAwB,EACxB,iBAAiB,EACjB,6BAA6B,EAC7B,mBAAmB,EACnB,2BAA2B,EAC3B,uBAAuB,EACvB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAE,KAAK,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAC3F,OAAO,EACL,kCAAkC,EAClC,iCAAiC,EACjC,4BAA4B,EAC5B,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,8BAA8B,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrF,OAAO,EACL,2BAA2B,EAC3B,iCAAiC,EACjC,KAAK,mBAAmB,GACzB,MAAM,4BAA4B,CAAC;AAuTpC,wBAAsB,cAAc,CAAC,MAAM,EAAE;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6EhB"}