chainlesschain 0.162.181 → 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 (180) hide show
  1. package/package.json +2 -1
  2. package/scripts/build-windows-sandbox-helper.ps1 +163 -0
  3. package/src/assets/web-panel/assets/{AIOps-cq0dwbnf.js → AIOps-DzZ5_xoj.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-CvcgGl3w.js → ActionButton-DeLXddIg.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-hM2-jFqg.js → Analytics-rvDCmet1.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-B9_Gsd_g.js → AppLayout-Yt6QVDnp.js} +5 -5
  7. package/src/assets/web-panel/assets/{Artifacts-B7bu52Og.js → Artifacts-BS112K5L.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-DThfDgqB.js → Audit-0wJuQrNu.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-DjlFiD4v.js → BackgroundAgents-B90PMgbn.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-CK9xJKnG.js → Backup-TkgMglQQ.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-DEiSU8K8.js → BaseInput-CQVS9p1l.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-CpT96czj.js → Chat-YTjQHoC7.js} +5 -5
  13. package/src/assets/web-panel/assets/{ChatBubbleRenderer-BKPPNmZI.js → ChatBubbleRenderer-PR074hUN.js} +1 -1
  14. package/src/assets/web-panel/assets/{Checkbox-C1GfDnO0.js → Checkbox-5bwaOabq.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-3DAKgiLx.js → Codegen-BFmNQ_Xe.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-74cOwZU1.js → Col-BT_u4Dzp.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-tn9Kkz9j.js → Community-CJP52u5b.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-BcoXH7m4.js → Compact-BpzhJE9i.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-DIPGUBgi.js → Compliance-Cg7rfslp.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-doD5_91c.js → Cowork-JisxL6Yy.js} +3 -3
  21. package/src/assets/web-panel/assets/{Cron-C-IDvubz.js → Cron-Bu7Ug_MC.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-CdcCoBdj.js → Crosschain-CvuqoLdj.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-DdH5aMMA.js → DID-C2u9G8Pu.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-DHLA4mm0.js → Dashboard-BFt5Yv3d.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-dEeCt7Md.js → Dropdown-DIaT9Wxq.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-BMaecFv9.js → EmailListRenderer-D_A601Y4.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DUaUukTN.js → FamilyGuardDashboard--IyQ8I8w.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-CMBE0_rp.js → Federation-BihWHxuY.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-PG-JDbXq.js → FormItemContext-BB8dOXc_.js} +1 -1
  30. package/src/assets/web-panel/assets/{GenericCardRenderer-Bcb0p88m.js → GenericCardRenderer-DQYhj1HH.js} +1 -1
  31. package/src/assets/web-panel/assets/{Git-Bgv15myB.js → Git-B-2QZxGf.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-DB8YTArI.js → Governance-CusSb-nG.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-BQMwCWaS.js → Inference-BAjmvPPL.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-B1_ZziiB.js → KnowledgeGraph-DoNYWKYq.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-DovEEnt_.js → Logs-B8fKWD-n.js} +2 -2
  36. package/src/assets/web-panel/assets/{MarkdownRenderer-D201OL4T.js → MarkdownRenderer-BlJm1J7E.js} +1 -1
  37. package/src/assets/web-panel/assets/{Marketplace-BlCXSpyB.js → Marketplace-CyOscbSL.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-CsCR09Wj.js → McpTools-Ex6Om5da.js} +5 -5
  39. package/src/assets/web-panel/assets/{Memory-CBVRLKno.js → Memory-CDcD8l8r.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-C9OIafgA.js → MobileBridge-xfBqoFDg.js} +1 -1
  41. package/src/assets/web-panel/assets/{MobileProjects-D_zoJ8Xs.js → MobileProjects-BwObMMA2.js} +1 -1
  42. package/src/assets/web-panel/assets/{Mtc-vE-HdvLj.js → Mtc-CIWd36OV.js} +5 -5
  43. package/src/assets/web-panel/assets/{MtcAudit-CPLaekCd.js → MtcAudit-CPX0ouuA.js} +4 -4
  44. package/src/assets/web-panel/assets/{Multisig-C_UP9C2o.js → Multisig-BDJsIUuW.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-2nODJcU1.js → NLProgramming-DEkbuD3N.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-BhE-SJGu.js → Notes-DJpHRhH1.js} +3 -3
  47. package/src/assets/web-panel/assets/{NotificationSettings-D21q7BNU.js → NotificationSettings-C1UZ-Qd5.js} +1 -1
  48. package/src/assets/web-panel/assets/{OrderTableRenderer-0b62GYOD.js → OrderTableRenderer-GlJtqLjT.js} +1 -1
  49. package/src/assets/web-panel/assets/{Organization-CEqmw_sb.js → Organization-Bbhj0fac.js} +4 -4
  50. package/src/assets/web-panel/assets/{Overflow-MW-gMDO_.js → Overflow-1H04x3kx.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-CY0hjI_G.js → P2P-CDpPe3et.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-BbWh7Man.js → PdhVaultBrowser-MUX0Bpvw.js} +3 -3
  53. package/src/assets/web-panel/assets/{Permissions-ChqEA_4Q.js → Permissions-A07-0Ci1.js} +4 -4
  54. package/src/assets/web-panel/assets/{PersonalDataHub-B3YrbYfD.js → PersonalDataHub-DhhDWxAZ.js} +5 -5
  55. package/src/assets/web-panel/assets/{Pipeline-B8WBhhlW.js → Pipeline-CyfbJfe-.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-Cmb0PXNx.js → Privacy-CNFps3ED.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-hF6zW3Nz.js → ProjectInit--T-u3Dr5.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-BFSVfpW0.js → ProjectSettings-DJmrK2fC.js} +2 -2
  59. package/src/assets/web-panel/assets/{Projects-DAWkVFkc.js → Projects-Qx_MdX9k.js} +1 -1
  60. package/src/assets/web-panel/assets/{Providers-B8yux8Dx.js → Providers-DLzzbOZd.js} +1 -1
  61. package/src/assets/web-panel/assets/{QrScannerModal-N76cQluO.js → QrScannerModal-CexOomKS.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-ClvZ0KYR.js → QuickAsk-QklGi19_.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend-B-GfgBpT.js → Recommend-Bb9kwSw8.js} +1 -1
  64. package/src/assets/web-panel/assets/{RemoteSession-mlglCdQi.js → RemoteSession-DZuVNNN5.js} +2 -2
  65. package/src/assets/web-panel/assets/{Reputation-DJIZzQeG.js → Reputation-Dr5cLP0N.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-COzxu_bb.js → Row-oCQHYv5t.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-CoYsJQuE.js → RssFeed-IFDEykIR.js} +3 -3
  68. package/src/assets/web-panel/assets/{Search-DC77Mq9S.js → Search-CspVIxDc.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-Loy2EdMO.js → Security-Bm66o_DH.js} +3 -3
  70. package/src/assets/web-panel/assets/{Services-GUD07Eu0.js → Services-DvanNqXl.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-DWzkptYU.js → Skeleton-CHjEe9_O.js} +1 -1
  72. package/src/assets/web-panel/assets/{Skills-CEDn1r-Z.js → Skills-Cb8jWjMX.js} +1 -1
  73. package/src/assets/web-panel/assets/{Sla-ub_k4pXh.js → Sla-DxZm1491.js} +1 -1
  74. package/src/assets/web-panel/assets/{SpeechSettings-D7HLX9CA.js → SpeechSettings-DWxEEclC.js} +1 -1
  75. package/src/assets/web-panel/assets/{SyncSettings-DbwOvl6m.js → SyncSettings-FIvOFw5p.js} +2 -2
  76. package/src/assets/web-panel/assets/{Tasks-CBQzoAu5.js → Tasks-CyuLnDFR.js} +1 -1
  77. package/src/assets/web-panel/assets/{Templates-BNVeIhud.js → Templates-CaNjzV_t.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-PS9AzhXU.js → Tenant-DjlP6TmH.js} +1 -1
  79. package/src/assets/web-panel/assets/Terminal-DwzGMniO.js +3 -0
  80. package/src/assets/web-panel/assets/{TimelineRenderer-CrmXMOkg.js → TimelineRenderer-DoZ8y7y8.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-DD-VDHw1.js → Tokens-390cg2TC.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-BsoN_n-n.js → Trigger-CLrtCj5_.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-n8LmN4ZV.js → Trust-DpESfSPn.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-C9_7MImA.js → UkeySign-CN6279O0.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-DyBteNgn.js → VideoEditing-DPtAUlSe.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-BS5ixeXI.js → Wallet-nKOMV_1n.js} +4 -4
  87. package/src/assets/web-panel/assets/{WebAuthn-spc4UImU.js → WebAuthn-HuXlSOc4.js} +5 -5
  88. package/src/assets/web-panel/assets/{WorkflowEditor-D7iVvaBO.js → WorkflowEditor-CUfFjARi.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-6CmBkHrL.js → chat-6Eq0PcZJ.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-BGoCLkxI.js → colors-BP_Sf6Iy.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-fYZBetMO.js → compact-item-BufMKIh5.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-BeM-1UVj.js → createContext-BBMXxWSW.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-DgVKduH2.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-CE7ZuEnV.js → hasIn-fUK_tRO2.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-QIpnpZgz.js → index-2A5ph8b2.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-BU_2qiDk.js → index-3FuwBewR.js} +1 -1
  97. package/src/assets/web-panel/assets/{index--lap6cf7.js → index-6GmBa4Kg.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-De0quFDw.js → index-B2vS66eI.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-D1r9tT3J.js → index-B7Etk0Te.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-YjcumOZ4.js → index-B9WYSn4m.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-MtOuq2i6.js → index-BHy6yNiF.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-RMZ8a7Yt.js → index-BMLHv389.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-C0v6YKKO.js → index-BWKoBU8R.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CRnUE8Cb.js → index-Bkg4ZePE.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-BsMfoaeo.js → index-C44atv4k.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-DoXk5KJ8.js → index-CE2DdTP2.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-B4wiTEOM.js → index-CGjmILDm.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-zb7rVOhV.js → index-CW_G-MXw.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-ATcSr_2O.js → index-CZ6Yt17L.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-C9Y3k0HI.js → index-CeASi4fr.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-B2U-ObMq.js → index-CgiECHu2.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-Puq6Luf1.js → index-Cp8vhyZy.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-BV551878.js → index-CwSf5pnf.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BowH1eLQ.js → index-D4_MuGkd.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-B3CDgvNW.js → index-D9vU25ij.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-WUrJ6S1j.js → index-DASluSqY.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-CRLjEP1H.js → index-DLpIs_P_.js} +1 -1
  118. package/src/assets/web-panel/assets/index-DOZTSoS7.js +1 -0
  119. package/src/assets/web-panel/assets/{index-DT3zPSVX.js → index-DPdUNk1i.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-BunaQCa0.js → index-DVsqvI4M.js} +1 -1
  121. package/src/assets/web-panel/assets/index-DhpvjpqI.js +1 -0
  122. package/src/assets/web-panel/assets/{index-CIpVrf5P.js → index-DmkMXwnR.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-lJBjB1QX.js → index-DocdRcbd.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-BEVm0lCS.js → index-Dyngbd29.js} +19 -19
  125. package/src/assets/web-panel/assets/{index-C4SJVjs4.js → index-GwdRUZ-x.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-ukg99D1V.js → index-LvCBfTLo.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-BfPL-m46.js → index-cpEli44X.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-CpIGIB85.js → index-fzaMtSJ8.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-BNZDILcO.js → index-pum7HYBA.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-Dw1PyYPm.js → index-t8N1tSeX.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-Cip8emOQ.js → index-uCbEN7cY.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-DsvfrESp.js → index-wKTLbKyc.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-B8BsdNV_.js → index-wV6iGdpY.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-CYHMs1ag.js → initDefaultProps-V5Fo95FM.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-DDB2Ffk5.js → motion-BYWU0hUT.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-Bg3cD-dX.js → move-Cr1M-J2h.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-B5nedjTS.js → mtc-parser-BysQKi2N.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-BHyuUILu.js → omit-D1zHU8GC.js} +1 -1
  139. package/src/assets/web-panel/assets/{pickAttrs-C9YQnEN9.js → pickAttrs-CUArxtfi.js} +1 -1
  140. package/src/assets/web-panel/assets/{placementArrow-DBUFYUe7.js → placementArrow-ChoYEys0.js} +1 -1
  141. package/src/assets/web-panel/assets/{responsiveObserve-nBs2Obnk.js → responsiveObserve-BQRs3Mo7.js} +1 -1
  142. package/src/assets/web-panel/assets/{slide-DkCEaXNU.js → slide-B8zbsCkg.js} +1 -1
  143. package/src/assets/web-panel/assets/{statusUtils-aqE1Wi6U.js → statusUtils-C2U8Gs6h.js} +1 -1
  144. package/src/assets/web-panel/assets/{styleChecker-CN5bhfHB.js → styleChecker-Dd8MgL_V.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFlexGapSupport-B_oX_kvJ.js → useFlexGapSupport-hknqY5NH.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFs-rCuXHeme.js → useFs-CLTAmcfw.js} +1 -1
  147. package/src/assets/web-panel/assets/{usePersonalDataHub-DZR9Abyd.js → usePersonalDataHub-ByegHbiB.js} +1 -1
  148. package/src/assets/web-panel/assets/{vnode-ConCYQlX.js → vnode-DqlAy5DP.js} +1 -1
  149. package/src/assets/web-panel/assets/{zoom-CUdDxG5M.js → zoom-DiXiztQn.js} +1 -1
  150. package/src/assets/web-panel/index.html +1 -1
  151. package/src/commands/agenda.js +115 -3
  152. package/src/commands/agent.js +6 -0
  153. package/src/data/changelog.json +13 -0
  154. package/src/gateways/terminal/PtyManager.js +45 -4
  155. package/src/gateways/ws/ws-server.js +10 -1
  156. package/src/harness/background-task-manager.js +70 -2
  157. package/src/harness/worktree-isolator.js +14 -3
  158. package/src/lib/agent-core.js +1 -0
  159. package/src/lib/agent-schedule-store.js +45 -22
  160. package/src/lib/hook-runner.js +6 -2
  161. package/src/lib/packer/pkg-config-generator.js +3 -1
  162. package/src/lib/plugin-runtime/bin.js +1148 -70
  163. package/src/lib/plugin-runtime/manifest.js +68 -12
  164. package/src/lib/plugin-runtime/scopes.js +20 -10
  165. package/src/lib/process-execution-broker/index.js +375 -48
  166. package/src/lib/process-execution-broker/platform-sandbox.js +3831 -276
  167. package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
  168. package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
  169. package/src/lib/process-execution-broker/windows-sandbox.cs +3856 -0
  170. package/src/lib/repl-bang-memorize.js +67 -10
  171. package/src/lib/slash-commands.js +27 -4
  172. package/src/repl/agent-repl.js +4 -3
  173. package/src/runtime/agent-core.js +376 -52
  174. package/src/runtime/agent-runtime.js +13 -1
  175. package/src/runtime/headless-runner.js +4 -3
  176. package/src/assets/web-panel/assets/Terminal-Cgb4eLB_.js +0 -3
  177. package/src/assets/web-panel/assets/devWarning-BzPwHnw8.js +0 -1
  178. package/src/assets/web-panel/assets/index-DacrAdc-.js +0 -1
  179. package/src/assets/web-panel/assets/index-EHzNJozo.js +0 -1
  180. package/src/lib/process-execution-broker/windows-sandbox.ps1 +0 -999
@@ -38,6 +38,7 @@ import {
38
38
  postSpawnSandbox as _postSpawnSandbox,
39
39
  SANDBOX_BOUNDARIES,
40
40
  } from "./platform-sandbox.js";
41
+ import { consumeIssuedPluginSandboxExecutionContract } from "../plugin-runtime/bin.js";
41
42
  import { credentialAgent } from "./credential-agent.js";
42
43
 
43
44
  const SUPPORTED_SANDBOX_BOUNDARIES = new Set(Object.values(SANDBOX_BOUNDARIES));
@@ -197,6 +198,222 @@ class ProcessExecutionBroker extends EventEmitter {
197
198
  return safe;
198
199
  }
199
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
+
200
417
  _sandboxStrictEnabled() {
201
418
  return process.env.CC_SANDBOX_STRICT === "1";
202
419
  }
@@ -213,7 +430,7 @@ class ProcessExecutionBroker extends EventEmitter {
213
430
  * @param {Object} options
214
431
  * @returns {{profile: "default"|"strict"|"network-only"|null, requiredBoundaries: string[]}}
215
432
  */
216
- _normalizeSandboxPolicy(options = {}) {
433
+ _normalizeSandboxPolicy(options = {}, launch = {}) {
217
434
  const rawPolicy = options.sandboxPolicy;
218
435
  if (
219
436
  rawPolicy !== undefined &&
@@ -269,12 +486,19 @@ class ProcessExecutionBroker extends EventEmitter {
269
486
  { requiredBoundaries },
270
487
  );
271
488
  }
272
- return { profile, requiredBoundaries };
489
+ const executionContract = this._normalizeSandboxExecutionContract(
490
+ options.sandboxExecutionContract,
491
+ options,
492
+ requiredBoundaries,
493
+ launch,
494
+ );
495
+ return { profile, requiredBoundaries, executionContract };
273
496
  }
274
497
 
275
498
  _stripSandboxControlOptions(options) {
276
499
  delete options.sandboxPolicy;
277
500
  delete options.requiredBoundaries;
501
+ delete options.sandboxExecutionContract;
278
502
  }
279
503
 
280
504
  _sandboxUnavailablePlan(command, args, options, reason, sandboxPolicy = {}) {
@@ -318,6 +542,7 @@ class ProcessExecutionBroker extends EventEmitter {
318
542
  typeof metadata.sandboxPolicyAttested === "boolean"
319
543
  ? metadata.sandboxPolicyAttested
320
544
  : null;
545
+ error.sandboxPolicyDigest = metadata.sandboxPolicyDigest || null;
321
546
  error.sandboxCandidateReason = metadata.sandboxCandidateReason || null;
322
547
  return error;
323
548
  }
@@ -400,6 +625,16 @@ class ProcessExecutionBroker extends EventEmitter {
400
625
  "Sandbox policy attestation must be boolean",
401
626
  );
402
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
+ }
403
638
  let runtimeProbe = null;
404
639
  if (plan.runtimeProbe !== null && plan.runtimeProbe !== undefined) {
405
640
  if (
@@ -416,11 +651,62 @@ class ProcessExecutionBroker extends EventEmitter {
416
651
  "Sandbox runtime probe must use the typed probe contract",
417
652
  );
418
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
+ }
419
682
  runtimeProbe = {
420
683
  kind: plan.runtimeProbe.kind,
421
684
  attempted: plan.runtimeProbe.attempted,
422
685
  runnable: plan.runtimeProbe.runnable,
423
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
+ : {}),
424
710
  };
425
711
  }
426
712
  const postSpawn = plan.postSpawn || { required: false, mode: "none" };
@@ -442,6 +728,7 @@ class ProcessExecutionBroker extends EventEmitter {
442
728
  guarantees: [...new Set(guarantees)],
443
729
  candidateBackend,
444
730
  policyAttested,
731
+ policyDigest,
445
732
  runtimeProbe,
446
733
  postSpawn: { ...postSpawn },
447
734
  };
@@ -465,6 +752,7 @@ class ProcessExecutionBroker extends EventEmitter {
465
752
  sandboxCandidateBackend: plan.candidateBackend,
466
753
  sandboxRuntimeProbe: plan.runtimeProbe,
467
754
  sandboxPolicyAttested: plan.policyAttested,
755
+ sandboxPolicyDigest: plan.policyDigest,
468
756
  sandboxCandidateReason: plan.candidateBackend ? plan.reason : null,
469
757
  },
470
758
  );
@@ -517,55 +805,70 @@ class ProcessExecutionBroker extends EventEmitter {
517
805
  const adapterRequest = Object.freeze({
518
806
  profile,
519
807
  requiredBoundaries: Object.freeze([...requiredBoundaries]),
808
+ sync,
809
+ ...(sandboxPolicy.executionContract
810
+ ? { executionContract: sandboxPolicy.executionContract }
811
+ : {}),
520
812
  });
521
- let plan = this._validateSandboxPlan(
522
- // Keep the legacy string profile in argument four. The built-in adapter
523
- // reserves argument five for runtime injection, so the typed request is
524
- // additive in argument six and legacy injected adapters can ignore it.
525
- this._sandboxAdapter.applySandbox(
526
- command,
527
- args || [],
528
- options,
529
- profile,
530
- undefined,
531
- adapterRequest,
532
- ),
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,
533
823
  );
534
- plan = this._assertRequiredSandboxBoundaries(plan, requiredBoundaries);
535
-
536
- if (!plan.applied && strict) {
537
- throw this._sandboxError(
538
- plan.reason || "sandbox_unavailable",
539
- `Sandbox is unavailable in strict mode: ${
540
- plan.reason || "unknown reason"
541
- }`,
542
- );
543
- }
824
+ let plan;
825
+ try {
826
+ plan = this._validateSandboxPlan(rawPlan);
827
+ plan = this._assertRequiredSandboxBoundaries(plan, requiredBoundaries);
544
828
 
545
- if (plan.applied && plan.postSpawn.required) {
546
- if (typeof this._sandboxAdapter.postSpawnSandbox !== "function") {
829
+ if (!plan.applied && strict) {
547
830
  throw this._sandboxError(
548
- "post_spawn_adapter_unavailable",
549
- "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
+ }`,
550
835
  );
551
836
  }
552
- if (sync) {
553
- throw this._sandboxError(
554
- "post_spawn_unavailable_for_sync",
555
- "spawnSync cannot satisfy required post-spawn sandbox enforcement",
556
- );
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
+ }
557
860
  }
558
- if (
559
- (strict || requiredBoundaries.length > 0) &&
560
- plan.postSpawn.mode !== "sync"
561
- ) {
562
- throw this._sandboxError(
563
- "async_post_spawn_disallowed_in_strict_mode",
564
- "Fail-closed sandbox enforcement requires synchronous post-spawn enforcement",
565
- );
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
+ }
566
869
  }
870
+ throw error;
567
871
  }
568
- return plan;
569
872
  }
570
873
 
571
874
  _applySandboxAudit(auditEntry, plan, applied) {
@@ -580,6 +883,7 @@ class ProcessExecutionBroker extends EventEmitter {
580
883
  : null;
581
884
  auditEntry.sandboxPolicyAttested =
582
885
  typeof plan?.policyAttested === "boolean" ? plan.policyAttested : null;
886
+ auditEntry.sandboxPolicyDigest = plan?.policyDigest || null;
583
887
  auditEntry.sandboxCandidateReason = plan?.candidateBackend
584
888
  ? plan?.reason || null
585
889
  : null;
@@ -616,6 +920,8 @@ class ProcessExecutionBroker extends EventEmitter {
616
920
  typeof error.sandboxPolicyAttested === "boolean"
617
921
  ? error.sandboxPolicyAttested
618
922
  : (auditEntry.sandboxPolicyAttested ?? null);
923
+ auditEntry.sandboxPolicyDigest =
924
+ error.sandboxPolicyDigest || auditEntry.sandboxPolicyDigest || null;
619
925
  auditEntry.sandboxCandidateReason =
620
926
  error.sandboxCandidateReason || auditEntry.sandboxCandidateReason || null;
621
927
  auditEntry.deniedReason = `sandbox-init-failed: ${error.message}`;
@@ -923,6 +1229,9 @@ class ProcessExecutionBroker extends EventEmitter {
923
1229
  pluginId: options.pluginId || null,
924
1230
  pluginVersion: options.pluginVersion || null,
925
1231
  pluginSource: options.pluginSource || null,
1232
+ pluginExecutableIdentity: this._normalizePluginExecutableIdentity(
1233
+ options.pluginExecutableIdentity,
1234
+ ),
926
1235
  sandboxRequired: [],
927
1236
  sandboxGuarantees: [],
928
1237
  sandboxBackend: null,
@@ -930,7 +1239,11 @@ class ProcessExecutionBroker extends EventEmitter {
930
1239
 
931
1240
  let sandboxPolicy;
932
1241
  try {
933
- sandboxPolicy = this._normalizeSandboxPolicy(options);
1242
+ sandboxPolicy = this._normalizeSandboxPolicy(options, {
1243
+ command,
1244
+ args,
1245
+ sync: false,
1246
+ });
934
1247
  auditEntry.sandboxRequired = [...sandboxPolicy.requiredBoundaries];
935
1248
  } catch (sandboxPolicyError) {
936
1249
  this._recordSandboxDenial(auditEntry, sandboxPolicyError, startTime);
@@ -966,6 +1279,7 @@ class ProcessExecutionBroker extends EventEmitter {
966
1279
  // 传播traceparent环境变量
967
1280
  const spawnOpts = this._sanitizeOptions(options);
968
1281
  this._stripSandboxControlOptions(spawnOpts);
1282
+ this._stripPluginControlOptions(spawnOpts);
969
1283
  if (traceCtx) {
970
1284
  spawnOpts.env = { ...(spawnOpts.env || process.env) };
971
1285
  spawnOpts.env.TRACEPARENT = traceCtx.traceparent;
@@ -1138,6 +1452,9 @@ class ProcessExecutionBroker extends EventEmitter {
1138
1452
  pluginId: options.pluginId || null,
1139
1453
  pluginVersion: options.pluginVersion || null,
1140
1454
  pluginSource: options.pluginSource || null,
1455
+ pluginExecutableIdentity: this._normalizePluginExecutableIdentity(
1456
+ options.pluginExecutableIdentity,
1457
+ ),
1141
1458
  sandboxRequired: [],
1142
1459
  sandboxGuarantees: [],
1143
1460
  sandboxBackend: null,
@@ -1145,7 +1462,11 @@ class ProcessExecutionBroker extends EventEmitter {
1145
1462
 
1146
1463
  let sandboxPolicy;
1147
1464
  try {
1148
- sandboxPolicy = this._normalizeSandboxPolicy(options);
1465
+ sandboxPolicy = this._normalizeSandboxPolicy(options, {
1466
+ command,
1467
+ args,
1468
+ sync: true,
1469
+ });
1149
1470
  auditEntry.sandboxRequired = [...sandboxPolicy.requiredBoundaries];
1150
1471
  } catch (sandboxPolicyError) {
1151
1472
  this._recordSandboxDenial(auditEntry, sandboxPolicyError, startTime);
@@ -1174,6 +1495,7 @@ class ProcessExecutionBroker extends EventEmitter {
1174
1495
 
1175
1496
  const spawnOpts = this._sanitizeOptions(options);
1176
1497
  this._stripSandboxControlOptions(spawnOpts);
1498
+ this._stripPluginControlOptions(spawnOpts);
1177
1499
  if (traceCtx) {
1178
1500
  spawnOpts.env = { ...(spawnOpts.env || process.env) };
1179
1501
  spawnOpts.env.TRACEPARENT = traceCtx.traceparent;
@@ -1291,10 +1613,17 @@ class ProcessExecutionBroker extends EventEmitter {
1291
1613
  pluginId: options.pluginId || null,
1292
1614
  pluginVersion: options.pluginVersion || null,
1293
1615
  pluginSource: options.pluginSource || null,
1616
+ pluginExecutableIdentity: this._normalizePluginExecutableIdentity(
1617
+ options.pluginExecutableIdentity,
1618
+ ),
1294
1619
  };
1295
1620
  let sandboxPolicy;
1296
1621
  try {
1297
- sandboxPolicy = this._normalizeSandboxPolicy(options);
1622
+ sandboxPolicy = this._normalizeSandboxPolicy(options, {
1623
+ command,
1624
+ args,
1625
+ sync: false,
1626
+ });
1298
1627
  auditEntry.sandboxRequired = [...sandboxPolicy.requiredBoundaries];
1299
1628
  } catch (sandboxPolicyError) {
1300
1629
  this._recordSandboxDenial(auditEntry, sandboxPolicyError, startTime);
@@ -1331,12 +1660,10 @@ class ProcessExecutionBroker extends EventEmitter {
1331
1660
 
1332
1661
  const spawnOptions = { ...options, args: [...auditEntry.args] };
1333
1662
  this._stripSandboxControlOptions(spawnOptions);
1663
+ this._stripPluginControlOptions(spawnOptions);
1334
1664
  delete spawnOptions.origin;
1335
1665
  delete spawnOptions.policy;
1336
1666
  delete spawnOptions.scope;
1337
- delete spawnOptions.pluginId;
1338
- delete spawnOptions.pluginVersion;
1339
- delete spawnOptions.pluginSource;
1340
1667
  try {
1341
1668
  if (this._credentialBoundaryEnabled()) {
1342
1669
  spawnOptions.credentialContext = this._createCredentialContext(