chainlesschain 0.162.182 → 0.162.184

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 (202) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/.build-hash +1 -1
  3. package/src/assets/web-panel/assets/{AIOps-DzZ5_xoj.js → AIOps-DzAl5fGx.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-DeLXddIg.js → ActionButton-DAHtMGeC.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-rvDCmet1.js → Analytics-BHQaexv5.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-Yt6QVDnp.js → AppLayout-Phz_pD0n.js} +5 -5
  7. package/src/assets/web-panel/assets/{Artifacts-BS112K5L.js → Artifacts-DHt47kCA.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-0wJuQrNu.js → Audit--Y_8FULl.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-B90PMgbn.js → BackgroundAgents-N1zchH7D.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-TkgMglQQ.js → Backup-B_BoyN30.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-CQVS9p1l.js → BaseInput-Gl4uQHcT.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-YTjQHoC7.js → Chat-Cg-eIyAZ.js} +5 -5
  13. package/src/assets/web-panel/assets/ChatBubbleRenderer-BzeUi3JH.js +1 -0
  14. package/src/assets/web-panel/assets/{Checkbox-5bwaOabq.js → Checkbox-D0MGR2wA.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-BFmNQ_Xe.js → Codegen-BdObJEFn.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-BT_u4Dzp.js → Col--ghxXT3z.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-CJP52u5b.js → Community-BUFeXOqz.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-BpzhJE9i.js → Compact-DhQO2_Mr.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-Cg7rfslp.js → Compliance-3HoTqKYd.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-JisxL6Yy.js → Cowork-B3zmO4VW.js} +3 -3
  21. package/src/assets/web-panel/assets/{Cron-Bu7Ug_MC.js → Cron-CJDrZOcc.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-CvuqoLdj.js → Crosschain-SMl15obd.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-C2u9G8Pu.js → DID-CgTrTWrl.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-BFt5Yv3d.js → Dashboard-dXFKaKol.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-DIaT9Wxq.js → Dropdown-qQHEhCvI.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-D_A601Y4.js → EmailListRenderer-C_ej0MWH.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard--IyQ8I8w.js → FamilyGuardDashboard-D6ajoE7I.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-BihWHxuY.js → Federation-Cio2y49h.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-BB8dOXc_.js → FormItemContext-ClJz1cYp.js} +1 -1
  30. package/src/assets/web-panel/assets/{GenericCardRenderer-DQYhj1HH.js → GenericCardRenderer-Dr_8Maca.js} +1 -1
  31. package/src/assets/web-panel/assets/{Git-B-2QZxGf.js → Git-CevLwp5u.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-CusSb-nG.js → Governance-CW9YyQUY.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-BAjmvPPL.js → Inference-CQqeAyER.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-DoNYWKYq.js → KnowledgeGraph-cuGVxHrw.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-B8fKWD-n.js → Logs-DIuHri5d.js} +2 -2
  36. package/src/assets/web-panel/assets/{MarkdownRenderer-BlJm1J7E.js → MarkdownRenderer-R91Qw5JA.js} +1 -1
  37. package/src/assets/web-panel/assets/{Marketplace-CyOscbSL.js → Marketplace-CY1VhFGx.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-Ex6Om5da.js → McpTools-BBAbi1vt.js} +5 -5
  39. package/src/assets/web-panel/assets/{Memory-CDcD8l8r.js → Memory-BWYGHxJA.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-xfBqoFDg.js → MobileBridge-CPIFkW7A.js} +1 -1
  41. package/src/assets/web-panel/assets/{MobileProjects-BwObMMA2.js → MobileProjects-DQyWxCho.js} +1 -1
  42. package/src/assets/web-panel/assets/{Mtc-CIWd36OV.js → Mtc-Bo3GnQbx.js} +4 -4
  43. package/src/assets/web-panel/assets/{MtcAudit-CPX0ouuA.js → MtcAudit-C8-c4rSW.js} +4 -4
  44. package/src/assets/web-panel/assets/{Multisig-BDJsIUuW.js → Multisig-ChqMTtoq.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-DEkbuD3N.js → NLProgramming-C48TyhvI.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-DJpHRhH1.js → Notes-zogUFWxp.js} +3 -3
  47. package/src/assets/web-panel/assets/{NotificationSettings-C1UZ-Qd5.js → NotificationSettings-v-K9XpSB.js} +1 -1
  48. package/src/assets/web-panel/assets/OrderTableRenderer-P94JGGNz.js +1 -0
  49. package/src/assets/web-panel/assets/{Organization-Bbhj0fac.js → Organization-Boi1dQfR.js} +4 -4
  50. package/src/assets/web-panel/assets/{Overflow-1H04x3kx.js → Overflow-DM5YWwgA.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-CDpPe3et.js → P2P-C57LKpKK.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-MUX0Bpvw.js → PdhVaultBrowser-BFkPqu6Q.js} +3 -3
  53. package/src/assets/web-panel/assets/{Permissions-A07-0Ci1.js → Permissions-D6fB9YSp.js} +4 -4
  54. package/src/assets/web-panel/assets/{PersonalDataHub-DhhDWxAZ.js → PersonalDataHub-Bp7EefEo.js} +5 -5
  55. package/src/assets/web-panel/assets/{Pipeline-CyfbJfe-.js → Pipeline-BVln3hZf.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-CNFps3ED.js → Privacy-Bf8P3nF6.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit--T-u3Dr5.js → ProjectInit-DM6wA2E2.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-DJmrK2fC.js → ProjectSettings-CGbc5Iho.js} +2 -2
  59. package/src/assets/web-panel/assets/Projects-D0p9EOxm.js +1 -0
  60. package/src/assets/web-panel/assets/{Providers-DLzzbOZd.js → Providers-B2kJcxS6.js} +1 -1
  61. package/src/assets/web-panel/assets/{QrScannerModal-CexOomKS.js → QrScannerModal-Cxu7dXYy.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-QklGi19_.js → QuickAsk-DTlrTPms.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend-Bb9kwSw8.js → Recommend-Cm3X-cCj.js} +1 -1
  64. package/src/assets/web-panel/assets/{RemoteSession-DZuVNNN5.js → RemoteSession-DNb2kjvt.js} +2 -2
  65. package/src/assets/web-panel/assets/{Reputation-Dr5cLP0N.js → Reputation-CZUFFjc1.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-oCQHYv5t.js → Row-DAPgloxA.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-IFDEykIR.js → RssFeed-dsx9S793.js} +2 -2
  68. package/src/assets/web-panel/assets/{Search-CspVIxDc.js → Search-DnnC8kz-.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-Bm66o_DH.js → Security-VuZknRMK.js} +4 -4
  70. package/src/assets/web-panel/assets/{Services-DvanNqXl.js → Services-B3XNX8Vx.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-CHjEe9_O.js → Skeleton-Dl1nVtCj.js} +1 -1
  72. package/src/assets/web-panel/assets/Skills-CY09CZ_W.js +1 -0
  73. package/src/assets/web-panel/assets/{Sla-DxZm1491.js → Sla-HzU56n1z.js} +1 -1
  74. package/src/assets/web-panel/assets/{SpeechSettings-DWxEEclC.js → SpeechSettings-CRle7Jl2.js} +1 -1
  75. package/src/assets/web-panel/assets/{SyncSettings-FIvOFw5p.js → SyncSettings-DWadz7Sl.js} +2 -2
  76. package/src/assets/web-panel/assets/Tasks-CNVTDGg8.js +1 -0
  77. package/src/assets/web-panel/assets/{Templates-CaNjzV_t.js → Templates-BBAgvrlM.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-DjlP6TmH.js → Tenant-BsbbvGN8.js} +1 -1
  79. package/src/assets/web-panel/assets/Terminal-uscpZI4q.js +3 -0
  80. package/src/assets/web-panel/assets/{TimelineRenderer-DoZ8y7y8.js → TimelineRenderer-mTyjNE6r.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-390cg2TC.js → Tokens-Bz97oBgs.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-CLrtCj5_.js → Trigger-BTRKC140.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-DpESfSPn.js → Trust-B4A_KuyX.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-CN6279O0.js → UkeySign-DES9TmLU.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-DPtAUlSe.js → VideoEditing-ClXs7Qxp.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-nKOMV_1n.js → Wallet-IzZqFz-7.js} +4 -4
  87. package/src/assets/web-panel/assets/{WebAuthn-HuXlSOc4.js → WebAuthn-BtOP04g_.js} +5 -5
  88. package/src/assets/web-panel/assets/{WorkflowEditor-CUfFjARi.js → WorkflowEditor-_0cqnopY.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-6Eq0PcZJ.js → chat-ax7193uU.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-BP_Sf6Iy.js → colors-Bu4WGJah.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-BufMKIh5.js → compact-item-BX1dlTW0.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-BBMXxWSW.js → createContext-CktA_Dj7.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-x877iKKS.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-fUK_tRO2.js → hasIn-D5wd817l.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-t8N1tSeX.js → index-5PYYkr8S.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-DLpIs_P_.js → index-A4uBPQCz.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-DVsqvI4M.js → index-BAtBNfkr.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-Bkg4ZePE.js → index-BLLsUNDc.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-cpEli44X.js → index-BQtoRyTO.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-wKTLbKyc.js → index-BRfXoRuh.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-B7Etk0Te.js → index-Bad2CYeH.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-CwSf5pnf.js → index-BcGdL3sG.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-3FuwBewR.js → index-C3HmzCLt.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-BHy6yNiF.js → index-C8DkWyNr.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-CgiECHu2.js → index-C8tLR2TG.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-C44atv4k.js → index-CP8ELJBc.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-CW_G-MXw.js → index-CUForzsG.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-pum7HYBA.js → index-CYRE0NJA.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-BWKoBU8R.js → index-CeVZaJSC.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-D4_MuGkd.js → index-CfzxR61U.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-Dyngbd29.js → index-Ci3y1ZAv.js} +19 -19
  112. package/src/assets/web-panel/assets/{index-fzaMtSJ8.js → index-CjEJjl5C.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-Cp8vhyZy.js → index-Cv7bVWJ5.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-DPdUNk1i.js → index-D-o4Rwjk.js} +1 -1
  115. package/src/assets/web-panel/assets/index-D7pfPouB.js +1 -0
  116. package/src/assets/web-panel/assets/{index-CeASi4fr.js → index-D9op8poE.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-DASluSqY.js → index-DF1TysIF.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-DocdRcbd.js → index-DYo9S5OT.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-2A5ph8b2.js → index-D_cycOET.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-wV6iGdpY.js → index-Db3CpWTr.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-BMLHv389.js → index-DkD1K-fF.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-B9WYSn4m.js → index-DmPJ6T6F.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-uCbEN7cY.js → index-DmVUeWUk.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-DmkMXwnR.js → index-Dzdr0zDf.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-CZ6Yt17L.js → index-PBLzwYnu.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-CE2DdTP2.js → index-bFCaM7Eq.js} +1 -1
  127. package/src/assets/web-panel/assets/index-e4i-VLBd.js +1 -0
  128. package/src/assets/web-panel/assets/{index-GwdRUZ-x.js → index-h3KJZr95.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-B2vS66eI.js → index-iHcPtQ2e.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-6GmBa4Kg.js → index-jzlzm4VK.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-D9vU25ij.js → index-o14NNnxw.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-CGjmILDm.js → index-tYPSfGbd.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-LvCBfTLo.js → index-ytp2H5Zx.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-V5Fo95FM.js → initDefaultProps-D2Iut83B.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-BYWU0hUT.js → motion-BuaJVdK9.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-Cr1M-J2h.js → move-CaEuM92y.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-BysQKi2N.js → mtc-parser-wuKNBwys.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-D1zHU8GC.js → omit-7a3eklaq.js} +1 -1
  139. package/src/assets/web-panel/assets/{pickAttrs-CUArxtfi.js → pickAttrs-Dn4z7KvJ.js} +1 -1
  140. package/src/assets/web-panel/assets/{placementArrow-ChoYEys0.js → placementArrow-DVn_qT4-.js} +1 -1
  141. package/src/assets/web-panel/assets/{responsiveObserve-BQRs3Mo7.js → responsiveObserve-Dodz1OMQ.js} +1 -1
  142. package/src/assets/web-panel/assets/{slide-B8zbsCkg.js → slide-CxoGskbp.js} +1 -1
  143. package/src/assets/web-panel/assets/{statusUtils-C2U8Gs6h.js → statusUtils-DBh_epQH.js} +1 -1
  144. package/src/assets/web-panel/assets/{styleChecker-Dd8MgL_V.js → styleChecker-RXQ4gG5P.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFlexGapSupport-hknqY5NH.js → useFlexGapSupport-1Wxm0HEG.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFs-CLTAmcfw.js → useFs-CI_ySNxJ.js} +1 -1
  147. package/src/assets/web-panel/assets/{usePersonalDataHub-ByegHbiB.js → usePersonalDataHub-C6973rZP.js} +1 -1
  148. package/src/assets/web-panel/assets/{vnode-DqlAy5DP.js → vnode-CalynwKr.js} +1 -1
  149. package/src/assets/web-panel/assets/{zoom-DiXiztQn.js → zoom-CM1cd-Q0.js} +1 -1
  150. package/src/assets/web-panel/index.html +1 -1
  151. package/src/commands/agenda.js +74 -1
  152. package/src/commands/agent.js +9 -0
  153. package/src/commands/background-session.js +60 -1
  154. package/src/commands/batch.js +160 -5
  155. package/src/commands/plugin.js +318 -43
  156. package/src/commands/session.js +44 -1
  157. package/src/commands/team.js +212 -6
  158. package/src/data/changelog.json +26 -0
  159. package/src/harness/jsonl-session-store.js +59 -6
  160. package/src/harness/mcp-client.js +65 -43
  161. package/src/lib/agent-batch.js +4 -1
  162. package/src/lib/agent-team/team-runner.js +19 -1
  163. package/src/lib/agent-team/team-worktree.js +3 -0
  164. package/src/lib/async-hook-supervisor.cjs +82 -10
  165. package/src/lib/async-hook-supervisor.js +50 -4
  166. package/src/lib/background-agent-supervisor.js +49 -0
  167. package/src/lib/collaboration-run-store.js +362 -0
  168. package/src/lib/hook-runner.cjs +98 -17
  169. package/src/lib/hook-runner.js +77 -6
  170. package/src/lib/hook-shell-command.cjs +148 -0
  171. package/src/lib/hooks-v2-runtime.js +188 -77
  172. package/src/lib/jsonl-session-store.js +2 -0
  173. package/src/lib/lsp/__tests__/lsp-client.test.js +18 -0
  174. package/src/lib/lsp/lsp-client.js +12 -1
  175. package/src/lib/plugin-monitor-supervisor.js +53 -16
  176. package/src/lib/plugin-runtime/bin.js +1 -1
  177. package/src/lib/plugin-runtime/install.js +465 -54
  178. package/src/lib/plugin-runtime/mcp.js +21 -2
  179. package/src/lib/plugin-runtime/monitors.js +19 -3
  180. package/src/lib/plugin-runtime/sandbox-policy.js +99 -0
  181. package/src/lib/plugin-runtime/scopes.js +13 -2
  182. package/src/lib/plugin-usage-attribution.js +44 -0
  183. package/src/lib/process-execution-broker/index.js +705 -13
  184. package/src/lib/process-execution-broker/linux-generic-bwrap-runtime.js +1347 -0
  185. package/src/lib/process-execution-broker/linux-generic-bwrap.js +1260 -0
  186. package/src/lib/process-execution-broker/platform-sandbox.js +1831 -157
  187. package/src/lib/session-usage.js +278 -1
  188. package/src/lib/stream-retry.js +29 -0
  189. package/src/repl/agent-repl.js +38 -9
  190. package/src/runtime/agent-core.js +32 -4
  191. package/src/runtime/headless-runner.js +46 -1
  192. package/src/runtime/headless-stream.js +54 -3
  193. package/src/runtime/mcp-config.js +15 -5
  194. package/src/assets/web-panel/assets/ChatBubbleRenderer-PR074hUN.js +0 -1
  195. package/src/assets/web-panel/assets/OrderTableRenderer-GlJtqLjT.js +0 -1
  196. package/src/assets/web-panel/assets/Projects-Qx_MdX9k.js +0 -1
  197. package/src/assets/web-panel/assets/Skills-Cb8jWjMX.js +0 -1
  198. package/src/assets/web-panel/assets/Tasks-CyuLnDFR.js +0 -1
  199. package/src/assets/web-panel/assets/Terminal-DwzGMniO.js +0 -3
  200. package/src/assets/web-panel/assets/devWarning-DgVKduH2.js +0 -1
  201. package/src/assets/web-panel/assets/index-DOZTSoS7.js +0 -1
  202. package/src/assets/web-panel/assets/index-DhpvjpqI.js +0 -1
@@ -38,7 +38,13 @@ import {
38
38
  postSpawnSandbox as _postSpawnSandbox,
39
39
  SANDBOX_BOUNDARIES,
40
40
  } from "./platform-sandbox.js";
41
+ import {
42
+ admitLinuxGenericSandboxExecutionContract,
43
+ issueLinuxGenericSandboxExecutionContract,
44
+ LINUX_GENERIC_CONTRACT_KIND,
45
+ } from "./linux-generic-bwrap.js";
41
46
  import { consumeIssuedPluginSandboxExecutionContract } from "../plugin-runtime/bin.js";
47
+ import runtimeProvenanceLedger from "../runtime-provenance-ledger.js";
42
48
  import { credentialAgent } from "./credential-agent.js";
43
49
 
44
50
  const SUPPORTED_SANDBOX_BOUNDARIES = new Set(Object.values(SANDBOX_BOUNDARIES));
@@ -50,7 +56,6 @@ const SUPPORTED_SANDBOX_PROFILES = new Set([
50
56
 
51
57
  // 延迟导入避免循环依赖
52
58
  let _traceCtx = null;
53
- let _rpl = null;
54
59
  let _hooksV2 = null;
55
60
  const _ipcBus = null;
56
61
 
@@ -66,14 +71,7 @@ function getTraceCtx() {
66
71
  }
67
72
 
68
73
  function getRpl() {
69
- if (!_rpl) {
70
- try {
71
- _rpl = require("../runtime-provenance-ledger.js");
72
- } catch {
73
- _rpl = null;
74
- }
75
- }
76
- return _rpl;
74
+ return runtimeProvenanceLedger;
77
75
  }
78
76
 
79
77
  function getHooksV2() {
@@ -271,6 +269,24 @@ class ProcessExecutionBroker extends EventEmitter {
271
269
  },
272
270
  );
273
271
  };
272
+ if (raw?.kind === LINUX_GENERIC_CONTRACT_KIND) {
273
+ const admitted = admitLinuxGenericSandboxExecutionContract(raw, {
274
+ origin: options.origin || "unknown",
275
+ command: launch?.command,
276
+ args: launch?.args,
277
+ cwd: options.cwd || process.cwd(),
278
+ shell: options.shell,
279
+ sync: launch?.sync === true,
280
+ stdio: options.stdio,
281
+ requiredBoundaries,
282
+ });
283
+ if (!admitted) {
284
+ return invalid(
285
+ "sandboxExecutionContract was not issued for this workspace launch provenance",
286
+ );
287
+ }
288
+ return admitted;
289
+ }
274
290
  if (
275
291
  !consumeIssuedPluginSandboxExecutionContract(raw, {
276
292
  origin: options.origin,
@@ -315,6 +331,7 @@ class ProcessExecutionBroker extends EventEmitter {
315
331
  ![
316
332
  "strict-plugin-node-bin",
317
333
  "strict-plugin-native-static-elf-bin",
334
+ "strict-plugin-native-elf-bin",
318
335
  ].includes(raw.kind)
319
336
  ) {
320
337
  return invalid("unsupported sandboxExecutionContract kind or version");
@@ -407,6 +424,57 @@ class ProcessExecutionBroker extends EventEmitter {
407
424
  });
408
425
  }
409
426
 
427
+ /**
428
+ * Issue a private one-launch Linux workspace authority for trusted host
429
+ * call-sites. The writable root is a positional host value, never read from
430
+ * a manifest/spawn option. Unsupported platforms and mixed boundary sets
431
+ * return null so the normal fail-closed adapter path remains authoritative.
432
+ */
433
+ issueLinuxWorkspaceSandboxExecutionContract(
434
+ command,
435
+ args = [],
436
+ options = {},
437
+ trustedWorkspaceRoot = process.cwd(),
438
+ { sync = false } = {},
439
+ ) {
440
+ const requiredBoundaries = [
441
+ ...new Set([
442
+ ...(options.requiredBoundaries || []),
443
+ ...(options.sandboxPolicy?.requiredBoundaries || []),
444
+ ]),
445
+ ];
446
+ if (
447
+ process.platform !== "linux" ||
448
+ requiredBoundaries.length === 0 ||
449
+ (options.shell !== undefined &&
450
+ options.shell !== null &&
451
+ options.shell !== false) ||
452
+ requiredBoundaries.some(
453
+ (boundary) =>
454
+ boundary !== SANDBOX_BOUNDARIES.FILESYSTEM &&
455
+ boundary !== SANDBOX_BOUNDARIES.NETWORK,
456
+ )
457
+ ) {
458
+ return null;
459
+ }
460
+ return issueLinuxGenericSandboxExecutionContract({
461
+ origin: options.origin || "unknown",
462
+ command,
463
+ args,
464
+ cwd: options.cwd || trustedWorkspaceRoot,
465
+ workspaceRoot: trustedWorkspaceRoot,
466
+ shell: options.shell,
467
+ sync,
468
+ stdio: options.stdio,
469
+ requiredBoundaries,
470
+ detached: options.detached,
471
+ uid: options.uid,
472
+ gid: options.gid,
473
+ argv0: options.argv0,
474
+ serialization: options.serialization,
475
+ });
476
+ }
477
+
410
478
  _stripPluginControlOptions(options) {
411
479
  delete options.pluginId;
412
480
  delete options.pluginVersion;
@@ -636,6 +704,9 @@ class ProcessExecutionBroker extends EventEmitter {
636
704
  );
637
705
  }
638
706
  let runtimeProbe = null;
707
+ let genericWorkspaceProbe = false;
708
+ let sanitizedFilesystemPolicy = null;
709
+ let sanitizedNetworkPolicy = null;
639
710
  if (plan.runtimeProbe !== null && plan.runtimeProbe !== undefined) {
640
711
  if (
641
712
  typeof plan.runtimeProbe !== "object" ||
@@ -656,6 +727,12 @@ class ProcessExecutionBroker extends EventEmitter {
656
727
  "targetRuntime",
657
728
  "contentSnapshotScope",
658
729
  "contentSnapshotMechanism",
730
+ "pluginTreeContentSnapshotScope",
731
+ "pluginTreeContentSnapshotMechanism",
732
+ "pluginTreeSnapshotConsistency",
733
+ "initialDynamicLoadClosureScope",
734
+ "initialDynamicLoadClosureMechanism",
735
+ "initialDynamicInterpreter",
659
736
  ]) {
660
737
  if (
661
738
  plan.runtimeProbe[field] !== undefined &&
@@ -668,7 +745,14 @@ class ProcessExecutionBroker extends EventEmitter {
668
745
  );
669
746
  }
670
747
  }
671
- for (const field of ["contentSnapshot", "handleAtomic"]) {
748
+ for (const field of [
749
+ "contentSnapshot",
750
+ "handleAtomic",
751
+ "pluginTreeContentSnapshot",
752
+ "pluginTreeSnapshotContractBound",
753
+ "pluginTreeSnapshotAtomic",
754
+ "initialDynamicLoadClosureDescriptorBound",
755
+ ]) {
672
756
  if (
673
757
  plan.runtimeProbe[field] !== undefined &&
674
758
  typeof plan.runtimeProbe[field] !== "boolean"
@@ -679,6 +763,503 @@ class ProcessExecutionBroker extends EventEmitter {
679
763
  );
680
764
  }
681
765
  }
766
+ for (const field of [
767
+ "pluginTreeContentSnapshotFiles",
768
+ "pluginTreeContentSnapshotBytes",
769
+ "initialDynamicDependencyCount",
770
+ "initialDynamicRuntimeFileCount",
771
+ ]) {
772
+ if (
773
+ plan.runtimeProbe[field] !== undefined &&
774
+ (!Number.isSafeInteger(plan.runtimeProbe[field]) ||
775
+ plan.runtimeProbe[field] < 0)
776
+ ) {
777
+ throw this._sandboxError(
778
+ "invalid_sandbox_plan",
779
+ `Sandbox runtime probe ${field} must be a non-negative safe integer`,
780
+ );
781
+ }
782
+ }
783
+ if (
784
+ plan.runtimeProbe.pluginTreeContentSnapshotDigest !== undefined &&
785
+ (typeof plan.runtimeProbe.pluginTreeContentSnapshotDigest !==
786
+ "string" ||
787
+ !/^[a-f0-9]{64}$/.test(
788
+ plan.runtimeProbe.pluginTreeContentSnapshotDigest,
789
+ ))
790
+ ) {
791
+ throw this._sandboxError(
792
+ "invalid_sandbox_plan",
793
+ "Sandbox runtime probe pluginTreeContentSnapshotDigest must be a lowercase SHA-256 value",
794
+ );
795
+ }
796
+ if (
797
+ plan.runtimeProbe.initialDynamicLoadClosureDigest !== undefined &&
798
+ (typeof plan.runtimeProbe.initialDynamicLoadClosureDigest !==
799
+ "string" ||
800
+ !/^[a-f0-9]{64}$/.test(
801
+ plan.runtimeProbe.initialDynamicLoadClosureDigest,
802
+ ))
803
+ ) {
804
+ throw this._sandboxError(
805
+ "invalid_sandbox_plan",
806
+ "Sandbox runtime probe initialDynamicLoadClosureDigest must be a lowercase SHA-256 value",
807
+ );
808
+ }
809
+ const pluginTreeSnapshot =
810
+ plan.runtimeProbe.pluginTreeContentSnapshot === true;
811
+ const pluginTreeEvidenceFields = [
812
+ "pluginTreeContentSnapshotScope",
813
+ "pluginTreeContentSnapshotMechanism",
814
+ "pluginTreeContentSnapshotFiles",
815
+ "pluginTreeContentSnapshotBytes",
816
+ "pluginTreeContentSnapshotDigest",
817
+ "pluginTreeSnapshotConsistency",
818
+ "pluginTreeSnapshotContractBound",
819
+ "pluginTreeSnapshotAtomic",
820
+ ];
821
+ if (
822
+ pluginTreeSnapshot &&
823
+ (plan.applied !== true ||
824
+ plan.platform !== "linux" ||
825
+ plan.enforcement !== "linux-bwrap" ||
826
+ backend !== "linux-bwrap" ||
827
+ candidateBackend !== null ||
828
+ policyAttested !== true ||
829
+ policyDigest === null ||
830
+ !guarantees.includes(SANDBOX_BOUNDARIES.FILESYSTEM) ||
831
+ !guarantees.includes(SANDBOX_BOUNDARIES.NETWORK) ||
832
+ plan.runtimeProbe.attempted !== true ||
833
+ plan.runtimeProbe.runnable !== true ||
834
+ plan.runtimeProbe.reason !== null ||
835
+ plan.runtimeProbe.kind !== "linux-bwrap-plugin-node-policy-v1" ||
836
+ plan.runtimeProbe.probeRuntime !== "node" ||
837
+ plan.runtimeProbe.targetRuntime !== "node" ||
838
+ plan.runtimeProbe.contentSnapshot !== true ||
839
+ plan.runtimeProbe.contentSnapshotScope !== "plugin-entry-source" ||
840
+ plan.runtimeProbe.contentSnapshotMechanism !==
841
+ "verified-o_tmpfile-copy-bwrap-ro-bind-data-v1" ||
842
+ plan.runtimeProbe.handleAtomic !== false ||
843
+ plan.runtimeProbe.supervisorDescriptorBound !== true ||
844
+ plan.runtimeProbe.pluginTreeContentSnapshotScope !==
845
+ "all-pinned-plugin-regular-files" ||
846
+ plan.runtimeProbe.pluginTreeContentSnapshotMechanism !==
847
+ "verified-o_tmpfile-copy-bwrap-ro-bind-data-v1" ||
848
+ !Number.isSafeInteger(
849
+ plan.runtimeProbe.pluginTreeContentSnapshotFiles,
850
+ ) ||
851
+ plan.runtimeProbe.pluginTreeContentSnapshotFiles < 1 ||
852
+ plan.runtimeProbe.pluginTreeContentSnapshotFiles > 256 ||
853
+ !Number.isSafeInteger(
854
+ plan.runtimeProbe.pluginTreeContentSnapshotBytes,
855
+ ) ||
856
+ plan.runtimeProbe.pluginTreeContentSnapshotBytes < 0 ||
857
+ plan.runtimeProbe.pluginTreeContentSnapshotBytes >
858
+ 256 * 1024 * 1024 ||
859
+ !/^[a-f0-9]{64}$/.test(
860
+ plan.runtimeProbe.pluginTreeContentSnapshotDigest || "",
861
+ ) ||
862
+ plan.runtimeProbe.pluginTreeSnapshotConsistency !==
863
+ "per-file-pin-to-launch" ||
864
+ plan.runtimeProbe.pluginTreeSnapshotContractBound !== false ||
865
+ plan.runtimeProbe.pluginTreeSnapshotAtomic !== false)
866
+ ) {
867
+ throw this._sandboxError(
868
+ "invalid_sandbox_plan",
869
+ "Sandbox runtime probe plugin tree snapshot evidence must use the typed complete-tree contract",
870
+ );
871
+ }
872
+ if (
873
+ !pluginTreeSnapshot &&
874
+ pluginTreeEvidenceFields.some(
875
+ (field) => plan.runtimeProbe[field] !== undefined,
876
+ )
877
+ ) {
878
+ throw this._sandboxError(
879
+ "invalid_sandbox_plan",
880
+ "Sandbox runtime probe plugin tree snapshot evidence requires pluginTreeContentSnapshot",
881
+ );
882
+ }
883
+ const supervisorStringFields = [
884
+ "supervisorBindingScope",
885
+ "supervisorDescriptorBindingMechanism",
886
+ "supervisorPid1ExecutableExposure",
887
+ ];
888
+ const supervisorBooleanFields = [
889
+ "supervisorDescriptorBound",
890
+ "supervisorExecutablePinned",
891
+ "supervisorDescriptorContained",
892
+ "supervisorDescriptorConsumedBeforeTarget",
893
+ "supervisorStagingPathHidden",
894
+ "supervisorTemporaryCopyObscured",
895
+ ];
896
+ for (const field of supervisorStringFields) {
897
+ if (
898
+ plan.runtimeProbe[field] !== undefined &&
899
+ (typeof plan.runtimeProbe[field] !== "string" ||
900
+ !plan.runtimeProbe[field])
901
+ ) {
902
+ throw this._sandboxError(
903
+ "invalid_sandbox_plan",
904
+ `Sandbox runtime probe ${field} must be a non-empty string`,
905
+ );
906
+ }
907
+ }
908
+ for (const field of supervisorBooleanFields) {
909
+ if (
910
+ plan.runtimeProbe[field] !== undefined &&
911
+ typeof plan.runtimeProbe[field] !== "boolean"
912
+ ) {
913
+ throw this._sandboxError(
914
+ "invalid_sandbox_plan",
915
+ `Sandbox runtime probe ${field} must be boolean`,
916
+ );
917
+ }
918
+ }
919
+ const supervisorIdentity = plan.runtimeProbe.supervisorExecutableIdentity;
920
+ if (supervisorIdentity !== undefined) {
921
+ const fileId = supervisorIdentity?.fileId;
922
+ if (
923
+ !supervisorIdentity ||
924
+ typeof supervisorIdentity !== "object" ||
925
+ Array.isArray(supervisorIdentity) ||
926
+ typeof supervisorIdentity.path !== "string" ||
927
+ !supervisorIdentity.path.startsWith("/") ||
928
+ !fileId ||
929
+ typeof fileId !== "object" ||
930
+ Array.isArray(fileId) ||
931
+ typeof fileId.dev !== "string" ||
932
+ !/^\d+$/.test(fileId.dev) ||
933
+ typeof fileId.ino !== "string" ||
934
+ !/^\d+$/.test(fileId.ino) ||
935
+ typeof supervisorIdentity.sha256 !== "string" ||
936
+ !/^[a-f0-9]{64}$/.test(supervisorIdentity.sha256) ||
937
+ !Number.isSafeInteger(supervisorIdentity.bytes) ||
938
+ supervisorIdentity.bytes <= 0 ||
939
+ supervisorIdentity.bytes > 256 * 1024 * 1024 ||
940
+ !Number.isFinite(supervisorIdentity.mtimeMs) ||
941
+ !Number.isSafeInteger(supervisorIdentity.mode) ||
942
+ supervisorIdentity.mode <= 0 ||
943
+ (supervisorIdentity.mode & 0o170000) !== 0o100000 ||
944
+ (supervisorIdentity.mode & 0o111) === 0 ||
945
+ (supervisorIdentity.mode & 0o022) !== 0 ||
946
+ !Number.isSafeInteger(supervisorIdentity.uid) ||
947
+ supervisorIdentity.uid !== 0 ||
948
+ !Number.isSafeInteger(supervisorIdentity.gid) ||
949
+ supervisorIdentity.gid < 0
950
+ ) {
951
+ throw this._sandboxError(
952
+ "invalid_sandbox_plan",
953
+ "Sandbox runtime probe supervisorExecutableIdentity must use the typed executable identity contract",
954
+ );
955
+ }
956
+ }
957
+ const supervisorBound =
958
+ plan.runtimeProbe.supervisorDescriptorBound === true;
959
+ if (
960
+ supervisorBound &&
961
+ (plan.runtimeProbe.supervisorExecutablePinned !== true ||
962
+ supervisorIdentity === undefined ||
963
+ plan.runtimeProbe.supervisorBindingScope !==
964
+ "host-path-replacement" ||
965
+ plan.runtimeProbe.supervisorDescriptorBindingMechanism !==
966
+ "pinned-child-fd3-file-consume-run-overmount-v1" ||
967
+ plan.runtimeProbe.supervisorPid1ExecutableExposure !== "procfs")
968
+ ) {
969
+ throw this._sandboxError(
970
+ "invalid_sandbox_plan",
971
+ "Sandbox runtime probe bound supervisor evidence must include its typed identity and binding contract",
972
+ );
973
+ }
974
+ for (const field of [
975
+ "supervisorDescriptorContained",
976
+ "supervisorDescriptorConsumedBeforeTarget",
977
+ "supervisorStagingPathHidden",
978
+ "supervisorTemporaryCopyObscured",
979
+ ]) {
980
+ if (
981
+ (plan.runtimeProbe[field] === true &&
982
+ (!supervisorBound || plan.runtimeProbe.runnable !== true)) ||
983
+ (supervisorBound &&
984
+ plan.runtimeProbe[field] !== plan.runtimeProbe.runnable)
985
+ ) {
986
+ throw this._sandboxError(
987
+ "invalid_sandbox_plan",
988
+ `Sandbox runtime probe ${field} requires a runnable bound supervisor`,
989
+ );
990
+ }
991
+ }
992
+ const initialDynamicLoadClosureBound =
993
+ plan.runtimeProbe.initialDynamicLoadClosureDescriptorBound === true;
994
+ const initialDynamicEvidenceFields = [
995
+ "initialDynamicLoadClosureScope",
996
+ "initialDynamicLoadClosureMechanism",
997
+ "initialDynamicInterpreter",
998
+ "initialDynamicDependencyCount",
999
+ "initialDynamicRuntimeFileCount",
1000
+ "initialDynamicLoadClosureDigest",
1001
+ ];
1002
+ const initialDynamicInterpreter =
1003
+ plan.runtimeProbe.initialDynamicInterpreter;
1004
+ const initialDynamicDependencyCount =
1005
+ plan.runtimeProbe.initialDynamicDependencyCount;
1006
+ const initialDynamicRuntimeFileCount =
1007
+ plan.runtimeProbe.initialDynamicRuntimeFileCount;
1008
+ const successfulDynamicProbe =
1009
+ plan.applied === true &&
1010
+ plan.runtimeProbe.kind ===
1011
+ "linux-bwrap-plugin-native-dynamic-elf-policy-v1" &&
1012
+ plan.runtimeProbe.runnable === true;
1013
+ if (
1014
+ initialDynamicLoadClosureBound &&
1015
+ (plan.applied !== true ||
1016
+ plan.platform !== "linux" ||
1017
+ plan.enforcement !== "linux-bwrap" ||
1018
+ backend !== "linux-bwrap" ||
1019
+ candidateBackend !== null ||
1020
+ policyAttested !== true ||
1021
+ policyDigest === null ||
1022
+ !guarantees.includes(SANDBOX_BOUNDARIES.FILESYSTEM) ||
1023
+ !guarantees.includes(SANDBOX_BOUNDARIES.NETWORK) ||
1024
+ plan.runtimeProbe.attempted !== true ||
1025
+ plan.runtimeProbe.runnable !== true ||
1026
+ plan.runtimeProbe.reason !== null ||
1027
+ plan.runtimeProbe.kind !==
1028
+ "linux-bwrap-plugin-native-dynamic-elf-policy-v1" ||
1029
+ plan.runtimeProbe.probeRuntime !== "node" ||
1030
+ plan.runtimeProbe.targetRuntime !== "native-dynamic-elf" ||
1031
+ plan.runtimeProbe.contentSnapshot !== true ||
1032
+ plan.runtimeProbe.contentSnapshotScope !==
1033
+ "plugin-entry-executable" ||
1034
+ plan.runtimeProbe.contentSnapshotMechanism !==
1035
+ "verified-o_tmpfile-copy-bwrap-ro-bind-data-v1" ||
1036
+ plan.runtimeProbe.handleAtomic !== false ||
1037
+ !supervisorBound ||
1038
+ plan.runtimeProbe.initialDynamicLoadClosureScope !==
1039
+ "initial-pt_interp-and-direct-dt_needed-attested-system-set" ||
1040
+ plan.runtimeProbe.initialDynamicLoadClosureMechanism !==
1041
+ "parsed-elf-direct-system-set-to-attested-node-runtime-fds-v1" ||
1042
+ typeof initialDynamicInterpreter !== "string" ||
1043
+ !path.posix.isAbsolute(initialDynamicInterpreter) ||
1044
+ path.posix.normalize(initialDynamicInterpreter) !==
1045
+ initialDynamicInterpreter ||
1046
+ !["/lib/", "/lib64/", "/usr/lib/", "/usr/lib64/"].some((prefix) =>
1047
+ initialDynamicInterpreter.startsWith(prefix),
1048
+ ) ||
1049
+ !Number.isSafeInteger(initialDynamicDependencyCount) ||
1050
+ initialDynamicDependencyCount < 0 ||
1051
+ initialDynamicDependencyCount > 128 ||
1052
+ !Number.isSafeInteger(initialDynamicRuntimeFileCount) ||
1053
+ initialDynamicRuntimeFileCount < 1 ||
1054
+ initialDynamicRuntimeFileCount > 129 ||
1055
+ initialDynamicRuntimeFileCount <
1056
+ Math.max(1, initialDynamicDependencyCount) ||
1057
+ initialDynamicRuntimeFileCount > initialDynamicDependencyCount + 1 ||
1058
+ !/^[a-f0-9]{64}$/.test(
1059
+ plan.runtimeProbe.initialDynamicLoadClosureDigest || "",
1060
+ ))
1061
+ ) {
1062
+ throw this._sandboxError(
1063
+ "invalid_sandbox_plan",
1064
+ "Sandbox runtime probe initial dynamic direct system set evidence must use the typed descriptor-bound contract",
1065
+ );
1066
+ }
1067
+ if (
1068
+ !initialDynamicLoadClosureBound &&
1069
+ initialDynamicEvidenceFields.some(
1070
+ (field) => plan.runtimeProbe[field] !== undefined,
1071
+ )
1072
+ ) {
1073
+ throw this._sandboxError(
1074
+ "invalid_sandbox_plan",
1075
+ "Sandbox runtime probe initial dynamic direct system set evidence requires initialDynamicLoadClosureDescriptorBound",
1076
+ );
1077
+ }
1078
+ if (successfulDynamicProbe && !initialDynamicLoadClosureBound) {
1079
+ throw this._sandboxError(
1080
+ "invalid_sandbox_plan",
1081
+ "Sandbox runtime probe successful dynamic ELF evidence requires a descriptor-bound initial direct system set",
1082
+ );
1083
+ }
1084
+ const genericWorkspaceEvidenceFields = [
1085
+ "contractDigest",
1086
+ "policyDigest",
1087
+ "mountTopologyDigest",
1088
+ "emptyRoot",
1089
+ "undeclaredRootReadOnly",
1090
+ "workspaceReadWrite",
1091
+ "workspaceMountTopologyAttested",
1092
+ "workspaceRootAliasAttested",
1093
+ "anonymousDevWritable",
1094
+ "systemReadOnly",
1095
+ "hostHomeHidden",
1096
+ "outsideMarkerHidden",
1097
+ "networkNamespace",
1098
+ "networkNamespaceChanged",
1099
+ "socketCreationDenied",
1100
+ "descriptorMounts",
1101
+ "mountTopologyAtomic",
1102
+ ];
1103
+ for (const field of [
1104
+ "contractDigest",
1105
+ "policyDigest",
1106
+ "mountTopologyDigest",
1107
+ ]) {
1108
+ if (
1109
+ plan.runtimeProbe[field] !== undefined &&
1110
+ (typeof plan.runtimeProbe[field] !== "string" ||
1111
+ !/^[a-f0-9]{64}$/.test(plan.runtimeProbe[field]))
1112
+ ) {
1113
+ throw this._sandboxError(
1114
+ "invalid_sandbox_plan",
1115
+ `Sandbox runtime probe ${field} must be a lowercase SHA-256 value`,
1116
+ );
1117
+ }
1118
+ }
1119
+ for (const field of genericWorkspaceEvidenceFields.slice(3)) {
1120
+ if (
1121
+ plan.runtimeProbe[field] !== undefined &&
1122
+ typeof plan.runtimeProbe[field] !== "boolean"
1123
+ ) {
1124
+ throw this._sandboxError(
1125
+ "invalid_sandbox_plan",
1126
+ `Sandbox runtime probe ${field} must be boolean`,
1127
+ );
1128
+ }
1129
+ }
1130
+ const genericWorkspaceKind =
1131
+ plan.runtimeProbe.kind === "linux-bwrap-generic-workspace-policy-v1";
1132
+ if (
1133
+ !genericWorkspaceKind &&
1134
+ genericWorkspaceEvidenceFields.some(
1135
+ (field) => plan.runtimeProbe[field] !== undefined,
1136
+ )
1137
+ ) {
1138
+ throw this._sandboxError(
1139
+ "invalid_sandbox_plan",
1140
+ "Linux generic workspace evidence requires its typed runtime probe kind",
1141
+ );
1142
+ }
1143
+ if (genericWorkspaceKind) {
1144
+ const filesystemPolicy = plan.filesystemPolicy;
1145
+ const networkPolicy = plan.networkPolicy;
1146
+ const workspaceRoot = filesystemPolicy?.workspaceRoot;
1147
+ const workingDirectory = filesystemPolicy?.workingDirectory;
1148
+ const workspaceRelative =
1149
+ typeof workspaceRoot === "string" &&
1150
+ typeof workingDirectory === "string"
1151
+ ? path.posix.relative(workspaceRoot, workingDirectory)
1152
+ : "..";
1153
+ genericWorkspaceProbe =
1154
+ plan.applied === true &&
1155
+ plan.platform === "linux" &&
1156
+ plan.enforcement === "linux-bwrap-workspace" &&
1157
+ backend === "linux-bwrap-workspace" &&
1158
+ candidateBackend === null &&
1159
+ policyAttested === true &&
1160
+ policyDigest !== null &&
1161
+ plan.runtimeProbe.policyDigest === policyDigest &&
1162
+ /^[a-f0-9]{64}$/.test(plan.runtimeProbe.contractDigest || "") &&
1163
+ guarantees.includes(SANDBOX_BOUNDARIES.FILESYSTEM) &&
1164
+ guarantees.includes(SANDBOX_BOUNDARIES.NETWORK) &&
1165
+ plan.runtimeProbe.attempted === true &&
1166
+ plan.runtimeProbe.runnable === true &&
1167
+ plan.runtimeProbe.reason === null &&
1168
+ plan.runtimeProbe.probeRuntime === "posix-sh" &&
1169
+ plan.runtimeProbe.targetRuntime === "generic-command" &&
1170
+ plan.runtimeProbe.contentSnapshot === false &&
1171
+ plan.runtimeProbe.handleAtomic === false &&
1172
+ plan.runtimeProbe.mountTopologyAtomic === false &&
1173
+ plan.runtimeProbe.mountTopologyDigest ===
1174
+ filesystemPolicy?.mountTopologyDigest &&
1175
+ [
1176
+ "emptyRoot",
1177
+ "undeclaredRootReadOnly",
1178
+ "workspaceReadWrite",
1179
+ "workspaceMountTopologyAttested",
1180
+ "workspaceRootAliasAttested",
1181
+ "anonymousDevWritable",
1182
+ "systemReadOnly",
1183
+ "hostHomeHidden",
1184
+ "outsideMarkerHidden",
1185
+ "networkNamespace",
1186
+ "networkNamespaceChanged",
1187
+ "socketCreationDenied",
1188
+ "descriptorMounts",
1189
+ ].every((field) => plan.runtimeProbe[field] === true) &&
1190
+ typeof workspaceRoot === "string" &&
1191
+ path.posix.isAbsolute(workspaceRoot) &&
1192
+ workspaceRoot !== "/" &&
1193
+ typeof workingDirectory === "string" &&
1194
+ path.posix.isAbsolute(workingDirectory) &&
1195
+ workspaceRelative !== ".." &&
1196
+ !workspaceRelative.startsWith("../") &&
1197
+ !path.posix.isAbsolute(workspaceRelative) &&
1198
+ filesystemPolicy.workspaceAccess === "read-write" &&
1199
+ filesystemPolicy.systemAccess === "read-only" &&
1200
+ filesystemPolicy.undeclaredRootAccess === "read-only" &&
1201
+ filesystemPolicy.hostRootMapped === false &&
1202
+ filesystemPolicy.hostHomeMapped === false &&
1203
+ filesystemPolicy.workspaceDescriptorBound === true &&
1204
+ filesystemPolicy.systemDescriptorBound === true &&
1205
+ filesystemPolicy.exactEtcFileDescriptors === true &&
1206
+ filesystemPolicy.workspaceRecursiveBind === true &&
1207
+ filesystemPolicy.workspaceMountTopology ===
1208
+ "no-strict-descendants-or-forbidden-root-aliases-at-attestation" &&
1209
+ filesystemPolicy.mountTopologySource === "proc-self-mountinfo" &&
1210
+ /^[a-f0-9]{64}$/.test(filesystemPolicy.mountTopologyDigest || "") &&
1211
+ filesystemPolicy.mountTopologyAtomic === false &&
1212
+ Array.isArray(filesystemPolicy.anonymousWritablePaths) &&
1213
+ filesystemPolicy.anonymousWritablePaths.length === 5 &&
1214
+ ["/home/sandbox", "/dev", "/run", "/tmp", "/var/tmp"].every(
1215
+ (value, index) =>
1216
+ filesystemPolicy.anonymousWritablePaths[index] === value,
1217
+ ) &&
1218
+ networkPolicy?.namespace === "new" &&
1219
+ networkPolicy?.namespaceIdentityChanged === true &&
1220
+ networkPolicy?.seccomp === "deny-network-creation" &&
1221
+ plan.command.startsWith("/proc/self/fd/") &&
1222
+ plan.options?.cwd === "/" &&
1223
+ plan.options?.shell === false &&
1224
+ Array.isArray(plan.options?.stdio) &&
1225
+ plan.args.includes("--bind-fd") &&
1226
+ plan.args.includes("--ro-bind-fd") &&
1227
+ plan.args.includes("--remount-ro") &&
1228
+ plan.args.includes("--unshare-net") &&
1229
+ plan.args.includes("--seccomp") &&
1230
+ !plan.args.includes("--ro-bind");
1231
+ if (!genericWorkspaceProbe) {
1232
+ throw this._sandboxError(
1233
+ "invalid_sandbox_plan",
1234
+ "Linux generic workspace evidence must use the typed descriptor-bound empty-root contract",
1235
+ );
1236
+ }
1237
+ sanitizedFilesystemPolicy = Object.freeze({
1238
+ workspaceRoot,
1239
+ workingDirectory,
1240
+ workspaceAccess: filesystemPolicy.workspaceAccess,
1241
+ systemAccess: filesystemPolicy.systemAccess,
1242
+ undeclaredRootAccess: filesystemPolicy.undeclaredRootAccess,
1243
+ anonymousWritablePaths: Object.freeze([
1244
+ ...filesystemPolicy.anonymousWritablePaths,
1245
+ ]),
1246
+ hostRootMapped: filesystemPolicy.hostRootMapped,
1247
+ hostHomeMapped: filesystemPolicy.hostHomeMapped,
1248
+ workspaceDescriptorBound: filesystemPolicy.workspaceDescriptorBound,
1249
+ systemDescriptorBound: filesystemPolicy.systemDescriptorBound,
1250
+ exactEtcFileDescriptors: filesystemPolicy.exactEtcFileDescriptors,
1251
+ workspaceRecursiveBind: filesystemPolicy.workspaceRecursiveBind,
1252
+ workspaceMountTopology: filesystemPolicy.workspaceMountTopology,
1253
+ mountTopologySource: filesystemPolicy.mountTopologySource,
1254
+ mountTopologyDigest: filesystemPolicy.mountTopologyDigest,
1255
+ mountTopologyAtomic: filesystemPolicy.mountTopologyAtomic,
1256
+ });
1257
+ sanitizedNetworkPolicy = Object.freeze({
1258
+ namespace: networkPolicy.namespace,
1259
+ namespaceIdentityChanged: networkPolicy.namespaceIdentityChanged,
1260
+ seccomp: networkPolicy.seccomp,
1261
+ });
1262
+ }
682
1263
  runtimeProbe = {
683
1264
  kind: plan.runtimeProbe.kind,
684
1265
  attempted: plan.runtimeProbe.attempted,
@@ -708,6 +1289,56 @@ class ProcessExecutionBroker extends EventEmitter {
708
1289
  }
709
1290
  : {}),
710
1291
  };
1292
+ for (const field of [
1293
+ "pluginTreeContentSnapshot",
1294
+ ...pluginTreeEvidenceFields,
1295
+ ]) {
1296
+ if (plan.runtimeProbe[field] !== undefined) {
1297
+ runtimeProbe[field] = plan.runtimeProbe[field];
1298
+ }
1299
+ }
1300
+ for (const field of [
1301
+ ...supervisorStringFields,
1302
+ ...supervisorBooleanFields,
1303
+ ]) {
1304
+ if (plan.runtimeProbe[field] !== undefined) {
1305
+ runtimeProbe[field] = plan.runtimeProbe[field];
1306
+ }
1307
+ }
1308
+ for (const field of [
1309
+ "initialDynamicLoadClosureDescriptorBound",
1310
+ ...initialDynamicEvidenceFields,
1311
+ ]) {
1312
+ if (plan.runtimeProbe[field] !== undefined) {
1313
+ runtimeProbe[field] = plan.runtimeProbe[field];
1314
+ }
1315
+ }
1316
+ for (const field of genericWorkspaceEvidenceFields) {
1317
+ if (plan.runtimeProbe[field] !== undefined) {
1318
+ runtimeProbe[field] = plan.runtimeProbe[field];
1319
+ }
1320
+ }
1321
+ if (supervisorIdentity !== undefined) {
1322
+ runtimeProbe.supervisorExecutableIdentity = {
1323
+ path: supervisorIdentity.path,
1324
+ fileId: {
1325
+ dev: supervisorIdentity.fileId.dev,
1326
+ ino: supervisorIdentity.fileId.ino,
1327
+ },
1328
+ sha256: supervisorIdentity.sha256,
1329
+ bytes: supervisorIdentity.bytes,
1330
+ mtimeMs: supervisorIdentity.mtimeMs,
1331
+ mode: supervisorIdentity.mode,
1332
+ uid: supervisorIdentity.uid,
1333
+ gid: supervisorIdentity.gid,
1334
+ };
1335
+ }
1336
+ }
1337
+ if (backend === "linux-bwrap-workspace" && !genericWorkspaceProbe) {
1338
+ throw this._sandboxError(
1339
+ "invalid_sandbox_plan",
1340
+ "Applied Linux generic workspace plans require typed runtime evidence",
1341
+ );
711
1342
  }
712
1343
  const postSpawn = plan.postSpawn || { required: false, mode: "none" };
713
1344
  if (
@@ -730,6 +1361,12 @@ class ProcessExecutionBroker extends EventEmitter {
730
1361
  policyAttested,
731
1362
  policyDigest,
732
1363
  runtimeProbe,
1364
+ ...(sanitizedFilesystemPolicy
1365
+ ? {
1366
+ filesystemPolicy: sanitizedFilesystemPolicy,
1367
+ networkPolicy: sanitizedNetworkPolicy,
1368
+ }
1369
+ : {}),
733
1370
  postSpawn: { ...postSpawn },
734
1371
  };
735
1372
  }
@@ -884,6 +1521,39 @@ class ProcessExecutionBroker extends EventEmitter {
884
1521
  auditEntry.sandboxPolicyAttested =
885
1522
  typeof plan?.policyAttested === "boolean" ? plan.policyAttested : null;
886
1523
  auditEntry.sandboxPolicyDigest = plan?.policyDigest || null;
1524
+ const genericPolicy =
1525
+ applied === true && plan?.backend === "linux-bwrap-workspace";
1526
+ auditEntry.sandboxFilesystemPolicy = genericPolicy
1527
+ ? {
1528
+ workspaceRoot: plan.filesystemPolicy.workspaceRoot,
1529
+ workingDirectory: plan.filesystemPolicy.workingDirectory,
1530
+ workspaceAccess: plan.filesystemPolicy.workspaceAccess,
1531
+ systemAccess: plan.filesystemPolicy.systemAccess,
1532
+ undeclaredRootAccess: plan.filesystemPolicy.undeclaredRootAccess,
1533
+ anonymousWritablePaths: [
1534
+ ...plan.filesystemPolicy.anonymousWritablePaths,
1535
+ ],
1536
+ hostRootMapped: plan.filesystemPolicy.hostRootMapped,
1537
+ hostHomeMapped: plan.filesystemPolicy.hostHomeMapped,
1538
+ workspaceDescriptorBound:
1539
+ plan.filesystemPolicy.workspaceDescriptorBound,
1540
+ systemDescriptorBound: plan.filesystemPolicy.systemDescriptorBound,
1541
+ exactEtcFileDescriptors:
1542
+ plan.filesystemPolicy.exactEtcFileDescriptors,
1543
+ workspaceRecursiveBind: plan.filesystemPolicy.workspaceRecursiveBind,
1544
+ workspaceMountTopology: plan.filesystemPolicy.workspaceMountTopology,
1545
+ mountTopologySource: plan.filesystemPolicy.mountTopologySource,
1546
+ mountTopologyDigest: plan.filesystemPolicy.mountTopologyDigest,
1547
+ mountTopologyAtomic: plan.filesystemPolicy.mountTopologyAtomic,
1548
+ }
1549
+ : null;
1550
+ auditEntry.sandboxNetworkPolicy = genericPolicy
1551
+ ? {
1552
+ namespace: plan.networkPolicy.namespace,
1553
+ namespaceIdentityChanged: plan.networkPolicy.namespaceIdentityChanged,
1554
+ seccomp: plan.networkPolicy.seccomp,
1555
+ }
1556
+ : null;
887
1557
  auditEntry.sandboxCandidateReason = plan?.candidateBackend
888
1558
  ? plan?.reason || null
889
1559
  : null;
@@ -1145,12 +1815,13 @@ class ProcessExecutionBroker extends EventEmitter {
1145
1815
 
1146
1816
  _writeRplEntry(auditEntry, status = "started", error = null) {
1147
1817
  const rpl = getRpl();
1148
- if (!rpl || !rpl.default) return;
1818
+ if (!rpl) return;
1149
1819
  try {
1150
1820
  const traceCtx = this._getTraceContext();
1151
- rpl.default.append(
1821
+ if (typeof rpl.record !== "function") return;
1822
+ rpl.record(
1823
+ "process.execution",
1152
1824
  {
1153
- kind: "process.execution",
1154
1825
  component: auditEntry.origin,
1155
1826
  action: "spawn",
1156
1827
  artifactId: auditEntry.executionId,
@@ -1171,6 +1842,15 @@ class ProcessExecutionBroker extends EventEmitter {
1171
1842
  policy: auditEntry.policy,
1172
1843
  scope: auditEntry.scope,
1173
1844
  },
1845
+ sandbox: {
1846
+ applied: auditEntry.sandboxed === true,
1847
+ backend: auditEntry.sandboxBackend || null,
1848
+ guarantees: [...(auditEntry.sandboxGuarantees || [])],
1849
+ policyAttested: auditEntry.sandboxPolicyAttested === true,
1850
+ policyDigest: auditEntry.sandboxPolicyDigest || null,
1851
+ filesystemPolicy: auditEntry.sandboxFilesystemPolicy || null,
1852
+ networkPolicy: auditEntry.sandboxNetworkPolicy || null,
1853
+ },
1174
1854
  traceId:
1175
1855
  traceCtx?.traceId || auditEntry.traceId || `trace-${Date.now()}`,
1176
1856
  parentSpanId: traceCtx?.spanId || null,
@@ -1356,6 +2036,18 @@ class ProcessExecutionBroker extends EventEmitter {
1356
2036
  proc,
1357
2037
  sandboxPlan.cleanup,
1358
2038
  );
2039
+ if (
2040
+ sandboxPlan.applied === true &&
2041
+ sandboxPlan.backend === "linux-bwrap-workspace" &&
2042
+ sandboxPlan.postSpawn.required === false
2043
+ ) {
2044
+ // child_process.spawn() has synchronously duplicated every stdio entry
2045
+ // into the launched bwrap process before returning. Generic workspace
2046
+ // plans do not need a parent-side post-spawn handle, so retaining their
2047
+ // pinned mount/seccomp descriptors until a long-lived MCP/LSP/monitor
2048
+ // exits would turn each child into an avoidable FD leak.
2049
+ cleanupSandbox();
2050
+ }
1359
2051
  try {
1360
2052
  this._runPostSpawnSandbox(proc, sandboxPlan, auditEntry);
1361
2053
  auditEntry.pid = proc.pid;