chainlesschain 0.162.180 → 0.162.182

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 (263) hide show
  1. package/package.json +7 -3
  2. package/scripts/build-windows-sandbox-helper.ps1 +163 -0
  3. package/src/assets/web-panel/.build-hash +1 -1
  4. package/src/assets/web-panel/assets/{AIOps-D_TIL54O.js → AIOps-DzZ5_xoj.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-eQwy9r-f.js → ActionButton-DeLXddIg.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-D2eNuDgT.js → Analytics-rvDCmet1.js} +3 -3
  7. package/src/assets/web-panel/assets/{AppLayout-CFhwOFsf.js → AppLayout-Yt6QVDnp.js} +5 -5
  8. package/src/assets/web-panel/assets/{Artifacts-CJUMw6PB.js → Artifacts-BS112K5L.js} +1 -1
  9. package/src/assets/web-panel/assets/{Audit-CDB9V58o.js → Audit-0wJuQrNu.js} +1 -1
  10. package/src/assets/web-panel/assets/{BackgroundAgents-TBppYFjN.js → BackgroundAgents-B90PMgbn.js} +1 -1
  11. package/src/assets/web-panel/assets/{Backup-CYEOUpzJ.js → Backup-TkgMglQQ.js} +1 -1
  12. package/src/assets/web-panel/assets/{BaseInput-C88fFT2u.js → BaseInput-CQVS9p1l.js} +1 -1
  13. package/src/assets/web-panel/assets/{Chat-mkr1vC3N.js → Chat-YTjQHoC7.js} +6 -6
  14. package/src/assets/web-panel/assets/ChatBubbleRenderer-PR074hUN.js +1 -0
  15. package/src/assets/web-panel/assets/{Checkbox-CVU4xqti.js → Checkbox-5bwaOabq.js} +1 -1
  16. package/src/assets/web-panel/assets/{Codegen-rrNcByz3.js → Codegen-BFmNQ_Xe.js} +1 -1
  17. package/src/assets/web-panel/assets/{Col-Cqu-zCvh.js → Col-BT_u4Dzp.js} +1 -1
  18. package/src/assets/web-panel/assets/{Community-RGRlSgXV.js → Community-CJP52u5b.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compact-DBm6epOK.js → Compact-BpzhJE9i.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compliance-BgKw5iaW.js → Compliance-Cg7rfslp.js} +1 -1
  21. package/src/assets/web-panel/assets/{Cowork-BqQcNO3Z.js → Cowork-JisxL6Yy.js} +3 -3
  22. package/src/assets/web-panel/assets/{Cron-DO5gTFNb.js → Cron-Bu7Ug_MC.js} +2 -2
  23. package/src/assets/web-panel/assets/{Crosschain-B8hbJNuN.js → Crosschain-CvuqoLdj.js} +1 -1
  24. package/src/assets/web-panel/assets/{DID-B08bFJ2C.js → DID-C2u9G8Pu.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dashboard-xNdy_ifo.js → Dashboard-BFt5Yv3d.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dropdown-D-KIZgWL.js → Dropdown-DIaT9Wxq.js} +1 -1
  27. package/src/assets/web-panel/assets/{EmailListRenderer-DKCvsaGo.js → EmailListRenderer-D_A601Y4.js} +1 -1
  28. package/src/assets/web-panel/assets/{FamilyGuardDashboard-D_cfqama.js → FamilyGuardDashboard--IyQ8I8w.js} +1 -1
  29. package/src/assets/web-panel/assets/{Federation-B-UqQD68.js → Federation-BihWHxuY.js} +1 -1
  30. package/src/assets/web-panel/assets/{FormItemContext-BWWvWuJW.js → FormItemContext-BB8dOXc_.js} +1 -1
  31. package/src/assets/web-panel/assets/{GenericCardRenderer-CPchx6N7.js → GenericCardRenderer-DQYhj1HH.js} +1 -1
  32. package/src/assets/web-panel/assets/{Git-Vx4co9Ff.js → Git-B-2QZxGf.js} +2 -2
  33. package/src/assets/web-panel/assets/{Governance-D4x0pp_m.js → Governance-CusSb-nG.js} +1 -1
  34. package/src/assets/web-panel/assets/{Inference-T3KvwPYR.js → Inference-BAjmvPPL.js} +1 -1
  35. package/src/assets/web-panel/assets/{KnowledgeGraph-Ddv3KUv3.js → KnowledgeGraph-DoNYWKYq.js} +1 -1
  36. package/src/assets/web-panel/assets/{Logs-DfH-Dkae.js → Logs-B8fKWD-n.js} +2 -2
  37. package/src/assets/web-panel/assets/{MarkdownRenderer-DHW3PbCq.js → MarkdownRenderer-BlJm1J7E.js} +1 -1
  38. package/src/assets/web-panel/assets/{Marketplace-tjgb0R3D.js → Marketplace-CyOscbSL.js} +1 -1
  39. package/src/assets/web-panel/assets/{McpTools-DHAk5nYX.js → McpTools-Ex6Om5da.js} +5 -5
  40. package/src/assets/web-panel/assets/{Memory-A2Yx7thM.js → Memory-CDcD8l8r.js} +2 -2
  41. package/src/assets/web-panel/assets/{MobileBridge-BEmTVfN5.js → MobileBridge-xfBqoFDg.js} +1 -1
  42. package/src/assets/web-panel/assets/{MobileProjects-DuFHUgE4.js → MobileProjects-BwObMMA2.js} +1 -1
  43. package/src/assets/web-panel/assets/{Mtc-BDSll0OZ.js → Mtc-CIWd36OV.js} +4 -4
  44. package/src/assets/web-panel/assets/{MtcAudit-CuBvluaS.js → MtcAudit-CPX0ouuA.js} +4 -4
  45. package/src/assets/web-panel/assets/{Multisig-BmXAA-Sb.js → Multisig-BDJsIUuW.js} +3 -3
  46. package/src/assets/web-panel/assets/{NLProgramming-ci2stZAe.js → NLProgramming-DEkbuD3N.js} +1 -1
  47. package/src/assets/web-panel/assets/{Notes-D-1RpqnS.js → Notes-DJpHRhH1.js} +3 -3
  48. package/src/assets/web-panel/assets/{NotificationSettings-C0GyitIT.js → NotificationSettings-C1UZ-Qd5.js} +1 -1
  49. package/src/assets/web-panel/assets/{OrderTableRenderer-U2bN-hj5.js → OrderTableRenderer-GlJtqLjT.js} +1 -1
  50. package/src/assets/web-panel/assets/{Organization-BNZgpPci.js → Organization-Bbhj0fac.js} +4 -4
  51. package/src/assets/web-panel/assets/{Overflow-CDidKmUN.js → Overflow-1H04x3kx.js} +1 -1
  52. package/src/assets/web-panel/assets/{P2P-BnreBaXq.js → P2P-CDpPe3et.js} +2 -2
  53. package/src/assets/web-panel/assets/{PdhVaultBrowser-DwJUxO9j.js → PdhVaultBrowser-MUX0Bpvw.js} +3 -3
  54. package/src/assets/web-panel/assets/{Permissions-BQGgJPH0.js → Permissions-A07-0Ci1.js} +4 -4
  55. package/src/assets/web-panel/assets/{PersonalDataHub-k_fSkCwL.js → PersonalDataHub-DhhDWxAZ.js} +5 -5
  56. package/src/assets/web-panel/assets/{Pipeline-WGqKMqau.js → Pipeline-CyfbJfe-.js} +1 -1
  57. package/src/assets/web-panel/assets/{Privacy-DtHj9Ymq.js → Privacy-CNFps3ED.js} +1 -1
  58. package/src/assets/web-panel/assets/{ProjectInit-B3wH2SFC.js → ProjectInit--T-u3Dr5.js} +2 -2
  59. package/src/assets/web-panel/assets/{ProjectSettings-Cd0cgcA1.js → ProjectSettings-DJmrK2fC.js} +2 -2
  60. package/src/assets/web-panel/assets/Projects-Qx_MdX9k.js +1 -0
  61. package/src/assets/web-panel/assets/{Providers-DTpxEXur.js → Providers-DLzzbOZd.js} +1 -1
  62. package/src/assets/web-panel/assets/{QrScannerModal-B2v6gR-C.js → QrScannerModal-CexOomKS.js} +1 -1
  63. package/src/assets/web-panel/assets/{QuickAsk-D3Nr9xXR.js → QuickAsk-QklGi19_.js} +1 -1
  64. package/src/assets/web-panel/assets/{Recommend-C9inoMky.js → Recommend-Bb9kwSw8.js} +1 -1
  65. package/src/assets/web-panel/assets/RemoteSession-DZuVNNN5.js +5 -0
  66. package/src/assets/web-panel/assets/{Reputation-41KFG646.js → Reputation-Dr5cLP0N.js} +1 -1
  67. package/src/assets/web-panel/assets/{Row-DqAaqqCv.js → Row-oCQHYv5t.js} +1 -1
  68. package/src/assets/web-panel/assets/{RssFeed-CMDpCDKc.js → RssFeed-IFDEykIR.js} +3 -3
  69. package/src/assets/web-panel/assets/{Search-B6mtegNL.js → Search-CspVIxDc.js} +1 -1
  70. package/src/assets/web-panel/assets/{Security-BaePFVZ8.js → Security-Bm66o_DH.js} +3 -3
  71. package/src/assets/web-panel/assets/{Services-DeG3Qscl.js → Services-DvanNqXl.js} +2 -2
  72. package/src/assets/web-panel/assets/{Skeleton-D_QP7F90.js → Skeleton-CHjEe9_O.js} +1 -1
  73. package/src/assets/web-panel/assets/{Skills-DLGyUgIA.js → Skills-Cb8jWjMX.js} +1 -1
  74. package/src/assets/web-panel/assets/{Sla-BN2pxW1Q.js → Sla-DxZm1491.js} +1 -1
  75. package/src/assets/web-panel/assets/{SpeechSettings-BWsZPd8B.js → SpeechSettings-DWxEEclC.js} +1 -1
  76. package/src/assets/web-panel/assets/{SyncSettings-VOZRPODW.js → SyncSettings-FIvOFw5p.js} +2 -2
  77. package/src/assets/web-panel/assets/Tasks-CyuLnDFR.js +1 -0
  78. package/src/assets/web-panel/assets/{Templates-eJSob-q0.js → Templates-CaNjzV_t.js} +1 -1
  79. package/src/assets/web-panel/assets/{Tenant-Bdwk8Rwy.js → Tenant-DjlP6TmH.js} +1 -1
  80. package/src/assets/web-panel/assets/Terminal-DwzGMniO.js +3 -0
  81. package/src/assets/web-panel/assets/{TimelineRenderer-D5qkbPKT.js → TimelineRenderer-DoZ8y7y8.js} +1 -1
  82. package/src/assets/web-panel/assets/{Tokens-DKgwn8hI.js → Tokens-390cg2TC.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trigger-HlEHniGM.js → Trigger-CLrtCj5_.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trust-CdPcsBpN.js → Trust-DpESfSPn.js} +1 -1
  85. package/src/assets/web-panel/assets/{UkeySign-vAdXd-vG.js → UkeySign-CN6279O0.js} +1 -1
  86. package/src/assets/web-panel/assets/{VideoEditing-9hHBYFnH.js → VideoEditing-DPtAUlSe.js} +1 -1
  87. package/src/assets/web-panel/assets/{Wallet-Dxh5d1yR.js → Wallet-nKOMV_1n.js} +4 -4
  88. package/src/assets/web-panel/assets/{WebAuthn-BsFmLHkp.js → WebAuthn-HuXlSOc4.js} +5 -5
  89. package/src/assets/web-panel/assets/{WorkflowEditor-Cn0OIwLn.js → WorkflowEditor-CUfFjARi.js} +1 -1
  90. package/src/assets/web-panel/assets/chat-6Eq0PcZJ.js +1 -0
  91. package/src/assets/web-panel/assets/{colors-Du9jzLN0.js → colors-BP_Sf6Iy.js} +1 -1
  92. package/src/assets/web-panel/assets/{compact-item-DhEscfzw.js → compact-item-BufMKIh5.js} +1 -1
  93. package/src/assets/web-panel/assets/{createContext-CwzEfF3i.js → createContext-BBMXxWSW.js} +1 -1
  94. package/src/assets/web-panel/assets/devWarning-DgVKduH2.js +1 -0
  95. package/src/assets/web-panel/assets/{hasIn-DT_GSE6J.js → hasIn-fUK_tRO2.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-tND8-TDU.js → index-2A5ph8b2.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-B8s5FxJY.js → index-3FuwBewR.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-53z1YUxX.js → index-6GmBa4Kg.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-BFD0cEna.js → index-B2vS66eI.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-CQWxDOvM.js → index-B7Etk0Te.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-VeHs6qH0.js → index-B9WYSn4m.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-CGvgnfl9.js → index-BHy6yNiF.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-D3llLkYM.js → index-BMLHv389.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-Dny_ZnAO.js → index-BWKoBU8R.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-DzjzrOli.js → index-Bkg4ZePE.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-DN60VBn5.js → index-C44atv4k.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-v5HLYCVa.js → index-CE2DdTP2.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-BF-ZCVGE.js → index-CGjmILDm.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-gFjYdstW.js → index-CW_G-MXw.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-NA2oBLSB.js → index-CZ6Yt17L.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-Mobw3PHs.js → index-CeASi4fr.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-DWL3SYN3.js → index-CgiECHu2.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-1LoutPJd.js → index-Cp8vhyZy.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BnHhFnwt.js → index-CwSf5pnf.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-B6QDWRLk.js → index-D4_MuGkd.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-D-QkW1fp.js → index-D9vU25ij.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-C4SN3by5.js → index-DASluSqY.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CyEhUJcu.js → index-DLpIs_P_.js} +1 -1
  119. package/src/assets/web-panel/assets/index-DOZTSoS7.js +1 -0
  120. package/src/assets/web-panel/assets/{index-BrkJ7JPm.js → index-DPdUNk1i.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-Cnok8mhZ.js → index-DVsqvI4M.js} +1 -1
  122. package/src/assets/web-panel/assets/index-DhpvjpqI.js +1 -0
  123. package/src/assets/web-panel/assets/{index-CAVW0cWM.js → index-DmkMXwnR.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-Cc9aPkv-.js → index-DocdRcbd.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-DnVVYKCE.js → index-Dyngbd29.js} +20 -20
  126. package/src/assets/web-panel/assets/{index-D8gt0j7r.js → index-GwdRUZ-x.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-BIYTjbv_.js → index-LvCBfTLo.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-DhXay17G.js → index-cpEli44X.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-BQWENaZf.js → index-fzaMtSJ8.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-DfRDyY1q.js → index-pum7HYBA.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-BgSR2WMG.js → index-t8N1tSeX.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-D5IytTND.js → index-uCbEN7cY.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-DtRwLhee.js → index-wKTLbKyc.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-D4kZoXNr.js → index-wV6iGdpY.js} +1 -1
  135. package/src/assets/web-panel/assets/{initDefaultProps-Cvt59c10.js → initDefaultProps-V5Fo95FM.js} +1 -1
  136. package/src/assets/web-panel/assets/{motion-D15pPEzl.js → motion-BYWU0hUT.js} +1 -1
  137. package/src/assets/web-panel/assets/{move-N55KeXJ7.js → move-Cr1M-J2h.js} +1 -1
  138. package/src/assets/web-panel/assets/{mtc-parser-CyFO1bYP.js → mtc-parser-BysQKi2N.js} +1 -1
  139. package/src/assets/web-panel/assets/{omit-B5IXfxU2.js → omit-D1zHU8GC.js} +1 -1
  140. package/src/assets/web-panel/assets/{pickAttrs-CpVqsulV.js → pickAttrs-CUArxtfi.js} +1 -1
  141. package/src/assets/web-panel/assets/{placementArrow-ME36sMF3.js → placementArrow-ChoYEys0.js} +1 -1
  142. package/src/assets/web-panel/assets/{responsiveObserve-BXAIR1r-.js → responsiveObserve-BQRs3Mo7.js} +1 -1
  143. package/src/assets/web-panel/assets/{slide-BkOX3-Dp.js → slide-B8zbsCkg.js} +1 -1
  144. package/src/assets/web-panel/assets/{statusUtils-Cy4Aklpt.js → statusUtils-C2U8Gs6h.js} +1 -1
  145. package/src/assets/web-panel/assets/{styleChecker-gUd2T206.js → styleChecker-Dd8MgL_V.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFlexGapSupport-CaVD4o99.js → useFlexGapSupport-hknqY5NH.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFs--pFGl0KD.js → useFs-CLTAmcfw.js} +1 -1
  148. package/src/assets/web-panel/assets/{usePersonalDataHub-D45iP86i.js → usePersonalDataHub-ByegHbiB.js} +1 -1
  149. package/src/assets/web-panel/assets/{vnode-BayoChH_.js → vnode-DqlAy5DP.js} +1 -1
  150. package/src/assets/web-panel/assets/{zoom-CpP38poi.js → zoom-DiXiztQn.js} +1 -1
  151. package/src/assets/web-panel/index.html +1 -1
  152. package/src/commands/agenda.js +115 -3
  153. package/src/commands/agent.js +10 -1
  154. package/src/commands/background-session.js +2 -1
  155. package/src/commands/context.js +69 -2
  156. package/src/data/changelog.json +26 -0
  157. package/src/gateways/terminal/PtyManager.js +45 -4
  158. package/src/gateways/ws/background-agent-protocol.js +38 -0
  159. package/src/gateways/ws/message-dispatcher.js +1 -0
  160. package/src/gateways/ws/remote-session-protocol.js +65 -6
  161. package/src/gateways/ws/ws-server.js +18 -2
  162. package/src/harness/background-task-manager.js +70 -2
  163. package/src/harness/feature-flags.js +15 -8
  164. package/src/harness/mcp-client.js +618 -43
  165. package/src/harness/worktree-isolator.js +14 -3
  166. package/src/lazy-dispatch.js +30 -1
  167. package/src/lib/agent-authority.js +22 -0
  168. package/src/lib/agent-core.js +3 -0
  169. package/src/lib/agent-sandbox.js +161 -0
  170. package/src/lib/agent-schedule-store.js +45 -22
  171. package/src/lib/agent-team/team-runner.js +22 -0
  172. package/src/lib/artifact-store.js +35 -0
  173. package/src/lib/async-hook-supervisor.cjs +13 -2
  174. package/src/lib/audit-mtc.js +3 -2
  175. package/src/lib/background-agent-supervisor.js +104 -3
  176. package/src/lib/background-interaction-journal.js +407 -0
  177. package/src/lib/background-interaction-resolver.js +23 -34
  178. package/src/lib/background-session-transport.js +12 -2
  179. package/src/lib/capability-manifest.js +41 -3
  180. package/src/lib/capability-negotiation.js +1 -1
  181. package/src/lib/channels/channel-manager.js +33 -0
  182. package/src/lib/channels/telegram-channel.js +23 -5
  183. package/src/lib/channels/webhook-channel.js +38 -15
  184. package/src/lib/chrome-connector.js +169 -23
  185. package/src/lib/config-manager.js +23 -9
  186. package/src/lib/context-breakdown.js +31 -0
  187. package/src/lib/cowork-cron.js +274 -32
  188. package/src/lib/cross-chain-mtc.js +3 -2
  189. package/src/lib/durable-security-store.js +124 -0
  190. package/src/lib/event-runtime-host.js +67 -6
  191. package/src/lib/event-runtime-store.js +163 -0
  192. package/src/lib/goal-store.js +32 -12
  193. package/src/lib/headless-manifest.js +2 -1
  194. package/src/lib/hook-environment.cjs +58 -0
  195. package/src/lib/hook-manager.js +12 -5
  196. package/src/lib/hook-runner.cjs +122 -28
  197. package/src/lib/hook-runner.js +7 -2
  198. package/src/lib/hooks-v2-producers.js +36 -0
  199. package/src/lib/hooks-v2-runtime.js +329 -52
  200. package/src/lib/interaction-adapter.js +60 -19
  201. package/src/lib/interaction-binding.js +64 -0
  202. package/src/lib/json-schema-output.js +439 -14
  203. package/src/lib/json-schema-validate.js +514 -883
  204. package/src/lib/lan-pairing-tokens.js +115 -57
  205. package/src/lib/lsp/__tests__/lsp-client.test.js +32 -0
  206. package/src/lib/lsp/__tests__/lsp-manager.test.js +25 -0
  207. package/src/lib/lsp/lsp-client.js +4 -0
  208. package/src/lib/lsp/lsp-manager.js +3 -0
  209. package/src/lib/lsp/lsp-server-registry.js +18 -0
  210. package/src/lib/mcp-client.js +1 -0
  211. package/src/lib/mcp-oauth.js +35 -21
  212. package/src/lib/packer/pkg-config-generator.js +3 -0
  213. package/src/lib/permission-decision.js +99 -0
  214. package/src/lib/plugin-monitor-supervisor.js +3 -0
  215. package/src/lib/plugin-runtime/bin.js +1148 -70
  216. package/src/lib/plugin-runtime/capabilities.js +50 -0
  217. package/src/lib/plugin-runtime/capability-consent.js +42 -35
  218. package/src/lib/plugin-runtime/hooks.js +36 -9
  219. package/src/lib/plugin-runtime/install.js +23 -7
  220. package/src/lib/plugin-runtime/lsp.js +4 -0
  221. package/src/lib/plugin-runtime/manifest.js +112 -8
  222. package/src/lib/plugin-runtime/mcp.js +30 -5
  223. package/src/lib/plugin-runtime/monitors.js +11 -0
  224. package/src/lib/plugin-runtime/plugin-options.js +94 -38
  225. package/src/lib/plugin-runtime/policy.js +29 -2
  226. package/src/lib/plugin-runtime/sandbox-policy.js +84 -0
  227. package/src/lib/plugin-runtime/scopes.js +27 -13
  228. package/src/lib/plugin-runtime/trust.js +36 -31
  229. package/src/lib/process-execution-broker/credential-agent.js +114 -16
  230. package/src/lib/process-execution-broker/credential-transport-worker.js +312 -0
  231. package/src/lib/process-execution-broker/credential-transport.js +378 -0
  232. package/src/lib/process-execution-broker/index.js +765 -49
  233. package/src/lib/process-execution-broker/platform-sandbox.js +4233 -138
  234. package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
  235. package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
  236. package/src/lib/process-execution-broker/windows-sandbox.cs +3856 -0
  237. package/src/lib/project-mcp-trust.js +21 -26
  238. package/src/lib/protocol-replay.js +19 -12
  239. package/src/lib/repl-bang-memorize.js +67 -10
  240. package/src/lib/settings-hooks.cjs +13 -0
  241. package/src/lib/skill-loader.js +83 -10
  242. package/src/lib/slash-commands.js +27 -4
  243. package/src/lib/sync-credentials.js +5 -4
  244. package/src/lib/turn-binding.js +8 -6
  245. package/src/repl/agent-repl.js +117 -31
  246. package/src/repl/repl-turn-binding.js +5 -2
  247. package/src/runtime/agent-core.js +699 -70
  248. package/src/runtime/agent-runtime.js +13 -1
  249. package/src/runtime/coding-agent-contract-shared.cjs +3 -3
  250. package/src/runtime/headless-runner.js +105 -7
  251. package/src/runtime/headless-stream.js +209 -23
  252. package/src/runtime/mcp-config.js +29 -17
  253. package/src/runtime/policies/agent-policy.js +2 -0
  254. package/src/workers/background-agent-worker.js +128 -13
  255. package/src/assets/web-panel/assets/ChatBubbleRenderer-C7bofJuA.js +0 -1
  256. package/src/assets/web-panel/assets/Projects-BbgmyQnS.js +0 -1
  257. package/src/assets/web-panel/assets/RemoteSession-Bqk3EYSu.js +0 -4
  258. package/src/assets/web-panel/assets/Tasks-3bDAUz8K.js +0 -1
  259. package/src/assets/web-panel/assets/Terminal-CsMLKIoV.js +0 -3
  260. package/src/assets/web-panel/assets/chat-CJ19O6Dh.js +0 -1
  261. package/src/assets/web-panel/assets/devWarning-BBMFnsja.js +0 -1
  262. package/src/assets/web-panel/assets/index-Do8JMV4N.js +0 -1
  263. package/src/assets/web-panel/assets/index-UYAJ6iNM.js +0 -1
@@ -4,8 +4,8 @@
4
4
  *
5
5
  * 统一拦截所有子进程执行:
6
6
  * - M1: 所有子进程唯一入口,权限检查
7
- * - **P0-1**: 可审计的平台执行计划(macOS Seatbelt / Linux prlimit
8
- * Windows 原生 Job Object 未实现时明确报告 unavailable
7
+ * - **P0-1**: 可审计的平台执行计划(macOS Seatbelt / Linux prlimit /
8
+ * Windows Job Object + Restricted Token
9
9
  * - **P0-1**: 凭据代理 default-on(secrets 永远不裸传给子进程)
10
10
  * - M3: 集成W3C trace context自动传播
11
11
  * - M4: 自动写入Runtime Provenance Ledger (RPL)
@@ -36,9 +36,18 @@ const require = createRequire(import.meta.url);
36
36
  import {
37
37
  applySandbox as _applySandbox,
38
38
  postSpawnSandbox as _postSpawnSandbox,
39
+ SANDBOX_BOUNDARIES,
39
40
  } from "./platform-sandbox.js";
41
+ import { consumeIssuedPluginSandboxExecutionContract } from "../plugin-runtime/bin.js";
40
42
  import { credentialAgent } from "./credential-agent.js";
41
43
 
44
+ const SUPPORTED_SANDBOX_BOUNDARIES = new Set(Object.values(SANDBOX_BOUNDARIES));
45
+ const SUPPORTED_SANDBOX_PROFILES = new Set([
46
+ "default",
47
+ "strict",
48
+ "network-only",
49
+ ]);
50
+
42
51
  // 延迟导入避免循环依赖
43
52
  let _traceCtx = null;
44
53
  let _rpl = null;
@@ -189,6 +198,222 @@ class ProcessExecutionBroker extends EventEmitter {
189
198
  return safe;
190
199
  }
191
200
 
201
+ _normalizePluginExecutableIdentity(raw) {
202
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
203
+ const realPath =
204
+ typeof raw.realPath === "string" && raw.realPath ? raw.realPath : null;
205
+ const sha256 =
206
+ typeof raw.sha256 === "string" && /^[a-f0-9]{64}$/i.test(raw.sha256)
207
+ ? raw.sha256.toLowerCase()
208
+ : null;
209
+ if (!realPath || !sha256) return null;
210
+ return {
211
+ contractVersion: 1,
212
+ realPath,
213
+ sha256,
214
+ bytes:
215
+ Number.isSafeInteger(raw.bytes) && raw.bytes >= 0 ? raw.bytes : null,
216
+ fileId:
217
+ raw.dev !== undefined && raw.ino !== undefined
218
+ ? {
219
+ dev: String(raw.dev),
220
+ ino: String(raw.ino),
221
+ }
222
+ : null,
223
+ mtimeMs: Number.isFinite(raw.mtimeMs) ? raw.mtimeMs : null,
224
+ attestation: "realpath-file-id-sha256",
225
+ };
226
+ }
227
+
228
+ _freezeExecutableIdentity(identity) {
229
+ if (!identity) return null;
230
+ return Object.freeze({
231
+ ...identity,
232
+ fileId: identity.fileId ? Object.freeze({ ...identity.fileId }) : null,
233
+ });
234
+ }
235
+
236
+ _normalizePluginRootIdentity(raw) {
237
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
238
+ if (
239
+ typeof raw.realPath !== "string" ||
240
+ !raw.realPath ||
241
+ raw.dev === undefined ||
242
+ raw.ino === undefined
243
+ ) {
244
+ return null;
245
+ }
246
+ return Object.freeze({
247
+ realPath: raw.realPath,
248
+ fileId: Object.freeze({
249
+ dev: String(raw.dev),
250
+ ino: String(raw.ino),
251
+ }),
252
+ attestation: "realpath-directory-file-id",
253
+ });
254
+ }
255
+
256
+ /**
257
+ * Normalize the private execution contract produced by agent-core for one
258
+ * direct, already-attested strict Plugin Node or static-native bin. Plugin
259
+ * manifests cannot provide this top-level option; they can only add
260
+ * required boundaries.
261
+ */
262
+ _normalizeSandboxExecutionContract(raw, options, requiredBoundaries, launch) {
263
+ if (raw === undefined) return null;
264
+ const invalid = (message) => {
265
+ throw this._sandboxBoundaryError(
266
+ "invalid_sandbox_execution_contract",
267
+ message,
268
+ {
269
+ requiredBoundaries,
270
+ missingBoundaries: requiredBoundaries,
271
+ },
272
+ );
273
+ };
274
+ if (
275
+ !consumeIssuedPluginSandboxExecutionContract(raw, {
276
+ origin: options.origin,
277
+ command: launch?.command,
278
+ args: launch?.args,
279
+ cwd: options.cwd,
280
+ pluginId: options.pluginId,
281
+ pluginVersion: options.pluginVersion,
282
+ pluginSource: options.pluginSource,
283
+ pluginExecutableIdentity: options.pluginExecutableIdentity,
284
+ requiredBoundaries,
285
+ sync: launch?.sync === true,
286
+ })
287
+ ) {
288
+ return invalid(
289
+ "sandboxExecutionContract was not issued for this plugin launch provenance",
290
+ );
291
+ }
292
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
293
+ return invalid("sandboxExecutionContract must be an object");
294
+ }
295
+ const supportedKeys = new Set([
296
+ "contractVersion",
297
+ "kind",
298
+ "pluginRoot",
299
+ "workingDirectory",
300
+ "runtimePath",
301
+ "rootIdentity",
302
+ "entryIdentity",
303
+ "runtimeIdentity",
304
+ ]);
305
+ const unsupportedKey = Object.keys(raw).find(
306
+ (key) => !supportedKeys.has(key),
307
+ );
308
+ if (unsupportedKey) {
309
+ return invalid(
310
+ `sandboxExecutionContract contains unsupported field: ${unsupportedKey}`,
311
+ );
312
+ }
313
+ if (
314
+ raw.contractVersion !== 1 ||
315
+ ![
316
+ "strict-plugin-node-bin",
317
+ "strict-plugin-native-static-elf-bin",
318
+ ].includes(raw.kind)
319
+ ) {
320
+ return invalid("unsupported sandboxExecutionContract kind or version");
321
+ }
322
+ if (
323
+ options.origin !== "plugin:bin" ||
324
+ typeof options.pluginId !== "string" ||
325
+ !options.pluginId ||
326
+ options.shell !== false
327
+ ) {
328
+ return invalid(
329
+ "sandboxExecutionContract is restricted to direct plugin:bin shell:false launches",
330
+ );
331
+ }
332
+
333
+ for (const [label, value] of [
334
+ ["pluginRoot", raw.pluginRoot],
335
+ ["workingDirectory", raw.workingDirectory],
336
+ ["runtimePath", raw.runtimePath],
337
+ ]) {
338
+ if (
339
+ typeof value !== "string" ||
340
+ !value ||
341
+ value.includes("\0") ||
342
+ !path.isAbsolute(value)
343
+ ) {
344
+ return invalid(`sandboxExecutionContract.${label} must be absolute`);
345
+ }
346
+ }
347
+ const entryIdentity = this._normalizePluginExecutableIdentity(
348
+ raw.entryIdentity,
349
+ );
350
+ const runtimeIdentity = this._normalizePluginExecutableIdentity(
351
+ raw.runtimeIdentity,
352
+ );
353
+ const rootIdentity = this._normalizePluginRootIdentity(raw.rootIdentity);
354
+ if (!rootIdentity || !entryIdentity || !runtimeIdentity) {
355
+ return invalid(
356
+ "sandboxExecutionContract requires attested root, entry, and runtime identities",
357
+ );
358
+ }
359
+ if (
360
+ rootIdentity.realPath !== raw.pluginRoot ||
361
+ raw.runtimeIdentity?.requestedPath !== path.resolve(process.execPath) ||
362
+ raw.runtimePath !== runtimeIdentity.realPath ||
363
+ !path.isAbsolute(entryIdentity.realPath) ||
364
+ !path.isAbsolute(runtimeIdentity.realPath)
365
+ ) {
366
+ return invalid(
367
+ "sandboxExecutionContract identity paths do not match the launch contract",
368
+ );
369
+ }
370
+
371
+ const provenanceIdentity = this._normalizePluginExecutableIdentity(
372
+ options.pluginExecutableIdentity,
373
+ );
374
+ if (
375
+ !provenanceIdentity ||
376
+ provenanceIdentity.realPath !== entryIdentity.realPath ||
377
+ provenanceIdentity.sha256 !== entryIdentity.sha256
378
+ ) {
379
+ return invalid(
380
+ "sandboxExecutionContract entry identity does not match plugin provenance",
381
+ );
382
+ }
383
+ const entryRelative = path.relative(
384
+ path.resolve(raw.pluginRoot),
385
+ path.resolve(entryIdentity.realPath),
386
+ );
387
+ if (
388
+ entryRelative === "" ||
389
+ entryRelative === ".." ||
390
+ entryRelative.startsWith(`..${path.sep}`) ||
391
+ path.isAbsolute(entryRelative)
392
+ ) {
393
+ return invalid(
394
+ "sandboxExecutionContract entry must be inside pluginRoot",
395
+ );
396
+ }
397
+
398
+ return Object.freeze({
399
+ contractVersion: 1,
400
+ kind: raw.kind,
401
+ pluginRoot: raw.pluginRoot,
402
+ workingDirectory: raw.workingDirectory,
403
+ runtimePath: raw.runtimePath,
404
+ rootIdentity,
405
+ entryIdentity: this._freezeExecutableIdentity(entryIdentity),
406
+ runtimeIdentity: this._freezeExecutableIdentity(runtimeIdentity),
407
+ });
408
+ }
409
+
410
+ _stripPluginControlOptions(options) {
411
+ delete options.pluginId;
412
+ delete options.pluginVersion;
413
+ delete options.pluginSource;
414
+ delete options.pluginExecutableIdentity;
415
+ }
416
+
192
417
  _sandboxStrictEnabled() {
193
418
  return process.env.CC_SANDBOX_STRICT === "1";
194
419
  }
@@ -197,16 +422,98 @@ class ProcessExecutionBroker extends EventEmitter {
197
422
  return process.env.CC_SANDBOX_DISABLE === "1";
198
423
  }
199
424
 
200
- _sandboxUnavailablePlan(command, args, options, reason) {
425
+ /**
426
+ * Normalize the public per-spawn boundary contract. `requiredBoundaries` is
427
+ * retained as a top-level alias so callers can adopt the contract without
428
+ * migrating all spawn options to `sandboxPolicy` in one change.
429
+ *
430
+ * @param {Object} options
431
+ * @returns {{profile: "default"|"strict"|"network-only"|null, requiredBoundaries: string[]}}
432
+ */
433
+ _normalizeSandboxPolicy(options = {}, launch = {}) {
434
+ const rawPolicy = options.sandboxPolicy;
435
+ if (
436
+ rawPolicy !== undefined &&
437
+ (rawPolicy === null ||
438
+ typeof rawPolicy !== "object" ||
439
+ Array.isArray(rawPolicy))
440
+ ) {
441
+ throw this._sandboxBoundaryError(
442
+ "invalid_sandbox_policy",
443
+ "sandboxPolicy must be an object",
444
+ );
445
+ }
446
+
447
+ const direct = options.requiredBoundaries;
448
+ const nested = rawPolicy?.requiredBoundaries;
449
+ for (const [name, value] of [
450
+ ["requiredBoundaries", direct],
451
+ ["sandboxPolicy.requiredBoundaries", nested],
452
+ ]) {
453
+ if (value !== undefined && !Array.isArray(value)) {
454
+ throw this._sandboxBoundaryError(
455
+ "invalid_required_boundaries",
456
+ `${name} must be an array`,
457
+ );
458
+ }
459
+ }
460
+
461
+ const requiredBoundaries = [];
462
+ for (const boundary of [...(direct || []), ...(nested || [])]) {
463
+ if (
464
+ typeof boundary !== "string" ||
465
+ !SUPPORTED_SANDBOX_BOUNDARIES.has(boundary)
466
+ ) {
467
+ throw this._sandboxBoundaryError(
468
+ "invalid_required_boundary",
469
+ `Unsupported sandbox boundary: ${String(boundary)}`,
470
+ {
471
+ requiredBoundaries,
472
+ missingBoundaries: [String(boundary)],
473
+ },
474
+ );
475
+ }
476
+ if (!requiredBoundaries.includes(boundary)) {
477
+ requiredBoundaries.push(boundary);
478
+ }
479
+ }
480
+
481
+ const profile = rawPolicy?.profile ?? null;
482
+ if (profile !== null && !SUPPORTED_SANDBOX_PROFILES.has(profile)) {
483
+ throw this._sandboxBoundaryError(
484
+ "invalid_sandbox_profile",
485
+ `Unsupported sandbox profile: ${String(profile)}`,
486
+ { requiredBoundaries },
487
+ );
488
+ }
489
+ const executionContract = this._normalizeSandboxExecutionContract(
490
+ options.sandboxExecutionContract,
491
+ options,
492
+ requiredBoundaries,
493
+ launch,
494
+ );
495
+ return { profile, requiredBoundaries, executionContract };
496
+ }
497
+
498
+ _stripSandboxControlOptions(options) {
499
+ delete options.sandboxPolicy;
500
+ delete options.requiredBoundaries;
501
+ delete options.sandboxExecutionContract;
502
+ }
503
+
504
+ _sandboxUnavailablePlan(command, args, options, reason, sandboxPolicy = {}) {
201
505
  return {
202
506
  contractVersion: 1,
203
507
  applied: false,
204
508
  platform: process.platform,
205
- profile: "default",
509
+ profile: sandboxPolicy.profile || "default",
206
510
  command,
207
511
  args: [...(args || [])],
208
512
  options: { ...options },
209
513
  enforcement: null,
514
+ backend: null,
515
+ guarantees: [],
516
+ requiredBoundaries: [...(sandboxPolicy.requiredBoundaries || [])],
210
517
  reason,
211
518
  postSpawn: { required: false, mode: "none" },
212
519
  };
@@ -219,6 +526,27 @@ class ProcessExecutionBroker extends EventEmitter {
219
526
  return error;
220
527
  }
221
528
 
529
+ _sandboxBoundaryError(reason, message = reason, metadata = {}) {
530
+ const error = this._sandboxError(reason, message);
531
+ error.code = "ERR_PROCESS_SANDBOX_BOUNDARY_UNSATISFIED";
532
+ error.sandboxFailClosed = true;
533
+ error.requiredBoundaries = [...(metadata.requiredBoundaries || [])];
534
+ error.actualGuarantees = [...(metadata.actualGuarantees || [])];
535
+ error.missingBoundaries = [...(metadata.missingBoundaries || [])];
536
+ error.sandboxBackend = metadata.sandboxBackend || null;
537
+ error.sandboxCandidateBackend = metadata.sandboxCandidateBackend || null;
538
+ error.sandboxRuntimeProbe = metadata.sandboxRuntimeProbe
539
+ ? { ...metadata.sandboxRuntimeProbe }
540
+ : null;
541
+ error.sandboxPolicyAttested =
542
+ typeof metadata.sandboxPolicyAttested === "boolean"
543
+ ? metadata.sandboxPolicyAttested
544
+ : null;
545
+ error.sandboxPolicyDigest = metadata.sandboxPolicyDigest || null;
546
+ error.sandboxCandidateReason = metadata.sandboxCandidateReason || null;
547
+ return error;
548
+ }
549
+
222
550
  _validateSandboxPlan(plan) {
223
551
  if (!plan || typeof plan !== "object") {
224
552
  throw this._sandboxError(
@@ -262,6 +590,125 @@ class ProcessExecutionBroker extends EventEmitter {
262
590
  "Unavailable sandbox spawn plan must provide a reason",
263
591
  );
264
592
  }
593
+ const backend = plan.backend ?? plan.enforcement ?? null;
594
+ if (plan.applied && typeof backend !== "string") {
595
+ throw this._sandboxError(
596
+ "invalid_sandbox_plan",
597
+ "Applied sandbox spawn plan must name its backend",
598
+ );
599
+ }
600
+ const guarantees = plan.guarantees ?? [];
601
+ if (
602
+ !Array.isArray(guarantees) ||
603
+ guarantees.some(
604
+ (boundary) =>
605
+ typeof boundary !== "string" ||
606
+ !SUPPORTED_SANDBOX_BOUNDARIES.has(boundary),
607
+ )
608
+ ) {
609
+ throw this._sandboxError(
610
+ "invalid_sandbox_plan",
611
+ "Sandbox spawn plan guarantees must use supported boundary identifiers",
612
+ );
613
+ }
614
+ const candidateBackend = plan.candidateBackend ?? null;
615
+ if (candidateBackend !== null && typeof candidateBackend !== "string") {
616
+ throw this._sandboxError(
617
+ "invalid_sandbox_plan",
618
+ "Sandbox candidate backend must be a string",
619
+ );
620
+ }
621
+ const policyAttested = plan.policyAttested ?? null;
622
+ if (policyAttested !== null && typeof policyAttested !== "boolean") {
623
+ throw this._sandboxError(
624
+ "invalid_sandbox_plan",
625
+ "Sandbox policy attestation must be boolean",
626
+ );
627
+ }
628
+ const policyDigest = plan.policyDigest ?? null;
629
+ if (
630
+ policyDigest !== null &&
631
+ (typeof policyDigest !== "string" || !/^[a-f0-9]{64}$/.test(policyDigest))
632
+ ) {
633
+ throw this._sandboxError(
634
+ "invalid_sandbox_plan",
635
+ "Sandbox policy digest must be a lowercase SHA-256 value",
636
+ );
637
+ }
638
+ let runtimeProbe = null;
639
+ if (plan.runtimeProbe !== null && plan.runtimeProbe !== undefined) {
640
+ if (
641
+ typeof plan.runtimeProbe !== "object" ||
642
+ Array.isArray(plan.runtimeProbe) ||
643
+ typeof plan.runtimeProbe.kind !== "string" ||
644
+ typeof plan.runtimeProbe.attempted !== "boolean" ||
645
+ typeof plan.runtimeProbe.runnable !== "boolean" ||
646
+ (plan.runtimeProbe.reason !== null &&
647
+ typeof plan.runtimeProbe.reason !== "string")
648
+ ) {
649
+ throw this._sandboxError(
650
+ "invalid_sandbox_plan",
651
+ "Sandbox runtime probe must use the typed probe contract",
652
+ );
653
+ }
654
+ for (const field of [
655
+ "probeRuntime",
656
+ "targetRuntime",
657
+ "contentSnapshotScope",
658
+ "contentSnapshotMechanism",
659
+ ]) {
660
+ if (
661
+ plan.runtimeProbe[field] !== undefined &&
662
+ (typeof plan.runtimeProbe[field] !== "string" ||
663
+ !plan.runtimeProbe[field])
664
+ ) {
665
+ throw this._sandboxError(
666
+ "invalid_sandbox_plan",
667
+ `Sandbox runtime probe ${field} must be a non-empty string`,
668
+ );
669
+ }
670
+ }
671
+ for (const field of ["contentSnapshot", "handleAtomic"]) {
672
+ if (
673
+ plan.runtimeProbe[field] !== undefined &&
674
+ typeof plan.runtimeProbe[field] !== "boolean"
675
+ ) {
676
+ throw this._sandboxError(
677
+ "invalid_sandbox_plan",
678
+ `Sandbox runtime probe ${field} must be boolean`,
679
+ );
680
+ }
681
+ }
682
+ runtimeProbe = {
683
+ kind: plan.runtimeProbe.kind,
684
+ attempted: plan.runtimeProbe.attempted,
685
+ runnable: plan.runtimeProbe.runnable,
686
+ reason: plan.runtimeProbe.reason,
687
+ ...(plan.runtimeProbe.probeRuntime !== undefined
688
+ ? { probeRuntime: plan.runtimeProbe.probeRuntime }
689
+ : {}),
690
+ ...(plan.runtimeProbe.targetRuntime !== undefined
691
+ ? { targetRuntime: plan.runtimeProbe.targetRuntime }
692
+ : {}),
693
+ ...(plan.runtimeProbe.contentSnapshot !== undefined
694
+ ? { contentSnapshot: plan.runtimeProbe.contentSnapshot }
695
+ : {}),
696
+ ...(plan.runtimeProbe.handleAtomic !== undefined
697
+ ? { handleAtomic: plan.runtimeProbe.handleAtomic }
698
+ : {}),
699
+ ...(plan.runtimeProbe.contentSnapshotScope !== undefined
700
+ ? {
701
+ contentSnapshotScope: plan.runtimeProbe.contentSnapshotScope,
702
+ }
703
+ : {}),
704
+ ...(plan.runtimeProbe.contentSnapshotMechanism !== undefined
705
+ ? {
706
+ contentSnapshotMechanism:
707
+ plan.runtimeProbe.contentSnapshotMechanism,
708
+ }
709
+ : {}),
710
+ };
711
+ }
265
712
  const postSpawn = plan.postSpawn || { required: false, mode: "none" };
266
713
  if (
267
714
  postSpawn.required &&
@@ -277,12 +724,54 @@ class ProcessExecutionBroker extends EventEmitter {
277
724
  ...plan,
278
725
  args: [...plan.args],
279
726
  options: { ...plan.options },
727
+ backend,
728
+ guarantees: [...new Set(guarantees)],
729
+ candidateBackend,
730
+ policyAttested,
731
+ policyDigest,
732
+ runtimeProbe,
280
733
  postSpawn: { ...postSpawn },
281
734
  };
282
735
  }
283
736
 
284
- _prepareSandboxPlan(command, args, options, { sync = false } = {}) {
737
+ _assertRequiredSandboxBoundaries(plan, requiredBoundaries) {
738
+ const actualGuarantees = plan.applied ? plan.guarantees : [];
739
+ const guaranteed = new Set(actualGuarantees);
740
+ const missingBoundaries = requiredBoundaries.filter(
741
+ (boundary) => !guaranteed.has(boundary),
742
+ );
743
+ if (missingBoundaries.length > 0) {
744
+ throw this._sandboxBoundaryError(
745
+ "required_boundaries_unsatisfied",
746
+ `Sandbox backend ${plan.backend || plan.candidateBackend || "unavailable"} cannot satisfy required boundaries: ${missingBoundaries.join(", ")}`,
747
+ {
748
+ requiredBoundaries,
749
+ actualGuarantees,
750
+ missingBoundaries,
751
+ sandboxBackend: plan.backend,
752
+ sandboxCandidateBackend: plan.candidateBackend,
753
+ sandboxRuntimeProbe: plan.runtimeProbe,
754
+ sandboxPolicyAttested: plan.policyAttested,
755
+ sandboxPolicyDigest: plan.policyDigest,
756
+ sandboxCandidateReason: plan.candidateBackend ? plan.reason : null,
757
+ },
758
+ );
759
+ }
760
+ return {
761
+ ...plan,
762
+ requiredBoundaries: [...requiredBoundaries],
763
+ };
764
+ }
765
+
766
+ _prepareSandboxPlan(
767
+ command,
768
+ args,
769
+ options,
770
+ { sync = false, sandboxPolicy = {} } = {},
771
+ ) {
285
772
  const strict = this._sandboxStrictEnabled();
773
+ const requiredBoundaries = sandboxPolicy.requiredBoundaries || [];
774
+ const profile = strict ? "strict" : sandboxPolicy.profile || "default";
286
775
  let disabledReason = null;
287
776
  if (this._sandboxDisabledByEnvironment()) {
288
777
  disabledReason = "disabled_by_environment";
@@ -300,58 +789,104 @@ class ProcessExecutionBroker extends EventEmitter {
300
789
  `Sandbox is unavailable in strict mode: ${disabledReason}`,
301
790
  );
302
791
  }
303
- return this._sandboxUnavailablePlan(
792
+ const unavailablePlan = this._sandboxUnavailablePlan(
304
793
  command,
305
794
  args,
306
795
  options,
307
796
  disabledReason,
797
+ { ...sandboxPolicy, profile },
798
+ );
799
+ return this._assertRequiredSandboxBoundaries(
800
+ unavailablePlan,
801
+ requiredBoundaries,
308
802
  );
309
803
  }
310
804
 
311
- const plan = this._validateSandboxPlan(
312
- this._sandboxAdapter.applySandbox(
313
- command,
314
- args || [],
315
- options,
316
- "default",
317
- ),
805
+ const adapterRequest = Object.freeze({
806
+ profile,
807
+ requiredBoundaries: Object.freeze([...requiredBoundaries]),
808
+ sync,
809
+ ...(sandboxPolicy.executionContract
810
+ ? { executionContract: sandboxPolicy.executionContract }
811
+ : {}),
812
+ });
813
+ // Keep the legacy string profile in argument four. The built-in adapter
814
+ // reserves argument five for runtime injection, so the typed request is
815
+ // additive in argument six and legacy injected adapters can ignore it.
816
+ const rawPlan = this._sandboxAdapter.applySandbox(
817
+ command,
818
+ args || [],
819
+ options,
820
+ profile,
821
+ undefined,
822
+ adapterRequest,
318
823
  );
824
+ let plan;
825
+ try {
826
+ plan = this._validateSandboxPlan(rawPlan);
827
+ plan = this._assertRequiredSandboxBoundaries(plan, requiredBoundaries);
319
828
 
320
- if (!plan.applied && strict) {
321
- throw this._sandboxError(
322
- plan.reason || "sandbox_unavailable",
323
- `Sandbox is unavailable in strict mode: ${
324
- plan.reason || "unknown reason"
325
- }`,
326
- );
327
- }
328
-
329
- if (plan.applied && plan.postSpawn.required) {
330
- if (typeof this._sandboxAdapter.postSpawnSandbox !== "function") {
829
+ if (!plan.applied && strict) {
331
830
  throw this._sandboxError(
332
- "post_spawn_adapter_unavailable",
333
- "Required post-spawn sandbox adapter is unavailable",
831
+ plan.reason || "sandbox_unavailable",
832
+ `Sandbox is unavailable in strict mode: ${
833
+ plan.reason || "unknown reason"
834
+ }`,
334
835
  );
335
836
  }
336
- if (sync) {
337
- throw this._sandboxError(
338
- "post_spawn_unavailable_for_sync",
339
- "spawnSync cannot satisfy required post-spawn sandbox enforcement",
340
- );
837
+
838
+ if (plan.applied && plan.postSpawn.required) {
839
+ if (typeof this._sandboxAdapter.postSpawnSandbox !== "function") {
840
+ throw this._sandboxError(
841
+ "post_spawn_adapter_unavailable",
842
+ "Required post-spawn sandbox adapter is unavailable",
843
+ );
844
+ }
845
+ if (sync) {
846
+ throw this._sandboxError(
847
+ "post_spawn_unavailable_for_sync",
848
+ "spawnSync cannot satisfy required post-spawn sandbox enforcement",
849
+ );
850
+ }
851
+ if (
852
+ (strict || requiredBoundaries.length > 0) &&
853
+ plan.postSpawn.mode !== "sync"
854
+ ) {
855
+ throw this._sandboxError(
856
+ "async_post_spawn_disallowed_in_strict_mode",
857
+ "Fail-closed sandbox enforcement requires synchronous post-spawn enforcement",
858
+ );
859
+ }
341
860
  }
342
- if (strict && plan.postSpawn.mode !== "sync") {
343
- throw this._sandboxError(
344
- "async_post_spawn_disallowed_in_strict_mode",
345
- "Strict sandbox mode requires synchronous post-spawn enforcement",
346
- );
861
+ return plan;
862
+ } catch (error) {
863
+ if (typeof rawPlan?.cleanup === "function") {
864
+ try {
865
+ rawPlan.cleanup();
866
+ } catch {
867
+ // Preserve the boundary/contract failure that prevented execution.
868
+ }
347
869
  }
870
+ throw error;
348
871
  }
349
- return plan;
350
872
  }
351
873
 
352
874
  _applySandboxAudit(auditEntry, plan, applied) {
353
875
  auditEntry.sandboxed = applied;
354
876
  auditEntry.sandboxProfile = plan?.profile || null;
877
+ auditEntry.sandboxRequired = [...(plan?.requiredBoundaries || [])];
878
+ auditEntry.sandboxGuarantees = applied ? [...(plan?.guarantees || [])] : [];
879
+ auditEntry.sandboxBackend = plan?.backend || null;
880
+ auditEntry.sandboxCandidateBackend = plan?.candidateBackend || null;
881
+ auditEntry.sandboxRuntimeProbe = plan?.runtimeProbe
882
+ ? { ...plan.runtimeProbe }
883
+ : null;
884
+ auditEntry.sandboxPolicyAttested =
885
+ typeof plan?.policyAttested === "boolean" ? plan.policyAttested : null;
886
+ auditEntry.sandboxPolicyDigest = plan?.policyDigest || null;
887
+ auditEntry.sandboxCandidateReason = plan?.candidateBackend
888
+ ? plan?.reason || null
889
+ : null;
355
890
  auditEntry.sandboxEnforcement = applied
356
891
  ? plan?.enforcement || "platform"
357
892
  : null;
@@ -365,6 +900,30 @@ class ProcessExecutionBroker extends EventEmitter {
365
900
  auditEntry.sandboxState = "denied";
366
901
  auditEntry.sandboxReason =
367
902
  error.sandboxReason || "sandbox_initialization_failed";
903
+ auditEntry.sandboxRequired = [
904
+ ...(error.requiredBoundaries || auditEntry.sandboxRequired || []),
905
+ ];
906
+ auditEntry.sandboxGuarantees = [
907
+ ...(error.actualGuarantees || auditEntry.sandboxGuarantees || []),
908
+ ];
909
+ auditEntry.sandboxMissing = [...(error.missingBoundaries || [])];
910
+ auditEntry.sandboxBackend =
911
+ error.sandboxBackend || auditEntry.sandboxBackend || null;
912
+ auditEntry.sandboxCandidateBackend =
913
+ error.sandboxCandidateBackend ||
914
+ auditEntry.sandboxCandidateBackend ||
915
+ null;
916
+ auditEntry.sandboxRuntimeProbe = error.sandboxRuntimeProbe
917
+ ? { ...error.sandboxRuntimeProbe }
918
+ : auditEntry.sandboxRuntimeProbe || null;
919
+ auditEntry.sandboxPolicyAttested =
920
+ typeof error.sandboxPolicyAttested === "boolean"
921
+ ? error.sandboxPolicyAttested
922
+ : (auditEntry.sandboxPolicyAttested ?? null);
923
+ auditEntry.sandboxPolicyDigest =
924
+ error.sandboxPolicyDigest || auditEntry.sandboxPolicyDigest || null;
925
+ auditEntry.sandboxCandidateReason =
926
+ error.sandboxCandidateReason || auditEntry.sandboxCandidateReason || null;
368
927
  auditEntry.deniedReason = `sandbox-init-failed: ${error.message}`;
369
928
  auditEntry.endTime = Date.now();
370
929
  auditEntry.durationMs = auditEntry.endTime - startTime;
@@ -391,7 +950,11 @@ class ProcessExecutionBroker extends EventEmitter {
391
950
  if (!plan.applied || !plan.postSpawn.required) {
392
951
  this._applySandboxAudit(auditEntry, plan, plan.applied);
393
952
  if (plan.applied) this._stats.sandboxed++;
394
- const ready = Promise.resolve({ applied: plan.applied });
953
+ const ready = Promise.resolve({
954
+ applied: plan.applied,
955
+ backend: plan.backend,
956
+ guarantees: plan.applied ? [...plan.guarantees] : [],
957
+ });
395
958
  proc.sandboxReady = ready;
396
959
  return;
397
960
  }
@@ -403,7 +966,7 @@ class ProcessExecutionBroker extends EventEmitter {
403
966
  this._applySandboxAudit(auditEntry, plan, false);
404
967
  auditEntry.sandboxState = "failed";
405
968
  auditEntry.sandboxReason = `post_spawn_failed: ${error.message}`;
406
- if (this._sandboxStrictEnabled()) {
969
+ if (this._sandboxStrictEnabled() || plan.requiredBoundaries.length > 0) {
407
970
  if (typeof proc.once === "function") proc.once("error", () => {});
408
971
  try {
409
972
  proc.kill?.();
@@ -423,7 +986,7 @@ class ProcessExecutionBroker extends EventEmitter {
423
986
  }
424
987
 
425
988
  if (postSpawnResult && typeof postSpawnResult.then === "function") {
426
- if (this._sandboxStrictEnabled()) {
989
+ if (this._sandboxStrictEnabled() || plan.requiredBoundaries.length > 0) {
427
990
  Promise.resolve(postSpawnResult).catch(() => {});
428
991
  if (typeof proc.once === "function") proc.once("error", () => {});
429
992
  try {
@@ -442,7 +1005,11 @@ class ProcessExecutionBroker extends EventEmitter {
442
1005
  () => {
443
1006
  this._applySandboxAudit(auditEntry, plan, true);
444
1007
  this._stats.sandboxed++;
445
- return { applied: true };
1008
+ return {
1009
+ applied: true,
1010
+ backend: plan.backend,
1011
+ guarantees: [...plan.guarantees],
1012
+ };
446
1013
  },
447
1014
  (error) => {
448
1015
  this._applySandboxAudit(auditEntry, plan, false);
@@ -463,7 +1030,11 @@ class ProcessExecutionBroker extends EventEmitter {
463
1030
 
464
1031
  this._applySandboxAudit(auditEntry, plan, true);
465
1032
  this._stats.sandboxed++;
466
- proc.sandboxReady = Promise.resolve({ applied: true });
1033
+ proc.sandboxReady = Promise.resolve({
1034
+ applied: true,
1035
+ backend: plan.backend,
1036
+ guarantees: [...plan.guarantees],
1037
+ });
467
1038
  }
468
1039
 
469
1040
  _credentialBoundaryEnabled() {
@@ -527,6 +1098,35 @@ class ProcessExecutionBroker extends EventEmitter {
527
1098
  };
528
1099
  }
529
1100
 
1101
+ _createCredentialContext(command, options, executionId, decision) {
1102
+ if (typeof this._credentialAgent.createBrokerContext !== "function") {
1103
+ return options.credentialContext;
1104
+ }
1105
+ const supplied = options.credentialContext || {};
1106
+ return this._credentialAgent.createBrokerContext({
1107
+ approvalId: `${executionId}:${decision}`,
1108
+ process: command,
1109
+ host:
1110
+ supplied.target?.host ??
1111
+ supplied.host ??
1112
+ options.credentialTarget?.host ??
1113
+ options.credentialTargetHost ??
1114
+ null,
1115
+ ttlMs: supplied.ttlMs ?? options.credentialTtlMs,
1116
+ maxUses: supplied.maxUses ?? options.credentialMaxUses,
1117
+ });
1118
+ }
1119
+
1120
+ _stripCredentialControlOptions(options) {
1121
+ delete options.credentialContext;
1122
+ delete options.credentialApproved;
1123
+ delete options.credentialApprovalId;
1124
+ delete options.credentialTarget;
1125
+ delete options.credentialTargetHost;
1126
+ delete options.credentialTtlMs;
1127
+ delete options.credentialMaxUses;
1128
+ }
1129
+
530
1130
  _recordCredentialReport(auditEntry, report) {
531
1131
  const filtered = report?.filtered === true;
532
1132
  auditEntry.credentialFiltered = filtered;
@@ -629,8 +1229,28 @@ class ProcessExecutionBroker extends EventEmitter {
629
1229
  pluginId: options.pluginId || null,
630
1230
  pluginVersion: options.pluginVersion || null,
631
1231
  pluginSource: options.pluginSource || null,
1232
+ pluginExecutableIdentity: this._normalizePluginExecutableIdentity(
1233
+ options.pluginExecutableIdentity,
1234
+ ),
1235
+ sandboxRequired: [],
1236
+ sandboxGuarantees: [],
1237
+ sandboxBackend: null,
632
1238
  };
633
1239
 
1240
+ let sandboxPolicy;
1241
+ try {
1242
+ sandboxPolicy = this._normalizeSandboxPolicy(options, {
1243
+ command,
1244
+ args,
1245
+ sync: false,
1246
+ });
1247
+ auditEntry.sandboxRequired = [...sandboxPolicy.requiredBoundaries];
1248
+ } catch (sandboxPolicyError) {
1249
+ this._recordSandboxDenial(auditEntry, sandboxPolicyError, startTime);
1250
+ sandboxPolicyError.auditEntry = auditEntry;
1251
+ throw sandboxPolicyError;
1252
+ }
1253
+
634
1254
  if (decision === "deny" || decision === "prompt") {
635
1255
  auditEntry.deniedReason = isDangerous
636
1256
  ? "dangerous_command"
@@ -658,6 +1278,8 @@ class ProcessExecutionBroker extends EventEmitter {
658
1278
 
659
1279
  // 传播traceparent环境变量
660
1280
  const spawnOpts = this._sanitizeOptions(options);
1281
+ this._stripSandboxControlOptions(spawnOpts);
1282
+ this._stripPluginControlOptions(spawnOpts);
661
1283
  if (traceCtx) {
662
1284
  spawnOpts.env = { ...(spawnOpts.env || process.env) };
663
1285
  spawnOpts.env.TRACEPARENT = traceCtx.traceparent;
@@ -665,6 +1287,12 @@ class ProcessExecutionBroker extends EventEmitter {
665
1287
 
666
1288
  // P0-1: Credential filtering (default-on) — strip secrets from env/args
667
1289
  if (this._credentialBoundaryEnabled()) {
1290
+ spawnOpts.credentialContext = this._createCredentialContext(
1291
+ command,
1292
+ spawnOpts,
1293
+ executionId,
1294
+ decision,
1295
+ );
668
1296
  const credentialBoundary = this._applyCredentialBoundary(
669
1297
  command,
670
1298
  args,
@@ -675,14 +1303,21 @@ class ProcessExecutionBroker extends EventEmitter {
675
1303
  args = credentialBoundary.args;
676
1304
  auditEntry.args = [...args];
677
1305
  this._recordCredentialReport(auditEntry, credentialBoundary.report);
1306
+ this._stripCredentialControlOptions(spawnOpts);
678
1307
  }
679
1308
 
680
1309
  // P0-1: Platform sandbox wrapping — apply macOS/Windows/Linux sandbox
681
1310
  let sandboxPlan;
682
1311
  try {
683
- sandboxPlan = this._prepareSandboxPlan(command, args || [], spawnOpts);
1312
+ sandboxPlan = this._prepareSandboxPlan(command, args || [], spawnOpts, {
1313
+ sandboxPolicy,
1314
+ });
684
1315
  } catch (sandboxErr) {
685
- if (this._sandboxStrictEnabled()) {
1316
+ if (
1317
+ this._sandboxStrictEnabled() ||
1318
+ sandboxErr.sandboxFailClosed ||
1319
+ sandboxPolicy.requiredBoundaries.length > 0
1320
+ ) {
686
1321
  this._recordSandboxDenial(auditEntry, sandboxErr, startTime);
687
1322
  sandboxErr.auditEntry = auditEntry;
688
1323
  throw sandboxErr;
@@ -695,6 +1330,7 @@ class ProcessExecutionBroker extends EventEmitter {
695
1330
  args || [],
696
1331
  spawnOpts,
697
1332
  `sandbox_init_failed: ${sandboxErr.message}`,
1333
+ sandboxPolicy,
698
1334
  );
699
1335
  }
700
1336
  command = sandboxPlan.command;
@@ -722,6 +1358,13 @@ class ProcessExecutionBroker extends EventEmitter {
722
1358
  );
723
1359
  try {
724
1360
  this._runPostSpawnSandbox(proc, sandboxPlan, auditEntry);
1361
+ auditEntry.pid = proc.pid;
1362
+ if (Number.isSafeInteger(proc.sandboxWrapperPid)) {
1363
+ auditEntry.sandboxWrapperPid = proc.sandboxWrapperPid;
1364
+ }
1365
+ if (Number.isSafeInteger(proc.sandboxTargetPid)) {
1366
+ auditEntry.sandboxTargetPid = proc.sandboxTargetPid;
1367
+ }
725
1368
  } catch (postSpawnError) {
726
1369
  cleanupSandbox();
727
1370
  this._recordSandboxDenial(auditEntry, postSpawnError, startTime);
@@ -809,8 +1452,28 @@ class ProcessExecutionBroker extends EventEmitter {
809
1452
  pluginId: options.pluginId || null,
810
1453
  pluginVersion: options.pluginVersion || null,
811
1454
  pluginSource: options.pluginSource || null,
1455
+ pluginExecutableIdentity: this._normalizePluginExecutableIdentity(
1456
+ options.pluginExecutableIdentity,
1457
+ ),
1458
+ sandboxRequired: [],
1459
+ sandboxGuarantees: [],
1460
+ sandboxBackend: null,
812
1461
  };
813
1462
 
1463
+ let sandboxPolicy;
1464
+ try {
1465
+ sandboxPolicy = this._normalizeSandboxPolicy(options, {
1466
+ command,
1467
+ args,
1468
+ sync: true,
1469
+ });
1470
+ auditEntry.sandboxRequired = [...sandboxPolicy.requiredBoundaries];
1471
+ } catch (sandboxPolicyError) {
1472
+ this._recordSandboxDenial(auditEntry, sandboxPolicyError, startTime);
1473
+ sandboxPolicyError.auditEntry = auditEntry;
1474
+ throw sandboxPolicyError;
1475
+ }
1476
+
814
1477
  if (decision === "deny" || decision === "prompt") {
815
1478
  auditEntry.deniedReason = isDangerous
816
1479
  ? "dangerous_command"
@@ -831,6 +1494,8 @@ class ProcessExecutionBroker extends EventEmitter {
831
1494
  }
832
1495
 
833
1496
  const spawnOpts = this._sanitizeOptions(options);
1497
+ this._stripSandboxControlOptions(spawnOpts);
1498
+ this._stripPluginControlOptions(spawnOpts);
834
1499
  if (traceCtx) {
835
1500
  spawnOpts.env = { ...(spawnOpts.env || process.env) };
836
1501
  spawnOpts.env.TRACEPARENT = traceCtx.traceparent;
@@ -838,6 +1503,12 @@ class ProcessExecutionBroker extends EventEmitter {
838
1503
 
839
1504
  // P0-1: Credential filtering agent — strip secrets from env/args before spawn
840
1505
  if (this._credentialBoundaryEnabled()) {
1506
+ spawnOpts.credentialContext = this._createCredentialContext(
1507
+ command,
1508
+ spawnOpts,
1509
+ executionId,
1510
+ decision,
1511
+ );
841
1512
  const credentialBoundary = this._applyCredentialBoundary(
842
1513
  command,
843
1514
  args,
@@ -848,6 +1519,7 @@ class ProcessExecutionBroker extends EventEmitter {
848
1519
  args = credentialBoundary.args;
849
1520
  auditEntry.args = [...args];
850
1521
  this._recordCredentialReport(auditEntry, credentialBoundary.report);
1522
+ this._stripCredentialControlOptions(spawnOpts);
851
1523
  }
852
1524
 
853
1525
  // P0-1: Platform sandbox wrapping (sync path)
@@ -855,9 +1527,14 @@ class ProcessExecutionBroker extends EventEmitter {
855
1527
  try {
856
1528
  sandboxPlan = this._prepareSandboxPlan(command, args || [], spawnOpts, {
857
1529
  sync: true,
1530
+ sandboxPolicy,
858
1531
  });
859
1532
  } catch (sandboxErr) {
860
- if (this._sandboxStrictEnabled()) {
1533
+ if (
1534
+ this._sandboxStrictEnabled() ||
1535
+ sandboxErr.sandboxFailClosed ||
1536
+ sandboxPolicy.requiredBoundaries.length > 0
1537
+ ) {
861
1538
  this._recordSandboxDenial(auditEntry, sandboxErr, startTime);
862
1539
  sandboxErr.auditEntry = auditEntry;
863
1540
  throw sandboxErr;
@@ -870,6 +1547,7 @@ class ProcessExecutionBroker extends EventEmitter {
870
1547
  args || [],
871
1548
  spawnOpts,
872
1549
  `sandbox_init_failed: ${sandboxErr.message}`,
1550
+ sandboxPolicy,
873
1551
  );
874
1552
  }
875
1553
  command = sandboxPlan.command;
@@ -929,10 +1607,29 @@ class ProcessExecutionBroker extends EventEmitter {
929
1607
  pty: true,
930
1608
  sandboxed: false,
931
1609
  sandboxReason: "native_pty_host_boundary",
1610
+ sandboxRequired: [],
1611
+ sandboxGuarantees: [],
1612
+ sandboxBackend: null,
932
1613
  pluginId: options.pluginId || null,
933
1614
  pluginVersion: options.pluginVersion || null,
934
1615
  pluginSource: options.pluginSource || null,
1616
+ pluginExecutableIdentity: this._normalizePluginExecutableIdentity(
1617
+ options.pluginExecutableIdentity,
1618
+ ),
935
1619
  };
1620
+ let sandboxPolicy;
1621
+ try {
1622
+ sandboxPolicy = this._normalizeSandboxPolicy(options, {
1623
+ command,
1624
+ args,
1625
+ sync: false,
1626
+ });
1627
+ auditEntry.sandboxRequired = [...sandboxPolicy.requiredBoundaries];
1628
+ } catch (sandboxPolicyError) {
1629
+ this._recordSandboxDenial(auditEntry, sandboxPolicyError, startTime);
1630
+ sandboxPolicyError.auditEntry = auditEntry;
1631
+ throw sandboxPolicyError;
1632
+ }
936
1633
  if (policy === "deny" || policy === "prompt") {
937
1634
  auditEntry.deniedReason = `policy_${policy}`;
938
1635
  auditEntry.endTime = Date.now();
@@ -947,16 +1644,34 @@ class ProcessExecutionBroker extends EventEmitter {
947
1644
  error.auditEntry = auditEntry;
948
1645
  throw error;
949
1646
  }
1647
+ if (sandboxPolicy.requiredBoundaries.length > 0) {
1648
+ const sandboxError = this._sandboxBoundaryError(
1649
+ "required_boundaries_unsatisfied",
1650
+ `Native PTY host cannot satisfy required boundaries: ${sandboxPolicy.requiredBoundaries.join(", ")}`,
1651
+ {
1652
+ requiredBoundaries: sandboxPolicy.requiredBoundaries,
1653
+ missingBoundaries: sandboxPolicy.requiredBoundaries,
1654
+ },
1655
+ );
1656
+ this._recordSandboxDenial(auditEntry, sandboxError, startTime);
1657
+ sandboxError.auditEntry = auditEntry;
1658
+ throw sandboxError;
1659
+ }
950
1660
 
951
1661
  const spawnOptions = { ...options, args: [...auditEntry.args] };
1662
+ this._stripSandboxControlOptions(spawnOptions);
1663
+ this._stripPluginControlOptions(spawnOptions);
952
1664
  delete spawnOptions.origin;
953
1665
  delete spawnOptions.policy;
954
1666
  delete spawnOptions.scope;
955
- delete spawnOptions.pluginId;
956
- delete spawnOptions.pluginVersion;
957
- delete spawnOptions.pluginSource;
958
1667
  try {
959
1668
  if (this._credentialBoundaryEnabled()) {
1669
+ spawnOptions.credentialContext = this._createCredentialContext(
1670
+ command,
1671
+ spawnOptions,
1672
+ executionId,
1673
+ policy,
1674
+ );
960
1675
  const credentialBoundary = this._applyCredentialBoundary(
961
1676
  command,
962
1677
  args,
@@ -967,6 +1682,7 @@ class ProcessExecutionBroker extends EventEmitter {
967
1682
  spawnOptions.args = credentialBoundary.args;
968
1683
  auditEntry.args = [...credentialBoundary.args];
969
1684
  this._recordCredentialReport(auditEntry, credentialBoundary.report);
1685
+ this._stripCredentialControlOptions(spawnOptions);
970
1686
  }
971
1687
  const filteredArgs = spawnOptions.args || [];
972
1688
  delete spawnOptions.args;
@@ -1156,5 +1872,5 @@ class ProcessExecutionBroker extends EventEmitter {
1156
1872
  }
1157
1873
 
1158
1874
  const broker = new ProcessExecutionBroker();
1159
- export { broker as executionBroker };
1875
+ export { broker as executionBroker, SANDBOX_BOUNDARIES };
1160
1876
  export default broker;