nx 22.7.7 → 22.7.9

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 (52) hide show
  1. package/dist/src/ai/set-up-ai-agents/set-up-ai-agents.js +2 -1
  2. package/dist/src/command-line/configure-ai-agents/configure-ai-agents.js +1 -1
  3. package/dist/src/command-line/init/init-v2.js +1 -1
  4. package/dist/src/command-line/migrate/migrate-ui-api.js +17 -12
  5. package/dist/src/command-line/reset/reset.js +6 -1
  6. package/dist/src/daemon/client/client.d.ts +45 -3
  7. package/dist/src/daemon/client/client.js +138 -42
  8. package/dist/src/daemon/client/daemon-socket-messenger.js +4 -0
  9. package/dist/src/daemon/message-types/daemon-message.d.ts +33 -0
  10. package/dist/src/daemon/message-types/daemon-message.js +48 -0
  11. package/dist/src/daemon/server/latest-nx.js +3 -1
  12. package/dist/src/daemon/server/server.js +22 -0
  13. package/dist/src/daemon/server/shutdown-utils.d.ts +5 -0
  14. package/dist/src/daemon/server/shutdown-utils.js +11 -4
  15. package/dist/src/daemon/socket-utils.d.ts +1 -0
  16. package/dist/src/daemon/socket-utils.js +24 -3
  17. package/dist/src/daemon/tmp-dir.d.ts +43 -3
  18. package/dist/src/daemon/tmp-dir.js +437 -15
  19. package/dist/src/devkit-internals.d.ts +1 -0
  20. package/dist/src/devkit-internals.js +4 -1
  21. package/dist/src/native/index.js +71 -28
  22. package/dist/src/native/native-file-cache-location.d.ts +17 -1
  23. package/dist/src/native/native-file-cache-location.js +86 -12
  24. package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
  25. package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
  26. package/dist/src/project-graph/file-utils.js +5 -1
  27. package/dist/src/project-graph/plugins/isolation/isolated-plugin.d.ts +1 -0
  28. package/dist/src/project-graph/plugins/isolation/isolated-plugin.js +18 -1
  29. package/dist/src/project-graph/plugins/isolation/messaging.d.ts +16 -3
  30. package/dist/src/project-graph/plugins/isolation/messaging.js +3 -0
  31. package/dist/src/project-graph/plugins/isolation/plugin-worker.js +58 -8
  32. package/dist/src/project-graph/project-graph.js +20 -0
  33. package/dist/src/utils/command-line-utils.js +30 -20
  34. package/dist/src/utils/git-revision.d.ts +12 -0
  35. package/dist/src/utils/git-revision.js +25 -0
  36. package/dist/src/utils/git-utils.d.ts +1 -3
  37. package/dist/src/utils/git-utils.js +83 -47
  38. package/dist/src/utils/nx-tmp-dir.d.ts +18 -0
  39. package/dist/src/utils/nx-tmp-dir.js +40 -0
  40. package/dist/src/utils/owned-private-dir.d.ts +132 -0
  41. package/dist/src/utils/owned-private-dir.js +323 -0
  42. package/dist/src/utils/package-json.d.ts +3 -3
  43. package/dist/src/utils/package-json.js +30 -12
  44. package/dist/src/utils/package-manager.d.ts +13 -0
  45. package/dist/src/utils/package-manager.js +27 -0
  46. package/dist/src/utils/safe-spawn.d.ts +24 -0
  47. package/dist/src/utils/safe-spawn.js +104 -0
  48. package/dist/src/utils/shell-quoting.d.ts +15 -0
  49. package/dist/src/utils/shell-quoting.js +35 -0
  50. package/dist/src/utils/wait-for-socket-connection.d.ts +11 -0
  51. package/dist/src/utils/wait-for-socket-connection.js +14 -8
  52. package/package.json +17 -13
@@ -9,9 +9,9 @@ exports.getLatestCommitSha = getLatestCommitSha;
9
9
  const child_process_1 = require("child_process");
10
10
  const path_1 = require("path");
11
11
  const logger_1 = require("./logger");
12
- function execAsync(command, execOptions) {
12
+ function execFileAsync(file, args, execOptions) {
13
13
  return new Promise((res, rej) => {
14
- (0, child_process_1.exec)(command, { ...execOptions, windowsHide: true }, (err, stdout, stderr) => {
14
+ (0, child_process_1.execFile)(file, args, { ...execOptions, windowsHide: true }, (err, stdout) => {
15
15
  if (err) {
16
16
  return rej(err);
17
17
  }
@@ -22,7 +22,14 @@ function execAsync(command, execOptions) {
22
22
  async function cloneFromUpstream(url, destination, { originName, depth } = {
23
23
  originName: 'origin',
24
24
  }) {
25
- await execAsync(`git clone ${url} ${destination} ${depth ? `--depth ${depth}` : ''} --origin ${originName}`, {
25
+ await execFileAsync('git', [
26
+ 'clone',
27
+ url,
28
+ destination,
29
+ ...(depth ? ['--depth', `${depth}`] : []),
30
+ '--origin',
31
+ originName,
32
+ ], {
26
33
  cwd: (0, path_1.dirname)(destination),
27
34
  maxBuffer: 10 * 1024 * 1024,
28
35
  });
@@ -34,7 +41,7 @@ class GitRepository {
34
41
  this.root = this.getGitRootPath(this.directory);
35
42
  }
36
43
  getGitRootPath(cwd) {
37
- return (0, child_process_1.execSync)('git rev-parse --show-toplevel', {
44
+ return (0, child_process_1.execFileSync)('git', ['rev-parse', '--show-toplevel'], {
38
45
  cwd,
39
46
  windowsHide: true,
40
47
  })
@@ -42,17 +49,22 @@ class GitRepository {
42
49
  .trim();
43
50
  }
44
51
  async hasUncommittedChanges() {
45
- const data = await this.execAsync(`git status --porcelain`);
52
+ const data = await this.execGit(['status', '--porcelain']);
46
53
  return data.trim() !== '';
47
54
  }
48
55
  async addFetchRemote(remoteName, branch) {
49
- return await this.execAsync(`git config --add remote.${remoteName}.fetch "+refs/heads/${branch}:refs/remotes/${remoteName}/${branch}"`);
56
+ return await this.execGit([
57
+ 'config',
58
+ '--add',
59
+ `remote.${remoteName}.fetch`,
60
+ `+refs/heads/${branch}:refs/remotes/${remoteName}/${branch}`,
61
+ ]);
50
62
  }
51
63
  async showStat() {
52
- return await this.execAsync(`git show --stat`);
64
+ return await this.execGit(['show', '--stat']);
53
65
  }
54
66
  async listBranches() {
55
- return (await this.execAsync(`git ls-remote --heads --quiet`))
67
+ return (await this.execGit(['ls-remote', '--heads', '--quiet']))
56
68
  .trim()
57
69
  .split('\n')
58
70
  .map((s) => s
@@ -63,45 +75,58 @@ class GitRepository {
63
75
  async getGitFiles(path) {
64
76
  // Use -z to return file names exactly as they are stored in git, separated by NULL (\x00) character.
65
77
  // This avoids problems with special characters in file names.
66
- return (await this.execAsync(`git ls-files -z ${path}`))
78
+ return (await this.execGit(['ls-files', '-z', '--', path]))
67
79
  .trim()
68
80
  .split('\x00')
69
81
  .map((s) => s.trim())
70
82
  .filter(Boolean);
71
83
  }
72
84
  async reset(ref) {
73
- return await this.execAsync(`git reset ${ref} --hard`);
85
+ return await this.execGit(['reset', '--hard', ref]);
74
86
  }
75
87
  async mergeUnrelatedHistories(ref, message) {
76
- return await this.execAsync(`git merge ${ref} -X ours --allow-unrelated-histories -m "${message}"`);
88
+ return await this.execGit([
89
+ 'merge',
90
+ ref,
91
+ '-X',
92
+ 'ours',
93
+ '--allow-unrelated-histories',
94
+ '-m',
95
+ message,
96
+ ]);
77
97
  }
78
98
  async fetch(remote, ref) {
79
- return await this.execAsync(`git fetch ${remote}${ref ? ` ${ref}` : ''}`);
99
+ return await this.execGit(['fetch', remote, ...(ref ? [ref] : [])]);
80
100
  }
81
101
  async checkout(branch, opts) {
82
- return await this.execAsync(`git checkout ${opts.new ? '-b ' : ' '}${branch}${opts.base ? ' ' + opts.base : ''}`);
102
+ return await this.execGit([
103
+ 'checkout',
104
+ ...(opts.new ? ['-b'] : []),
105
+ branch,
106
+ ...(opts.base ? [opts.base] : []),
107
+ ]);
83
108
  }
84
109
  async move(path, destination) {
85
- return await this.execAsync(`git mv ${this.quotePath(path)} ${this.quotePath(destination)}`);
110
+ return await this.execGit(['mv', '--', path, destination]);
86
111
  }
87
112
  async push(ref, remoteName) {
88
- return await this.execAsync(`git push -u -f ${remoteName} ${ref}`);
113
+ return await this.execGit(['push', '-u', '-f', remoteName, ref]);
89
114
  }
90
115
  async commit(message) {
91
- return await this.execAsync(`git commit -am "${message}"`);
116
+ return await this.execGit(['commit', '-am', message]);
92
117
  }
93
118
  async amendCommit() {
94
- return await this.execAsync(`git commit --amend -a --no-edit`);
119
+ return await this.execGit(['commit', '--amend', '-a', '--no-edit']);
95
120
  }
96
121
  async deleteGitRemote(name) {
97
- return await this.execAsync(`git remote rm ${name}`);
122
+ return await this.execGit(['remote', 'rm', name]);
98
123
  }
99
124
  async addGitRemote(name, url) {
100
- return await this.execAsync(`git remote add ${name} ${url}`);
125
+ return await this.execGit(['remote', 'add', name, url]);
101
126
  }
102
127
  async hasFilterRepoInstalled() {
103
128
  try {
104
- await this.execAsync(`git filter-repo --help`);
129
+ await this.execGit(['filter-repo', '--help']);
105
130
  return true;
106
131
  }
107
132
  catch {
@@ -114,35 +139,57 @@ class GitRepository {
114
139
  // NOTE: filter-repo requires POSIX path to work
115
140
  const sourcePosixPath = source.split(path_1.sep).join(path_1.posix.sep);
116
141
  const destinationPosixPath = destination.split(path_1.sep).join(path_1.posix.sep);
117
- await this.execAsync(`git filter-repo -f ${source !== '' ? `--path ${this.quotePath(sourcePosixPath)}` : ''} ${source !== destination
118
- ? `--path-rename ${this.quotePath(sourcePosixPath, true)}:${this.quotePath(destinationPosixPath, true)}`
119
- : ''}`);
142
+ const sourcePath = ensureTrailingSlash(sourcePosixPath);
143
+ const destinationPath = ensureTrailingSlash(destinationPosixPath);
144
+ await this.execGit([
145
+ 'filter-repo',
146
+ '-f',
147
+ ...(source !== '' ? ['--path', sourcePosixPath] : []),
148
+ ...(source !== destination
149
+ ? ['--path-rename', `${sourcePath}:${destinationPath}`]
150
+ : []),
151
+ ]);
120
152
  }
121
153
  async filterBranch(source, destination, branchName) {
122
154
  // We need non-ASCII file names to not be quoted, or else filter-branch will exclude them.
123
- await this.execAsync(`git config core.quotepath false`);
155
+ await this.execGit(['config', 'core.quotepath', 'false']);
124
156
  // NOTE: filter-repo requires POSIX path to work
125
157
  const sourcePosixPath = source.split(path_1.sep).join(path_1.posix.sep);
126
158
  const destinationPosixPath = destination.split(path_1.sep).join(path_1.posix.sep);
127
159
  // First, if the source is not a root project, then only include commits relevant to the subdirectory.
128
160
  if (source !== '') {
129
- const indexFilterCommand = this.quoteArg(`node ${(0, path_1.join)(__dirname, 'git-utils.index-filter.js')}`);
130
- await this.execAsync(`git filter-branch -f --index-filter ${indexFilterCommand} --prune-empty -- ${branchName}`, {
161
+ const indexFilterCommand = `node ${quoteForShell((0, path_1.join)(__dirname, 'git-utils.index-filter.js'))}`;
162
+ await this.execGit([
163
+ 'filter-branch',
164
+ '-f',
165
+ '--index-filter',
166
+ indexFilterCommand,
167
+ '--prune-empty',
168
+ '--',
169
+ branchName,
170
+ ], {
131
171
  NX_IMPORT_SOURCE: sourcePosixPath,
132
172
  NX_IMPORT_DESTINATION: destinationPosixPath,
133
173
  });
134
174
  }
135
175
  // Then, move files to their new location if necessary.
136
176
  if (source === '' || source !== destination) {
137
- const treeFilterCommand = this.quoteArg(`node ${(0, path_1.join)(__dirname, 'git-utils.tree-filter.js')}`);
138
- await this.execAsync(`git filter-branch -f --tree-filter ${treeFilterCommand} -- ${branchName}`, {
177
+ const treeFilterCommand = `node ${quoteForShell((0, path_1.join)(__dirname, 'git-utils.tree-filter.js'))}`;
178
+ await this.execGit([
179
+ 'filter-branch',
180
+ '-f',
181
+ '--tree-filter',
182
+ treeFilterCommand,
183
+ '--',
184
+ branchName,
185
+ ], {
139
186
  NX_IMPORT_SOURCE: sourcePosixPath,
140
187
  NX_IMPORT_DESTINATION: destinationPosixPath,
141
188
  });
142
189
  }
143
190
  }
144
- execAsync(command, env) {
145
- return execAsync(command, {
191
+ execGit(args, env) {
192
+ return execFileAsync('git', args, {
146
193
  cwd: this.root,
147
194
  maxBuffer: 10 * 1024 * 1024,
148
195
  env: {
@@ -151,25 +198,14 @@ class GitRepository {
151
198
  },
152
199
  });
153
200
  }
154
- quotePath(path, ensureTrailingSlash) {
155
- return this.quoteArg(ensureTrailingSlash && path !== '' && !path.endsWith('/')
156
- ? `${path}/`
157
- : path);
158
- }
159
- quoteArg(arg) {
160
- return process.platform === 'win32'
161
- ? // Windows/CMD only understands double-quotes, single-quotes are treated as part of the file name
162
- // Bash and other shells will substitute `$` in file names with a variable value.
163
- `"${arg
164
- // Need to keep two slashes for Windows or else the path will be invalid.
165
- // e.g. 'C:\Users\bob\projects\repo' is invalid, but 'C:\\Users\\bob\\projects\\repo' is valid
166
- .replaceAll('\\', '\\\\')}"`
167
- : // e.g. `git mv "$$file.txt" "libs/a/$$file.txt"` will not work since `$$` is swapped with the PID of the last process.
168
- // Using single-quotes prevents this substitution.
169
- `'${arg}'`;
170
- }
171
201
  }
172
202
  exports.GitRepository = GitRepository;
203
+ function ensureTrailingSlash(path) {
204
+ return path !== '' && !path.endsWith('/') ? `${path}/` : path;
205
+ }
206
+ function quoteForShell(arg) {
207
+ return `'${arg.replaceAll("'", "'\"'\"'")}'`;
208
+ }
173
209
  function parseVcsRemoteUrl(url) {
174
210
  // Remove whitespace and handle common URL formats
175
211
  const cleanUrl = url.trim();
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Stable root for Nx runtime artifacts that need an OS tmp location. On POSIX a
3
+ * literal `/tmp`, not `os.tmpdir()`, which honours `$TMPDIR` — per-user on
4
+ * macOS, rewritten by sandboxes, stripped from the daemon env, so client and
5
+ * daemon would disagree. Windows has no `/tmp`, and `%TMP%` is already per-user
6
+ * and stable, so it keeps `os.tmpdir()`.
7
+ *
8
+ * Consumed by the native binding loader, so keep this file limited to local
9
+ * helpers that themselves use Node builtins only.
10
+ */
11
+ export declare const NX_TMP_DIR: string;
12
+ /**
13
+ * Owner-only runtime root for the current user. No user segment on Windows —
14
+ * `%TMP%` is already per-account, and the segment would only cost path length.
15
+ */
16
+ export declare const NX_USER_TMP_DIR: string;
17
+ /** Runtime root under the user's home, used when the shared container cannot be established. */
18
+ export declare const NX_HOME_TMP_DIR: string;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NX_HOME_TMP_DIR = exports.NX_USER_TMP_DIR = exports.NX_TMP_DIR = void 0;
4
+ const node_os_1 = require("node:os");
5
+ const node_path_1 = require("node:path");
6
+ const owned_private_dir_1 = require("./owned-private-dir");
7
+ /**
8
+ * Stable root for Nx runtime artifacts that need an OS tmp location. On POSIX a
9
+ * literal `/tmp`, not `os.tmpdir()`, which honours `$TMPDIR` — per-user on
10
+ * macOS, rewritten by sandboxes, stripped from the daemon env, so client and
11
+ * daemon would disagree. Windows has no `/tmp`, and `%TMP%` is already per-user
12
+ * and stable, so it keeps `os.tmpdir()`.
13
+ *
14
+ * Consumed by the native binding loader, so keep this file limited to local
15
+ * helpers that themselves use Node builtins only.
16
+ */
17
+ exports.NX_TMP_DIR = (0, node_os_1.platform)() === 'win32' ? (0, node_path_1.join)((0, node_os_1.tmpdir)(), '.nx') : '/tmp/.nx';
18
+ /**
19
+ * Owner-only runtime root for the current user. No user segment on Windows —
20
+ * `%TMP%` is already per-account, and the segment would only cost path length.
21
+ */
22
+ exports.NX_USER_TMP_DIR = (0, node_os_1.platform)() === 'win32' ? exports.NX_TMP_DIR : (0, node_path_1.join)(exports.NX_TMP_DIR, (0, owned_private_dir_1.getUserSegment)());
23
+ /** Runtime root under the user's home, used when the shared container cannot be established. */
24
+ exports.NX_HOME_TMP_DIR = resolveHomeTmpDir();
25
+ /**
26
+ * Absolute, not merely non-empty: a relative `$HOME` would make `join` return
27
+ * `.nx`, putting sockets under the cwd and aiming `removeSocketDir`'s recursive
28
+ * delete at it. A rootless container has no `$HOME` and no passwd entry, so
29
+ * `homedir()` throws or returns empty — caught here because this runs at module
30
+ * scope and the native binding loader imports this file.
31
+ */
32
+ function resolveHomeTmpDir() {
33
+ try {
34
+ const home = (0, node_os_1.homedir)();
35
+ return home && (0, node_path_1.isAbsolute)(home) ? (0, node_path_1.join)(home, '.nx') : undefined;
36
+ }
37
+ catch {
38
+ return undefined;
39
+ }
40
+ }
@@ -0,0 +1,132 @@
1
+ declare const safeSharedRootBrand: unique symbol;
2
+ declare const sharedRootEstablishedBrand: unique symbol;
3
+ declare const ownedRealDirBrand: unique symbol;
4
+ declare const ownedPrivateDirBrand: unique symbol;
5
+ /** Verified safe to keep an owner-only directory under. Not created. */
6
+ export type SafeSharedRoot = string & {
7
+ readonly [safeSharedRootBrand]: true;
8
+ };
9
+ /** Created if absent, then verified safe as above. */
10
+ export type EstablishedSharedRoot = string & {
11
+ readonly [sharedRootEstablishedBrand]: true;
12
+ };
13
+ /** An existing real directory owned by us. Mode is *not* checked. */
14
+ export type OwnedRealDir = string & {
15
+ readonly [ownedRealDirBrand]: true;
16
+ };
17
+ /**
18
+ * POSIX: created if absent, owned by us, and carrying no group or other bits —
19
+ * re-locked first if it was looser. The mode is checked on whichever branch
20
+ * produced it, so the brand does not depend on who created the directory.
21
+ *
22
+ * Windows: only *is a real directory*. `getuid` is unavailable there, so
23
+ * neither ownership nor mode is checked; `%TMP%` is already per-account.
24
+ */
25
+ export type OwnedPrivateDir = string & {
26
+ readonly [ownedPrivateDirBrand]: true;
27
+ };
28
+ /** Why a guard refused a directory. Data, not a sentence: `remedyFor` decides on it. */
29
+ export type DirRefusal = {
30
+ kind: 'not-created';
31
+ dir: string;
32
+ code?: string;
33
+ } | {
34
+ kind: 'not-inspectable';
35
+ dir: string;
36
+ code?: string;
37
+ } | {
38
+ kind: 'not-a-directory';
39
+ dir: string;
40
+ symlink?: true;
41
+ } | {
42
+ kind: 'foreign-owner';
43
+ dir: string;
44
+ uid: number;
45
+ } | {
46
+ kind: 'foreign-shared-container';
47
+ dir: string;
48
+ uid: number;
49
+ } | {
50
+ kind: 'not-tightenable';
51
+ dir: string;
52
+ mode: number;
53
+ } | {
54
+ kind: 'peer-writable-not-sticky';
55
+ dir: string;
56
+ mode: number;
57
+ };
58
+ /** A guard's verdict. */
59
+ export type GuardResult<T> = {
60
+ status: 'ok';
61
+ path: T;
62
+ } | {
63
+ status: 'refused';
64
+ refusal: DirRefusal;
65
+ };
66
+ /** The user-facing sentence for a refusal. The only place wording is decided. */
67
+ export declare function describeRefusal(r: DirRefusal): string;
68
+ /** What the user can do about a refusal, or `undefined` when there is nothing. */
69
+ export declare function remedyFor(r: DirRefusal): string | undefined;
70
+ /** One refusal as an `Error`, so several can travel in an `AggregateError`. */
71
+ export declare class DirectoryRefusedError extends Error {
72
+ readonly refusal: DirRefusal;
73
+ constructor(refusal: DirRefusal);
74
+ }
75
+ /**
76
+ * Whether a shared container is safe to keep an owner-only directory under.
77
+ *
78
+ * On POSIX, a container writable by other users must be sticky, and it must be
79
+ * owned by either root or the current user. Windows short-circuits after the
80
+ * directory test — the OS temp root is already scoped to one account, so there
81
+ * is no shared level whose ownership could matter.
82
+ *
83
+ * Sticky directories still let the directory's own owner rename entries, so a
84
+ * container owned by another unprivileged user could replace a previously
85
+ * verified private directory beneath it.
86
+ */
87
+ export declare function isSafeSharedRoot(dir: string): GuardResult<SafeSharedRoot>;
88
+ /**
89
+ * Whether other users on this machine can write into `dir`. Gates whether a
90
+ * refusal message may cite other users, so it must not over-report: `false` on
91
+ * Windows, where libuv synthesizes `st_mode` from the READONLY attribute and
92
+ * reports an ordinary per-account directory as `0666`, and `false` on a path
93
+ * that cannot be inspected.
94
+ *
95
+ * `statSync`, not `lstatSync`: the question is about the directory that will be
96
+ * used, not the link pointing at it. Link modes mislead in both directions —
97
+ * Linux creates symlinks `0777`, macOS applies the umask. Nothing here decides
98
+ * whether a path is accepted, so following the link costs nothing the guards
99
+ * do not already re-check.
100
+ */
101
+ export declare function isPeerWritable(dir: string): boolean;
102
+ /**
103
+ * Create a shared container as sticky + world-writable if it does not exist,
104
+ * and report whether the resulting path is safe for the current user.
105
+ *
106
+ * **A container that already exists is never modified — only judged.** Do not
107
+ * chmod before deciding trust: `CAP_FOWNER` (root's default in Docker and most
108
+ * CI images) can chmod a directory it does not own, so a peer-owned root would
109
+ * be widened to `1777` and then refused, and an operator who deliberately
110
+ * tightened this root would have it re-widened on every `nx` process.
111
+ */
112
+ export declare function ensureSafeSharedRoot(dir: string): GuardResult<EstablishedSharedRoot>;
113
+ /**
114
+ * Whether `dir` is an existing real directory owned by us. Unlike
115
+ * `ensureOwnedPrivateDir` it creates nothing and repairs nothing — for callers
116
+ * that only want to know whether a path is safe to act on, such as deleting.
117
+ */
118
+ export declare function isOwnedRealDirectory(dir: string): OwnedRealDir | null;
119
+ /** The path segment separating one user's Nx runtime state from another's. */
120
+ export declare function getUserSegment(): string;
121
+ /**
122
+ * Ensure `dir` exists, is a real directory owned by us, and carries no group or
123
+ * other bits at all — read and search alone reach a socket inside it, so 0755 is
124
+ * re-locked rather than accepted. A `refused` status carries which check said
125
+ * no — usually `foreign-owner` for a directory another user planted, but also
126
+ * `not-created`/`not-inspectable` for a filesystem error, `not-a-directory`, or
127
+ * `not-tightenable` when the re-lock did not land.
128
+ *
129
+ * Node builtins only: reached from the native binding loader.
130
+ */
131
+ export declare function ensureOwnedPrivateDir(dir: string): GuardResult<OwnedPrivateDir>;
132
+ export {};