@miller-tech/uap 2.21.3 → 2.36.1

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 (328) hide show
  1. package/README.md +22 -10
  2. package/config/model-profiles/qwen38-coder390.json +46 -0
  3. package/config/model-profiles/qwen38.json +3 -2
  4. package/config/model-registry.json +110 -0
  5. package/dist/.tsbuildinfo +1 -1
  6. package/dist/benchmarks/paired/types.d.ts +2 -2
  7. package/dist/bin/cli.js +315 -20
  8. package/dist/bin/cli.js.map +1 -1
  9. package/dist/cli/attention.d.ts +6 -0
  10. package/dist/cli/attention.d.ts.map +1 -0
  11. package/dist/cli/attention.js +115 -0
  12. package/dist/cli/attention.js.map +1 -0
  13. package/dist/cli/bench-report.d.ts +82 -0
  14. package/dist/cli/bench-report.d.ts.map +1 -0
  15. package/dist/cli/bench-report.js +237 -0
  16. package/dist/cli/bench-report.js.map +1 -0
  17. package/dist/cli/clients.d.ts +6 -0
  18. package/dist/cli/clients.d.ts.map +1 -0
  19. package/dist/cli/clients.js +142 -0
  20. package/dist/cli/clients.js.map +1 -0
  21. package/dist/cli/dashboard-grants.d.ts +26 -0
  22. package/dist/cli/dashboard-grants.d.ts.map +1 -0
  23. package/dist/cli/dashboard-grants.js +69 -0
  24. package/dist/cli/dashboard-grants.js.map +1 -0
  25. package/dist/cli/dashboard-pace.d.ts +31 -0
  26. package/dist/cli/dashboard-pace.d.ts.map +1 -0
  27. package/dist/cli/dashboard-pace.js +42 -0
  28. package/dist/cli/dashboard-pace.js.map +1 -0
  29. package/dist/cli/dashboard-session.d.ts +25 -0
  30. package/dist/cli/dashboard-session.d.ts.map +1 -0
  31. package/dist/cli/dashboard-session.js +814 -0
  32. package/dist/cli/dashboard-session.js.map +1 -0
  33. package/dist/cli/dashboard-types.d.ts +18 -0
  34. package/dist/cli/dashboard-types.d.ts.map +1 -0
  35. package/dist/cli/dashboard-types.js +9 -0
  36. package/dist/cli/dashboard-types.js.map +1 -0
  37. package/dist/cli/dashboard.d.ts +2 -18
  38. package/dist/cli/dashboard.d.ts.map +1 -1
  39. package/dist/cli/dashboard.js +43 -793
  40. package/dist/cli/dashboard.js.map +1 -1
  41. package/dist/cli/deliver.d.ts +35 -0
  42. package/dist/cli/deliver.d.ts.map +1 -1
  43. package/dist/cli/deliver.js +93 -9
  44. package/dist/cli/deliver.js.map +1 -1
  45. package/dist/cli/diff.d.ts +85 -0
  46. package/dist/cli/diff.d.ts.map +1 -0
  47. package/dist/cli/diff.js +293 -0
  48. package/dist/cli/diff.js.map +1 -0
  49. package/dist/cli/eta.d.ts +35 -0
  50. package/dist/cli/eta.d.ts.map +1 -0
  51. package/dist/cli/eta.js +101 -0
  52. package/dist/cli/eta.js.map +1 -0
  53. package/dist/cli/handsfree.d.ts +7 -0
  54. package/dist/cli/handsfree.d.ts.map +1 -1
  55. package/dist/cli/handsfree.js +27 -0
  56. package/dist/cli/handsfree.js.map +1 -1
  57. package/dist/cli/hooks.d.ts.map +1 -1
  58. package/dist/cli/hooks.js +126 -5
  59. package/dist/cli/hooks.js.map +1 -1
  60. package/dist/cli/loops.d.ts +24 -5
  61. package/dist/cli/loops.d.ts.map +1 -1
  62. package/dist/cli/loops.js +92 -12
  63. package/dist/cli/loops.js.map +1 -1
  64. package/dist/cli/models.d.ts +62 -0
  65. package/dist/cli/models.d.ts.map +1 -0
  66. package/dist/cli/models.js +567 -0
  67. package/dist/cli/models.js.map +1 -0
  68. package/dist/cli/plan.d.ts +9 -0
  69. package/dist/cli/plan.d.ts.map +1 -1
  70. package/dist/cli/plan.js +57 -4
  71. package/dist/cli/plan.js.map +1 -1
  72. package/dist/cli/proxy-relay.d.ts +55 -0
  73. package/dist/cli/proxy-relay.d.ts.map +1 -0
  74. package/dist/cli/proxy-relay.js +116 -0
  75. package/dist/cli/proxy-relay.js.map +1 -0
  76. package/dist/cli/proxy.d.ts +4 -0
  77. package/dist/cli/proxy.d.ts.map +1 -1
  78. package/dist/cli/proxy.js +26 -1
  79. package/dist/cli/proxy.js.map +1 -1
  80. package/dist/cli/sandbox.d.ts +101 -4
  81. package/dist/cli/sandbox.d.ts.map +1 -1
  82. package/dist/cli/sandbox.js +393 -44
  83. package/dist/cli/sandbox.js.map +1 -1
  84. package/dist/cli/self.d.ts +13 -0
  85. package/dist/cli/self.d.ts.map +1 -0
  86. package/dist/cli/self.js +94 -0
  87. package/dist/cli/self.js.map +1 -0
  88. package/dist/cli/systemd-services.d.ts +2 -8
  89. package/dist/cli/systemd-services.d.ts.map +1 -1
  90. package/dist/cli/systemd-services.js +5 -20
  91. package/dist/cli/systemd-services.js.map +1 -1
  92. package/dist/cli/task.js +1 -1
  93. package/dist/cli/task.js.map +1 -1
  94. package/dist/cli/wizard-config.d.ts.map +1 -1
  95. package/dist/cli/wizard-config.js +31 -2
  96. package/dist/cli/wizard-config.js.map +1 -1
  97. package/dist/config/settings-registry.d.ts +1 -1
  98. package/dist/config/settings-registry.d.ts.map +1 -1
  99. package/dist/config/settings-registry.js +108 -0
  100. package/dist/config/settings-registry.js.map +1 -1
  101. package/dist/coordination/capability-router.js +2 -2
  102. package/dist/coordination/capability-router.js.map +1 -1
  103. package/dist/coordination/database.d.ts +13 -0
  104. package/dist/coordination/database.d.ts.map +1 -1
  105. package/dist/coordination/database.js +63 -7
  106. package/dist/coordination/database.js.map +1 -1
  107. package/dist/coordination/eta-inject.d.ts +32 -0
  108. package/dist/coordination/eta-inject.d.ts.map +1 -0
  109. package/dist/coordination/eta-inject.js +64 -0
  110. package/dist/coordination/eta-inject.js.map +1 -0
  111. package/dist/coordination/reactor.d.ts.map +1 -1
  112. package/dist/coordination/reactor.js +14 -0
  113. package/dist/coordination/reactor.js.map +1 -1
  114. package/dist/coordination/service.d.ts +18 -8
  115. package/dist/coordination/service.d.ts.map +1 -1
  116. package/dist/coordination/service.js +38 -28
  117. package/dist/coordination/service.js.map +1 -1
  118. package/dist/dashboard/client-registry.d.ts +163 -0
  119. package/dist/dashboard/client-registry.d.ts.map +1 -0
  120. package/dist/dashboard/client-registry.js +549 -0
  121. package/dist/dashboard/client-registry.js.map +1 -0
  122. package/dist/dashboard/controls.d.ts.map +1 -1
  123. package/dist/dashboard/controls.js +33 -4
  124. package/dist/dashboard/controls.js.map +1 -1
  125. package/dist/dashboard/data-seeder.d.ts +10 -7
  126. package/dist/dashboard/data-seeder.d.ts.map +1 -1
  127. package/dist/dashboard/data-seeder.js +31 -75
  128. package/dist/dashboard/data-seeder.js.map +1 -1
  129. package/dist/dashboard/data-service.d.ts +9 -0
  130. package/dist/dashboard/data-service.d.ts.map +1 -1
  131. package/dist/dashboard/data-service.js +32 -3
  132. package/dist/dashboard/data-service.js.map +1 -1
  133. package/dist/dashboard/placement-routes.d.ts +119 -0
  134. package/dist/dashboard/placement-routes.d.ts.map +1 -0
  135. package/dist/dashboard/placement-routes.js +331 -0
  136. package/dist/dashboard/placement-routes.js.map +1 -0
  137. package/dist/dashboard/server.d.ts.map +1 -1
  138. package/dist/dashboard/server.js +408 -2
  139. package/dist/dashboard/server.js.map +1 -1
  140. package/dist/delivery/attention.d.ts +130 -0
  141. package/dist/delivery/attention.d.ts.map +1 -0
  142. package/dist/delivery/attention.js +341 -0
  143. package/dist/delivery/attention.js.map +1 -0
  144. package/dist/delivery/decompose.d.ts +18 -0
  145. package/dist/delivery/decompose.d.ts.map +1 -1
  146. package/dist/delivery/decompose.js +22 -1
  147. package/dist/delivery/decompose.js.map +1 -1
  148. package/dist/delivery/eta-estimate.d.ts +111 -0
  149. package/dist/delivery/eta-estimate.d.ts.map +1 -0
  150. package/dist/delivery/eta-estimate.js +171 -0
  151. package/dist/delivery/eta-estimate.js.map +1 -0
  152. package/dist/delivery/eta.d.ts +23 -0
  153. package/dist/delivery/eta.d.ts.map +1 -0
  154. package/dist/delivery/eta.js +59 -0
  155. package/dist/delivery/eta.js.map +1 -0
  156. package/dist/delivery/orchestrated-mission.d.ts +10 -0
  157. package/dist/delivery/orchestrated-mission.d.ts.map +1 -1
  158. package/dist/delivery/orchestrated-mission.js +15 -1
  159. package/dist/delivery/orchestrated-mission.js.map +1 -1
  160. package/dist/delivery/plan-check.d.ts +7 -1
  161. package/dist/delivery/plan-check.d.ts.map +1 -1
  162. package/dist/delivery/plan-check.js +23 -2
  163. package/dist/delivery/plan-check.js.map +1 -1
  164. package/dist/delivery/run-state.d.ts +1 -1
  165. package/dist/delivery/run-state.d.ts.map +1 -1
  166. package/dist/delivery/run-state.js +8 -1
  167. package/dist/delivery/run-state.js.map +1 -1
  168. package/dist/delivery/task-orchestrator.d.ts +8 -3
  169. package/dist/delivery/task-orchestrator.d.ts.map +1 -1
  170. package/dist/delivery/task-orchestrator.js +75 -43
  171. package/dist/delivery/task-orchestrator.js.map +1 -1
  172. package/dist/delivery/task-sync.d.ts +21 -0
  173. package/dist/delivery/task-sync.d.ts.map +1 -1
  174. package/dist/delivery/task-sync.js +44 -8
  175. package/dist/delivery/task-sync.js.map +1 -1
  176. package/dist/delivery/task-workspace.d.ts +3 -3
  177. package/dist/delivery/task-workspace.js +3 -3
  178. package/dist/generators/self-card.d.ts +65 -0
  179. package/dist/generators/self-card.d.ts.map +1 -0
  180. package/dist/generators/self-card.js +256 -0
  181. package/dist/generators/self-card.js.map +1 -0
  182. package/dist/inference/probe.js +1 -1
  183. package/dist/inference/probe.js.map +1 -1
  184. package/dist/memory/prepopulate.d.ts.map +1 -1
  185. package/dist/memory/prepopulate.js +2 -0
  186. package/dist/memory/prepopulate.js.map +1 -1
  187. package/dist/models/analytics.d.ts +32 -0
  188. package/dist/models/analytics.d.ts.map +1 -1
  189. package/dist/models/analytics.js +68 -5
  190. package/dist/models/analytics.js.map +1 -1
  191. package/dist/models/plan-readability.d.ts +55 -0
  192. package/dist/models/plan-readability.d.ts.map +1 -0
  193. package/dist/models/plan-readability.js +339 -0
  194. package/dist/models/plan-readability.js.map +1 -0
  195. package/dist/placement/admission.d.ts +59 -0
  196. package/dist/placement/admission.d.ts.map +1 -0
  197. package/dist/placement/admission.js +197 -0
  198. package/dist/placement/admission.js.map +1 -0
  199. package/dist/placement/auto.d.ts +44 -0
  200. package/dist/placement/auto.d.ts.map +1 -0
  201. package/dist/placement/auto.js +212 -0
  202. package/dist/placement/auto.js.map +1 -0
  203. package/dist/placement/enforce.d.ts +128 -0
  204. package/dist/placement/enforce.d.ts.map +1 -0
  205. package/dist/placement/enforce.js +655 -0
  206. package/dist/placement/enforce.js.map +1 -0
  207. package/dist/placement/idle.d.ts +50 -0
  208. package/dist/placement/idle.d.ts.map +1 -0
  209. package/dist/placement/idle.js +213 -0
  210. package/dist/placement/idle.js.map +1 -0
  211. package/dist/placement/ledger.d.ts +323 -0
  212. package/dist/placement/ledger.d.ts.map +1 -0
  213. package/dist/placement/ledger.js +263 -0
  214. package/dist/placement/ledger.js.map +1 -0
  215. package/dist/placement/preview.d.ts +51 -0
  216. package/dist/placement/preview.d.ts.map +1 -0
  217. package/dist/placement/preview.js +61 -0
  218. package/dist/placement/preview.js.map +1 -0
  219. package/dist/placement/probes.d.ts +47 -0
  220. package/dist/placement/probes.d.ts.map +1 -0
  221. package/dist/placement/probes.js +207 -0
  222. package/dist/placement/probes.js.map +1 -0
  223. package/dist/placement/proxy-env.d.ts +21 -0
  224. package/dist/placement/proxy-env.d.ts.map +1 -0
  225. package/dist/placement/proxy-env.js +42 -0
  226. package/dist/placement/proxy-env.js.map +1 -0
  227. package/dist/placement/registry.d.ts +1038 -0
  228. package/dist/placement/registry.d.ts.map +1 -0
  229. package/dist/placement/registry.js +274 -0
  230. package/dist/placement/registry.js.map +1 -0
  231. package/dist/policies/liveness.d.ts +6 -8
  232. package/dist/policies/liveness.d.ts.map +1 -1
  233. package/dist/policies/liveness.js +6 -25
  234. package/dist/policies/liveness.js.map +1 -1
  235. package/dist/policies/sandbox-anchor.d.ts +91 -0
  236. package/dist/policies/sandbox-anchor.d.ts.map +1 -0
  237. package/dist/policies/sandbox-anchor.js +187 -0
  238. package/dist/policies/sandbox-anchor.js.map +1 -0
  239. package/dist/policies/sandbox-grants.d.ts +131 -0
  240. package/dist/policies/sandbox-grants.d.ts.map +1 -0
  241. package/dist/policies/sandbox-grants.js +562 -0
  242. package/dist/policies/sandbox-grants.js.map +1 -0
  243. package/dist/state/manifest.d.ts +4 -2
  244. package/dist/state/manifest.d.ts.map +1 -1
  245. package/dist/state/manifest.js +32 -16
  246. package/dist/state/manifest.js.map +1 -1
  247. package/dist/utils/checkout-root.d.ts +2 -0
  248. package/dist/utils/checkout-root.d.ts.map +1 -0
  249. package/dist/utils/checkout-root.js +43 -0
  250. package/dist/utils/checkout-root.js.map +1 -0
  251. package/dist/utils/resolve-uap-bin.d.ts +5 -0
  252. package/dist/utils/resolve-uap-bin.d.ts.map +1 -0
  253. package/dist/utils/resolve-uap-bin.js +33 -0
  254. package/dist/utils/resolve-uap-bin.js.map +1 -0
  255. package/dist/utils/terminal-safe.d.ts +12 -0
  256. package/dist/utils/terminal-safe.d.ts.map +1 -0
  257. package/dist/utils/terminal-safe.js +53 -0
  258. package/dist/utils/terminal-safe.js.map +1 -0
  259. package/docs/ATTRIBUTION.md +1 -0
  260. package/docs/DASHBOARD_UPLIFT_SPEC.md +8 -8
  261. package/docs/INDEX.md +6 -5
  262. package/docs/architecture/OVERVIEW.md +15 -3
  263. package/docs/architecture/PROTOCOL.md +7 -1
  264. package/docs/architecture/adr/0006-operator-directed-model-placement.md +86 -0
  265. package/docs/architecture/adr/0007-auto-displacement-allowlist-as-standing-consent.md +79 -0
  266. package/docs/architecture/adr/0008-fleet-clients-link-out.md +92 -0
  267. package/docs/architecture/adr/0009-completion-triggered-dispatch-and-per-leaf-model-dials.md +71 -0
  268. package/docs/architecture/adr/0010-attention-queue-and-afk-auto-decider.md +159 -0
  269. package/docs/architecture/adr/0011-sandbox-grants-and-network-egress-boundary.md +219 -0
  270. package/docs/architecture/adr/0012-operator-legibility-surfaces.md +175 -0
  271. package/docs/getting-started/INSTALLATION.md +1 -1
  272. package/docs/guides/AUTOMATIC_FEATURES.md +8 -0
  273. package/docs/guides/LOCAL_MODELS.md +1 -1
  274. package/docs/guides/PROXY.md +2 -1
  275. package/docs/guides/SANDBOX.md +91 -4
  276. package/docs/integrations/MCP_ROUTER.md +1 -1
  277. package/docs/plans/model-performance-proof-options.md +176 -0
  278. package/docs/reference/API.md +1 -1
  279. package/docs/reference/CLI.md +169 -4
  280. package/docs/reference/COMPARISON.md +1 -1
  281. package/docs/reference/CONFIGURATION.md +12 -3
  282. package/docs/reference/CONFIGURATION_REFERENCE.md +269 -14
  283. package/docs/reference/DATABASE_SCHEMA.md +1 -1
  284. package/docs/reference/FEATURES.md +15 -3
  285. package/docs/reference/PATTERNS.md +1 -1
  286. package/docs/reference/PLATFORMS.md +14 -1
  287. package/docs/specs/operator-model-placement.md +1314 -0
  288. package/docs/specs/operator-model-placement.review.md +339 -0
  289. package/package.json +2 -2
  290. package/scripts/maintenance/publish-npm.sh +23 -11
  291. package/scripts/version-bump.sh +6 -51
  292. package/src/policies/enforcers/__pycache__/_common.cpython-311.pyc +0 -0
  293. package/src/policies/enforcers/__pycache__/expert_review_required.cpython-311.pyc +0 -0
  294. package/src/policies/enforcers/__pycache__/quality_metrics_gate.cpython-311.pyc +0 -0
  295. package/src/policies/schemas/policies/mandatory-testing-deployment.md +2 -5
  296. package/templates/hooks/__pycache__/deliver_autoroute.cpython-311.pyc +0 -0
  297. package/templates/hooks/session-start.sh +44 -0
  298. package/tools/agents/UAP/cli.py +14 -3
  299. package/tools/agents/UAP/paths.py +50 -0
  300. package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-311.pyc +0 -0
  301. package/tools/agents/scripts/anthropic_proxy.py +1386 -99
  302. package/tools/agents/scripts/toolcall_path_normalizer.py +46 -1
  303. package/tools/agents/tests/test_anthropic_proxy_streaming.py +29 -6
  304. package/tools/agents/tests/test_doubling_break.py +64 -5
  305. package/tools/agents/tests/test_error_loop_break.py +10 -4
  306. package/tools/agents/tests/test_error_loop_ignores_correctives.py +13 -2
  307. package/tools/agents/tests/test_lockstep_escalation.py +280 -9
  308. package/tools/agents/tests/test_path_containment.py +94 -0
  309. package/tools/agents/tests/test_proxy_unix_socket.py +162 -0
  310. package/tools/agents/tests/test_signature_quality.py +349 -0
  311. package/tools/agents/tests/test_uap_compliance.py +11 -1
  312. package/web/dash/core.js +1 -0
  313. package/web/dash/tab-clients.js +196 -0
  314. package/web/dash/tab-models.js +387 -8
  315. package/web/dash/tab-policies.js +87 -4
  316. package/web/dash/tabs.js +77 -73
  317. package/web/dashboard.html +6 -0
  318. package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
  319. package/src/policies/enforcers/__pycache__/expert_review_required.cpython-312.pyc +0 -0
  320. package/src/policies/enforcers/__pycache__/quality_metrics_gate.cpython-312.pyc +0 -0
  321. package/templates/hooks/__pycache__/deliver_autoroute.cpython-312.pyc +0 -0
  322. package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
  323. package/web/dash/tab-agents.js +0 -21
  324. package/web/dash/tab-deliver.js +0 -12
  325. package/web/dash/tab-memory.js +0 -12
  326. package/web/dash/tab-orchestration.js +0 -21
  327. package/web/dash/tab-overview.js +0 -21
  328. package/web/dash/tab-tasks.js +0 -21
@@ -6,14 +6,103 @@
6
6
  * the KERNEL — for Write/Edit tools, Bash, and any subprocess alike.
7
7
  *
8
8
  * This is the workdir boundary that `--dangerously-skip-permissions` cannot
9
- * bypass: the client can't escape the mount namespace. Network is shared so the
10
- * agent still reaches the local proxy (127.0.0.1:4000).
9
+ * bypass: the client can't escape the mount namespace.
10
+ *
11
+ * Bridge Phase 4 adds two authorities on top of that floor:
12
+ *
13
+ * - Per-session GRANTS (`uap sandbox grant`, D2): extra writable holes
14
+ * recorded in a consent ledger (session-scoped, TTL-bounded, reason-
15
+ * stated, audit-logged). The pre-P4 answer, `UAP_SANDBOX_ALLOW=path:path`,
16
+ * still works but is UNRECORDED authority — it is honored for backwards
17
+ * compatibility and named as unrecorded in the audit and the banner.
18
+ *
19
+ * - The NETWORK EGRESS BOUNDARY (`--net off`, D1): the sandbox gets its own
20
+ * network namespace (--unshare-net) and NOTHING is brought up — no TCP,
21
+ * no DNS, no loopback, no egress of any kind, at the kernel. This is the
22
+ * complete boundary, for untrusted code, evals, and data-only work; model
23
+ * access is impossible by design (a harness that needs the model will fail
24
+ * loudly with connection refused).
25
+ *
26
+ * Why there is no "--net proxy" (netns cut with a single hole to the
27
+ * proxy): rootless Linux cannot express it. AF_UNIX pathname sockets are
28
+ * NETWORK-NAMESPACE-SCOPED — a socket bind-mounted across the netns wall
29
+ * is unreachable (empirically ECONNREFUSED, see ADR 0011), bwrap closes
30
+ * every inherited fd (so no SCM_RIGHTS broker), and the userspace network
31
+ * helpers (pasta/slirp4netns) provide no outbound port allowlist. A
32
+ * boundary that only works when the right helper is present would be a
33
+ * suggestion, not enforcement — so the shipped modes are the two REAL
34
+ * ones: shared (no claim) and off (kernel-complete). The proxy's own
35
+ * PROXY_SOCKET (0600 AF_UNIX) remains the model-path choke point for
36
+ * every non-sandboxed surface; `uap proxy connect` re-serves it on local
37
+ * TCP for clients that cannot speak AF_UNIX.
11
38
  *
12
39
  * Env:
13
40
  * UAP_SANDBOX_WORKDIR workdir to make writable (default: cwd)
14
- * UAP_SANDBOX_ALLOW extra writable paths, colon-separated
41
+ * UAP_SANDBOX_ALLOW extra writable paths, colon-separated (UNRECORDED)
42
+ * UAP_SANDBOX_NET 'off' to default the net mode (shared otherwise)
43
+ * UAP_SANDBOX_GRANTS pins the grant ledger file (tests, odd layouts)
44
+ * UAP_SANDBOX_AUDIT pins the audit JSONL file (tests, odd layouts)
45
+ * UAP_SANDBOX_GRANTS_OFF=1 resolve zero grants (escape hatch; the sandbox itself stays)
15
46
  * UAP_SANDBOX_OFF=1 bypass the sandbox entirely (run the command as-is)
16
47
  */
48
+ import { type ResolvedGrants } from '../policies/sandbox-grants.js';
49
+ export type SandboxNetMode = 'shared' | 'off';
50
+ export interface SandboxPlanInput {
51
+ /** Command to run inside the sandbox. */
52
+ command: string[];
53
+ /** Session id (scopes the grant lookup; empty = no grants). */
54
+ session?: string;
55
+ /** Net mode: 'shared' (default) or 'off' (the kernel egress boundary).
56
+ * Undefined = fall back to `envNet`. */
57
+ net?: SandboxNetMode;
58
+ /** Writable workdir. */
59
+ workdir: string;
60
+ /** $HOME inside the sandbox. */
61
+ home: string;
62
+ /** Legacy unrecorded extra writable paths (UAP_SANDBOX_ALLOW, split). */
63
+ legacyAllow: string[];
64
+ /** Session-resolved grants (empty when the ledger is off/unreadable). */
65
+ grants: ResolvedGrants;
66
+ /** $UAP_SANDBOX_NET — the env default for the net mode (planner stays
67
+ * input-only: the CALLER resolves process.env, so the plan is a pure
68
+ * function of its inputs and unit tests need no env plumbing). */
69
+ envNet?: string;
70
+ /** $ANTHROPIC_CUSTOM_HEADERS — appended to, never clobbered. */
71
+ existingCustomHeaders?: string;
72
+ /** The grant-ledger file and audit JSONL, ro-bound into the namespace so
73
+ * a sandboxed agent can neither plant rows nor forge audit lines (a
74
+ * bind-mounted file cannot be unlinked or replaced inside the ns).
75
+ * Resolved by the CALLER (they honor the env overrides). P4 security
76
+ * review: without this, the consent store lives inside the writable
77
+ * hole and consent is forgeable by the very thing it guards against. */
78
+ grantsLedgerPath?: string;
79
+ auditLogPath?: string;
80
+ }
81
+ export interface SandboxPlan {
82
+ /** Full bwrap argv (bwrap args first, then the inner command). */
83
+ argv: string[];
84
+ /** The command bwrap execs (argv tail) — the session command, verbatim. */
85
+ inner: string[];
86
+ /** Extra env delivered via --setenv. */
87
+ setenv: Record<string, string>;
88
+ /** The net mode actually engaged ('off' = kernel egress boundary). */
89
+ netMode: SandboxNetMode;
90
+ /** Granted writable holes actually opened for this run. */
91
+ grantedPaths: string[];
92
+ /** Legacy-env holes actually opened (resolved targets — what was bound). */
93
+ legacyBound: string[];
94
+ /** Legacy-env entries refused at plan time (raw spellings — over-broad
95
+ * resolutions, or resolutions covering the trust-anchor dir). */
96
+ legacyRefused: string[];
97
+ /** Human-readable lines for the launch banner (colored at the print site). */
98
+ notes: string[];
99
+ }
100
+ /** Compute the bwrap invocation. Pure: a function of its inputs only — the
101
+ * CALLER resolves process.env into `envNet`/`existingCustomHeaders`. */
102
+ export declare function planSandbox(input: SandboxPlanInput): {
103
+ plan?: SandboxPlan;
104
+ error?: string;
105
+ };
17
106
  /**
18
107
  * Build the ANTHROPIC_CUSTOM_HEADERS value for a sandboxed session: append the
19
108
  * `X-Uap-Sandbox: 1` marker (which the proxy uses to strip sandbox-unreachable
@@ -22,5 +111,13 @@
22
111
  * (newline-separated "Name: Value" pairs).
23
112
  */
24
113
  export declare function sandboxCustomHeaders(existing: string | undefined): string;
25
- export declare function sandboxCommand(command: string[]): Promise<void>;
114
+ /**
115
+ * Should `command[0]` be dispatched as a ledger verb? Only when the
116
+ * invocation did NOT use the `--` separator: `uap sandbox -- revoke …` means
117
+ * the operator wants to run a BINARY named `revoke`, and a positional
118
+ * intercept that cannot be escaped would shadow legitimate commands (P4
119
+ * review finding). Exposed for the CLI-surface tests.
120
+ */
121
+ export declare function shouldDispatchGrantVerb(command: string[], argv?: string[]): boolean;
122
+ export declare function sandboxCommand(command: string[], options?: Record<string, unknown>): Promise<void>;
26
123
  //# sourceMappingURL=sandbox.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../src/cli/sandbox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAOH;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CASzE;AAYD,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuErE"}
1
+ {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../src/cli/sandbox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAOH,OAAO,EAUL,KAAK,cAAc,EACpB,MAAM,+BAA+B,CAAC;AAkBvC,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,KAAK,CAAC;AAE9C,MAAM,WAAW,gBAAgB;IAC/B,yCAAyC;IACzC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;6CACyC;IACzC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,wBAAwB;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,yEAAyE;IACzE,MAAM,EAAE,cAAc,CAAC;IACvB;;uEAEmE;IACnE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;;6EAKyE;IACzE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,kEAAkE;IAClE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,2EAA2E;IAC3E,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,sEAAsE;IACtE,OAAO,EAAE,cAAc,CAAC;IACxB,2DAA2D;IAC3D,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,4EAA4E;IAC5E,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB;sEACkE;IAClE,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,8EAA8E;IAC9E,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAMD;yEACyE;AACzE,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG;IAAE,IAAI,CAAC,EAAE,WAAW,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAwK3F;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CASzE;AAQD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,GAAE,MAAM,EAAiB,GAAG,OAAO,CAGjG;AAoGD,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6G5G"}
@@ -6,18 +6,236 @@
6
6
  * the KERNEL — for Write/Edit tools, Bash, and any subprocess alike.
7
7
  *
8
8
  * This is the workdir boundary that `--dangerously-skip-permissions` cannot
9
- * bypass: the client can't escape the mount namespace. Network is shared so the
10
- * agent still reaches the local proxy (127.0.0.1:4000).
9
+ * bypass: the client can't escape the mount namespace.
10
+ *
11
+ * Bridge Phase 4 adds two authorities on top of that floor:
12
+ *
13
+ * - Per-session GRANTS (`uap sandbox grant`, D2): extra writable holes
14
+ * recorded in a consent ledger (session-scoped, TTL-bounded, reason-
15
+ * stated, audit-logged). The pre-P4 answer, `UAP_SANDBOX_ALLOW=path:path`,
16
+ * still works but is UNRECORDED authority — it is honored for backwards
17
+ * compatibility and named as unrecorded in the audit and the banner.
18
+ *
19
+ * - The NETWORK EGRESS BOUNDARY (`--net off`, D1): the sandbox gets its own
20
+ * network namespace (--unshare-net) and NOTHING is brought up — no TCP,
21
+ * no DNS, no loopback, no egress of any kind, at the kernel. This is the
22
+ * complete boundary, for untrusted code, evals, and data-only work; model
23
+ * access is impossible by design (a harness that needs the model will fail
24
+ * loudly with connection refused).
25
+ *
26
+ * Why there is no "--net proxy" (netns cut with a single hole to the
27
+ * proxy): rootless Linux cannot express it. AF_UNIX pathname sockets are
28
+ * NETWORK-NAMESPACE-SCOPED — a socket bind-mounted across the netns wall
29
+ * is unreachable (empirically ECONNREFUSED, see ADR 0011), bwrap closes
30
+ * every inherited fd (so no SCM_RIGHTS broker), and the userspace network
31
+ * helpers (pasta/slirp4netns) provide no outbound port allowlist. A
32
+ * boundary that only works when the right helper is present would be a
33
+ * suggestion, not enforcement — so the shipped modes are the two REAL
34
+ * ones: shared (no claim) and off (kernel-complete). The proxy's own
35
+ * PROXY_SOCKET (0600 AF_UNIX) remains the model-path choke point for
36
+ * every non-sandboxed surface; `uap proxy connect` re-serves it on local
37
+ * TCP for clients that cannot speak AF_UNIX.
11
38
  *
12
39
  * Env:
13
40
  * UAP_SANDBOX_WORKDIR workdir to make writable (default: cwd)
14
- * UAP_SANDBOX_ALLOW extra writable paths, colon-separated
41
+ * UAP_SANDBOX_ALLOW extra writable paths, colon-separated (UNRECORDED)
42
+ * UAP_SANDBOX_NET 'off' to default the net mode (shared otherwise)
43
+ * UAP_SANDBOX_GRANTS pins the grant ledger file (tests, odd layouts)
44
+ * UAP_SANDBOX_AUDIT pins the audit JSONL file (tests, odd layouts)
45
+ * UAP_SANDBOX_GRANTS_OFF=1 resolve zero grants (escape hatch; the sandbox itself stays)
15
46
  * UAP_SANDBOX_OFF=1 bypass the sandbox entirely (run the command as-is)
16
47
  */
17
48
  import { spawnSync } from 'child_process';
18
49
  import { existsSync, realpathSync } from 'fs';
19
50
  import { homedir } from 'os';
20
51
  import { join } from 'path';
52
+ import chalk from 'chalk';
53
+ import { grantAuthority, listAuthority, resolveSessionGrants, revokeAuthority, auditSandboxUse, sandboxGrantsPath, sandboxAuditPath, verifyLedgerIntegrity, } from '../policies/sandbox-grants.js';
54
+ import { pathCoversAnchorDir } from '../policies/sandbox-anchor.js';
55
+ import { termSafe } from '../utils/terminal-safe.js';
56
+ function fail(msg, code = 2) {
57
+ console.error(`uap sandbox: ${msg}`);
58
+ process.exit(code);
59
+ }
60
+ function hasBwrap() {
61
+ const r = spawnSync('bwrap', ['--version'], { stdio: 'ignore' });
62
+ return !r.error && r.status === 0;
63
+ }
64
+ function planError(msg) {
65
+ return { error: msg };
66
+ }
67
+ /** Compute the bwrap invocation. Pure: a function of its inputs only — the
68
+ * CALLER resolves process.env into `envNet`/`existingCustomHeaders`. */
69
+ export function planSandbox(input) {
70
+ const workdir = input.workdir;
71
+ // Guard: never sandbox with an over-broad workdir — it would expose the tree.
72
+ if (workdir === input.home || workdir === '/' || workdir === '/home') {
73
+ return planError(`refusing to sandbox with workdir='${workdir}' (too broad)`);
74
+ }
75
+ const netMode = input.net === 'off' || input.net === 'shared'
76
+ ? input.net
77
+ : input.envNet === 'off'
78
+ ? 'off'
79
+ : 'shared';
80
+ // Read-only root with writable "holes".
81
+ const args = [
82
+ '--ro-bind', '/', '/',
83
+ '--dev', '/dev',
84
+ '--proc', '/proc',
85
+ '--tmpfs', '/run',
86
+ '--die-with-parent',
87
+ '--new-session',
88
+ '--unshare-pid',
89
+ ];
90
+ if (netMode === 'off') {
91
+ // The egress boundary: a network namespace with NOTHING brought up —
92
+ // not even loopback. Any connect() fails at the kernel.
93
+ args.push('--unshare-net');
94
+ }
95
+ // writable holes:
96
+ args.push('--bind', workdir, workdir, '--bind', '/tmp', '/tmp', '--tmpfs', '/var/tmp');
97
+ for (const rel of ['.claude', '.cache', '.npm']) {
98
+ const p = join(input.home, rel);
99
+ if (existsSync(p))
100
+ args.push('--bind', p, p);
101
+ }
102
+ const grantedPaths = [];
103
+ // Seeded with the holes the floor already binds, so a legacy entry matching
104
+ // one skips its (harmless, bwrap-tolerated) duplicate bind. The grants loop
105
+ // above only WRITES the set (a grant of /tmp or the workdir legitimately
106
+ // re-binds them — bwrap tolerates the duplicate mount); only the legacy
107
+ // loop reads it.
108
+ const boundPaths = new Set([workdir, '/tmp']);
109
+ // The breadth trio is checked against the RESOLVED value, and $HOME can
110
+ // itself be a symlink (/home/u -> /disk/users/u): compare against BOTH the
111
+ // caller's spelling and its resolution, or an entry pointing at the real
112
+ // home through the symlink would bind the whole home (security review).
113
+ const homeResolved = (() => {
114
+ try {
115
+ return realpathSync(input.home);
116
+ }
117
+ catch {
118
+ return input.home;
119
+ }
120
+ })();
121
+ const tooBroad = (p) => p === '/' || p === '/home' || p === input.home || p === homeResolved;
122
+ for (const p of input.grants.paths) {
123
+ // TOCTOU (security review): the row's path was realpath-validated at
124
+ // LOAD; a concurrent writer could swap it for a symlink in the
125
+ // load→exec window. Resolve AGAIN at plan time, re-check breadth on the
126
+ // RESOLVED value, and bind what the resolution says — not the row's
127
+ // word for it. (A microsecond window remains between this resolution
128
+ // and bwrap's own; documented as residual in ADR 0011.)
129
+ let resolved;
130
+ try {
131
+ resolved = realpathSync(p);
132
+ }
133
+ catch {
134
+ continue; // vanished between load and plan — open nothing
135
+ }
136
+ if (tooBroad(resolved))
137
+ continue;
138
+ // The anchor dir is "the one hole that must never open" (grant minting
139
+ // refuses it outright); plan time re-checks because a grant minted under
140
+ // a different anchor-dir pin could otherwise open it after a re-pin.
141
+ if (pathCoversAnchorDir(resolved))
142
+ continue;
143
+ grantedPaths.push(resolved);
144
+ boundPaths.add(resolved);
145
+ args.push('--bind', resolved, resolved);
146
+ }
147
+ const refusedLegacy = [];
148
+ const legacyBound = [];
149
+ for (const p of input.legacyAllow) {
150
+ // The legacy env is UNRECORDED authority — that is the whole complaint
151
+ // — so it gets the SAME plan-time re-check recorded grants get:
152
+ // resolve at plan time, refuse over-broad resolutions, bind what the
153
+ // resolution says. An env var in a shell history is not consent, and
154
+ // unrecorded must not mean unchecked.
155
+ if (!p)
156
+ continue;
157
+ let resolved;
158
+ try {
159
+ resolved = realpathSync(p);
160
+ }
161
+ catch {
162
+ continue; // nonexistent entries stay inert, as before
163
+ }
164
+ if (tooBroad(resolved) || pathCoversAnchorDir(resolved)) {
165
+ // Raw env values are foreign strings reaching an operator terminal
166
+ // exactly when attention is on them — termSafe before interpolating.
167
+ refusedLegacy.push(`${termSafe(p)} → ${termSafe(resolved)}`);
168
+ continue;
169
+ }
170
+ if (boundPaths.has(resolved))
171
+ continue; // already a writable hole; no dup binds
172
+ boundPaths.add(resolved);
173
+ legacyBound.push(resolved);
174
+ args.push('--bind', resolved, resolved);
175
+ }
176
+ // The consent store must be TAMPER-PROOF from the untrusted side: ro-bind
177
+ // the ledger and audit files over their host paths so a sandboxed agent
178
+ // can neither plant grant rows nor forge audit lines (security review
179
+ // — a planted well-formed `paths:["/etc"]` row opened the hole for real).
180
+ // A bind-mounted file cannot be unlinked or replaced inside the namespace;
181
+ // a MISSING file gets /dev/null bound at its path so planting one is
182
+ // equally impossible (it reads empty and refuses writes).
183
+ for (const target of [input.grantsLedgerPath, input.auditLogPath]) {
184
+ if (!target)
185
+ continue;
186
+ args.push('--ro-bind', existsSync(target) ? target : '/dev/null', target);
187
+ }
188
+ const setenv = {
189
+ HOME: input.home,
190
+ UAP_SANDBOX_ACTIVE: '1',
191
+ };
192
+ if (input.session)
193
+ setenv.UAP_SESSION_ID = input.session;
194
+ const notes = [];
195
+ if (netMode === 'off') {
196
+ notes.push('net: OFF (kernel egress boundary — no network at all, not even loopback; model access impossible by design)');
197
+ }
198
+ else {
199
+ notes.push('net: shared (the sandbox has normal network)');
200
+ }
201
+ if (grantedPaths.length > 0)
202
+ notes.push(`granted holes: ${grantedPaths.join(', ')}`);
203
+ if (input.grants.paths.length > 0 && grantedPaths.length !== input.grants.paths.length) {
204
+ notes.push('(some granted paths were not opened: no longer present, or their plan-time resolution is over-broad)');
205
+ }
206
+ if (refusedLegacy.length > 0) {
207
+ notes.push(`refused UAP_SANDBOX_ALLOW entries: ${refusedLegacy.join(', ')} — /, /home, $HOME, and the trust-anchor dir are never writable holes`);
208
+ }
209
+ if (input.legacyAllow.filter(Boolean).length > 0) {
210
+ // The raw env spelling is the operator's own consent surface — show it
211
+ // verbatim (termSafe'd: env values are foreign strings too).
212
+ notes.push(`UNRECORDED allow (legacy env, consider 'uap sandbox grant'): ${input.legacyAllow.map((p) => termSafe(p)).join(':')}`);
213
+ }
214
+ const argv = [...args];
215
+ for (const [k, v] of Object.entries(setenv)) {
216
+ argv.push('--setenv', k, v);
217
+ }
218
+ // Tell the proxy this session is sandboxed so it can strip MCP tools the
219
+ // bubblewrap sandbox can't reach (the claude-in-chrome browser extension
220
+ // socket is unreachable here — offering browser_batch guarantees dead-end
221
+ // loops). Claude Code forwards ANTHROPIC_CUSTOM_HEADERS verbatim to its
222
+ // endpoint; append rather than clobber any pre-existing value.
223
+ const customHeaders = sandboxCustomHeaders(input.existingCustomHeaders);
224
+ argv.push('--setenv', 'ANTHROPIC_CUSTOM_HEADERS', customHeaders);
225
+ argv.push('--chdir', workdir, ...input.command);
226
+ return {
227
+ plan: {
228
+ argv,
229
+ inner: input.command,
230
+ setenv: { ...setenv, ANTHROPIC_CUSTOM_HEADERS: customHeaders },
231
+ netMode,
232
+ grantedPaths,
233
+ legacyBound,
234
+ legacyRefused: refusedLegacy,
235
+ notes,
236
+ },
237
+ };
238
+ }
21
239
  /**
22
240
  * Build the ANTHROPIC_CUSTOM_HEADERS value for a sandboxed session: append the
23
241
  * `X-Uap-Sandbox: 1` marker (which the proxy uses to strip sandbox-unreachable
@@ -36,16 +254,119 @@ export function sandboxCustomHeaders(existing) {
36
254
  .some((h) => h.trim().toLowerCase() === marker.toLowerCase());
37
255
  return already ? prior : `${prior}\n${marker}`;
38
256
  }
39
- function fail(msg, code = 2) {
40
- console.error(`uap sandbox: ${msg}`);
41
- process.exit(code);
257
+ // ---------------------------------------------------------------------------
258
+ // Grant verbs (D2).
259
+ // ---------------------------------------------------------------------------
260
+ const GRANT_VERBS = new Set(['grant', 'grants', 'revoke']);
261
+ /**
262
+ * Should `command[0]` be dispatched as a ledger verb? Only when the
263
+ * invocation did NOT use the `--` separator: `uap sandbox -- revoke …` means
264
+ * the operator wants to run a BINARY named `revoke`, and a positional
265
+ * intercept that cannot be escaped would shadow legitimate commands (P4
266
+ * review finding). Exposed for the CLI-surface tests.
267
+ */
268
+ export function shouldDispatchGrantVerb(command, argv = process.argv) {
269
+ if (!command.length || !GRANT_VERBS.has(command[0]))
270
+ return false;
271
+ return !argv.slice(2).includes('--');
42
272
  }
43
- function hasBwrap() {
44
- const r = spawnSync('bwrap', ['--version'], { stdio: 'ignore' });
45
- return !r.error && r.status === 0;
273
+ function grantsDisabled() {
274
+ const v = process.env.UAP_SANDBOX_GRANTS_OFF;
275
+ return v === '1' || v === 'true' || v === 'yes';
46
276
  }
47
- export async function sandboxCommand(command) {
48
- // Strip a leading '--' separator if commander passed it through.
277
+ function resolveSessionGrantsSafe(projectRoot, session) {
278
+ const none = { grants: [], paths: [] };
279
+ if (!session || grantsDisabled())
280
+ return none;
281
+ try {
282
+ return resolveSessionGrants(projectRoot, session);
283
+ }
284
+ catch (err) {
285
+ console.warn(`[sandbox] grant resolution failed (continuing with NO granted holes): ${err instanceof Error ? err.message : String(err)}`);
286
+ return none;
287
+ }
288
+ }
289
+ async function grantVerb(args, options) {
290
+ const verb = args[0];
291
+ const projectRoot = process.cwd();
292
+ if ((verb === 'grant' || verb === 'revoke') && process.env.UAP_SANDBOX_ACTIVE === '1') {
293
+ // Consent cannot come from the thing being guarded (P4 security
294
+ // review): UAP_SANDBOX_ACTIVE is set by the sandbox itself, on the
295
+ // UNTRUSTED side, so a shell inside a sandbox must not be able to
296
+ // write new authority or remove the operator's. Listing stays
297
+ // available (read-only — the agent can see what it was granted).
298
+ fail('refusing to grant/revoke from inside a sandbox — consent must come from the operator (run it outside the sandbox)');
299
+ }
300
+ if (verb === 'grant') {
301
+ const paths = args.slice(1);
302
+ const input = {
303
+ sessionId: String(options.session || process.env.UAP_SESSION_ID || process.env.CLAUDE_SESSION_ID || ''),
304
+ paths,
305
+ reason: String(options.reason || ''),
306
+ ttlSecs: options.ttl === undefined ? undefined : Number(options.ttl),
307
+ };
308
+ const r = grantAuthority(projectRoot, input);
309
+ if (!r.ok)
310
+ fail(r.error);
311
+ console.log(chalk.green(`✓ grant ${r.grant.id}`) +
312
+ ` — session '${r.grant.sessionId}' may write:\n ${r.grant.paths.join('\n ')}` +
313
+ chalk.dim(`\n reason: ${r.grant.reason}\n expires: ${r.grant.expiresAt} (granted by ${r.grant.grantedBy})`));
314
+ return;
315
+ }
316
+ if (verb === 'grants') {
317
+ const sid = String(options.session || '');
318
+ // Tamper evidence (ADR 0011 anchor): the listing is the inspection
319
+ // surface, so the integrity verdict is stated here — on the human path
320
+ // as a red banner, on --json via stderr so the data stays pure.
321
+ const integrity = verifyLedgerIntegrity(projectRoot);
322
+ if (integrity.state === 'mismatch') {
323
+ const msg = `ledger INTEGRITY MISMATCH — ${integrity.detail}. Treat every listed row as unverified.`;
324
+ if (options.json)
325
+ console.error(`[sandbox] ${msg}`);
326
+ else
327
+ console.log(chalk.red(`⚠ ${msg}`));
328
+ }
329
+ else if (integrity.state === 'unanchored' && !options.json) {
330
+ console.log(chalk.dim(`ℹ ${integrity.detail}`));
331
+ }
332
+ const all = listAuthority(projectRoot, sid || undefined);
333
+ if (options.json) {
334
+ console.log(JSON.stringify(all, null, 2));
335
+ return;
336
+ }
337
+ if (all.length === 0) {
338
+ console.log(sid ? `No active grants for session '${sid}'.` : 'No active grants.');
339
+ return;
340
+ }
341
+ for (const g of all) {
342
+ console.log(`${chalk.green(g.id)} session '${g.sessionId}' expires ${g.expiresAt}` +
343
+ `\n ${g.paths.join('\n ')}` +
344
+ chalk.dim(`\n reason: ${g.reason} (granted by ${g.grantedBy})`));
345
+ }
346
+ return;
347
+ }
348
+ if (verb === 'revoke') {
349
+ const id = args[1];
350
+ if (!id)
351
+ fail('usage: uap sandbox revoke <grantId>');
352
+ if (!revokeAuthority(projectRoot, id)) {
353
+ // Not found, or the ledger refused to persist the removal — either way
354
+ // the grant may still be ACTIVE, so the refusal must not sound like
355
+ // "nothing to do" (the persist failure already warned above).
356
+ fail(`could not revoke '${id}' — it is not in the ledger, or the ledger failed to persist the removal`);
357
+ }
358
+ console.log(chalk.green(`✓ revoked ${id}`));
359
+ return;
360
+ }
361
+ fail(`unknown sandbox grant verb '${verb}' (grant | grants | revoke)`);
362
+ }
363
+ // ---------------------------------------------------------------------------
364
+ // Command entry.
365
+ // ---------------------------------------------------------------------------
366
+ export async function sandboxCommand(command, options = {}) {
367
+ // Belt-and-braces: commander v12 strips the `--` separator itself (the
368
+ // marker never reaches command[]), but older parsers and hand-built
369
+ // invocations (tests) may pass it through — strip if it survived.
49
370
  if (command[0] === '--')
50
371
  command = command.slice(1);
51
372
  if (process.env.UAP_SANDBOX_OFF === '1') {
@@ -54,8 +375,15 @@ export async function sandboxCommand(command) {
54
375
  const r = spawnSync(command[0], command.slice(1), { stdio: 'inherit' });
55
376
  process.exit(r.status ?? (r.error ? 127 : 0));
56
377
  }
378
+ // Grant verbs are ledger operations, not sandbox runs — but only when the
379
+ // invocation did NOT use the `--` separator (see shouldDispatchGrantVerb).
380
+ if (shouldDispatchGrantVerb(command)) {
381
+ await grantVerb(command, options);
382
+ return;
383
+ }
57
384
  if (command.length === 0) {
58
- fail('no command given. Usage: uap sandbox -- <command> [args...]');
385
+ fail('no command given. Usage: uap sandbox [--session <id>] [--net shared|off] -- <command> [args...]; ' +
386
+ `authority: uap sandbox grant <path...> --session <id> --reason "..." | grants | revoke <id>`);
59
387
  }
60
388
  if (!hasBwrap()) {
61
389
  fail('bwrap (bubblewrap) not found — refusing to run unsandboxed. ' +
@@ -69,41 +397,62 @@ export async function sandboxCommand(command) {
69
397
  catch {
70
398
  workdir = process.env.UAP_SANDBOX_WORKDIR || process.cwd();
71
399
  }
72
- // Guard: never sandbox with an over-broad workdir — it would expose the tree.
73
- if (workdir === home || workdir === '/' || workdir === '/home') {
74
- fail(`refusing to sandbox with workdir='${workdir}' (too broad)`);
400
+ const session = String(options.session || process.env.UAP_SESSION_ID || process.env.CLAUDE_SESSION_ID || '');
401
+ const rawNet = options.net;
402
+ if (rawNet !== undefined && rawNet !== 'off' && rawNet !== 'shared') {
403
+ // Loud, not silent: an unknown --net value (e.g. the documented-then-cut
404
+ // 'proxy') silently downgrading to full network would be the exact hole
405
+ // the boundary exists to close.
406
+ fail(`unknown --net mode '${String(rawNet)}' (shared | off)`);
75
407
  }
76
- // Read-only root with writable "holes".
77
- const args = [
78
- '--ro-bind', '/', '/',
79
- '--dev', '/dev',
80
- '--proc', '/proc',
81
- '--tmpfs', '/run',
82
- '--die-with-parent',
83
- '--unshare-pid',
84
- '--new-session',
85
- // writable holes:
86
- '--bind', workdir, workdir,
87
- '--bind', '/tmp', '/tmp',
88
- '--tmpfs', '/var/tmp',
89
- ];
90
- for (const rel of ['.claude', '.cache', '.npm']) {
91
- const p = join(home, rel);
92
- if (existsSync(p))
93
- args.push('--bind', p, p);
408
+ const netOpt = rawNet === 'off' ? 'off' : rawNet === 'shared' ? 'shared' : undefined;
409
+ // The env default is validated exactly like the flag (security review):
410
+ // 'OFF', 'off ', '0ff' silently meaning FULL network is the exact hole
411
+ // the boundary exists to close. Whitespace is trimmed (shell quirks),
412
+ // anything else fails loud.
413
+ const envNet = process.env.UAP_SANDBOX_NET?.trim();
414
+ if (envNet && envNet !== 'shared' && envNet !== 'off') {
415
+ fail(`unknown UAP_SANDBOX_NET value '${envNet}' (shared | off)`);
94
416
  }
95
- for (const p of (process.env.UAP_SANDBOX_ALLOW || '').split(':')) {
96
- if (p && existsSync(p))
97
- args.push('--bind', p, p);
417
+ const legacyAllow = (process.env.UAP_SANDBOX_ALLOW || '').split(':');
418
+ const grants = resolveSessionGrantsSafe(process.cwd(), session);
419
+ const planned = planSandbox({
420
+ command,
421
+ session: session || undefined,
422
+ net: netOpt,
423
+ workdir,
424
+ home,
425
+ legacyAllow,
426
+ grants,
427
+ envNet,
428
+ existingCustomHeaders: process.env.ANTHROPIC_CUSTOM_HEADERS,
429
+ // Ro-bound into the namespace by the planner: the consent store must be
430
+ // untouchable from the sandboxed side (security review finding 1).
431
+ grantsLedgerPath: sandboxGrantsPath(process.cwd()),
432
+ auditLogPath: sandboxAuditPath(process.cwd()),
433
+ });
434
+ if (planned.error)
435
+ fail(planned.error);
436
+ const plan = planned.plan;
437
+ // The consent record: who granted, what was actually OPENED (not merely
438
+ // resolved — a granted path that no longer exists opens nothing and must
439
+ // not be recorded as authority exercised), what ran unrecorded, and the
440
+ // net boundary actually engaged.
441
+ const openedGrants = grants.grants.filter((g) => g.paths.some((p) => plan.grantedPaths.includes(p)));
442
+ // The legacy-env record must state what ACTUALLY opened vs what was
443
+ // refused at plan time — recording a refused entry under the run's allow
444
+ // would attribute authority the run never had (the banner and the
445
+ // durable record must agree).
446
+ auditSandboxUse(process.cwd(), session, { grants: openedGrants, paths: plan.grantedPaths }, plan.legacyBound, plan.legacyRefused, plan.netMode);
447
+ console.error(chalk.dim(`uap sandbox: workdir ${workdir} (writable); everything else is EROFS`));
448
+ for (const n of plan.notes)
449
+ console.error(chalk.dim(` ${n}`));
450
+ if (grantsDisabled())
451
+ console.error(chalk.dim(' grants: ledger off (UAP_SANDBOX_GRANTS_OFF=1)'));
452
+ if (!session) {
453
+ console.error(chalk.dim(' grants: none (no --session; grant one with: uap sandbox grant <path> --session <id> --reason "...")'));
98
454
  }
99
- // Tell the proxy this session is sandboxed so it can strip MCP tools the
100
- // bubblewrap sandbox can't reach (the claude-in-chrome browser extension
101
- // socket is unreachable here — offering browser_batch guarantees dead-end
102
- // loops). Claude Code forwards ANTHROPIC_CUSTOM_HEADERS verbatim to its
103
- // endpoint; append rather than clobber any pre-existing value.
104
- const customHeaders = sandboxCustomHeaders(process.env.ANTHROPIC_CUSTOM_HEADERS);
105
- args.push('--setenv', 'HOME', home, '--setenv', 'UAP_SANDBOX_ACTIVE', '1', '--setenv', 'ANTHROPIC_CUSTOM_HEADERS', customHeaders, '--chdir', workdir);
106
- const r = spawnSync('bwrap', [...args, ...command], { stdio: 'inherit' });
455
+ const r = spawnSync('bwrap', plan.argv, { stdio: 'inherit' });
107
456
  if (r.error)
108
457
  fail(`failed to launch bwrap: ${r.error.message}`, 127);
109
458
  process.exit(r.status ?? 1);
@@ -1 +1 @@
1
- {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/cli/sandbox.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/cli/sandbox.ts"],"names":[],"mappings":"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"}