chainlesschain 0.162.183 → 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 (196) 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-BapS7lz4.js → AIOps-DzAl5fGx.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-CXYdXEUI.js → ActionButton-DAHtMGeC.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-CKR5Lexn.js → Analytics-BHQaexv5.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-DATVUOXB.js → AppLayout-Phz_pD0n.js} +4 -4
  7. package/src/assets/web-panel/assets/{Artifacts-vb_0ZlV1.js → Artifacts-DHt47kCA.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-BI1l9GWt.js → Audit--Y_8FULl.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-BFXbaUEf.js → BackgroundAgents-N1zchH7D.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-DEYBJJ6H.js → Backup-B_BoyN30.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-COdzeO0M.js → BaseInput-Gl4uQHcT.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-oSN6sfM5.js → Chat-Cg-eIyAZ.js} +6 -6
  13. package/src/assets/web-panel/assets/ChatBubbleRenderer-BzeUi3JH.js +1 -0
  14. package/src/assets/web-panel/assets/{Checkbox-BezEa4tm.js → Checkbox-D0MGR2wA.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-CNEL0Ife.js → Codegen-BdObJEFn.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-Bf2Y2Bn1.js → Col--ghxXT3z.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-BfUlu4Hc.js → Community-BUFeXOqz.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-BN4xWP9e.js → Compact-DhQO2_Mr.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-Bt6BKmEP.js → Compliance-3HoTqKYd.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-DKLp8YxO.js → Cowork-B3zmO4VW.js} +3 -3
  21. package/src/assets/web-panel/assets/{Cron-o7Hhw6ky.js → Cron-CJDrZOcc.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-DaNXWJIw.js → Crosschain-SMl15obd.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-B-Qa2mha.js → DID-CgTrTWrl.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-CMX0Qnxw.js → Dashboard-dXFKaKol.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-BLuLyRu_.js → Dropdown-qQHEhCvI.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-CFBAeMij.js → EmailListRenderer-C_ej0MWH.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DWzXQ67V.js → FamilyGuardDashboard-D6ajoE7I.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-DB1QSLgr.js → Federation-Cio2y49h.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-C-OKCToP.js → FormItemContext-ClJz1cYp.js} +1 -1
  30. package/src/assets/web-panel/assets/{GenericCardRenderer-DMJFtFZf.js → GenericCardRenderer-Dr_8Maca.js} +1 -1
  31. package/src/assets/web-panel/assets/{Git-DsGSujOV.js → Git-CevLwp5u.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-B0iS9NEW.js → Governance-CW9YyQUY.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-CH004H7c.js → Inference-CQqeAyER.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-Q9MTQ83c.js → KnowledgeGraph-cuGVxHrw.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-B_fyjZK9.js → Logs-DIuHri5d.js} +2 -2
  36. package/src/assets/web-panel/assets/{MarkdownRenderer-C0o4FtpD.js → MarkdownRenderer-R91Qw5JA.js} +1 -1
  37. package/src/assets/web-panel/assets/{Marketplace-BIStF9d1.js → Marketplace-CY1VhFGx.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-pGfal768.js → McpTools-BBAbi1vt.js} +5 -5
  39. package/src/assets/web-panel/assets/{Memory-xbNqpIqB.js → Memory-BWYGHxJA.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-B5EQGrIK.js → MobileBridge-CPIFkW7A.js} +1 -1
  41. package/src/assets/web-panel/assets/MobileProjects-DQyWxCho.js +1 -0
  42. package/src/assets/web-panel/assets/{Mtc-a_rmfxJH.js → Mtc-Bo3GnQbx.js} +4 -4
  43. package/src/assets/web-panel/assets/{MtcAudit-BmKuofUr.js → MtcAudit-C8-c4rSW.js} +4 -4
  44. package/src/assets/web-panel/assets/{Multisig-BQbJ-CAN.js → Multisig-ChqMTtoq.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-JtPJKX25.js → NLProgramming-C48TyhvI.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-ZFKznTSG.js → Notes-zogUFWxp.js} +3 -3
  47. package/src/assets/web-panel/assets/{NotificationSettings-B6aHRBBR.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-BFDTAUgS.js → Organization-Boi1dQfR.js} +4 -4
  50. package/src/assets/web-panel/assets/{Overflow-0FoTfbWH.js → Overflow-DM5YWwgA.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-CWd90etw.js → P2P-C57LKpKK.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-DtCGC-W-.js → PdhVaultBrowser-BFkPqu6Q.js} +3 -3
  53. package/src/assets/web-panel/assets/{Permissions-CvQ7nr7T.js → Permissions-D6fB9YSp.js} +4 -4
  54. package/src/assets/web-panel/assets/{PersonalDataHub-rdNPcR-Z.js → PersonalDataHub-Bp7EefEo.js} +3 -3
  55. package/src/assets/web-panel/assets/{Pipeline-CmrfiNOs.js → Pipeline-BVln3hZf.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-D7ep1h_t.js → Privacy-Bf8P3nF6.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-C0xKINHS.js → ProjectInit-DM6wA2E2.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-AOmZFp-F.js → ProjectSettings-CGbc5Iho.js} +2 -2
  59. package/src/assets/web-panel/assets/{Projects-BWHSkXZP.js → Projects-D0p9EOxm.js} +1 -1
  60. package/src/assets/web-panel/assets/{Providers-Cb7JCTPL.js → Providers-B2kJcxS6.js} +1 -1
  61. package/src/assets/web-panel/assets/{QrScannerModal-BDMehcXC.js → QrScannerModal-Cxu7dXYy.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-BF6_1nvx.js → QuickAsk-DTlrTPms.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend-BHfT-A28.js → Recommend-Cm3X-cCj.js} +1 -1
  64. package/src/assets/web-panel/assets/RemoteSession-DNb2kjvt.js +5 -0
  65. package/src/assets/web-panel/assets/{Reputation-CsWHLEcj.js → Reputation-CZUFFjc1.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-D6srnWhm.js → Row-DAPgloxA.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-Xhr-KyVd.js → RssFeed-dsx9S793.js} +3 -3
  68. package/src/assets/web-panel/assets/{Search-vIbIJvwL.js → Search-DnnC8kz-.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-Bzi5Aiko.js → Security-VuZknRMK.js} +4 -4
  70. package/src/assets/web-panel/assets/{Services-BHtVX52P.js → Services-B3XNX8Vx.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-C0R8B2jf.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-0B37mxVU.js → Sla-HzU56n1z.js} +1 -1
  74. package/src/assets/web-panel/assets/{SpeechSettings-0V2jE1Bs.js → SpeechSettings-CRle7Jl2.js} +1 -1
  75. package/src/assets/web-panel/assets/{SyncSettings-CYedRzaj.js → SyncSettings-DWadz7Sl.js} +2 -2
  76. package/src/assets/web-panel/assets/{Tasks-D-R1x8vm.js → Tasks-CNVTDGg8.js} +1 -1
  77. package/src/assets/web-panel/assets/{Templates-BKoHztGT.js → Templates-BBAgvrlM.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant--17nwVNZ.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-C5jx4AE3.js → TimelineRenderer-mTyjNE6r.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-DYJKYa9t.js → Tokens-Bz97oBgs.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-DChpWiQ9.js → Trigger-BTRKC140.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-DfWG52EA.js → Trust-B4A_KuyX.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-CMugYcyA.js → UkeySign-DES9TmLU.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-BOSmrHAd.js → VideoEditing-ClXs7Qxp.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-D5g3k3Sa.js → Wallet-IzZqFz-7.js} +4 -4
  87. package/src/assets/web-panel/assets/{WebAuthn-D-7u4Mkc.js → WebAuthn-BtOP04g_.js} +3 -3
  88. package/src/assets/web-panel/assets/{WorkflowEditor-CFzZMSUJ.js → WorkflowEditor-_0cqnopY.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-VbR6l6mc.js → chat-ax7193uU.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-BSZn8EDS.js → colors-Bu4WGJah.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-y74obMEq.js → compact-item-BX1dlTW0.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-C326bjex.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-D_INJQT_.js → hasIn-D5wd817l.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-CsovTpx9.js → index-5PYYkr8S.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-9PIVuXqo.js → index-A4uBPQCz.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-BjcWKg1S.js → index-BAtBNfkr.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-CMHqs3Jb.js → index-BLLsUNDc.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-B7SrC-On.js → index-BQtoRyTO.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DUU2606o.js → index-BRfXoRuh.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-Iw0FfqUz.js → index-Bad2CYeH.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-Dlxh9D8D.js → index-BcGdL3sG.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DuIkfnTF.js → index-C3HmzCLt.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-E_v1ZCTP.js → index-C8DkWyNr.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-4eyH-eC2.js → index-C8tLR2TG.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-BnSfnSMP.js → index-CP8ELJBc.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-DwHSZLXg.js → index-CUForzsG.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-C2NyllnW.js → index-CYRE0NJA.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Bnua8IX3.js → index-CeVZaJSC.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-KF9Zmqln.js → index-CfzxR61U.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-Cr3uuz0C.js → index-Ci3y1ZAv.js} +3 -3
  112. package/src/assets/web-panel/assets/{index-DBkzrpiL.js → index-CjEJjl5C.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-abmn_8Yz.js → index-Cv7bVWJ5.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-qMA4GYdQ.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-jYaogFE8.js → index-D9op8poE.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-GA80ir_u.js → index-DF1TysIF.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CzE53HiB.js → index-DYo9S5OT.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-gINyI1rh.js → index-D_cycOET.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-FQBsuExX.js → index-Db3CpWTr.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-IZAWt0H8.js → index-DkD1K-fF.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-C327pLbw.js → index-DmPJ6T6F.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-DdyjrCAu.js → index-DmVUeWUk.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-CfLJ42kv.js → index-Dzdr0zDf.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-DkH1JvEt.js → index-PBLzwYnu.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-DNMxIsDg.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-C-ZCaUJc.js → index-h3KJZr95.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-Bfw2hf2s.js → index-iHcPtQ2e.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-BJi3UqBt.js → index-jzlzm4VK.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-BY8-nCgs.js → index-o14NNnxw.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-nSn2-C4N.js → index-tYPSfGbd.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-4PIeTM--.js → index-ytp2H5Zx.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-DI0Zaf8-.js → initDefaultProps-D2Iut83B.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-BZDKSy3Z.js → motion-BuaJVdK9.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-DsIW01Vp.js → move-CaEuM92y.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-CohkDhsf.js → mtc-parser-wuKNBwys.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-DpiN5rzg.js → omit-7a3eklaq.js} +1 -1
  139. package/src/assets/web-panel/assets/{pickAttrs-qbuqni3y.js → pickAttrs-Dn4z7KvJ.js} +1 -1
  140. package/src/assets/web-panel/assets/{placementArrow-mBky6714.js → placementArrow-DVn_qT4-.js} +1 -1
  141. package/src/assets/web-panel/assets/{responsiveObserve-Bas3eQ2K.js → responsiveObserve-Dodz1OMQ.js} +1 -1
  142. package/src/assets/web-panel/assets/{slide-CBx_SKoK.js → slide-CxoGskbp.js} +1 -1
  143. package/src/assets/web-panel/assets/{statusUtils-BlYguJSV.js → statusUtils-DBh_epQH.js} +1 -1
  144. package/src/assets/web-panel/assets/{styleChecker-BCYQmRGv.js → styleChecker-RXQ4gG5P.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFlexGapSupport-Dp5dybLM.js → useFlexGapSupport-1Wxm0HEG.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFs-DHAMBgA2.js → useFs-CI_ySNxJ.js} +1 -1
  147. package/src/assets/web-panel/assets/{usePersonalDataHub-W6jsSw76.js → usePersonalDataHub-C6973rZP.js} +1 -1
  148. package/src/assets/web-panel/assets/{vnode-BkI6aayc.js → vnode-CalynwKr.js} +1 -1
  149. package/src/assets/web-panel/assets/{zoom-C_IMGueq.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/background-session.js +11 -1
  153. package/src/commands/batch.js +160 -5
  154. package/src/commands/plugin.js +90 -27
  155. package/src/commands/session.js +31 -1
  156. package/src/commands/team.js +212 -6
  157. package/src/data/changelog.json +13 -0
  158. package/src/harness/jsonl-session-store.js +57 -6
  159. package/src/harness/mcp-client.js +65 -43
  160. package/src/lib/agent-batch.js +4 -1
  161. package/src/lib/agent-team/team-worktree.js +3 -0
  162. package/src/lib/async-hook-supervisor.cjs +82 -10
  163. package/src/lib/async-hook-supervisor.js +50 -4
  164. package/src/lib/collaboration-run-store.js +362 -0
  165. package/src/lib/hook-runner.cjs +98 -17
  166. package/src/lib/hook-runner.js +77 -6
  167. package/src/lib/hook-shell-command.cjs +148 -0
  168. package/src/lib/hooks-v2-runtime.js +188 -77
  169. package/src/lib/jsonl-session-store.js +2 -0
  170. package/src/lib/lsp/__tests__/lsp-client.test.js +18 -0
  171. package/src/lib/lsp/lsp-client.js +12 -1
  172. package/src/lib/plugin-monitor-supervisor.js +53 -16
  173. package/src/lib/plugin-runtime/bin.js +1 -1
  174. package/src/lib/plugin-runtime/install.js +249 -57
  175. package/src/lib/plugin-runtime/mcp.js +21 -2
  176. package/src/lib/plugin-runtime/monitors.js +19 -3
  177. package/src/lib/plugin-runtime/sandbox-policy.js +99 -0
  178. package/src/lib/process-execution-broker/index.js +453 -12
  179. package/src/lib/process-execution-broker/linux-generic-bwrap-runtime.js +1347 -0
  180. package/src/lib/process-execution-broker/linux-generic-bwrap.js +1260 -0
  181. package/src/lib/process-execution-broker/platform-sandbox.js +580 -56
  182. package/src/lib/session-usage.js +202 -2
  183. package/src/lib/stream-retry.js +29 -0
  184. package/src/repl/agent-repl.js +32 -3
  185. package/src/runtime/agent-core.js +32 -4
  186. package/src/runtime/headless-runner.js +37 -0
  187. package/src/runtime/headless-stream.js +34 -2
  188. package/src/assets/web-panel/assets/ChatBubbleRenderer-CI_jT0ru.js +0 -1
  189. package/src/assets/web-panel/assets/MobileProjects-VTc3gT1y.js +0 -1
  190. package/src/assets/web-panel/assets/OrderTableRenderer-DdcsOqEz.js +0 -1
  191. package/src/assets/web-panel/assets/RemoteSession-B6EEf8hh.js +0 -5
  192. package/src/assets/web-panel/assets/Skills-DtT6rWOX.js +0 -1
  193. package/src/assets/web-panel/assets/Terminal-Dnkos7vW.js +0 -3
  194. package/src/assets/web-panel/assets/devWarning-D3Bho_6u.js +0 -1
  195. package/src/assets/web-panel/assets/index-5iAFwYx1.js +0 -1
  196. package/src/assets/web-panel/assets/index-BfnB7LPx.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" ||
@@ -659,6 +730,9 @@ class ProcessExecutionBroker extends EventEmitter {
659
730
  "pluginTreeContentSnapshotScope",
660
731
  "pluginTreeContentSnapshotMechanism",
661
732
  "pluginTreeSnapshotConsistency",
733
+ "initialDynamicLoadClosureScope",
734
+ "initialDynamicLoadClosureMechanism",
735
+ "initialDynamicInterpreter",
662
736
  ]) {
663
737
  if (
664
738
  plan.runtimeProbe[field] !== undefined &&
@@ -677,6 +751,7 @@ class ProcessExecutionBroker extends EventEmitter {
677
751
  "pluginTreeContentSnapshot",
678
752
  "pluginTreeSnapshotContractBound",
679
753
  "pluginTreeSnapshotAtomic",
754
+ "initialDynamicLoadClosureDescriptorBound",
680
755
  ]) {
681
756
  if (
682
757
  plan.runtimeProbe[field] !== undefined &&
@@ -691,6 +766,8 @@ class ProcessExecutionBroker extends EventEmitter {
691
766
  for (const field of [
692
767
  "pluginTreeContentSnapshotFiles",
693
768
  "pluginTreeContentSnapshotBytes",
769
+ "initialDynamicDependencyCount",
770
+ "initialDynamicRuntimeFileCount",
694
771
  ]) {
695
772
  if (
696
773
  plan.runtimeProbe[field] !== undefined &&
@@ -716,6 +793,19 @@ class ProcessExecutionBroker extends EventEmitter {
716
793
  "Sandbox runtime probe pluginTreeContentSnapshotDigest must be a lowercase SHA-256 value",
717
794
  );
718
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
+ }
719
809
  const pluginTreeSnapshot =
720
810
  plan.runtimeProbe.pluginTreeContentSnapshot === true;
721
811
  const pluginTreeEvidenceFields = [
@@ -899,6 +989,277 @@ class ProcessExecutionBroker extends EventEmitter {
899
989
  );
900
990
  }
901
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
+ }
902
1263
  runtimeProbe = {
903
1264
  kind: plan.runtimeProbe.kind,
904
1265
  attempted: plan.runtimeProbe.attempted,
@@ -944,6 +1305,19 @@ class ProcessExecutionBroker extends EventEmitter {
944
1305
  runtimeProbe[field] = plan.runtimeProbe[field];
945
1306
  }
946
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
+ }
947
1321
  if (supervisorIdentity !== undefined) {
948
1322
  runtimeProbe.supervisorExecutableIdentity = {
949
1323
  path: supervisorIdentity.path,
@@ -960,6 +1334,12 @@ class ProcessExecutionBroker extends EventEmitter {
960
1334
  };
961
1335
  }
962
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
+ );
1342
+ }
963
1343
  const postSpawn = plan.postSpawn || { required: false, mode: "none" };
964
1344
  if (
965
1345
  postSpawn.required &&
@@ -981,6 +1361,12 @@ class ProcessExecutionBroker extends EventEmitter {
981
1361
  policyAttested,
982
1362
  policyDigest,
983
1363
  runtimeProbe,
1364
+ ...(sanitizedFilesystemPolicy
1365
+ ? {
1366
+ filesystemPolicy: sanitizedFilesystemPolicy,
1367
+ networkPolicy: sanitizedNetworkPolicy,
1368
+ }
1369
+ : {}),
984
1370
  postSpawn: { ...postSpawn },
985
1371
  };
986
1372
  }
@@ -1135,6 +1521,39 @@ class ProcessExecutionBroker extends EventEmitter {
1135
1521
  auditEntry.sandboxPolicyAttested =
1136
1522
  typeof plan?.policyAttested === "boolean" ? plan.policyAttested : null;
1137
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;
1138
1557
  auditEntry.sandboxCandidateReason = plan?.candidateBackend
1139
1558
  ? plan?.reason || null
1140
1559
  : null;
@@ -1396,12 +1815,13 @@ class ProcessExecutionBroker extends EventEmitter {
1396
1815
 
1397
1816
  _writeRplEntry(auditEntry, status = "started", error = null) {
1398
1817
  const rpl = getRpl();
1399
- if (!rpl || !rpl.default) return;
1818
+ if (!rpl) return;
1400
1819
  try {
1401
1820
  const traceCtx = this._getTraceContext();
1402
- rpl.default.append(
1821
+ if (typeof rpl.record !== "function") return;
1822
+ rpl.record(
1823
+ "process.execution",
1403
1824
  {
1404
- kind: "process.execution",
1405
1825
  component: auditEntry.origin,
1406
1826
  action: "spawn",
1407
1827
  artifactId: auditEntry.executionId,
@@ -1422,6 +1842,15 @@ class ProcessExecutionBroker extends EventEmitter {
1422
1842
  policy: auditEntry.policy,
1423
1843
  scope: auditEntry.scope,
1424
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
+ },
1425
1854
  traceId:
1426
1855
  traceCtx?.traceId || auditEntry.traceId || `trace-${Date.now()}`,
1427
1856
  parentSpanId: traceCtx?.spanId || null,
@@ -1607,6 +2036,18 @@ class ProcessExecutionBroker extends EventEmitter {
1607
2036
  proc,
1608
2037
  sandboxPlan.cleanup,
1609
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
+ }
1610
2051
  try {
1611
2052
  this._runPostSpawnSandbox(proc, sandboxPlan, auditEntry);
1612
2053
  auditEntry.pid = proc.pid;