@openclaw/fs-safe 0.18.0 → 0.18.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.
- package/CHANGELOG.md +18 -0
- package/dist/advanced.d.ts +4 -2
- package/dist/advanced.js +1 -1
- package/dist/archive-durability.d.ts +1 -1
- package/dist/archive-merge.js +0 -1
- package/dist/archive-parser.wasm +0 -0
- package/dist/archive-plan.d.ts +64 -3
- package/dist/archive-plan.js +55 -1
- package/dist/archive-staging.d.ts +1 -2
- package/dist/archive-staging.js +0 -2
- package/dist/archive-tar-wasm.d.ts +1 -1
- package/dist/archive-zip-directory.d.ts +1 -1
- package/dist/archive-zip-entry.d.ts +1 -1
- package/dist/archive-zip-entry.js +1 -1
- package/dist/archive-zip-preflight.d.ts +0 -2
- package/dist/archive-zip-preflight.js +0 -1
- package/dist/archive.d.ts +14 -8
- package/dist/archive.js +127 -12
- package/dist/atomic.d.ts +3 -1
- package/dist/copy-publication.d.ts +1 -1
- package/dist/create.d.ts +16 -2
- package/dist/create.js +388 -2
- package/dist/creation-boundary.d.ts +60 -0
- package/dist/creation-boundary.js +371 -0
- package/dist/directory-guard.d.ts +0 -1
- package/dist/directory-guard.js +0 -3
- package/dist/directory-mode-node.d.ts +20 -2
- package/dist/directory-mode-node.js +89 -3
- package/dist/durability.d.ts +2 -1
- package/dist/file-lock-sync-acquisition.js +3 -3
- package/dist/file-lock-sync-root-acquire.js +2 -6
- package/dist/file-lock-sync-root-options.d.ts +2 -10
- package/dist/file-lock-sync-root.d.ts +2 -1
- package/dist/file-lock-sync-stale-admission.js +3 -10
- package/dist/file-lock-sync.d.ts +4 -21
- package/dist/file-store-boundary.d.ts +7 -0
- package/dist/file-store-boundary.js +58 -1
- package/dist/file-store-sync-write.js +2 -3
- package/dist/file-store.js +1 -6
- package/dist/guarded-mkdir.d.ts +1 -1
- package/dist/index.d.ts +9 -6
- package/dist/json-durable-queue-ownership.d.ts +1 -5
- package/dist/json-durable-queue-read.js +7 -3
- package/dist/json-durable-queue.d.ts +0 -1
- package/dist/json-durable-queue.js +1 -3
- package/dist/json-store.js +1 -2
- package/dist/json.js +1 -2
- package/dist/move-path.js +1 -2
- package/dist/native-operations.js +0 -1
- package/dist/native-pinned-write-windows.d.ts +1 -1
- package/dist/native-pinned-write-windows.js +1 -1
- package/dist/native-pinned-write.d.ts +1 -1
- package/dist/native-pinned-write.js +3 -6
- package/dist/native-policy-parent-windows.d.ts +1 -1
- package/dist/native-staged-file.d.ts +2 -2
- package/dist/native-staged-file.js +1 -2
- package/dist/permission-exec.d.ts +6 -0
- package/dist/permissions-public.d.ts +2 -1
- package/dist/permissions-windows.d.ts +3 -6
- package/dist/permissions.d.ts +3 -10
- package/dist/permissions.js +0 -1
- package/dist/pinned-mutation-admission.d.ts +1 -1
- package/dist/pinned-open.d.ts +1 -0
- package/dist/pinned-open.js +7 -2
- package/dist/pinned-operation.d.ts +1 -1
- package/dist/pinned-operation.js +3 -16
- package/dist/pinned-write-mode.js +1 -1
- package/dist/pinned-write-staged.js +1 -2
- package/dist/pinned-write.d.ts +0 -1
- package/dist/pinned-write.js +3 -5
- package/dist/private-producer-handoff-sync.d.ts +2 -12
- package/dist/private-producer-handoff-sync.js +1 -1
- package/dist/private-producer-handoff.d.ts +3 -3
- package/dist/private-temp-workspace.js +1 -2
- package/dist/publish-copy-stage.d.ts +1 -1
- package/dist/publish-file.d.ts +0 -1
- package/dist/publish-file.js +1 -2
- package/dist/replace-directory.js +6 -19
- package/dist/replace-file-copy-fallback.d.ts +1 -8
- package/dist/replace-file-descriptor.d.ts +3 -11
- package/dist/replace-file-descriptor.js +1 -1
- package/dist/replace-file-rename-policy.d.ts +1 -2
- package/dist/replace-file.d.ts +3 -3
- package/dist/replace-file.js +1 -1
- package/dist/retained-directory-replacement.d.ts +1 -0
- package/dist/retained-directory-replacement.js +1 -1
- package/dist/root-context.js +3 -7
- package/dist/root-create-input.d.ts +1 -1
- package/dist/root-directory-creation.d.ts +1 -1
- package/dist/root-directory-creation.js +1 -1
- package/dist/root-directory-list.js +3 -7
- package/dist/root-entries.js +2 -2
- package/dist/root-errors.d.ts +4 -0
- package/dist/root-errors.js +5 -3
- package/dist/root-file-final-admission.d.ts +1 -1
- package/dist/root-file-final-admission.js +1 -6
- package/dist/root-file.js +2 -5
- package/dist/root-impl.d.ts +0 -5
- package/dist/root-impl.js +22 -21
- package/dist/root-move-noreplace.js +4 -10
- package/dist/root-observed-path.js +2 -4
- package/dist/root-options.d.ts +1 -1
- package/dist/root-path-existing.js +2 -3
- package/dist/root-path-stat.js +2 -4
- package/dist/root-public-types.d.ts +11 -0
- package/dist/root-remove-identity.js +2 -4
- package/dist/root-remove.js +2 -4
- package/dist/root-write-admission.d.ts +1 -1
- package/dist/root-write-admission.js +3 -7
- package/dist/root-write-complete-parent.js +2 -3
- package/dist/root-write-verification.d.ts +1 -1
- package/dist/root.d.ts +2 -6
- package/dist/secret-file.js +11 -17
- package/dist/secret-read-policy.js +1 -1
- package/dist/secure-file-windows.js +4 -9
- package/dist/secure-temp-dir.js +2 -7
- package/dist/secure-temp-repair.js +5 -1
- package/dist/sidecar-lock-acquire.js +8 -11
- package/dist/sidecar-lock-policy.d.ts +1 -0
- package/dist/sidecar-lock-policy.js +7 -0
- package/dist/sidecar-lock-reclaim.js +5 -6
- package/dist/sidecar-lock-stale-admission.js +2 -6
- package/dist/sidecar-lock-types.d.ts +22 -16
- package/dist/stat-observation.js +3 -10
- package/dist/strict-file-identity.d.ts +2 -0
- package/dist/strict-file-identity.js +6 -6
- package/dist/temp-target.js +3 -8
- package/dist/temp-workspace-admission.js +7 -15
- package/dist/temp-workspace-child-admission.d.ts +16 -2
- package/dist/temp-workspace-child-admission.js +65 -3
- package/dist/temp-workspace-descriptor.d.ts +1 -1
- package/dist/temp-workspace-descriptor.js +2 -4
- package/dist/text-atomic.js +1 -1
- package/dist/windows-owner.d.ts +3 -6
- package/dist/windows-owner.js +1 -1
- package/dist/windows-path-alias.d.ts +1 -0
- package/dist/windows-path-alias.js +5 -0
- package/dist/windows-security-bridge.cs +0 -2
- package/docs/advanced.md +3 -1
- package/docs/secret-file.md +13 -0
- package/docs/sidecar-lock.md +6 -0
- package/docs/store.md +6 -0
- package/docs/temp.md +8 -1
- package/docs/writing.md +5 -0
- package/package.json +8 -8
- package/dist/archive-native.d.ts +0 -10
- package/dist/archive-native.js +0 -73
- package/dist/archive-options.d.ts +0 -30
- package/dist/archive-policy.d.ts +0 -21
- package/dist/archive-policy.js +0 -38
- package/dist/archive-tar-inspect.d.ts +0 -6
- package/dist/archive-tar-inspect.js +0 -62
- package/dist/archive-tar.d.ts +0 -18
- package/dist/archive-tar.js +0 -21
- package/dist/create-directory.d.ts +0 -18
- package/dist/create-directory.js +0 -111
- package/dist/create-file-async.d.ts +0 -6
- package/dist/create-file-async.js +0 -121
- package/dist/create-file.d.ts +0 -7
- package/dist/create-file.js +0 -179
- package/dist/creation-darwin.d.ts +0 -5
- package/dist/creation-darwin.js +0 -70
- package/dist/creation-file-state.d.ts +0 -18
- package/dist/creation-file-state.js +0 -118
- package/dist/creation-path.d.ts +0 -22
- package/dist/creation-path.js +0 -83
- package/dist/creation-permissions.d.ts +0 -18
- package/dist/creation-permissions.js +0 -115
- package/dist/directory-mode-owner.d.ts +0 -20
- package/dist/directory-mode-owner.js +0 -78
- package/dist/file-store-copy-source.d.ts +0 -4
- package/dist/file-store-copy-source.js +0 -31
- package/dist/file-store-limit.d.ts +0 -1
- package/dist/file-store-limit.js +0 -7
- package/dist/file-store-path.d.ts +0 -2
- package/dist/file-store-path.js +0 -30
- package/dist/standalone-publication-path.d.ts +0 -1
- package/dist/standalone-publication-path.js +0 -6
- package/dist/temp-workspace-identity.d.ts +0 -14
- package/dist/temp-workspace-identity.js +0 -41
- package/dist/temp-workspace-permissions.d.ts +0 -3
- package/dist/temp-workspace-permissions.js +0 -32
- /package/dist/{archive-options.js → root-public-types.js} +0 -0
package/dist/file-lock-sync.d.ts
CHANGED
|
@@ -1,28 +1,11 @@
|
|
|
1
|
-
import type { Root } from "./root-impl.js";
|
|
2
1
|
import { type SidecarLockStaleSnapshot } from "./sidecar-lock-reclaim.js";
|
|
3
|
-
import type {
|
|
4
|
-
export type FileLockSyncAcquireOptions<TPayload extends Record<string, unknown>> = {
|
|
5
|
-
lockPath?: string;
|
|
2
|
+
import type { SidecarLockCommonAcquireOptions, SidecarLockOptionFields, SidecarLockReclaimParams } from "./sidecar-lock-types.js";
|
|
3
|
+
export type FileLockSyncAcquireOptions<TPayload extends Record<string, unknown>> = SidecarLockOptionFields<SidecarLockCommonAcquireOptions & {
|
|
6
4
|
staleMs?: number;
|
|
7
|
-
timeoutMs?: number;
|
|
8
|
-
retry?: SidecarLockRetryOptions;
|
|
9
|
-
staleRecovery?: SidecarLockStaleRecovery;
|
|
10
|
-
reentrantOwner?: string;
|
|
11
5
|
payload: () => TPayload;
|
|
12
|
-
shouldReclaim?: (params:
|
|
13
|
-
lockPath: string;
|
|
14
|
-
normalizedTargetPath: string;
|
|
15
|
-
payload: unknown;
|
|
16
|
-
staleMs: number;
|
|
17
|
-
nowMs: number;
|
|
18
|
-
heldByThisProcess: false;
|
|
19
|
-
}) => boolean;
|
|
6
|
+
shouldReclaim?: (params: SidecarLockReclaimParams<false>) => boolean;
|
|
20
7
|
shouldRemoveStaleLock?: (snapshot: SidecarLockStaleSnapshot) => boolean;
|
|
21
|
-
|
|
22
|
-
lockRoot?: Root;
|
|
23
|
-
onCompromised?: (info: SidecarLockCompromisedInfo) => void;
|
|
24
|
-
compromiseCheckIntervalMs?: number;
|
|
25
|
-
};
|
|
8
|
+
}>;
|
|
26
9
|
export type FileLockSyncHandle = {
|
|
27
10
|
lockPath: string;
|
|
28
11
|
normalizedTargetPath: string;
|
|
@@ -29,3 +29,10 @@ export declare function ensureStoreDirectorySync(params: {
|
|
|
29
29
|
mode: number;
|
|
30
30
|
messagePrefix: "private store" | "store";
|
|
31
31
|
}): SyncParentGuard;
|
|
32
|
+
export declare function assertRelativePath(relativePath: string): string;
|
|
33
|
+
export declare function resolveStorePath(rootDir: string, relativePath: string): string;
|
|
34
|
+
export declare function assertFileStoreMaxBytes(size: number, limit: number | undefined): void;
|
|
35
|
+
export declare function readFileStoreCopySource(params: {
|
|
36
|
+
sourcePath: string;
|
|
37
|
+
maxBytes: number;
|
|
38
|
+
}): Promise<Buffer>;
|
|
@@ -5,13 +5,15 @@ import { createByteLimitTransform } from "./bounded-read-stream.js";
|
|
|
5
5
|
import { pipeline } from "node:stream/promises";
|
|
6
6
|
import { FsSafeError } from "./errors.js";
|
|
7
7
|
import { assertSyncStoreDirectoryReceipt, ensureSyncStoreDirectory, } from "./file-store-sync-directory.js";
|
|
8
|
-
import { isPathInside } from "./path.js";
|
|
8
|
+
import { isPathInside, splitSafeRelativePath } from "./path.js";
|
|
9
9
|
import { resolveOpenedFileRealPathForHandle, root } from "./root.js";
|
|
10
10
|
import { ensureTrailingSep } from "./root-context.js";
|
|
11
11
|
import { RootHandle } from "./root-impl.js";
|
|
12
12
|
import { prepareSecretFileWrite } from "./secret-file.js";
|
|
13
13
|
import { resolveSecureTempRoot } from "./secure-temp-dir.js";
|
|
14
14
|
import { recursiveMkdirPath } from "./recursive-mkdir-path.js";
|
|
15
|
+
import { readRegularFile } from "./regular-file.js";
|
|
16
|
+
import { errorCauseOptions } from "./root-errors.js";
|
|
15
17
|
import { assertNoWindowsPathAlias } from "./windows-path-alias.js";
|
|
16
18
|
export async function ensureParentInRoot(scopedRoot, relativePath, mode) {
|
|
17
19
|
const parent = path.posix.dirname(relativePath);
|
|
@@ -118,3 +120,58 @@ export function ensureStoreDirectorySync(params) {
|
|
|
118
120
|
assertSyncStoreDirectoryReceipt(guard);
|
|
119
121
|
return guard;
|
|
120
122
|
}
|
|
123
|
+
export function assertRelativePath(relativePath) {
|
|
124
|
+
const raw = relativePath.trim();
|
|
125
|
+
if (!raw || raw !== relativePath) {
|
|
126
|
+
throw new FsSafeError("invalid-path", "store key must be non-empty and unpadded");
|
|
127
|
+
}
|
|
128
|
+
const segments = splitSafeRelativePath(raw);
|
|
129
|
+
if (segments.length === 0 ||
|
|
130
|
+
segments.join("/") !== raw ||
|
|
131
|
+
raw.normalize("NFC") !== raw ||
|
|
132
|
+
segments.some((segment) => /[ .]$/u.test(segment))) {
|
|
133
|
+
throw new FsSafeError("invalid-path", "store key must use one canonical relative spelling");
|
|
134
|
+
}
|
|
135
|
+
return raw;
|
|
136
|
+
}
|
|
137
|
+
export function resolveStorePath(rootDir, relativePath) {
|
|
138
|
+
const key = assertRelativePath(relativePath);
|
|
139
|
+
// FileStore constructors snapshot an absolute root before this helper runs.
|
|
140
|
+
// Do not re-resolve it: Node drops the trailing separator from an exact
|
|
141
|
+
// Windows namespace drive root such as `\\?\C:\`.
|
|
142
|
+
const root = path.isAbsolute(rootDir) ? rootDir : path.resolve(rootDir);
|
|
143
|
+
// The immutable key already passed segment validation; keep the containment check.
|
|
144
|
+
const target = path.resolve(root, key);
|
|
145
|
+
if (!isPathInside(root, target)) {
|
|
146
|
+
throw new FsSafeError("outside-workspace", "relative path escapes root");
|
|
147
|
+
}
|
|
148
|
+
return target;
|
|
149
|
+
}
|
|
150
|
+
// Store operation boundaries admit the primitive limit before reaching this helper.
|
|
151
|
+
export function assertFileStoreMaxBytes(size, limit) {
|
|
152
|
+
if (limit !== undefined && size > limit) {
|
|
153
|
+
throw new FsSafeError("too-large", `file exceeds maximum size of ${limit} bytes`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
export async function readFileStoreCopySource(params) {
|
|
157
|
+
assertNoWindowsPathAlias(params.sourcePath, "filesystem", "source path uses a Windows filesystem namespace alias");
|
|
158
|
+
const sourceStat = syncFs.lstatSync(params.sourcePath);
|
|
159
|
+
if (sourceStat.isSymbolicLink() || !sourceStat.isFile()) {
|
|
160
|
+
throw new FsSafeError("not-file", "source path is not a file");
|
|
161
|
+
}
|
|
162
|
+
assertFileStoreMaxBytes(sourceStat.size, params.maxBytes);
|
|
163
|
+
try {
|
|
164
|
+
return (await readRegularFile({ filePath: params.sourcePath, maxBytes: params.maxBytes }))
|
|
165
|
+
.buffer;
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
169
|
+
if (message.includes("regular file") || message.includes("not a regular file")) {
|
|
170
|
+
throw new FsSafeError("not-file", "source path is not a file", errorCauseOptions(error));
|
|
171
|
+
}
|
|
172
|
+
if (message.includes(`exceeds ${params.maxBytes} bytes`)) {
|
|
173
|
+
throw new FsSafeError("too-large", `file exceeds maximum size of ${params.maxBytes} bytes`, errorCauseOptions(error));
|
|
174
|
+
}
|
|
175
|
+
throw error;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
@@ -10,6 +10,7 @@ import { isPathInside } from "./path.js";
|
|
|
10
10
|
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
11
11
|
import { writeTempFileSync } from "./replace-file-descriptor.js";
|
|
12
12
|
import { SyncAtomicTempOwner } from "./replace-file-temp-owner.js";
|
|
13
|
+
import { errorCauseOptions } from "./root-errors.js";
|
|
13
14
|
import { inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
14
15
|
import { getFsSafeTestHooks } from "./test-hooks.js";
|
|
15
16
|
function verifyStoreFile(fd, expected, filePath) {
|
|
@@ -108,9 +109,7 @@ export function writeFileSyncAtomic(params) {
|
|
|
108
109
|
if (error instanceof FsSafeError) {
|
|
109
110
|
throw error;
|
|
110
111
|
}
|
|
111
|
-
throw new FsSafeError("path-mismatch", "store target changed after write",
|
|
112
|
-
cause: error instanceof Error ? error : undefined,
|
|
113
|
-
});
|
|
112
|
+
throw new FsSafeError("path-mismatch", "store target changed after write", errorCauseOptions(error));
|
|
114
113
|
}
|
|
115
114
|
assertSyncStoreDirectoryReceipt(parentGuard);
|
|
116
115
|
if (params.durable) {
|
package/dist/file-store.js
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import syncFs from "node:fs";
|
|
2
|
-
import fs from "node:fs/promises";
|
|
3
|
-
import path from "node:path";
|
|
4
2
|
import { normalizeMaxBytes } from "./byte-budget.js";
|
|
5
3
|
import { readFileDescriptorBoundedSync } from "./bounded-read.js";
|
|
6
4
|
import { FsSafeError } from "./errors.js";
|
|
7
|
-
import { assertFileStoreMaxBytes } from "./file-store-limit.js";
|
|
8
|
-
import { assertRelativePath, resolveStorePath } from "./file-store-path.js";
|
|
9
5
|
import { pruneExpiredStoreEntries } from "./file-store-prune.js";
|
|
10
|
-
import { ensureParentInRoot, openPrivateStoreLockRoot, openWritableStoreRoot, writeStreamToTempSource, } from "./file-store-boundary.js";
|
|
6
|
+
import { assertFileStoreMaxBytes, assertRelativePath, ensureParentInRoot, openPrivateStoreLockRoot, openWritableStoreRoot, readFileStoreCopySource, resolveStorePath, writeStreamToTempSource, } from "./file-store-boundary.js";
|
|
11
7
|
import { writeFileSyncAtomic } from "./file-store-sync-write.js";
|
|
12
8
|
import { createJsonStore } from "./json-document-store.js";
|
|
13
9
|
import { stringifyJsonDocument } from "./json-stringify.js";
|
|
@@ -18,7 +14,6 @@ import { DEFAULT_ROOT_MAX_BYTES } from "./root-impl.js";
|
|
|
18
14
|
import { matchRootFileOpenFailure, openRootFileSync } from "./root-file.js";
|
|
19
15
|
import { writeSecretFileAtomic } from "./secret-file.js";
|
|
20
16
|
import { assertNoWindowsPathAlias, resolvePathPreservingWindowsRoot, } from "./windows-path-alias.js";
|
|
21
|
-
import { readFileStoreCopySource } from "./file-store-copy-source.js";
|
|
22
17
|
function snapshotWriteOptions(options, durabilityFirst = true) {
|
|
23
18
|
if (options == null)
|
|
24
19
|
return undefined;
|
package/dist/guarded-mkdir.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type RootBoundaryIdentity } from "./root-boundary.js";
|
|
2
2
|
import { type MutationDirectoryObservation } from "./pinned-mutation-observation.js";
|
|
3
|
-
import type { PinnedCreatedDirectoryReceipt, PinnedMutationAdmissionReceipt, PinnedMutationAuthorizationToken } from "./pinned-write.js";
|
|
3
|
+
import type { PinnedCreatedDirectoryReceipt, PinnedMutationAdmissionReceipt, PinnedMutationAuthorizationToken } from "./pinned-write-types.js";
|
|
4
4
|
/**
|
|
5
5
|
* Creates each missing path component from `rootReal` down to `targetPath`,
|
|
6
6
|
* guarding every step. Returns the real (symlink-resolved) path of the final
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
export { FsSafeError, categorizeFsSafeError,
|
|
2
|
-
export
|
|
3
|
-
export type
|
|
4
|
-
export
|
|
5
|
-
export {
|
|
6
|
-
export
|
|
1
|
+
export { FsSafeError, categorizeFsSafeError, } from "./errors.js";
|
|
2
|
+
export type * from "./errors.js";
|
|
3
|
+
export { DEFAULT_ROOT_MAX_BYTES, root, type Root, } from "./root.js";
|
|
4
|
+
export type * from "./root-public-types.js";
|
|
5
|
+
export { configureFsSafePython, configureFsSafeNative, getFsSafeNativeConfig, } from "./native-config.js";
|
|
6
|
+
export type * from "./config.js";
|
|
7
|
+
export { writeExternalFileWithinRoot, } from "./output.js";
|
|
8
|
+
export type * from "./output.js";
|
|
9
|
+
export { configureFsSafeLocks, getFsSafeLockConfig, } from "./lock-config.js";
|
|
@@ -4,11 +4,7 @@ export type DurableQueueEntryPathsLike = {
|
|
|
4
4
|
deliveredPath: string;
|
|
5
5
|
processingPath?: string;
|
|
6
6
|
};
|
|
7
|
-
export type ValidatedDurableQueueEntryPaths = Readonly<
|
|
8
|
-
jsonPath: string;
|
|
9
|
-
deliveredPath: string;
|
|
10
|
-
processingPath: string;
|
|
11
|
-
}>;
|
|
7
|
+
export type ValidatedDurableQueueEntryPaths = Readonly<Required<DurableQueueEntryPathsLike>>;
|
|
12
8
|
export declare function validateDurableQueueEntryPaths(paths: DurableQueueEntryPathsLike): ValidatedDurableQueueEntryPaths;
|
|
13
9
|
export declare function claimDurableQueueEntry(paths: DurableQueueEntryPathsLike, options?: {
|
|
14
10
|
skipUnowned?: boolean;
|
|
@@ -43,6 +43,7 @@ export async function withJsonDurableQueueEntry(filePath, options, run) {
|
|
|
43
43
|
const handle = await fs.promises.open(filePath, resolveReadOpenFlags());
|
|
44
44
|
let closePromise;
|
|
45
45
|
const releaseReadPin = () => closePromise ??= (async () => { await handle.close(); })();
|
|
46
|
+
let result;
|
|
46
47
|
try {
|
|
47
48
|
const openedStat = inspectQueueEntry(() => fs.fstatSync(handle.fd, { bigint: true }), maxBytes, initialStat);
|
|
48
49
|
inspectQueueEntry(inspectPath, maxBytes, openedStat);
|
|
@@ -53,9 +54,12 @@ export async function withJsonDurableQueueEntry(filePath, options, run) {
|
|
|
53
54
|
});
|
|
54
55
|
// The migration owner may release this pin only at the verified publication
|
|
55
56
|
// boundary; until then an unlinked inode cannot be recycled into a new claim.
|
|
56
|
-
|
|
57
|
+
result = await run(JSON.parse(bytes.toString("utf8")), openedStat, releaseReadPin);
|
|
57
58
|
}
|
|
58
|
-
|
|
59
|
-
await releaseReadPin();
|
|
59
|
+
catch (error) {
|
|
60
|
+
await releaseReadPin().catch(() => undefined);
|
|
61
|
+
throw error;
|
|
60
62
|
}
|
|
63
|
+
await releaseReadPin();
|
|
64
|
+
return result;
|
|
61
65
|
}
|
|
@@ -7,9 +7,7 @@ import { withJsonDurableQueueEntry } from "./json-durable-queue-read.js";
|
|
|
7
7
|
import { stringifyJsonDocument } from "./json-stringify.js";
|
|
8
8
|
import { replaceFileAtomicWithDirectorySync } from "./replace-file.js";
|
|
9
9
|
import { assertSafePathSegment } from "./safe-path-segment.js";
|
|
10
|
-
import { admitStandalonePublicationPath } from "./
|
|
11
|
-
import { assertNoWindowsPathAlias, hasWindowsPathAlias, } from "./windows-path-alias.js";
|
|
12
|
-
export { DEFAULT_JSON_DURABLE_QUEUE_ENTRY_MAX_BYTES } from "./json-durable-queue-read.js";
|
|
10
|
+
import { admitStandalonePublicationPath, assertNoWindowsPathAlias, hasWindowsPathAlias, } from "./windows-path-alias.js";
|
|
13
11
|
function assertSafeQueueEntryId(id) {
|
|
14
12
|
assertSafePathSegment(id, { label: "queue entry id" });
|
|
15
13
|
}
|
package/dist/json-store.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { fileStore } from "./file-store.js";
|
|
3
3
|
import {} from "./json-document-store.js";
|
|
4
|
-
import { admitStandalonePublicationPath } from "./
|
|
5
|
-
import { assertNoWindowsPathAlias } from "./windows-path-alias.js";
|
|
4
|
+
import { admitStandalonePublicationPath, assertNoWindowsPathAlias } from "./windows-path-alias.js";
|
|
6
5
|
export function jsonStore(options) {
|
|
7
6
|
const filePathInput = admitStandalonePublicationPath(options.filePath);
|
|
8
7
|
const filePath = path.resolve(filePathInput);
|
package/dist/json.js
CHANGED
|
@@ -9,10 +9,9 @@ import { openRootFileSync } from "./root-file.js";
|
|
|
9
9
|
import { recursiveMkdirPath } from "./recursive-mkdir-path.js";
|
|
10
10
|
import { writeTempFileSync } from "./replace-file-descriptor.js";
|
|
11
11
|
import { SyncAtomicTempOwner } from "./replace-file-temp-owner.js";
|
|
12
|
-
import { admitStandalonePublicationPath } from "./
|
|
12
|
+
import { admitStandalonePublicationPath, assertNoWindowsPathAlias } from "./windows-path-alias.js";
|
|
13
13
|
import { writeTextAtomic } from "./text-atomic.js";
|
|
14
14
|
import { sleep } from "./timing.js";
|
|
15
|
-
import { assertNoWindowsPathAlias } from "./windows-path-alias.js";
|
|
16
15
|
const READ_RETRY_MAX_ATTEMPTS = 5;
|
|
17
16
|
const READ_RETRY_BASE_DELAY_MS = 50;
|
|
18
17
|
function isRetryableReadError(err) {
|
package/dist/move-path.js
CHANGED
|
@@ -10,8 +10,7 @@ import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
|
10
10
|
import { realpathSync } from "./realpath.js";
|
|
11
11
|
import { cleanupPinnedFilePath } from "./file-cleanup.js";
|
|
12
12
|
import { createMoveStageOwner } from "./move-path-stage.js";
|
|
13
|
-
import { admitStandalonePublicationPath } from "./
|
|
14
|
-
import { assertNoWindowsPathAlias } from "./windows-path-alias.js";
|
|
13
|
+
import { admitStandalonePublicationPath, assertNoWindowsPathAlias } from "./windows-path-alias.js";
|
|
15
14
|
export function moveCopyFallbackReasonForRenameError(error, platform = process.platform) {
|
|
16
15
|
const code = error?.code;
|
|
17
16
|
if (code === "EXDEV") {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import fsSync, {} from "node:fs";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { FsSafeError } from "./errors.js";
|
|
5
4
|
import { sameFileIdentityForCleanup } from "./file-identity.js";
|
|
6
5
|
import { getNativeBinding } from "./native.js";
|
|
7
6
|
import { captureNativeFdClose } from "./native-binding.js";
|
|
@@ -2,5 +2,5 @@ import type { FileHandle } from "node:fs/promises";
|
|
|
2
2
|
import { type AnyAsyncDirectoryGuard } from "./directory-guard.js";
|
|
3
3
|
import type { FileIdentityStat } from "./file-identity.js";
|
|
4
4
|
import type { NativeBinding } from "./native.js";
|
|
5
|
-
import type { PinnedWriteParams } from "./pinned-write.js";
|
|
5
|
+
import type { PinnedWriteParams } from "./pinned-write-types.js";
|
|
6
6
|
export declare function runPinnedWriteWindows(binding: NativeBinding, params: PinnedWriteParams, root: FileHandle, parentFd: number, parentGuard: AnyAsyncDirectoryGuard): Promise<FileIdentityStat>;
|
|
@@ -3,7 +3,7 @@ import { randomUUID } from "node:crypto";
|
|
|
3
3
|
import fsSync, {} from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { createFileHandle } from "./create.js";
|
|
6
|
-
import { hasPreservedCreationArtifacts } from "./creation-
|
|
6
|
+
import { hasPreservedCreationArtifacts } from "./creation-boundary.js";
|
|
7
7
|
import { assertSyncDirectoryGuard } from "./directory-guard.js";
|
|
8
8
|
import { FsSafeError } from "./errors.js";
|
|
9
9
|
import { nativeOpenFlags, removeNativeCreatedFileIfStillPinned, } from "./native-operations.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { FileIdentityStat } from "./file-identity.js";
|
|
2
2
|
import type { NativeBinding } from "./native.js";
|
|
3
|
-
import type { PinnedWriteParams } from "./pinned-write.js";
|
|
3
|
+
import type { PinnedWriteParams } from "./pinned-write-types.js";
|
|
4
4
|
export declare function runPinnedWriteNative(binding: NativeBinding, params: PinnedWriteParams): Promise<FileIdentityStat>;
|
|
@@ -63,6 +63,7 @@ import { NativePolicyDirectoryMismatch } from "./native-policy-directory-observa
|
|
|
63
63
|
import { assertPolicyStagedDirectoryCurrent, assertStagedDirectoryCurrent, describePolicyStagedDirectory, describeStagedDirectory, refreshPolicyStagedDirectoryObservation, } from "./staged-directory.js";
|
|
64
64
|
import { inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
65
65
|
import { realpathSync } from "./realpath.js";
|
|
66
|
+
import { errorCauseOptions } from "./root-errors.js";
|
|
66
67
|
import { isNotFoundPathError, isSymlinkOpenError } from "./path.js";
|
|
67
68
|
import { checkedMutationDirectory, } from "./pinned-mutation-observation.js";
|
|
68
69
|
import { createPathSegmentRoute, joinPathSegmentRoute } from "./path-segment-route.js";
|
|
@@ -95,12 +96,8 @@ function normalizePolicyParentOpenError(error, params) {
|
|
|
95
96
|
if (!isSymlinkOpenError(error))
|
|
96
97
|
return error;
|
|
97
98
|
return params.mutationAdmission?.rejectParentSymlinks
|
|
98
|
-
? new FsSafeError("symlink", "symlink path component not allowed",
|
|
99
|
-
|
|
100
|
-
})
|
|
101
|
-
: new FsSafeError("path-mismatch", "native write parent changed during policy admission", {
|
|
102
|
-
cause: error instanceof Error ? error : undefined,
|
|
103
|
-
});
|
|
99
|
+
? new FsSafeError("symlink", "symlink path component not allowed", errorCauseOptions(error))
|
|
100
|
+
: new FsSafeError("path-mismatch", "native write parent changed during policy admission", errorCauseOptions(error));
|
|
104
101
|
}
|
|
105
102
|
async function describePosixParent(parentFd, pathname) {
|
|
106
103
|
const parentPath = realpathSync.native(pathname);
|
|
@@ -2,7 +2,7 @@ import { type BigIntStats } from "node:fs";
|
|
|
2
2
|
import { type AsyncDirectoryGuard } from "./directory-guard.js";
|
|
3
3
|
import { type NativeRootAdmission } from "./native-parent-admission.js";
|
|
4
4
|
import type { NativeBinding } from "./native.js";
|
|
5
|
-
import type { PinnedWriteParams } from "./pinned-write.js";
|
|
5
|
+
import type { PinnedWriteParams } from "./pinned-write-types.js";
|
|
6
6
|
import { type MutationDirectoryObservation } from "./pinned-mutation-observation.js";
|
|
7
7
|
type PolicyParent = {
|
|
8
8
|
fd: number;
|
|
@@ -3,7 +3,7 @@ import { type BigIntStats, type Stats } from "node:fs";
|
|
|
3
3
|
import type { AnyAsyncDirectoryGuard } from "./directory-guard.js";
|
|
4
4
|
import type { FileIdentityStat } from "./file-identity.js";
|
|
5
5
|
import { type NativeBinding } from "./native-binding.js";
|
|
6
|
-
import type { PinnedWriteInput, PinnedWriteParams } from "./pinned-write.js";
|
|
6
|
+
import type { PinnedWriteInput, PinnedWriteParams } from "./pinned-write-types.js";
|
|
7
7
|
import type { PublishedFileReceipt, StagedFile, StagedFileCleanupReceipt, StagedFileReceipt } from "./staged-file-types.js";
|
|
8
8
|
export type NativeStagingBinding = NativeBinding & Required<Pick<NativeBinding, "createStagedFile" | "stagedFileMatches" | "removeStagedFile">>;
|
|
9
9
|
export declare function assertNativeStaging(binding: NativeBinding): asserts binding is NativeStagingBinding;
|
|
@@ -36,10 +36,10 @@ declare class NativeStagedFile implements StagedFile {
|
|
|
36
36
|
}
|
|
37
37
|
export declare const createNativeStage: (...args: Parameters<typeof NativeStagedFile.create>) => Promise<StagedFile>;
|
|
38
38
|
export declare const writeNativeStage: typeof NativeStagedFile.write;
|
|
39
|
-
export type { PublishedFileReceipt, StagedFile, StagedFileCleanupReceipt, StagedFileFailureDetails, StagedFilePublication, StagedFileReceipt, } from "./staged-file-types.js";
|
|
40
39
|
export declare function stageFileInDirectory(options: {
|
|
41
40
|
directory: string | DirectoryReceipt<Stats | BigIntStats>;
|
|
42
41
|
content: string | Uint8Array;
|
|
43
42
|
/** Published mode; the unpublished stage stays at 0600. Defaults to 0600. */
|
|
44
43
|
mode?: number;
|
|
45
44
|
}): Promise<StagedFile>;
|
|
45
|
+
export {};
|
|
@@ -50,8 +50,7 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
50
50
|
var e = new Error(message);
|
|
51
51
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
52
|
});
|
|
53
|
-
import { assertDarwinCreationAcl } from "./creation-
|
|
54
|
-
import { assertPrivateCreationFile } from "./creation-file-state.js";
|
|
53
|
+
import { assertDarwinCreationAcl, assertPrivateCreationFile } from "./creation-boundary.js";
|
|
55
54
|
import { requireNativeBinding } from "./native.js";
|
|
56
55
|
import { syncFileBestEffortSync } from "./file-sync.js";
|
|
57
56
|
import { randomUUID } from "node:crypto";
|
|
@@ -7,6 +7,12 @@ export type PermissionCommandFailure = {
|
|
|
7
7
|
signal: string | null;
|
|
8
8
|
stderr: string;
|
|
9
9
|
};
|
|
10
|
+
export type PermissionFailureFields = {
|
|
11
|
+
error?: string;
|
|
12
|
+
errorDetail?: PermissionCommandFailure;
|
|
13
|
+
/** Original inspection failure, retained separately from serializable diagnostics. */
|
|
14
|
+
errorCause?: unknown;
|
|
15
|
+
};
|
|
10
16
|
export declare function formatPermissionErrorDetail(value: string): string;
|
|
11
17
|
/** Formats only caught permission-query failures without invoking user code. */
|
|
12
18
|
export declare function formatCaughtPermissionFailure(error: unknown): string;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export { formatOctal, formatPermissionDetail, formatPermissionRemediation, inspectPathPermissions, isGroupReadable, isGroupWritable, isWorldReadable, isWorldWritable, modeBits, safeStat, type PermissionCheck, type PermissionCheckOptions, type
|
|
1
|
+
export { formatOctal, formatPermissionDetail, formatPermissionRemediation, inspectPathPermissions, isGroupReadable, isGroupWritable, isWorldReadable, isWorldWritable, modeBits, safeStat, type PermissionCheck, type PermissionCheckOptions, type SafeStatResult, } from "./permissions.js";
|
|
2
|
+
export type { PermissionCommandFailure } from "./permission-exec.js";
|
|
2
3
|
export { createPrivateDirectory, type CreatePrivateDirectoryOptions, } from "./private-directory.js";
|
|
3
4
|
export { readOwnerAndDacl, type OwnerAndDaclResult, type WindowsAccessControlEntry, type WindowsAceFlags, } from "./owner-dacl.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type PermissionFailureFields } from "./permission-exec.js";
|
|
2
2
|
import { type PermissionCheck, type PermissionCheckOptions } from "./permissions.js";
|
|
3
3
|
export type PermissionExec = (command: string, args: string[]) => Promise<{
|
|
4
4
|
stdout: string;
|
|
@@ -13,16 +13,13 @@ export type WindowsAclEntry = {
|
|
|
13
13
|
canRead: boolean;
|
|
14
14
|
canWrite: boolean;
|
|
15
15
|
};
|
|
16
|
-
export type WindowsAclSummary = {
|
|
16
|
+
export type WindowsAclSummary = Omit<PermissionFailureFields & {
|
|
17
17
|
ok: boolean;
|
|
18
18
|
entries: WindowsAclEntry[];
|
|
19
19
|
untrustedWorld: WindowsAclEntry[];
|
|
20
20
|
untrustedGroup: WindowsAclEntry[];
|
|
21
21
|
trusted: WindowsAclEntry[];
|
|
22
|
-
|
|
23
|
-
errorDetail?: PermissionCommandFailure;
|
|
24
|
-
errorCause?: unknown;
|
|
25
|
-
};
|
|
22
|
+
}, never>;
|
|
26
23
|
export type WindowsUserInfoProvider = () => {
|
|
27
24
|
username?: string | null;
|
|
28
25
|
};
|
package/dist/permissions.d.ts
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PermissionFailureFields } from "./permission-exec.js";
|
|
2
2
|
import { type PermissionExec } from "./permissions-windows.js";
|
|
3
|
-
export type
|
|
4
|
-
export { createIcaclsResetCommand, formatIcaclsResetCommand, formatWindowsAclSummary, inspectWindowsAcl, parseIcaclsOutput, resolveWindowsUserPrincipal, summarizeWindowsAcl, } from "./permissions-windows.js";
|
|
5
|
-
export type { IcaclsResetCommandOptions, PermissionExec, WindowsAclEntry, WindowsAclSummary, WindowsUserInfoProvider, } from "./permissions-windows.js";
|
|
6
|
-
export type PermissionCheck = {
|
|
3
|
+
export type PermissionCheck = Omit<PermissionFailureFields & {
|
|
7
4
|
ok: boolean;
|
|
8
5
|
isSymlink: boolean;
|
|
9
6
|
isDir: boolean;
|
|
@@ -21,11 +18,7 @@ export type PermissionCheck = {
|
|
|
21
18
|
/** Owner-query failure detail when Windows ownership could not be verified. */
|
|
22
19
|
ownerError?: string;
|
|
23
20
|
aclSummary?: string;
|
|
24
|
-
|
|
25
|
-
errorDetail?: PermissionCommandFailure;
|
|
26
|
-
/** Original inspection failure, retained separately from serializable diagnostics. */
|
|
27
|
-
errorCause?: unknown;
|
|
28
|
-
};
|
|
21
|
+
}, never>;
|
|
29
22
|
export type PermissionCheckOptions = {
|
|
30
23
|
platform?: NodeJS.Platform;
|
|
31
24
|
env?: NodeJS.ProcessEnv;
|
package/dist/permissions.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import fsSync from "node:fs";
|
|
2
2
|
import { formatIcaclsResetCommand, inspectWindowsPermissions, } from "./permissions-windows.js";
|
|
3
3
|
import { hasWindowsPathAlias, pathForWindowsFilesystem, } from "./windows-path-alias.js";
|
|
4
|
-
export { createIcaclsResetCommand, formatIcaclsResetCommand, formatWindowsAclSummary, inspectWindowsAcl, parseIcaclsOutput, resolveWindowsUserPrincipal, summarizeWindowsAcl, } from "./permissions-windows.js";
|
|
5
4
|
function failedSafeStat(error) {
|
|
6
5
|
return {
|
|
7
6
|
ok: false,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type DenyMutationPolicy } from "./deny-mutations.js";
|
|
2
2
|
import { type RootBoundaryIdentity } from "./root-boundary.js";
|
|
3
|
-
import type { PinnedWriteMutationAdmission } from "./pinned-write.js";
|
|
3
|
+
import type { PinnedWriteMutationAdmission } from "./pinned-write-types.js";
|
|
4
4
|
import type { MutationSymlinkPolicy } from "./root-symlink-policy.js";
|
|
5
5
|
export type PinnedMutationPolicySnapshot = Readonly<{
|
|
6
6
|
denyMutations?: DenyMutationPolicy;
|
package/dist/pinned-open.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export type PinnedOpenSyncFinalAdmission = (params: {
|
|
|
18
18
|
descriptorIdentity: fs.BigIntStats;
|
|
19
19
|
}) => string;
|
|
20
20
|
export type PinnedOpenSyncFs = Pick<typeof fs, "constants" | "lstatSync" | "realpathSync" | "openSync" | "fstatSync" | "closeSync">;
|
|
21
|
+
export declare function isExpectedPathError(error: unknown): boolean;
|
|
21
22
|
export declare function openPinnedFileSync(params: {
|
|
22
23
|
filePath: string;
|
|
23
24
|
resolvedPath?: string;
|
package/dist/pinned-open.js
CHANGED
|
@@ -5,7 +5,7 @@ import { inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
|
5
5
|
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
6
6
|
import { assertNoWindowsPathAlias } from "./windows-path-alias.js";
|
|
7
7
|
import { realpathSync } from "./realpath.js";
|
|
8
|
-
function isExpectedPathError(error) {
|
|
8
|
+
export function isExpectedPathError(error) {
|
|
9
9
|
const code = typeof error === "object" && error !== null && "code" in error ? String(error.code) : "";
|
|
10
10
|
return code === "ENOENT" || code === "ENOTDIR" || code === "ELOOP";
|
|
11
11
|
}
|
|
@@ -77,7 +77,12 @@ export function openPinnedFileSync(params) {
|
|
|
77
77
|
}
|
|
78
78
|
finally {
|
|
79
79
|
if (fd !== null) {
|
|
80
|
-
|
|
80
|
+
try {
|
|
81
|
+
ioFs.closeSync(fd);
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// Preserve the failed admission result; success transfers fd above.
|
|
85
|
+
}
|
|
81
86
|
}
|
|
82
87
|
}
|
|
83
88
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function
|
|
1
|
+
export declare function validatePinnedRelativePath(relativePath: unknown): void;
|
package/dist/pinned-operation.js
CHANGED
|
@@ -1,19 +1,7 @@
|
|
|
1
1
|
import { FsSafeError } from "./errors.js";
|
|
2
|
-
export function
|
|
3
|
-
if (typeof
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
if (typeof payload.relativeParentPath === "string") {
|
|
7
|
-
validatePinnedRelativePath(payload.relativeParentPath);
|
|
8
|
-
}
|
|
9
|
-
if (typeof payload.from === "string") {
|
|
10
|
-
validatePinnedRelativePath(payload.from);
|
|
11
|
-
}
|
|
12
|
-
if (typeof payload.to === "string") {
|
|
13
|
-
validatePinnedRelativePath(payload.to);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
function validatePinnedRelativePath(relativePath) {
|
|
2
|
+
export function validatePinnedRelativePath(relativePath) {
|
|
3
|
+
if (typeof relativePath !== "string")
|
|
4
|
+
return;
|
|
17
5
|
if (relativePath.length === 0 || relativePath === ".") {
|
|
18
6
|
return;
|
|
19
7
|
}
|
|
@@ -21,7 +9,6 @@ function validatePinnedRelativePath(relativePath) {
|
|
|
21
9
|
throw new FsSafeError("invalid-path", "relative path contains a NUL byte");
|
|
22
10
|
}
|
|
23
11
|
if (relativePath.startsWith("/") ||
|
|
24
|
-
relativePath.startsWith("//") ||
|
|
25
12
|
relativePath === ".." ||
|
|
26
13
|
relativePath.startsWith("../") ||
|
|
27
14
|
relativePath.startsWith("..\\")) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import { FsSafeError } from "./errors.js";
|
|
3
3
|
import { assertSynchronousCallbackResult } from "./mutation-authority.js";
|
|
4
|
-
import { assertPrivateCreationFile } from "./creation-
|
|
4
|
+
import { assertPrivateCreationFile } from "./creation-boundary.js";
|
|
5
5
|
export function assertPinnedWriteMode(fd, mode, privateCreation = false) {
|
|
6
6
|
if (process.platform === "win32")
|
|
7
7
|
return;
|
|
@@ -3,8 +3,7 @@ import fsSync, {} from "node:fs";
|
|
|
3
3
|
import fs, {} from "node:fs/promises";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { createFileHandle } from "./create.js";
|
|
6
|
-
import { hasPreservedCreationArtifacts } from "./creation-
|
|
7
|
-
import { creationAdmissionFromParent } from "./creation-path.js";
|
|
6
|
+
import { hasPreservedCreationArtifacts, creationAdmissionFromParent } from "./creation-boundary.js";
|
|
8
7
|
import { syncDirectoryBestEffort } from "./directory-durability.js";
|
|
9
8
|
import { FsSafeError } from "./errors.js";
|
|
10
9
|
import { sameFileIdentity, sha256Hex } from "./file-identity.js";
|
package/dist/pinned-write.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { FileIdentityStat } from "./file-identity.js";
|
|
2
2
|
import type { PinnedWriteParams, RenameIdentityPolicy } from "./pinned-write-types.js";
|
|
3
|
-
export type { PinnedWriteInput, RenameIdentityPolicy, PublishedWriteIdentity, PinnedMutationAdmissionReceipt, PinnedMutationAuthorizationToken, PinnedCreatedDirectoryReceipt, PinnedMutationParentWalkSession, PinnedWriteMutationAdmission, PinnedWriteParams, } from "./pinned-write-types.js";
|
|
4
3
|
export declare function runPinnedWriteHelper(params: PinnedWriteParams): Promise<FileIdentityStat>;
|
|
5
4
|
export declare function runPinnedWriteWithRenamePolicy(params: PinnedWriteParams & {
|
|
6
5
|
targetPath: string;
|
package/dist/pinned-write.js
CHANGED
|
@@ -3,7 +3,7 @@ import fsSync, {} from "node:fs";
|
|
|
3
3
|
import fs from "node:fs/promises";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { createFileHandle } from "./create.js";
|
|
6
|
-
import { creationAdmissionFromParent } from "./creation-
|
|
6
|
+
import { creationAdmissionFromParent } from "./creation-boundary.js";
|
|
7
7
|
import { normalizeMaxBytes } from "./byte-budget.js";
|
|
8
8
|
import { assertAsyncDirectoryGuard, createAsyncDirectoryGuard, createNearestExistingDirectoryGuard, inspectDirectoryIdentity } from "./directory-guard.js";
|
|
9
9
|
import { FsSafeError } from "./errors.js";
|
|
@@ -13,7 +13,7 @@ import { withAsyncDirectoryGuards } from "./guarded-mutation.js";
|
|
|
13
13
|
import { mkdirPathComponentsWithGuards } from "./guarded-mkdir.js";
|
|
14
14
|
import { runPinnedWriteNative } from "./native-pinned-write.js";
|
|
15
15
|
import { getNativeBinding } from "./native.js";
|
|
16
|
-
import {
|
|
16
|
+
import { validatePinnedRelativePath } from "./pinned-operation.js";
|
|
17
17
|
import { cleanupPinnedFilePath } from "./file-cleanup.js";
|
|
18
18
|
import { withSidecarLock } from "./sidecar-lock.js";
|
|
19
19
|
import { getFsSafeTestHooks } from "./test-hooks.js";
|
|
@@ -71,9 +71,7 @@ export async function runPinnedWriteHelper(params) {
|
|
|
71
71
|
rootIdentity,
|
|
72
72
|
};
|
|
73
73
|
assertSafeBasename(normalizedParams.basename);
|
|
74
|
-
|
|
75
|
-
relativeParentPath: normalizedParams.relativeParentPath,
|
|
76
|
-
});
|
|
74
|
+
validatePinnedRelativePath(normalizedParams.relativeParentPath);
|
|
77
75
|
assertNoWindowsPathAlias(normalizedParams.rootPath, "filesystem", "pinned write root uses a Windows filesystem namespace alias");
|
|
78
76
|
assertNoWindowsPathAlias(normalizedParams.relativeParentPath, "relative", "pinned write parent uses a Windows filesystem namespace alias");
|
|
79
77
|
assertNoWindowsPathAlias(normalizedParams.basename, "relative", "pinned write basename uses a Windows filesystem namespace alias");
|