toolroll 0.9.62 → 0.9.63

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 (100) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +51 -3
  3. package/dist/agent-fence.d.ts +155 -10
  4. package/dist/agent-fence.js +473 -38
  5. package/dist/browser/workspace.css +1 -1
  6. package/dist/browser/workspace.js +21 -21
  7. package/dist/browser-workspace.d.ts +28 -0
  8. package/dist/chat-actions.js +2 -2
  9. package/dist/check-levels.js +3 -0
  10. package/dist/claim.js +1 -1
  11. package/dist/cli-help.d.ts +1 -1
  12. package/dist/cli-help.js +1 -0
  13. package/dist/cli.js +3 -0
  14. package/dist/contracts/cli.d.ts +8 -0
  15. package/dist/contracts/cli.js +3 -1
  16. package/dist/contracts/console-api.d.ts +19 -1
  17. package/dist/contracts/console-api.js +2 -1
  18. package/dist/contracts/integration-metadata.d.ts +2 -1
  19. package/dist/contracts/integration-metadata.js +2 -1
  20. package/dist/desktop-update.d.ts +1 -1
  21. package/dist/dispatch.js +7 -4
  22. package/dist/doctor.d.ts +53 -0
  23. package/dist/doctor.js +427 -0
  24. package/dist/evidence-pack.d.ts +1 -1
  25. package/dist/evidence-pack.js +2 -2
  26. package/dist/exec.d.ts +3 -0
  27. package/dist/exec.js +5 -4
  28. package/dist/flow-code.d.ts +2 -2
  29. package/dist/flow-code.js +4 -15
  30. package/dist/flow-engine.js +11 -6
  31. package/dist/flow-triggers.d.ts +8 -4
  32. package/dist/flow-triggers.js +45 -25
  33. package/dist/flow-unattended-words.d.ts +28 -0
  34. package/dist/flow-unattended-words.js +50 -0
  35. package/dist/flow-unattended.d.ts +227 -0
  36. package/dist/flow-unattended.js +776 -0
  37. package/dist/flows-cli.d.ts +28 -1
  38. package/dist/flows-cli.js +55 -10
  39. package/dist/flows-ui.d.ts +2 -1
  40. package/dist/flows-ui.js +4 -1
  41. package/dist/google-mail.d.ts +1 -0
  42. package/dist/google-mail.js +61 -18
  43. package/dist/integrations-ui.d.ts +2 -1
  44. package/dist/integrations-ui.js +6 -3
  45. package/dist/integrations.d.ts +17 -3
  46. package/dist/integrations.js +38 -18
  47. package/dist/invoke.js +300 -168
  48. package/dist/landed-cleanup.d.ts +3 -2
  49. package/dist/landed-cleanup.js +12 -5
  50. package/dist/lead-tools.js +11 -3
  51. package/dist/mcp-connect.d.ts +8 -7
  52. package/dist/mcp-connect.js +49 -51
  53. package/dist/oauth-run-token.d.ts +51 -0
  54. package/dist/oauth-run-token.js +127 -0
  55. package/dist/operate.js +7 -1
  56. package/dist/plan-auto.d.ts +11 -0
  57. package/dist/plan-auto.js +62 -11
  58. package/dist/process-recovery-eligibility.d.ts +1 -1
  59. package/dist/project-access.d.ts +3 -0
  60. package/dist/project-access.js +3 -0
  61. package/dist/project-delete.d.ts +3 -1
  62. package/dist/project-delete.js +10 -4
  63. package/dist/project-file.d.ts +3 -0
  64. package/dist/project-file.js +16 -0
  65. package/dist/project-tools.d.ts +99 -25
  66. package/dist/project-tools.js +394 -98
  67. package/dist/provider-home.d.ts +22 -0
  68. package/dist/provider-home.js +99 -0
  69. package/dist/provider.d.ts +17 -3
  70. package/dist/provider.js +34 -10
  71. package/dist/remote-main.d.ts +4 -0
  72. package/dist/remote-main.js +3 -3
  73. package/dist/scope.d.ts +1 -1
  74. package/dist/serve.js +11 -3
  75. package/dist/server/flows.js +27 -5
  76. package/dist/server/route-table.js +3 -0
  77. package/dist/server/runtime.d.ts +1 -1
  78. package/dist/server/settings.js +11 -3
  79. package/dist/storage-sweep-child.js +3 -1
  80. package/dist/storage-sweep-process.d.ts +12 -5
  81. package/dist/storage-sweep-process.js +23 -6
  82. package/dist/store.d.ts +38 -6
  83. package/dist/store.js +148 -15
  84. package/dist/subagent-tools.d.ts +1 -1
  85. package/dist/surface.js +6 -4
  86. package/dist/teardown-git.d.ts +14 -0
  87. package/dist/teardown-git.js +119 -0
  88. package/dist/tool-broker.d.ts +37 -0
  89. package/dist/tool-broker.js +369 -0
  90. package/dist/tool-launcher.js +5 -4
  91. package/dist/tool-secret-store.d.ts +170 -0
  92. package/dist/tool-secret-store.js +834 -0
  93. package/dist/toolroll-update.js +3 -2
  94. package/dist/tools-ui.d.ts +7 -1
  95. package/dist/tools-ui.js +17 -8
  96. package/dist/work-index.js +5 -3
  97. package/dist/worktree.d.ts +10 -4
  98. package/dist/worktree.js +70 -29
  99. package/package.json +3 -1
  100. package/scripts/provider-canary.mjs +210 -31
package/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.9.63 — 2026-10-13
4
+
5
+ - **Scheduled flows run on their own.** Sign a flow once with limits
6
+ (runs a day, budget, end date); its on-time firings build without a
7
+ person, and the script it runs is checked again when it fires.
8
+ - **Secrets in the OS keychain.** Tool keys, the Linear key, Google mail and
9
+ flow secrets move into the macOS Keychain or Linux Secret Service, never
10
+ argv or the database. OAuth tools give each run a short-lived token, never
11
+ the refresh token. Settings shows how each tool's runs get credentials.
12
+ - **Builds stay in their own checkout.** A build can't read or write another
13
+ project's or another task's checkout, and a checkout swapped for a link
14
+ is refused at the next launch.
15
+ - **Safer cleanup.** Removing finished checkouts runs git with hooks,
16
+ filters and nested-repo config switched off.
17
+ - **Attack suite.** Every bypass found in review is a permanent test, run by
18
+ the Quick check whenever sandbox or secrets code changes.
19
+ - **Tool secrets stay outside the build.** A broker outside the sandbox
20
+ holds them. Codex refuses tools that carry secrets. Shared dependencies and
21
+ `git gc` work inside the fence.
22
+ - **Tighter sandbox.** Builds can no longer rename folders above protected
23
+ paths or inspect other processes' memory; tool servers get only the
24
+ environment they need.
25
+ - **Tools with secrets need the macOS sandbox.** A build without it, and
26
+ every build on Linux, leaves those tools out and says why.
27
+ - **`toolroll doctor`.** Checks that Toolroll's service holds no key a build
28
+ could read, and lists the steps to fix it. It reads only.
29
+ - **Research tools answer every refusal**, even when the service accepts the
30
+ rest with an empty reply.
31
+
3
32
  ## 0.9.62 — 2026-10-12
4
33
 
5
34
  - **Release checks in minutes.** The upgrade path runs on a sample, CI's
package/README.md CHANGED
@@ -409,7 +409,7 @@ do not loosen when you leave the room:
409
409
  | touch a default branch | builds land on `toolroll/<task>` in a leased worktree; push + PR happen only under a publication grant naming the exact repo, branch prefix, and base |
410
410
  | approve its own work | approval nonces are minted only on screens that restate the digest-bound terms, and require your approver token typed again — **no LLM sits in any approval path** — and the [agent fence](#what-an-agent-can-reach) keeps your remembered login, runner tokens and the database out of the agent's reach |
411
411
  | act on an irreversible option | `reversible` is a schema field; irreversible choices never auto-apply, and answering one from a phone takes a second minted confirmation tap |
412
- | see Toolroll's secrets | the [agent fence](#what-an-agent-can-reach) blocks your login, runner and bot tokens, stored provider keys and project tool secrets at the operating system; other providers' keys are stripped from each agent's environment; secrets live in 0600 files, never in the database, URLs, or logs |
412
+ | see Toolroll's secrets | the [agent fence](#what-an-agent-can-reach) blocks your login, runner and bot tokens, stored provider keys and project tool secrets at the operating system; other providers' keys are stripped from each agent's environment; tool secrets rest sealed in the OS keychain ([how](#how-build-sessions-are-protected)) and other secrets in 0600 files, never in the database, URLs, or logs |
413
413
  | spend while idle | **an LLM never polls** — the daemon does every no-judgement chore at zero token cost and wakes an agent only on a real event |
414
414
  | spend without being counted | every provider spawn is stamped *before* it spends, so cost is measured, never asserted |
415
415
  | guess at a judgement call | it parks a typed decision — recap, options with reversibility, recommendation, evidence — and the other eleven tasks keep going |
@@ -572,6 +572,13 @@ runner and coordinator tokens, chat bot tokens, the database and its backups,
572
572
  other runs' evidence) — everything there except the build's own worktree —
573
573
  and `~/.toolroll` (stored provider keys and project tool secrets).
574
574
 
575
+ Seatbelt and bubblewrap deny the whole checkout pool and allow the build’s own
576
+ checkout back, covering other projects created after launch too. Codex keeps
577
+ the own checkout’s ancestors traversable and denies each other project folder
578
+ found in trusted checkout pools at launch. A project added after a Codex build
579
+ starts is covered on the next launch. Own Git data, linked shared dependencies
580
+ and launch tools remain available.
581
+
575
582
  | | Auto | Full access |
576
583
  |---|---|---|
577
584
  | **Codex / OpenRouter** (any OS) | Codex's workspace sandbox (workspace writes, no network) with the fence | Codex's sandbox widened to write anywhere with network, with the fence |
@@ -581,8 +588,49 @@ and `~/.toolroll` (stored provider keys and project tool secrets).
581
588
  Each attempt records how it was fenced. Two limits to know: in **API-key
582
589
  mode** an agent's own provider key is in its environment, so its shell can
583
590
  read it (subscription mode, the default, puts no key there); and a project's
584
- own tool secrets reach that project's tools. Reviews and the lead chat run
585
- with no tools and are confined to their own files. See [SECURITY.md](SECURITY.md).
591
+ own tool secrets reach that project's tools. They stay in a per-run broker
592
+ outside the fence: the agent gets only its address and a token that stops
593
+ working when the run ends, and on macOS it can't read another process's
594
+ arguments or environment. Reviews and the lead chat run with no tools and are
595
+ confined to their own files. See [SECURITY.md](SECURITY.md).
596
+
597
+ ### How build sessions are protected
598
+
599
+ A build runs as your own user, so Toolroll keeps the secrets it holds (tool
600
+ keys and sign-ins, the Linear key, a Google mail connection, flow webhook
601
+ secrets) away from it in layers:
602
+
603
+ - **The fence.** The operating system denies the build Toolroll's own
604
+ folders, your home configuration and other projects (the table above).
605
+ - **The broker.** A run's tools are served by a broker in Toolroll's own
606
+ process, outside the fence. The agent gets only the broker's local address
607
+ and a key for that run, which stops working when the run ends. Another
608
+ run's key opens nothing.
609
+ - **The keychain.** At rest, secrets are in the macOS Keychain (through
610
+ `security`, with the value on its input) or the Linux Secret Service (the
611
+ system's `secret-tool`, value on its input). A fenced build can still ask
612
+ the keychain for an item, so each is sealed with a key in `tool-secrets`
613
+ beside Toolroll's database. Toolroll makes that folder when it starts,
614
+ before any build, and records which key it made; a folder, key or link put
615
+ there by anything else is refused. What a build reads is ciphertext.
616
+ Secrets are read only when a run starts. Files from before move into the
617
+ keychain the first time they are used, and the plaintext copy is removed.
618
+ Where there is no keychain, or the keyring doesn't answer, secrets stay in
619
+ owner-only files, and Settings and `toolroll integrations` say so.
620
+ - **Short-lived tokens.** A service connected by signing in gives each run
621
+ a fresh access token of its own, made outside the fence when the run starts
622
+ and limited to read access for research steps where the service allows.
623
+ The refresh token never leaves Toolroll, and one renewal runs at a time
624
+ across Toolroll's processes. If a renewed sign-in can't be saved, the run
625
+ doesn't start and every token made for it is revoked. The run's token is
626
+ revoked when the run ends, or runs out on its own where the service has no
627
+ way to revoke it. Keys you paste in stay in the broker. Settings → Tools
628
+ shows which each tool uses.
629
+
630
+ What remains: any program of yours running outside the fence (not started by
631
+ a build) can read what you can, including Toolroll's folder and the keychain.
632
+ Toolroll protects your secrets from its builds, not from other software you
633
+ run.
586
634
 
587
635
  Every new-task and task-scope form has the same two-choice control. A task's
588
636
  choice is durable through planning rewrites and is sealed into the approved
@@ -1,5 +1,15 @@
1
1
  /** How a launch was fenced, as recorded on the run and said on the task. */
2
2
  export type FenceMethod = "codex-profile" | "macos-sandbox" | "linux-bubblewrap" | "claude-rules" | "none";
3
+ /** Only the plane's recorded repository may supply an own-Git exemption. */
4
+ export type WorktreeBinding = {
5
+ main: string;
6
+ gitdir: string;
7
+ };
8
+ export declare class CheckoutBindingError extends Error {
9
+ }
10
+ export declare const HARDENED_GIT_ARGS: readonly ["--no-optional-locks", "-c", "core.fsmonitor=false", "-c", "core.hooksPath=/dev/null"];
11
+ export declare function checkoutGitEnv(base?: Readonly<NodeJS.ProcessEnv>): Record<string, string>;
12
+ export declare function trustedWorktreeBinding(repository: string, worktree: string, poolRoots?: readonly (string | null)[]): WorktreeBinding;
3
13
  /**
4
14
  * Every path an agent must not reach: the Toolroll state folder
5
15
  * beside the database (all of it, except the folder that holds this run's
@@ -14,11 +24,17 @@ export declare function agentFence(options: {
14
24
  home?: string;
15
25
  extra?: readonly string[];
16
26
  boundary?: TaskBoundary | null;
27
+ binding?: WorktreeBinding | null;
28
+ runFolders?: RunFolders;
17
29
  }): string[];
18
- /** The task's boundary: `shell` joins the OS fence; `fileTools` only Claude's file-tool deny rules. */
30
+ /** The task's boundary: `shell` joins the OS fence; `fileTools` only Claude's file-tool deny rules; `readOnly` and
31
+ * `lookup` are other tasks' git metadata and checkout roots (see FenceGrants). */
19
32
  export type TaskBoundary = {
33
+ protectedShell?: string[];
20
34
  shell: string[];
21
35
  fileTools: string[];
36
+ readOnly: string[];
37
+ lookup: string[];
22
38
  };
23
39
  /**
24
40
  * Everything outside a task's own folders that a build could otherwise
@@ -32,19 +48,145 @@ export declare function taskBoundary(options: {
32
48
  worktree: string;
33
49
  provider: string;
34
50
  home?: string;
51
+ binding?: WorktreeBinding | null;
35
52
  }): TaskBoundary;
53
+ /** Where launches keep their private folders (the system temp folder), and this launch's own tool folder. */
54
+ export type RunFolders = {
55
+ root: string;
56
+ own: string | null;
57
+ };
58
+ /** The prefixes of every launch's private folders: its tools' config and a Codex build's own home. */
59
+ export declare const RUN_FOLDER_PREFIXES: readonly ["so-tools-", "so-codex-"];
60
+ export declare function runFolders(own: string | null, root?: string): RunFolders;
61
+ /**
62
+ * What a fence gives back beside its denied paths. Each is narrow and none
63
+ * ever writes: `readOnly` is read, never written (other tasks' git
64
+ * metadata); `readable` is read and run inside a denied folder (the shared
65
+ * dependencies this checkout links); `lookup` is only looked up, never
66
+ * listed or read (the deps root and the copy linked, other tasks' checkout
67
+ * roots); `runFolders` denies every launch folder in the temp folder but
68
+ * this launch's own (macOS: by pattern, so a later one is denied too);
69
+ * `pool` denies the plane's checkout pools whole and gives this build's own
70
+ * checkout back (CheckoutPool).
71
+ */
72
+ export type FenceGrants = {
73
+ readOnly: string[];
74
+ readable: string[];
75
+ lookup: string[];
76
+ runFolders?: RunFolders;
77
+ pool?: CheckoutPool;
78
+ };
79
+ export declare const NO_GRANTS: FenceGrants;
80
+ /**
81
+ * The plane's checkout pools, denied whole: every project's worktrees, and any made there after launch. `agentFence`
82
+ * drops a path at or above the checkout, so the deny lives here and each sandbox gives back, right after it, only
83
+ * `own` (this build's checkout, read and written) and `lookup` (the folders between, looked up, never listed).
84
+ */
85
+ export type CheckoutPool = {
86
+ deny: string[];
87
+ own: string | null;
88
+ lookup: string[];
89
+ gitPaths?: string[];
90
+ };
91
+ /**
92
+ * The pool deny for one launch. `roots` come from the plane's own records (the pool beside the database, and the one
93
+ * the recorded checkout was made in), never from the checkout. A root that holds this checkout's own Git data (the
94
+ * binding's gitdir or the repository's .git) is never denied whole: it is split around that data instead, entry by
95
+ * entry, so it is denied as far as it can be (fail closed by denying more, never by refusing). A root inside the
96
+ * checkout, the home folder, a folder above it or / is left alone: the first is the build's own work, the others the
97
+ * whole machine.
98
+ */
99
+ export declare function checkoutPool(options: {
100
+ roots: readonly (string | null)[];
101
+ worktree: string | null;
102
+ binding?: WorktreeBinding | null;
103
+ home?: string;
104
+ }, list?: (path: string) => string[]): CheckoutPool;
105
+ /** The grants for one build: its task boundary's git rules, the shared dependencies its checkout links, and the
106
+ * checkout pools (`poolRoots`, from the plane's records) denied around its own checkout. */
107
+ export declare function fenceGrants(options: {
108
+ databaseFile: string | null;
109
+ worktree: string | null;
110
+ boundary?: TaskBoundary | null;
111
+ runFolders?: RunFolders;
112
+ linked?: {
113
+ repo: string;
114
+ setupDigest: string | null;
115
+ } | null;
116
+ poolRoots?: readonly (string | null)[];
117
+ binding?: WorktreeBinding | null;
118
+ home?: string;
119
+ }): FenceGrants;
120
+ /**
121
+ * Git settings every fenced build runs with (GIT_CONFIG_COUNT, after any the
122
+ * caller already set): `git gc` never expires a reflog, so it never rewrites
123
+ * another task's reflog, which the fence would refuse mid-collection.
124
+ */
125
+ export declare function fencedGitEnv(base?: Readonly<Record<string, string | undefined>>): Record<string, string>;
36
126
  /**
37
127
  * Codex's own sandbox, fenced. Auto: the `:workspace` profile Codex's
38
128
  * `--sandbox workspace-write` already gives (workspace and temp writes, no
39
129
  * network). Full access: the same profile widened to write anywhere with
40
130
  * network on, instead of no sandbox at all. Either way the fenced paths are
41
- * denied, which in Codex outranks any write or read grant.
131
+ * denied, which in Codex outranks any write or read grant. The checkout pools
132
+ * are never `flattened` (which leaves what is made after launch readable): see
133
+ * `codexPool`, which denies them around the build's own checkout, written back.
134
+ */
135
+ export declare function codexFenceArgv(fence: readonly string[], fullAccess: boolean, grants?: FenceGrants): string[];
136
+ /**
137
+ * Codex cannot deny an ancestor and still traverse it to the own checkout. Deny existing
138
+ * siblings individually, from the trusted pool roots and a fresh listing, never through
139
+ * flattened or name patterns. A project added after launch is covered on the next launch;
140
+ * Seatbelt and bubblewrap retain the stronger whole-pool rule for later-created projects.
141
+ */
142
+ export declare function codexPool(pool: CheckoutPool, list?: (path: string) => string[]): {
143
+ read: string[];
144
+ deny: string[];
145
+ write: string[];
146
+ };
147
+ /** Secret-looking names denied by pattern inside a folder `flattened` makes read-only, so one written there after
148
+ * launch is denied too (the database and its journals, tokens, login and other text files). */
149
+ export declare const SPLIT_SECRET_PATTERNS: readonly ["orders.db*", "*token*", "up-login*", "*.txt", "*secret*", "*password*", "*credential*", "*.pem", "*.key"];
150
+ /**
151
+ * A fence as plain denied and read-only paths, for a sandbox that can't
152
+ * grant inside a denied folder (Codex: a deny outranks any grant): a denied
153
+ * folder holding something readable becomes read-only, with each of its
154
+ * entries not on the way to what is readable denied instead. Fails closed: a
155
+ * folder that can't be listed stays denied whole and its grant is dropped.
156
+ * Residual: an entry made after launch in a read-only folder is denied only
157
+ * when its name matches SPLIT_SECRET_PATTERNS; any other new entry there is
158
+ * readable (never writable) until the next launch. The macOS fence has no
159
+ * such gap: it denies the folder and grants back only the readable path.
160
+ */
161
+ export declare function flattened(fence: readonly string[], grants?: FenceGrants, list?: (path: string) => string[]): {
162
+ deny: string[];
163
+ readOnly: string[];
164
+ };
165
+ /** Claude's own file tools refuse the fenced paths in every mode (its shell is fenced by the macOS sandbox), and
166
+ * never edit a read-only one. */
167
+ export declare function claudeFenceSettings(fence: readonly string[], readOnly?: readonly string[]): string;
168
+ /**
169
+ * The folders the user owns above each path (never `/`, nor the path itself), and each `roots` folder itself when the
170
+ * user owns it. A Seatbelt path rule follows the name, not the folder: renaming one of these would bring a fenced path
171
+ * back under a name no rule mentions. A folder the user doesn't own can't be renamed by a build anyway.
172
+ */
173
+ export declare function ownedAncestors(paths: readonly string[], roots?: readonly string[], uid?: number | undefined): string[];
174
+ /**
175
+ * A Seatbelt profile that allows everything except reading or writing the
176
+ * fenced paths, less what `grants` gives back (a later Seatbelt rule
177
+ * outranks an earlier one). Whatever the paths, the process can't read
178
+ * another's arguments and environment (`kern.procargs`, which `ps -E` and
179
+ * KERN_PROCARGS2 use) or inspect a process outside its own sandbox:
180
+ * `process-info*` limited by target alone doesn't stop the sysctl. It can't
181
+ * take another process's task port either (`task_for_pid`, what lldb attaches
182
+ * with; a task name port too), so a tool server's or Toolroll's own memory
183
+ * and environment stay out of reach. Last, every folder of the user's above
184
+ * a fenced or read-only path and above the temp folder (and the temp folder
185
+ * itself) can't be renamed or removed, though what is inside them stays
186
+ * writable as before. The checkout pools are denied first, and the build's own
187
+ * checkout given back right after, so every later deny still holds inside it.
42
188
  */
43
- export declare function codexFenceArgv(fence: readonly string[], fullAccess: boolean): string[];
44
- /** Claude's own file tools refuse the fenced paths in every mode (its shell is fenced by the macOS sandbox). */
45
- export declare function claudeFenceSettings(fence: readonly string[]): string;
46
- /** A Seatbelt profile that allows everything except reading or writing the fenced paths. */
47
- export declare function macosFenceProfile(fence: readonly string[]): string;
189
+ export declare function macosFenceProfile(fence: readonly string[], grants?: FenceGrants): string;
48
190
  export declare const SANDBOX_EXEC = "/usr/bin/sandbox-exec";
49
191
  /**
50
192
  * Whether this machine can run an agent inside the macOS fence (checked once). Not from inside another
@@ -58,13 +200,16 @@ export declare function macosFenceAvailable(platform?: NodeJS.Platform, probe?:
58
200
  stderr: string;
59
201
  }): boolean;
60
202
  /** The spawn that runs `file args` inside the macOS fence (same process: sandbox-exec replaces itself with the agent). */
61
- export declare function macosFenced(file: string, args: readonly string[], fence: readonly string[]): {
203
+ export declare function macosFenced(file: string, args: readonly string[], fence: readonly string[], grants?: FenceGrants): {
62
204
  file: string;
63
205
  args: string[];
64
206
  };
65
207
  export declare function linuxFenceAvailable(platform?: NodeJS.Platform, probe?: () => boolean): boolean;
66
- /** The spawn that runs `file args` inside the Linux fence: the whole filesystem as it is, except each fenced path masked. */
67
- export declare function linuxFenced(file: string, args: readonly string[], fence: readonly string[]): {
208
+ /** The spawn that runs `file args` inside the Linux fence: the whole filesystem as it is, the checkout pools masked
209
+ * and the build's own checkout bound back read-write over them, then every fenced path masked whole (an empty
210
+ * folder, or /dev/null for a file), so what is made there after launch is masked too; then only the explicit grants
211
+ * bound back read-only (bubblewrap binds from the original root, so a grant inside a mask still reaches its files). */
212
+ export declare function linuxFenced(file: string, args: readonly string[], fence: readonly string[], grants?: FenceGrants): {
68
213
  file: string;
69
214
  args: string[];
70
215
  };