@openclaw/fs-safe 0.15.0 → 0.16.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.
- package/CHANGELOG.md +38 -0
- package/README.md +28 -6
- package/dist/advanced.d.ts +1 -0
- package/dist/advanced.d.ts.map +1 -1
- package/dist/advanced.js +1 -0
- package/dist/archive-kind.d.ts +0 -1
- package/dist/archive-kind.d.ts.map +1 -1
- package/dist/archive-kind.js +5 -17
- package/dist/archive-parser.wasm +0 -0
- package/dist/archive-read.d.ts.map +1 -1
- package/dist/archive-read.js +6 -7
- package/dist/archive-tar-stream.d.ts +3 -0
- package/dist/archive-tar-stream.d.ts.map +1 -1
- package/dist/archive-tar-stream.js +56 -37
- package/dist/archive-tar-wasm.d.ts +16 -4
- package/dist/archive-tar-wasm.d.ts.map +1 -1
- package/dist/archive-tar-wasm.js +134 -34
- package/dist/archive.d.ts.map +1 -1
- package/dist/archive.js +5 -6
- package/dist/clone-metadata.d.ts +1 -0
- package/dist/clone-metadata.d.ts.map +1 -1
- package/dist/clone-metadata.js +6 -2
- package/dist/create-directory.d.ts +20 -0
- package/dist/create-directory.d.ts.map +1 -0
- package/dist/create-directory.js +130 -0
- package/dist/create-file-async.d.ts +7 -0
- package/dist/create-file-async.d.ts.map +1 -0
- package/dist/create-file-async.js +121 -0
- package/dist/create-file.d.ts +8 -0
- package/dist/create-file.d.ts.map +1 -0
- package/dist/create-file.js +190 -0
- package/dist/create-owned-file.d.ts +8 -0
- package/dist/create-owned-file.d.ts.map +1 -0
- package/dist/create-owned-file.js +16 -0
- package/dist/create.d.ts +4 -0
- package/dist/create.d.ts.map +1 -0
- package/dist/create.js +2 -0
- package/dist/creation-darwin.d.ts +7 -0
- package/dist/creation-darwin.d.ts.map +1 -0
- package/dist/creation-darwin.js +79 -0
- package/dist/creation-file-state.d.ts +19 -0
- package/dist/creation-file-state.d.ts.map +1 -0
- package/dist/creation-file-state.js +118 -0
- package/dist/creation-path.d.ts +21 -0
- package/dist/creation-path.d.ts.map +1 -0
- package/dist/creation-path.js +71 -0
- package/dist/creation-permissions.d.ts +19 -0
- package/dist/creation-permissions.d.ts.map +1 -0
- package/dist/creation-permissions.js +125 -0
- package/dist/directory-durability.d.ts +1 -1
- package/dist/directory-durability.d.ts.map +1 -1
- package/dist/directory-durability.js +22 -80
- package/dist/directory-guard.d.ts +3 -0
- package/dist/directory-guard.d.ts.map +1 -1
- package/dist/directory-mode-node.d.ts +2 -0
- package/dist/directory-mode-node.d.ts.map +1 -1
- package/dist/directory-mode-node.js +8 -0
- package/dist/directory-receipt.d.ts +24 -0
- package/dist/directory-receipt.d.ts.map +1 -0
- package/dist/directory-receipt.js +127 -0
- package/dist/file-cleanup.d.ts +19 -0
- package/dist/file-cleanup.d.ts.map +1 -0
- package/dist/file-cleanup.js +78 -0
- package/dist/file-observation.d.ts +1 -1
- package/dist/file-observation.d.ts.map +1 -1
- package/dist/file-store-boundary.d.ts +2 -6
- package/dist/file-store-boundary.d.ts.map +1 -1
- package/dist/file-store-boundary.js +3 -9
- package/dist/file-store-sync-write.d.ts.map +1 -1
- package/dist/file-store-sync-write.js +2 -5
- package/dist/guarded-mkdir.d.ts +1 -0
- package/dist/guarded-mkdir.d.ts.map +1 -1
- package/dist/guarded-mkdir.js +36 -7
- package/dist/move-path.js +1 -1
- package/dist/native-binding.d.ts +11 -1
- package/dist/native-binding.d.ts.map +1 -1
- package/dist/native-fallback-warning.d.ts +4 -0
- package/dist/native-fallback-warning.d.ts.map +1 -0
- package/dist/native-fallback-warning.js +11 -0
- package/dist/native-operations.d.ts +0 -2
- package/dist/native-operations.d.ts.map +1 -1
- package/dist/native-operations.js +0 -24
- package/dist/native-parent-admission.d.ts +2 -0
- package/dist/native-parent-admission.d.ts.map +1 -1
- package/dist/native-parent-admission.js +3 -2
- package/dist/native-pinned-write-windows.d.ts +1 -1
- package/dist/native-pinned-write-windows.d.ts.map +1 -1
- package/dist/native-pinned-write-windows.js +173 -28
- package/dist/native-pinned-write.d.ts.map +1 -1
- package/dist/native-pinned-write.js +19 -3
- package/dist/native-policy-parent-windows.d.ts.map +1 -1
- package/dist/native-policy-parent-windows.js +15 -6
- package/dist/native-staged-file.d.ts +3 -2
- package/dist/native-staged-file.d.ts.map +1 -1
- package/dist/native-staged-file.js +86 -39
- package/dist/owner-dacl.d.ts.map +1 -1
- package/dist/owner-dacl.js +10 -4
- package/dist/pinned-write-input.d.ts +4 -0
- package/dist/pinned-write-input.d.ts.map +1 -0
- package/dist/pinned-write-input.js +25 -0
- package/dist/pinned-write-mode.d.ts +5 -0
- package/dist/pinned-write-mode.d.ts.map +1 -0
- package/dist/pinned-write-mode.js +24 -0
- package/dist/pinned-write-staged.d.ts +6 -0
- package/dist/pinned-write-staged.d.ts.map +1 -0
- package/dist/pinned-write-staged.js +187 -0
- package/dist/pinned-write-types.d.ts +3 -0
- package/dist/pinned-write-types.d.ts.map +1 -1
- package/dist/pinned-write.d.ts.map +1 -1
- package/dist/pinned-write.js +35 -145
- package/dist/private-directory.d.ts.map +1 -1
- package/dist/private-directory.js +18 -4
- package/dist/private-producer-handoff-sync.d.ts +14 -0
- package/dist/private-producer-handoff-sync.d.ts.map +1 -0
- package/dist/private-producer-handoff-sync.js +114 -0
- package/dist/private-producer-handoff.d.ts +22 -4
- package/dist/private-producer-handoff.d.ts.map +1 -1
- package/dist/private-producer-handoff.js +140 -77
- package/dist/publish-copy-stage.d.ts +2 -1
- package/dist/publish-copy-stage.d.ts.map +1 -1
- package/dist/publish-copy-stage.js +16 -7
- package/dist/publish-file.d.ts.map +1 -1
- package/dist/publish-file.js +2 -2
- package/dist/replace-file-temp-owner.d.ts +0 -7
- package/dist/replace-file-temp-owner.d.ts.map +1 -1
- package/dist/replace-file-temp-owner.js +3 -54
- package/dist/root-create-input.d.ts +2 -1
- package/dist/root-create-input.d.ts.map +1 -1
- package/dist/root-create-input.js +13 -4
- package/dist/root-directory-creation.d.ts +3 -3
- package/dist/root-directory-creation.d.ts.map +1 -1
- package/dist/root-directory-creation.js +15 -3
- package/dist/root-impl.d.ts.map +1 -1
- package/dist/root-impl.js +28 -7
- package/dist/root-move-noreplace.d.ts.map +1 -1
- package/dist/root-move-noreplace.js +22 -13
- package/dist/root-options.d.ts +12 -4
- package/dist/root-options.d.ts.map +1 -1
- package/dist/root-path-stat.d.ts.map +1 -1
- package/dist/root-path-stat.js +59 -7
- package/dist/root-write-publication.js +1 -1
- package/dist/secret-file.d.ts.map +1 -1
- package/dist/secret-file.js +1 -0
- package/dist/secure-file-windows.d.ts +6 -0
- package/dist/secure-file-windows.d.ts.map +1 -1
- package/dist/secure-file-windows.js +34 -117
- package/dist/secure-file.js +2 -2
- package/dist/sidecar-lock-root.d.ts.map +1 -1
- package/dist/sidecar-lock-root.js +2 -1
- package/dist/staged-directory.d.ts.map +1 -1
- package/dist/staged-directory.js +6 -6
- package/dist/staged-file-settlement.d.ts +17 -0
- package/dist/staged-file-settlement.d.ts.map +1 -0
- package/dist/staged-file-settlement.js +57 -0
- package/dist/windows-owner.d.ts.map +1 -1
- package/dist/windows-owner.js +2 -1
- package/dist/windows-security-bridge.cs +336 -0
- package/dist/windows-security-bridge.ps1 +15 -0
- package/dist/windows-security-command.d.ts +26 -0
- package/dist/windows-security-command.d.ts.map +1 -0
- package/dist/windows-security-command.js +363 -0
- package/dist/windows-security-facts.d.ts +6 -0
- package/dist/windows-security-facts.d.ts.map +1 -0
- package/dist/windows-security-facts.js +108 -0
- package/docs/advanced.md +3 -1
- package/docs/archive.md +61 -37
- package/docs/config.md +6 -2
- package/docs/contributing.md +44 -4
- package/docs/copy.md +2 -0
- package/docs/creation.md +128 -0
- package/docs/durability.md +24 -0
- package/docs/install.md +31 -7
- package/docs/migrating-to-0.5.md +15 -6
- package/docs/migrating-to-0.6.md +9 -4
- package/docs/native-helper.md +22 -9
- package/docs/native.md +38 -7
- package/docs/permissions.md +37 -14
- package/docs/root.md +34 -0
- package/docs/secret-file.md +11 -2
- package/docs/secure-file.md +9 -4
- package/docs/sidecar-lock.md +5 -4
- package/docs/staged-file.md +5 -0
- package/docs/writing.md +71 -5
- package/package.json +18 -15
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import fsSync, {} from "node:fs";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
|
+
import { assertPrivateDirectory } from "./creation-permissions.js";
|
|
4
5
|
import { assertAsyncDirectoryGuard, assertDirectoryIdentitySync, assertSyncDirectoryGuard, createAsyncDirectoryGuard, inspectDirectoryIdentitySync, } from "./directory-guard.js";
|
|
5
6
|
import { FsSafeError } from "./errors.js";
|
|
6
7
|
import { mkdirPathComponentsWithGuards } from "./guarded-mkdir.js";
|
|
7
8
|
import { hasNodeErrorCode } from "./path.js";
|
|
8
9
|
import { checkedMutationDirectory, } from "./pinned-mutation-observation.js";
|
|
9
10
|
import { admitPathInsideRoot } from "./root-boundary.js";
|
|
11
|
+
import { assertRootIdentityCurrent } from "./root-context.js";
|
|
10
12
|
import { assertFinalSymlinkRejected } from "./root-symlink-policy.js";
|
|
11
13
|
import { canReuseParentWithMutationAssertion } from "./root-write-lock-binding.js";
|
|
12
14
|
import { getFsSafeTestHooks } from "./test-hooks.js";
|
|
@@ -165,13 +167,15 @@ export async function tryMkdirAtExactParent(root, targetPath, mutationAdmission)
|
|
|
165
167
|
session.dispose();
|
|
166
168
|
}
|
|
167
169
|
}
|
|
168
|
-
export async function prepareRootWriteTarget(root, targetPath, assertBeforeMutation, mutationAdmission) {
|
|
170
|
+
export async function prepareRootWriteTarget(root, targetPath, assertBeforeMutation, mutationAdmission, privateMode = false) {
|
|
169
171
|
const basename = path.basename(targetPath);
|
|
170
172
|
const baseParams = {
|
|
171
173
|
rootReal: root.rootReal,
|
|
172
174
|
rootIdentity: root.rootIdentity,
|
|
173
175
|
targetPath: path.dirname(targetPath),
|
|
174
176
|
assertBeforeMutation,
|
|
177
|
+
private: privateMode,
|
|
178
|
+
mode: privateMode ? 0o700 : undefined,
|
|
175
179
|
};
|
|
176
180
|
const mutationWalk = mutationAdmission
|
|
177
181
|
? mutationWalkOptions(mutationAdmission, (prospectiveParent) => path.join(prospectiveParent, basename), assertBeforeMutation, root.rootReal, targetPath)
|
|
@@ -190,22 +194,30 @@ export async function prepareRootWriteTarget(root, targetPath, assertBeforeMutat
|
|
|
190
194
|
// the original path through a symlinked component.
|
|
191
195
|
return path.join(parentPath, basename);
|
|
192
196
|
}
|
|
193
|
-
export async function mkdirPathFallback(root, resolved, assertBeforeMutation, rejectSymlinks = false, mutationAdmission) {
|
|
197
|
+
export async function mkdirPathFallback(root, resolved, assertBeforeMutation, rejectSymlinks = false, mutationAdmission, privateMode = false) {
|
|
194
198
|
const baseParams = {
|
|
195
199
|
rootReal: resolved.rootReal, targetPath: resolved.resolved, assertBeforeMutation,
|
|
196
200
|
rootIdentity: root.rootIdentity,
|
|
197
201
|
rejectSymlinks,
|
|
202
|
+
private: privateMode,
|
|
203
|
+
mode: privateMode ? 0o700 : undefined,
|
|
198
204
|
beforeComponent: async (componentPath) => await getFsSafeTestHooks()?.beforeRootFallbackMutation?.("mkdir", componentPath),
|
|
199
205
|
};
|
|
200
206
|
const mutationWalk = mutationAdmission
|
|
201
207
|
? mutationWalkOptions(mutationAdmission, (prospectiveDirectory) => prospectiveDirectory, assertBeforeMutation, root.rootReal, resolved.resolved)
|
|
202
208
|
: undefined;
|
|
203
209
|
try {
|
|
204
|
-
await mkdirPathComponentsWithGuards(mutationWalk ? {
|
|
210
|
+
const directory = await mkdirPathComponentsWithGuards(mutationWalk ? {
|
|
205
211
|
...baseParams,
|
|
206
212
|
...mutationWalk.options,
|
|
207
213
|
rejectSymlinks: rejectSymlinks || mutationAdmission.rejectParentSymlinks,
|
|
208
214
|
} : baseParams);
|
|
215
|
+
if (privateMode) {
|
|
216
|
+
const guard = await createAsyncDirectoryGuard(directory, { bigint: true });
|
|
217
|
+
await assertPrivateDirectory(directory);
|
|
218
|
+
await assertAsyncDirectoryGuard(guard);
|
|
219
|
+
await assertRootIdentityCurrent(root);
|
|
220
|
+
}
|
|
209
221
|
}
|
|
210
222
|
finally {
|
|
211
223
|
mutationWalk?.dispose();
|
package/dist/root-impl.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root-impl.d.ts","sourceRoot":"","sources":["../src/root-impl.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAElD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAKnD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"root-impl.d.ts","sourceRoot":"","sources":["../src/root-impl.ts"],"names":[],"mappings":"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"}
|
package/dist/root-impl.js
CHANGED
|
@@ -56,6 +56,7 @@ import fs from "node:fs/promises";
|
|
|
56
56
|
import path from "node:path";
|
|
57
57
|
import { normalizeMaxBytes } from "./byte-budget.js";
|
|
58
58
|
import { assertCopySourceCurrent, resolveFileCopyCloneMode } from "./copy-file-input.js";
|
|
59
|
+
import { assertPrivateFileCreationAvailable, resolveCreationPermissions } from "./creation-permissions.js";
|
|
59
60
|
import { assertAsyncDirectoryGuard, assertSyncDirectoryGuard, createAsyncDirectoryGuard, createNearestExistingDirectoryGuard } from "./directory-guard.js";
|
|
60
61
|
import { FsSafeError } from "./errors.js";
|
|
61
62
|
import { syncDirectoryBestEffort } from "./directory-durability.js";
|
|
@@ -71,7 +72,8 @@ import { validatePinnedOperationPayload } from "./pinned-operation.js";
|
|
|
71
72
|
import { PATH_ALIAS_POLICIES } from "./path-policy.js";
|
|
72
73
|
import { assertNoNulPathInput, hasNodeErrorCode, isNotFoundPathError, isSymlinkOpenError, } from "./path.js";
|
|
73
74
|
import { readOpenedFileSafely } from "./read-opened-file.js";
|
|
74
|
-
import { cleanupPinnedFilePath
|
|
75
|
+
import { cleanupPinnedFilePath } from "./file-cleanup.js";
|
|
76
|
+
import { removePathIfIdentityUnchanged } from "./replace-file-temp-owner.js";
|
|
75
77
|
import { realpathSync } from "./realpath.js";
|
|
76
78
|
import { mkdirPathFallback, prepareRootWriteTarget, tryMkdirAtExactParent } from "./root-directory-creation.js";
|
|
77
79
|
import { isNonRegularWriteOpenError, resolveNonblockingWriteFlag } from "./write-open-flags.js";
|
|
@@ -315,13 +317,15 @@ export class RootHandle {
|
|
|
315
317
|
}
|
|
316
318
|
async create(relativePath, data, options = {}) {
|
|
317
319
|
assertValidRootDestinationPath(relativePath);
|
|
320
|
+
const durable = options.durable ?? this.defaults.durable ?? true;
|
|
318
321
|
await writeFileInRoot(this.context, {
|
|
319
322
|
relativePath,
|
|
320
323
|
data,
|
|
321
324
|
mkdir: this.defaults.mkdir,
|
|
322
325
|
mode: this.defaults.mode,
|
|
323
326
|
...this.mutationOptions(createInputOptions(data, options, this.defaults.maxBytes)),
|
|
324
|
-
durable:
|
|
327
|
+
durable: durable !== false,
|
|
328
|
+
strictFileSync: durable === "file",
|
|
325
329
|
overwrite: false,
|
|
326
330
|
}).catch(rethrowMutationAuthorityError).catch(rethrowCreateInputError);
|
|
327
331
|
}
|
|
@@ -377,7 +381,9 @@ export class RootHandle {
|
|
|
377
381
|
assertValidRootRelativePath(fromRelative);
|
|
378
382
|
assertValidRootDestinationPath(toRelative);
|
|
379
383
|
validatePinnedOperationPayload({ from: fromRelative, to: toRelative });
|
|
380
|
-
const
|
|
384
|
+
const mutationOptions = this.mutationOptions(options);
|
|
385
|
+
const { assertBeforeMutation } = mutationOptions;
|
|
386
|
+
const { denyMutations, mutationSymlinks } = snapshotPinnedMutationPolicy(mutationOptions.denyMutations, mutationOptions.mutationSymlinks) ?? {};
|
|
381
387
|
const overwrite = options.overwrite ?? false;
|
|
382
388
|
await assertMoveMutationAllowed(this.context, {
|
|
383
389
|
fromRelative,
|
|
@@ -778,6 +784,7 @@ async function removePathInRoot(root, params) {
|
|
|
778
784
|
}
|
|
779
785
|
}
|
|
780
786
|
async function mkdirPathInRoot(root, params) {
|
|
787
|
+
const privateMode = resolveCreationPermissions(params, true).private;
|
|
781
788
|
validatePinnedOperationPayload({ relativePath: params.relativePath });
|
|
782
789
|
const policy = params.denyMutations === undefined && params.mutationSymlinks === undefined
|
|
783
790
|
? undefined
|
|
@@ -810,19 +817,23 @@ async function mkdirPathInRoot(root, params) {
|
|
|
810
817
|
await getFsSafeTestHooks()?.beforePinnedWriteParentAdmission?.(resolved.resolved);
|
|
811
818
|
}
|
|
812
819
|
try {
|
|
813
|
-
if (prepared?.mutationAdmission && params.assertBeforeMutation === undefined &&
|
|
820
|
+
if (!privateMode && prepared?.mutationAdmission && params.assertBeforeMutation === undefined &&
|
|
814
821
|
await tryMkdirAtExactParent(root, resolved.resolved, prepared.mutationAdmission))
|
|
815
822
|
return;
|
|
816
|
-
await mkdirPathFallback(root, resolved, params.assertBeforeMutation, policy?.mutationSymlinks !== undefined, prepared?.mutationAdmission);
|
|
823
|
+
await mkdirPathFallback(root, resolved, params.assertBeforeMutation, policy?.mutationSymlinks !== undefined, prepared?.mutationAdmission, privateMode);
|
|
817
824
|
}
|
|
818
825
|
catch (error) {
|
|
819
826
|
throw normalizePinnedPathError(error);
|
|
820
827
|
}
|
|
821
828
|
}
|
|
822
829
|
async function writeFileInRoot(root, params) {
|
|
830
|
+
if (params.private !== undefined) {
|
|
831
|
+
const permissions = resolveCreationPermissions(params, false);
|
|
832
|
+
params = { ...params, private: permissions.private, mode: permissions.mode };
|
|
833
|
+
}
|
|
823
834
|
const input = rootWriteInput(params);
|
|
824
835
|
await serializePathWrite(rootWriteQueueKey(root, params.relativePath), async () => {
|
|
825
|
-
if (input.kind === "buffer" && process.platform === "win32" &&
|
|
836
|
+
if (!params.private && input.kind === "buffer" && !input.stageBeforePublish && process.platform === "win32" &&
|
|
826
837
|
(params.renameIdentity === "verify-content-with-lock" || !getNativeBinding())) {
|
|
827
838
|
await writeFileFallback(root, { ...params, data: input.data });
|
|
828
839
|
return;
|
|
@@ -836,15 +847,25 @@ async function writeFileInRoot(root, params) {
|
|
|
836
847
|
async function commitPinnedWriteInRoot(root, pinned, params, input) {
|
|
837
848
|
let verifyingPublication = false;
|
|
838
849
|
try {
|
|
850
|
+
if (params.private)
|
|
851
|
+
assertPrivateFileCreationAvailable();
|
|
852
|
+
if (params.private && params.mkdir !== false) {
|
|
853
|
+
const target = await prepareRootWriteTarget(root, pinned.targetPath, params.assertBeforeMutation, pinned.mutationAdmission, true);
|
|
854
|
+
if (target !== pinned.targetPath) {
|
|
855
|
+
throw new FsSafeError("path-mismatch", "private creation parent changed during admission");
|
|
856
|
+
}
|
|
857
|
+
}
|
|
839
858
|
await runPinnedWriteWithRenamePolicy({
|
|
840
859
|
rootPath: pinned.rootReal,
|
|
841
860
|
relativeParentPath: pinned.relativeParentPath,
|
|
842
861
|
basename: pinned.basename,
|
|
843
862
|
targetPath: pinned.targetPath,
|
|
844
863
|
renameIdentity: params.renameIdentity,
|
|
845
|
-
mkdir: params.mkdir !== false,
|
|
864
|
+
mkdir: !params.private && params.mkdir !== false,
|
|
865
|
+
private: params.private,
|
|
846
866
|
mode: params.mode ?? pinned.mode,
|
|
847
867
|
sync: params.durable !== false,
|
|
868
|
+
strictFileSync: params.strictFileSync,
|
|
848
869
|
overwrite: params.overwrite,
|
|
849
870
|
rejectFinalSymlink: params.mutationSymlinks !== undefined,
|
|
850
871
|
input,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root-move-noreplace.d.ts","sourceRoot":"","sources":["../src/root-move-noreplace.ts"],"names":[],"mappings":"AAIA,OAAO,EAA2B,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAQvF,OAAO,EAA4D,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAU/G,OAAO,EAA8B,KAAK,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"root-move-noreplace.d.ts","sourceRoot":"","sources":["../src/root-move-noreplace.ts"],"names":[],"mappings":"AAIA,OAAO,EAA2B,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAQvF,OAAO,EAA4D,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAU/G,OAAO,EAA8B,KAAK,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAmElG,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,WAAW,EACjB,MAAM,EAAE;IACN,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAC;IAClC,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,gBAAgB,CAAC,EAAE,qBAAqB,CAAC;CAC1C,EACD,KAAK,EAAE;IACL,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;CAC1B,GACA,OAAO,CAAC,IAAI,CAAC,CAsIf"}
|
|
@@ -12,6 +12,7 @@ import { admitPathInsideRoot } from "./root-boundary.js";
|
|
|
12
12
|
import { fileNotFoundError, hardlinkedPathNotAllowedError, isAlreadyExistsError, normalizePinnedPathError, outsideWorkspaceError, } from "./root-errors.js";
|
|
13
13
|
import { assertFinalSymlinkRejected } from "./root-symlink-policy.js";
|
|
14
14
|
import { createSuppressedError } from "./suppressed-error.js";
|
|
15
|
+
import { inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
15
16
|
import { getFsSafeTestHooks } from "./test-hooks.js";
|
|
16
17
|
function nativeParentRelativePath(rootReal, parentPath) {
|
|
17
18
|
const relative = path.relative(rootReal, parentPath);
|
|
@@ -57,6 +58,18 @@ function normalizeRenameNoReplaceError(error) {
|
|
|
57
58
|
}
|
|
58
59
|
return normalizeMoveError(error);
|
|
59
60
|
}
|
|
61
|
+
function admitMoveSourceStat(stat) {
|
|
62
|
+
if (stat.isSymbolicLink()) {
|
|
63
|
+
throw new FsSafeError("symlink", "symlink not allowed");
|
|
64
|
+
}
|
|
65
|
+
if (stat.isFile() && stat.nlink > 1) {
|
|
66
|
+
throw hardlinkedPathNotAllowedError();
|
|
67
|
+
}
|
|
68
|
+
if (stat.isDirectory()) {
|
|
69
|
+
throw new FsSafeError("invalid-path", "directory moves require overwrite: true");
|
|
70
|
+
}
|
|
71
|
+
return stat;
|
|
72
|
+
}
|
|
60
73
|
export async function movePathNoReplaceNative(root, params, paths) {
|
|
61
74
|
try {
|
|
62
75
|
fsSync.lstatSync(paths.targetPath);
|
|
@@ -104,21 +117,13 @@ export async function movePathNoReplaceNative(root, params, paths) {
|
|
|
104
117
|
await assertRootIdentityCurrent(root);
|
|
105
118
|
for (const admission of parentAdmissions)
|
|
106
119
|
assertSyncDirectoryGuard(admission.guard);
|
|
120
|
+
// Capture an exact receipt only when admission must survive a callback.
|
|
107
121
|
let sourceStat;
|
|
108
|
-
|
|
109
|
-
sourceStat = fsSync.lstatSync(admittedSourcePath);
|
|
122
|
+
if (params.assertBeforeMutation) {
|
|
123
|
+
sourceStat = inspectFileIdentitySync(() => admitMoveSourceStat(fsSync.lstatSync(admittedSourcePath, { bigint: true })));
|
|
110
124
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
if (sourceStat.isSymbolicLink()) {
|
|
115
|
-
throw new FsSafeError("symlink", "symlink not allowed");
|
|
116
|
-
}
|
|
117
|
-
if (sourceStat.isFile() && sourceStat.nlink > 1) {
|
|
118
|
-
throw hardlinkedPathNotAllowedError();
|
|
119
|
-
}
|
|
120
|
-
if (sourceStat.isDirectory()) {
|
|
121
|
-
throw new FsSafeError("invalid-path", "directory moves require overwrite: true");
|
|
125
|
+
else {
|
|
126
|
+
admitMoveSourceStat(fsSync.lstatSync(admittedSourcePath));
|
|
122
127
|
}
|
|
123
128
|
assertFinalSymlinkRejected(admittedTargetPath, params.mutationSymlinks !== undefined);
|
|
124
129
|
params.assertBeforeMutation?.();
|
|
@@ -143,6 +148,10 @@ export async function movePathNoReplaceNative(root, params, paths) {
|
|
|
143
148
|
for (const admission of parentAdmissions)
|
|
144
149
|
assertSyncDirectoryGuard(admission.guard);
|
|
145
150
|
}
|
|
151
|
+
// The callback can change a leaf without replacing its admitted parent.
|
|
152
|
+
if (sourceStat !== undefined) {
|
|
153
|
+
inspectFileIdentitySync(() => admitMoveSourceStat(fsSync.lstatSync(admittedSourcePath, { bigint: true })), sourceStat);
|
|
154
|
+
}
|
|
146
155
|
try {
|
|
147
156
|
binding.renameNoReplace(sourceParent.fd, path.basename(paths.sourcePath), targetParent.fd, path.basename(paths.targetPath));
|
|
148
157
|
}
|
package/dist/root-options.d.ts
CHANGED
|
@@ -50,12 +50,18 @@ export type RootWriteJsonOptions = RootWriteOptions & {
|
|
|
50
50
|
space?: Parameters<typeof JSON.stringify>[2];
|
|
51
51
|
trailingNewline?: boolean;
|
|
52
52
|
};
|
|
53
|
-
export type RootCreateOptions = Omit<RootWriteOptions, "overwrite"
|
|
54
|
-
|
|
53
|
+
export type RootCreateOptions = Omit<RootWriteOptions, "overwrite" | "durable"> & {
|
|
54
|
+
/** Publish complete content without replacing an existing entry, including without native support. */
|
|
55
|
+
atomic?: boolean;
|
|
56
|
+
private?: boolean;
|
|
57
|
+
/** "file" requires file synchronization; directory synchronization remains best effort. */
|
|
58
|
+
durable?: boolean | "file";
|
|
59
|
+
};
|
|
60
|
+
export type RootCreateStreamOptions = Omit<RootCreateOptions, "atomic" | "encoding" | "renameIdentity"> & {
|
|
55
61
|
maxBytes?: number;
|
|
56
62
|
signal?: AbortSignal;
|
|
57
63
|
};
|
|
58
|
-
export type RootCreateJsonOptions = Omit<RootWriteJsonOptions, "overwrite">;
|
|
64
|
+
export type RootCreateJsonOptions = Omit<RootWriteJsonOptions, "overwrite" | "durable"> & Pick<RootCreateOptions, "atomic" | "durable" | "private">;
|
|
59
65
|
export type RootAppendOptions = RootWriteOptions & {
|
|
60
66
|
prependNewlineIfNeeded?: boolean;
|
|
61
67
|
};
|
|
@@ -70,7 +76,9 @@ export type RootRemoveOptions = Pick<RootDefaults, "assertBeforeMutation" | "den
|
|
|
70
76
|
maxDepth?: number;
|
|
71
77
|
signal?: AbortSignal;
|
|
72
78
|
};
|
|
73
|
-
export type RootMkdirOptions = Pick<RootDefaults, "assertBeforeMutation" | "denyMutations" | "mutationSymlinks"
|
|
79
|
+
export type RootMkdirOptions = Pick<RootDefaults, "assertBeforeMutation" | "denyMutations" | "mutationSymlinks"> & {
|
|
80
|
+
private?: boolean;
|
|
81
|
+
};
|
|
74
82
|
export type RootReadParams = Omit<RootReadOptions, "nonBlockingRead">;
|
|
75
83
|
export declare function readDefaults(defaults: RootDefaults): RootReadParams;
|
|
76
84
|
export declare function mergeReadOptions(defaults: RootDefaults, options: RootReadOptions): RootReadParams;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root-options.d.ts","sourceRoot":"","sources":["../src/root-options.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"root-options.d.ts","sourceRoot":"","sources":["../src/root-options.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root-path-stat.d.ts","sourceRoot":"","sources":["../src/root-path-stat.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAIjE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"root-path-stat.d.ts","sourceRoot":"","sources":["../src/root-path-stat.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAIjE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AA2D3C,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,WAAW,EACjB,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,0BAA0B,GACnC,OAAO,CAAC,QAAQ,CAAC,CAUnB"}
|
package/dist/root-path-stat.js
CHANGED
|
@@ -1,14 +1,37 @@
|
|
|
1
1
|
import fsSync from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { FsSafeError } from "./errors.js";
|
|
4
|
-
import { recordFileObservationFailure } from "./file-observation.js";
|
|
4
|
+
import { fileObservation, recordFileObservationFailure } from "./file-observation.js";
|
|
5
5
|
import { hasNodeErrorCode, isNotFoundPathError } from "./path.js";
|
|
6
6
|
import { assertRootDirectoryObservationGuard, assertRootPathObservationReceiptCurrent, createRootDirectoryObservationGuard, pathStatFromStats, } from "./root-directory-list.js";
|
|
7
7
|
import { fileNotFoundError } from "./root-errors.js";
|
|
8
8
|
import { inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
9
9
|
import { assertStatObservationSync } from "./stat-observation.js";
|
|
10
10
|
import { getFsSafeTestHooks } from "./test-hooks.js";
|
|
11
|
-
|
|
11
|
+
function singleLinkFileIdentity(stat) {
|
|
12
|
+
if (!stat?.isFile() || stat.isSymbolicLink() || (stat.nlink !== 1 && stat.nlink !== 1n))
|
|
13
|
+
return;
|
|
14
|
+
const exact = (value) => typeof value === "bigint" ? value : Number.isSafeInteger(value) ? BigInt(value) : undefined;
|
|
15
|
+
const dev = exact(stat.dev), ino = exact(stat.ino);
|
|
16
|
+
if (dev === undefined || ino === undefined || dev < 0n || ino < 0n ||
|
|
17
|
+
(process.platform === "win32" && (dev === 0n || ino === 0n)))
|
|
18
|
+
return;
|
|
19
|
+
return { dev, ino };
|
|
20
|
+
}
|
|
21
|
+
async function captureChangedObservedFile(error, pathname, before, observed, assertParents, proof) {
|
|
22
|
+
try {
|
|
23
|
+
const previous = singleLinkFileIdentity(before), current = singleLinkFileIdentity(observed);
|
|
24
|
+
if (!previous || !current || (previous.dev === current.dev && previous.ino === current.ino))
|
|
25
|
+
return;
|
|
26
|
+
await assertParents();
|
|
27
|
+
// A changed metadata probe grants only a fresh acquisition attempt, never ownership.
|
|
28
|
+
proof.failure = { error, kind: `stat-leaf-changed:${pathname}` };
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// Ambiguous file or ancestry observations retain the original public error.
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async function missingObservedFileError(cause, pathname, before, assertParents, proof) {
|
|
12
35
|
const failure = new FsSafeError("path-mismatch", "file changed during operation", {
|
|
13
36
|
cause: cause instanceof Error ? cause : undefined,
|
|
14
37
|
});
|
|
@@ -17,7 +40,7 @@ async function missingObservedFileError(cause, pathname, before, assertParents)
|
|
|
17
40
|
try {
|
|
18
41
|
await assertParents();
|
|
19
42
|
// Metadata loss permits discarding a probe, never reading or owning a file.
|
|
20
|
-
|
|
43
|
+
proof.failure = { error: failure, kind: `stat-leaf-missing:${pathname}` };
|
|
21
44
|
}
|
|
22
45
|
catch {
|
|
23
46
|
// Keep the public mismatch and withhold provenance when ancestry changed.
|
|
@@ -26,6 +49,19 @@ async function missingObservedFileError(cause, pathname, before, assertParents)
|
|
|
26
49
|
return failure;
|
|
27
50
|
}
|
|
28
51
|
export async function statResolvedPathInRoot(root, resolvedPath, receipt) {
|
|
52
|
+
const proof = {};
|
|
53
|
+
try {
|
|
54
|
+
// Nested observations in a hook cannot grant this invocation discard authority.
|
|
55
|
+
return await fileObservation().run(() => statObservedPathInRoot(root, resolvedPath, proof, receipt));
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
const failure = proof.failure;
|
|
59
|
+
if (failure && failure.error === error)
|
|
60
|
+
recordFileObservationFailure(error, failure.kind);
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async function statObservedPathInRoot(root, resolvedPath, proof, receipt) {
|
|
29
65
|
let admittedTarget = false;
|
|
30
66
|
try {
|
|
31
67
|
if (receipt) {
|
|
@@ -37,13 +73,21 @@ export async function statResolvedPathInRoot(root, resolvedPath, receipt) {
|
|
|
37
73
|
if (beforeObservation)
|
|
38
74
|
await beforeObservation(resolvedPath);
|
|
39
75
|
let observed;
|
|
76
|
+
let sample, samples = 0;
|
|
77
|
+
const comparison = fileObservation();
|
|
40
78
|
try {
|
|
41
|
-
observed =
|
|
79
|
+
observed = comparison.run(() => assertStatObservationSync(bigint => {
|
|
80
|
+
sample = bigint ? fsSync.lstatSync(resolvedPath, { bigint: true }) : fsSync.lstatSync(resolvedPath);
|
|
81
|
+
samples += 1;
|
|
82
|
+
return sample;
|
|
83
|
+
}, receipt.target.identity));
|
|
42
84
|
}
|
|
43
85
|
catch (error) {
|
|
44
86
|
if (isNotFoundPathError(error)) {
|
|
45
|
-
throw await missingObservedFileError(error, resolvedPath, "stat" in receipt.target ? receipt.target.stat : undefined, () => assertRootPathObservationReceiptCurrent(root, receipt));
|
|
87
|
+
throw await missingObservedFileError(error, resolvedPath, "stat" in receipt.target ? receipt.target.stat : undefined, () => assertRootPathObservationReceiptCurrent(root, receipt), proof);
|
|
46
88
|
}
|
|
89
|
+
if (comparison.has(error, "identity"))
|
|
90
|
+
await captureChangedObservedFile(error, resolvedPath, "stat" in receipt.target ? receipt.target.stat : undefined, samples === 1 ? sample : undefined, () => assertRootPathObservationReceiptCurrent(root, receipt), proof);
|
|
47
91
|
throw error;
|
|
48
92
|
}
|
|
49
93
|
if (observed.isSymbolicLink()) {
|
|
@@ -77,13 +121,21 @@ export async function statResolvedPathInRoot(root, resolvedPath, receipt) {
|
|
|
77
121
|
if (beforeObservation)
|
|
78
122
|
await beforeObservation(resolvedPath);
|
|
79
123
|
let observed;
|
|
124
|
+
let sample, samples = 0;
|
|
125
|
+
const comparison = fileObservation();
|
|
80
126
|
try {
|
|
81
|
-
observed =
|
|
127
|
+
observed = comparison.run(() => inspectFileIdentitySync(() => {
|
|
128
|
+
sample = fsSync.lstatSync(resolvedPath, { bigint: true });
|
|
129
|
+
samples += 1;
|
|
130
|
+
return sample;
|
|
131
|
+
}, expected));
|
|
82
132
|
}
|
|
83
133
|
catch (error) {
|
|
84
134
|
if (isNotFoundPathError(error)) {
|
|
85
|
-
throw await missingObservedFileError(error, resolvedPath, expected, () => assertRootDirectoryObservationGuard(root, parentGuard));
|
|
135
|
+
throw await missingObservedFileError(error, resolvedPath, expected, () => assertRootDirectoryObservationGuard(root, parentGuard), proof);
|
|
86
136
|
}
|
|
137
|
+
if (comparison.has(error, "identity"))
|
|
138
|
+
await captureChangedObservedFile(error, resolvedPath, expected, samples === 1 ? sample : undefined, () => assertRootDirectoryObservationGuard(root, parentGuard), proof);
|
|
87
139
|
throw error;
|
|
88
140
|
}
|
|
89
141
|
if (observed.isSymbolicLink()) {
|
|
@@ -4,7 +4,7 @@ import { readFileHandleBounded } from "./bounded-read.js";
|
|
|
4
4
|
import { syncDirectoryBestEffort } from "./directory-durability.js";
|
|
5
5
|
import { FsSafeError } from "./errors.js";
|
|
6
6
|
import { sameFileIdentityForCleanup, sha256Hex } from "./file-identity.js";
|
|
7
|
-
import { cleanupPinnedFilePath } from "./
|
|
7
|
+
import { cleanupPinnedFilePath } from "./file-cleanup.js";
|
|
8
8
|
import { verifyAtomicWriteResult } from "./root-write-verification.js";
|
|
9
9
|
// Compatibility callers hold the lock throughout this operation. The caller
|
|
10
10
|
// owns the original write handle; this helper owns a content-verified reopen.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret-file.d.ts","sourceRoot":"","sources":["../src/secret-file.ts"],"names":[],"mappings":"AAAA,OAAW,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAM/C,OAAO,EAAkF,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAShJ,OAAO,EAIL,KAAK,qBAAqB,EAC3B,MAAM,yBAAyB,CAAC;AAQjC,eAAO,MAAM,uBAAuB,MAAQ,CAAC;AAC7C,eAAO,MAAM,wBAAwB,MAAQ,CAAC;AAE9C,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,qBAA0B,GAClC,MAAM,CA2CR;AAED,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,qBAA0B,GAClC,MAAM,GAAG,SAAS,CAUpB;AA8JD,KAAK,qBAAqB,GAAG;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,UAAU,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AA+BF,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,IAAI,CAAC,qBAAqB,EAAE,SAAS,CAAC,GAC7C,OAAO,CAAC;IACT,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAC5C,WAAW,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC,CAgCD;
|
|
1
|
+
{"version":3,"file":"secret-file.d.ts","sourceRoot":"","sources":["../src/secret-file.ts"],"names":[],"mappings":"AAAA,OAAW,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAM/C,OAAO,EAAkF,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAShJ,OAAO,EAIL,KAAK,qBAAqB,EAC3B,MAAM,yBAAyB,CAAC;AAQjC,eAAO,MAAM,uBAAuB,MAAQ,CAAC;AAC7C,eAAO,MAAM,wBAAwB,MAAQ,CAAC;AAE9C,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,qBAA0B,GAClC,MAAM,CA2CR;AAED,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,qBAA0B,GAClC,MAAM,GAAG,SAAS,CAUpB;AA8JD,KAAK,qBAAqB,GAAG;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,UAAU,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AA+BF,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,IAAI,CAAC,qBAAqB,EAAE,SAAS,CAAC,GAC7C,OAAO,CAAC;IACT,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAC5C,WAAW,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC,CAgCD;AAyDD,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAUxF;AAED,wBAAsB,sBAAsB,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBzF"}
|
package/dist/secret-file.js
CHANGED
|
@@ -291,6 +291,7 @@ async function materializeSecretFileAtomic(params, createOnly) {
|
|
|
291
291
|
basename: fileName,
|
|
292
292
|
mkdir: false,
|
|
293
293
|
mode,
|
|
294
|
+
verifyPosixMode: true,
|
|
294
295
|
sync: params.durable !== false,
|
|
295
296
|
overwrite: !createOnly,
|
|
296
297
|
input: { kind: "buffer", data: typeof params.content === "string" ? params.content : Buffer.from(params.content) },
|
|
@@ -6,5 +6,11 @@ export declare function inspectSecureWindowsDescriptor(params: {
|
|
|
6
6
|
identity: ExactIdentity;
|
|
7
7
|
stat: Stats;
|
|
8
8
|
}): PermissionCheck;
|
|
9
|
+
/** Both mechanisms inspect the same borrowed handle; the caller owns its lifetime. */
|
|
10
|
+
export declare function inspectSecureWindowsFile(params: {
|
|
11
|
+
fd: number;
|
|
12
|
+
identity: ExactIdentity;
|
|
13
|
+
stat: Stats;
|
|
14
|
+
}): Promise<PermissionCheck>;
|
|
9
15
|
export {};
|
|
10
16
|
//# sourceMappingURL=secure-file-windows.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secure-file-windows.d.ts","sourceRoot":"","sources":["../src/secure-file-windows.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"secure-file-windows.d.ts","sourceRoot":"","sources":["../src/secure-file-windows.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAOlD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAOxD,KAAK,aAAa,GAAG,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,KAAK,CAAC,CAAC;AA0BtD,wBAAgB,8BAA8B,CAAC,MAAM,EAAE;IACrD,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,aAAa,CAAC;IACxB,IAAI,EAAE,KAAK,CAAC;CACb,GAAG,eAAe,CAkBlB;AAgCD,sFAAsF;AACtF,wBAAsB,wBAAwB,CAAC,MAAM,EAAE;IACrD,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,aAAa,CAAC;IACxB,IAAI,EAAE,KAAK,CAAC;CACb,GAAG,OAAO,CAAC,eAAe,CAAC,CAiB3B"}
|