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
@@ -20,6 +20,7 @@
20
20
 
21
21
  import fs from "fs";
22
22
  import path from "path";
23
+ import crypto from "node:crypto";
23
24
  import { getElectronUserDataDir } from "../paths.js";
24
25
  import {
25
26
  optionDefaults,
@@ -31,12 +32,16 @@ import {
31
32
  isSecretRef,
32
33
  secretRef,
33
34
  } from "../secret-store.js";
35
+ import { withFileLock } from "../with-file-lock.js";
34
36
 
35
37
  export const _deps = {
36
38
  existsSync: fs.existsSync,
37
39
  readFileSync: fs.readFileSync,
40
+ renameSync: fs.renameSync,
41
+ unlinkSync: fs.unlinkSync,
38
42
  writeFileSync: fs.writeFileSync,
39
43
  mkdirSync: fs.mkdirSync,
44
+ withFileLock,
40
45
  secretStore: () => createSecretStore(),
41
46
  userStorePath: () =>
42
47
  path.join(getElectronUserDataDir(), "plugin-options.json"),
@@ -44,23 +49,54 @@ export const _deps = {
44
49
  path.join(cwd || process.cwd(), ".chainlesschain", "plugin-options.json"),
45
50
  };
46
51
 
47
- function readJsonObject(p) {
52
+ function readJsonObject(p, { failIfUnavailable = false } = {}) {
48
53
  try {
49
54
  if (!_deps.existsSync(p)) return {};
50
55
  const data = JSON.parse(_deps.readFileSync(p, "utf8"));
51
- return data && typeof data === "object" && !Array.isArray(data) ? data : {};
52
- } catch {
56
+ if (data && typeof data === "object" && !Array.isArray(data)) return data;
57
+ throw new TypeError("top-level value must be an object");
58
+ } catch (cause) {
59
+ if (failIfUnavailable) {
60
+ const error = new Error(`Plugin option store is unavailable: ${p}`, {
61
+ cause,
62
+ });
63
+ error.code = "PLUGIN_OPTION_STORE_UNAVAILABLE";
64
+ throw error;
65
+ }
53
66
  return {};
54
67
  }
55
68
  }
56
69
 
57
70
  function writeJsonObject(p, obj) {
58
71
  _deps.mkdirSync(path.dirname(p), { recursive: true });
59
- _deps.writeFileSync(p, JSON.stringify(obj, null, 2), "utf8");
72
+ const tmp = `${p}.${process.pid}.${crypto.randomUUID()}.tmp`;
73
+ try {
74
+ _deps.writeFileSync(tmp, `${JSON.stringify(obj, null, 2)}\n`, {
75
+ encoding: "utf8",
76
+ mode: 0o600,
77
+ });
78
+ _deps.renameSync(tmp, p);
79
+ } catch (error) {
80
+ try {
81
+ _deps.unlinkSync(tmp);
82
+ } catch {
83
+ // Preserve the original persistence error.
84
+ }
85
+ throw error;
86
+ }
87
+ }
88
+
89
+ function withOptionStoreLock(p, body) {
90
+ _deps.mkdirSync(path.dirname(p), { recursive: true, mode: 0o700 });
91
+ return _deps.withFileLock(p, body, { failIfUnavailable: true });
60
92
  }
61
93
 
62
94
  /** Load a plugin's option VALUES at the given scope (`user` | `project`). */
63
- export function loadPluginOptionValues(name, scope, { cwd, schema, secretStore } = {}) {
95
+ export function loadPluginOptionValues(
96
+ name,
97
+ scope,
98
+ { cwd, schema, secretStore } = {},
99
+ ) {
64
100
  const p =
65
101
  scope === "project" ? _deps.projectStorePath(cwd) : _deps.userStorePath();
66
102
  const store = readJsonObject(p);
@@ -71,7 +107,9 @@ export function loadPluginOptionValues(name, scope, { cwd, schema, secretStore }
71
107
  for (const [key, desc] of Object.entries(normalized)) {
72
108
  if (!desc?.sensitive || !isSecretRef(out[key])) continue;
73
109
  try {
74
- const value = (secretStore || _deps.secretStore)().get(out[key].__cc_secret_ref);
110
+ const value = (secretStore || _deps.secretStore)().get(
111
+ out[key].__cc_secret_ref,
112
+ );
75
113
  if (value != null) out[key] = value;
76
114
  else delete out[key];
77
115
  } catch {
@@ -92,40 +130,58 @@ export function setPluginOptionValues(
92
130
  ) {
93
131
  const p =
94
132
  scope === "project" ? _deps.projectStorePath(cwd) : _deps.userStorePath();
95
- const store = readJsonObject(p);
96
- const input = values && typeof values === "object" ? values : {};
97
- const persisted = { ...input };
98
- const normalized = schema || {};
99
- let secrets = null;
100
- const getSecrets = () => {
101
- if (!secrets) secrets = (secretStore || _deps.secretStore)();
102
- return secrets;
103
- };
104
- const rejectedSensitive = [];
105
- for (const [key, desc] of Object.entries(normalized)) {
106
- if (!desc?.sensitive || !Object.prototype.hasOwnProperty.call(input, key)) continue;
107
- // Project files are shareable and must never receive a sensitive value.
108
- if (scope === "project") {
109
- delete persisted[key];
110
- rejectedSensitive.push(key);
111
- continue;
133
+ return withOptionStoreLock(p, () => {
134
+ const store = readJsonObject(p, { failIfUnavailable: true });
135
+ const input = values && typeof values === "object" ? values : {};
136
+ const persisted = { ...input };
137
+ const normalized = schema || {};
138
+ let secrets = null;
139
+ const getSecrets = () => {
140
+ if (!secrets) secrets = (secretStore || _deps.secretStore)();
141
+ return secrets;
142
+ };
143
+ const rejectedSensitive = [];
144
+ for (const [key, desc] of Object.entries(normalized)) {
145
+ if (
146
+ !desc?.sensitive ||
147
+ !Object.prototype.hasOwnProperty.call(input, key)
148
+ ) {
149
+ continue;
150
+ }
151
+ // Project files are shareable and must never receive a sensitive value.
152
+ if (scope === "project") {
153
+ delete persisted[key];
154
+ rejectedSensitive.push(key);
155
+ continue;
156
+ }
157
+ if (input[key] == null || input[key] === "") {
158
+ delete persisted[key];
159
+ try {
160
+ getSecrets().delete(`${name}/${key}`);
161
+ } catch {
162
+ // Missing secrets already behave as absent on read.
163
+ }
164
+ continue;
165
+ }
166
+ getSecrets().set(`${name}/${key}`, input[key]);
167
+ persisted[key] = secretRef(`${name}/${key}`);
112
168
  }
113
- if (input[key] == null || input[key] === "") {
114
- delete persisted[key];
115
- try { getSecrets().delete(`${name}/${key}`); } catch {}
116
- continue;
169
+ if (rejectedSensitive.length > 0) {
170
+ persisted.__cc_rejected_sensitive = [
171
+ ...new Set(rejectedSensitive),
172
+ ].sort();
173
+ } else if (
174
+ Object.prototype.hasOwnProperty.call(
175
+ persisted,
176
+ "__cc_rejected_sensitive",
177
+ )
178
+ ) {
179
+ delete persisted.__cc_rejected_sensitive;
117
180
  }
118
- getSecrets().set(`${name}/${key}`, input[key]);
119
- persisted[key] = secretRef(`${name}/${key}`);
120
- }
121
- if (rejectedSensitive.length > 0) {
122
- persisted.__cc_rejected_sensitive = [...new Set(rejectedSensitive)].sort();
123
- } else if (Object.prototype.hasOwnProperty.call(persisted, "__cc_rejected_sensitive")) {
124
- delete persisted.__cc_rejected_sensitive;
125
- }
126
- store[name] = persisted;
127
- writeJsonObject(p, store);
128
- return { name, scope, path: p };
181
+ store[name] = persisted;
182
+ writeJsonObject(p, store);
183
+ return { name, scope, path: p };
184
+ });
129
185
  }
130
186
 
131
187
  /** Provided keys of `values` (that exist in schema) accepted at `scope`. */
@@ -164,6 +164,22 @@ export function capabilityConsentRequired(managed, env) {
164
164
  );
165
165
  }
166
166
 
167
+ /**
168
+ * Require every loadable plugin to opt into the capability model with an
169
+ * explicit `permissions` block. Mandatory consent implies this gate: otherwise
170
+ * a legacy plugin could bypass consent simply by omitting the declaration.
171
+ */
172
+ export function capabilityDeclarationsRequired(managed, env) {
173
+ const runtimeEnv = env || process.env;
174
+ const raw = runtimeEnv.CC_REQUIRE_PLUGIN_CAPABILITIES;
175
+ if (raw != null && /^(1|true|yes|on)$/i.test(String(raw).trim())) return true;
176
+ return (
177
+ managed?.requirePluginCapabilityDeclarations === true ||
178
+ managed?.requirePluginCapabilityDeclarations === "require" ||
179
+ capabilityConsentRequired(managed, runtimeEnv)
180
+ );
181
+ }
182
+
167
183
  /**
168
184
  * Drop plugins that DECLARE capabilities but whose current capability SET has
169
185
  * not been consented (first request or any widening). Fail-closed: a consent
@@ -175,12 +191,23 @@ export function capabilityConsentRequired(managed, env) {
175
191
  * @param {Array<{name, scope, manifest}>} plugins
176
192
  * @returns {{ kept: Array, dropped: Array<{name, reason}> }}
177
193
  */
178
- export function filterByCapabilityConsent(plugins) {
194
+ export function filterByCapabilityConsent(
195
+ plugins,
196
+ { requireDeclarations = false } = {},
197
+ ) {
179
198
  const kept = [];
180
199
  const dropped = [];
181
200
  for (const p of plugins) {
182
201
  if (!p.manifest?.capabilitiesDeclared) {
183
- kept.push(p); // legacy plugin, no declaration → not gated
202
+ if (requireDeclarations) {
203
+ dropped.push({
204
+ name: p.name,
205
+ reason:
206
+ "capability declaration required: add an explicit `permissions` block to plugin.json",
207
+ });
208
+ } else {
209
+ kept.push(p); // migration window: legacy declaration remains compatible
210
+ }
184
211
  continue;
185
212
  }
186
213
  let consented = false;
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Normalize the small, declarative sandbox contract exposed to plugins.
3
+ *
4
+ * Plugins may require filesystem and/or network isolation for processes they
5
+ * cause the CLI to spawn. They may not select a sandbox profile or claim other
6
+ * broker guarantees. Keeping this layer narrower than ProcessExecutionBroker's
7
+ * internal contract prevents plugin-controlled policy from weakening managed
8
+ * defaults while still allowing an explicit requirement to fail closed.
9
+ */
10
+
11
+ export const PLUGIN_SANDBOX_BOUNDARIES = Object.freeze([
12
+ "filesystem",
13
+ "network",
14
+ ]);
15
+
16
+ const SUPPORTED_BOUNDARIES = new Set(PLUGIN_SANDBOX_BOUNDARIES);
17
+
18
+ function invalidPolicy(message) {
19
+ const error = new Error(message);
20
+ error.code = "ERR_PLUGIN_SANDBOX_POLICY_INVALID";
21
+ return error;
22
+ }
23
+
24
+ /**
25
+ * @param {unknown} raw
26
+ * @param {{ label?: string }} [opts]
27
+ * @returns {{requiredBoundaries: string[]}|null}
28
+ */
29
+ export function normalizePluginSandboxPolicy(raw, opts = {}) {
30
+ const label = opts.label || "sandboxPolicy";
31
+ if (raw === undefined || raw === null) return null;
32
+ if (typeof raw !== "object" || Array.isArray(raw)) {
33
+ throw invalidPolicy(`${label} must be an object`);
34
+ }
35
+ const unsupportedKeys = Object.keys(raw).filter(
36
+ (key) => key !== "requiredBoundaries",
37
+ );
38
+ if (unsupportedKeys.length > 0) {
39
+ throw invalidPolicy(
40
+ `${label} contains unsupported field: ${unsupportedKeys[0]}`,
41
+ );
42
+ }
43
+
44
+ const boundaries = raw.requiredBoundaries;
45
+ if (boundaries === undefined) return null;
46
+ if (!Array.isArray(boundaries)) {
47
+ throw invalidPolicy(`${label}.requiredBoundaries must be an array`);
48
+ }
49
+
50
+ const requiredBoundaries = [];
51
+ for (const boundary of boundaries) {
52
+ if (
53
+ typeof boundary !== "string" ||
54
+ !SUPPORTED_BOUNDARIES.has(boundary)
55
+ ) {
56
+ throw invalidPolicy(
57
+ `${label}.requiredBoundaries contains unsupported boundary: ${String(boundary)}`,
58
+ );
59
+ }
60
+ if (!requiredBoundaries.includes(boundary)) {
61
+ requiredBoundaries.push(boundary);
62
+ }
63
+ }
64
+
65
+ return requiredBoundaries.length > 0 ? { requiredBoundaries } : null;
66
+ }
67
+
68
+ /**
69
+ * Merge manifest/component/descriptor requirements additively. A child
70
+ * descriptor can require more isolation, but cannot remove a manifest-level
71
+ * requirement.
72
+ */
73
+ export function mergePluginSandboxPolicies(...policies) {
74
+ const requiredBoundaries = [];
75
+ for (const raw of policies) {
76
+ const policy = normalizePluginSandboxPolicy(raw);
77
+ for (const boundary of policy?.requiredBoundaries || []) {
78
+ if (!requiredBoundaries.includes(boundary)) {
79
+ requiredBoundaries.push(boundary);
80
+ }
81
+ }
82
+ }
83
+ return requiredBoundaries.length > 0 ? { requiredBoundaries } : null;
84
+ }
@@ -29,6 +29,7 @@ import {
29
29
  filterByManagedPolicy,
30
30
  filterByCapabilityConsent,
31
31
  capabilityConsentRequired,
32
+ capabilityDeclarationsRequired,
32
33
  warnDroppedOnce,
33
34
  } from "./policy.js";
34
35
 
@@ -135,13 +136,20 @@ export function discoverPlugins(opts = {}) {
135
136
  const byName = new Map(); // name → record (later scope overrides earlier)
136
137
  for (const scope of scopes) {
137
138
  const root = scopeRoot(scope, opts);
138
- if (!dirExists(root)) continue;
139
- for (const encoded of listDirs(root)) {
139
+ if (!dirExists(root, opts.strictIo === true)) continue;
140
+ for (const encoded of listDirs(root, opts.strictIo === true)) {
140
141
  const nameDir = path.join(root, encoded);
141
- const version = activeVersionForDir(nameDir);
142
+ const version = activeVersionForDir(nameDir, opts.strictIo === true);
142
143
  if (!version) continue;
143
144
  const versionDir = path.join(nameDir, version);
144
145
  const manifest = parsePluginManifest(versionDir);
146
+ if (opts.strictIo === true && manifest.ok !== true) {
147
+ throw new Error(
148
+ `plugin manifest is not safely loadable at ${versionDir}: ${
149
+ manifest.errors?.join("; ") || "unknown manifest error"
150
+ }`,
151
+ );
152
+ }
145
153
  manifest.scope = scope;
146
154
  const name = manifest.metadata?.name || encoded;
147
155
  byName.set(name, {
@@ -163,9 +171,10 @@ export function discoverPlugins(opts = {}) {
163
171
  managedSettingsFile: opts.managedSettingsFile,
164
172
  });
165
173
  const consentGate = capabilityConsentRequired(managed, opts.env);
174
+ const declarationsGate = capabilityDeclarationsRequired(managed, opts.env);
166
175
  // Default (no managed policy AND consent enforcement off): byte-identical —
167
176
  // return every discovered plugin, exactly as before.
168
- if (!managed && !consentGate) return all;
177
+ if (!managed && !consentGate && !declarationsGate) return all;
169
178
  let list = all;
170
179
  if (managed) {
171
180
  const { kept, dropped } = filterByManagedPolicy(list, managed);
@@ -174,8 +183,10 @@ export function discoverPlugins(opts = {}) {
174
183
  }
175
184
  // Capability-consent enforcement funnels through the SAME chokepoint, so an
176
185
  // un-consented plugin loads NONE of its six component types (opt-in).
177
- if (consentGate) {
178
- const { kept, dropped } = filterByCapabilityConsent(list);
186
+ if (consentGate || declarationsGate) {
187
+ const { kept, dropped } = filterByCapabilityConsent(list, {
188
+ requireDeclarations: declarationsGate,
189
+ });
179
190
  if (dropped.length > 0) warnDroppedOnce(dropped);
180
191
  list = kept;
181
192
  }
@@ -184,8 +195,8 @@ export function discoverPlugins(opts = {}) {
184
195
 
185
196
  // ── internals ────────────────────────────────────────────────────────────
186
197
 
187
- function activeVersionForDir(nameDir) {
188
- if (!dirExists(nameDir)) return null;
198
+ function activeVersionForDir(nameDir, strictIo = false) {
199
+ if (!dirExists(nameDir, strictIo)) return null;
189
200
  const versions = _deps
190
201
  .readdirSync(nameDir, { withFileTypes: true })
191
202
  .filter((e) => e.isDirectory())
@@ -198,28 +209,31 @@ function activeVersionForDir(nameDir) {
198
209
  try {
199
210
  const pinned = _deps.readFileSync(activeFile, "utf8").trim();
200
211
  if (versions.includes(pinned)) return pinned;
201
- } catch {
212
+ } catch (error) {
213
+ if (strictIo) throw error;
202
214
  /* fall through */
203
215
  }
204
216
  }
205
217
  return versions[0];
206
218
  }
207
219
 
208
- function dirExists(dir) {
220
+ function dirExists(dir, strictIo = false) {
209
221
  try {
210
222
  return _deps.existsSync(dir) && _deps.statSync(dir).isDirectory();
211
- } catch {
223
+ } catch (error) {
224
+ if (strictIo) throw error;
212
225
  return false;
213
226
  }
214
227
  }
215
228
 
216
- function listDirs(dir) {
229
+ function listDirs(dir, strictIo = false) {
217
230
  try {
218
231
  return _deps
219
232
  .readdirSync(dir, { withFileTypes: true })
220
233
  .filter((e) => e.isDirectory())
221
234
  .map((e) => e.name);
222
- } catch {
235
+ } catch (error) {
236
+ if (strictIo) throw error;
223
237
  return [];
224
238
  }
225
239
  }
@@ -21,16 +21,17 @@
21
21
  * running untrusted SHELL/binaries behind the user's back.
22
22
  */
23
23
 
24
- import fs from "fs";
25
24
  import path from "path";
26
25
  import { getElectronUserDataDir } from "../paths.js";
26
+ import { withFileLock } from "../with-file-lock.js";
27
+ import {
28
+ mutateSecurityStore,
29
+ readSecurityStore,
30
+ } from "../durable-security-store.js";
27
31
 
28
32
  export const _deps = {
29
- existsSync: fs.existsSync,
30
- readFileSync: fs.readFileSync,
31
- writeFileSync: fs.writeFileSync,
32
- mkdirSync: fs.mkdirSync,
33
33
  now: () => new Date().toISOString(),
34
+ withFileLock,
34
35
  // Path of the trust store; injectable so unit tests never touch the real
35
36
  // user-data dir.
36
37
  storePath: () => path.join(getElectronUserDataDir(), "plugin-trust.json"),
@@ -39,20 +40,7 @@ export const _deps = {
39
40
  const AUTO_TRUSTED_SCOPES = new Set(["user", "local"]);
40
41
 
41
42
  export function loadTrustStore() {
42
- try {
43
- const p = _deps.storePath();
44
- if (!_deps.existsSync(p)) return {};
45
- const data = JSON.parse(_deps.readFileSync(p, "utf8"));
46
- return data && typeof data === "object" && !Array.isArray(data) ? data : {};
47
- } catch {
48
- return {};
49
- }
50
- }
51
-
52
- function saveTrustStore(store) {
53
- const p = _deps.storePath();
54
- _deps.mkdirSync(path.dirname(p), { recursive: true });
55
- _deps.writeFileSync(p, JSON.stringify(store, null, 2), "utf8");
43
+ return readSecurityStore(_deps.storePath(), "plugin trust");
56
44
  }
57
45
 
58
46
  function trustKey(scope, name) {
@@ -66,27 +54,44 @@ function trustKey(scope, name) {
66
54
  export function isPluginTrusted(plugin) {
67
55
  if (!plugin || !plugin.name) return false;
68
56
  if (AUTO_TRUSTED_SCOPES.has(plugin.scope)) return true;
69
- const entry = loadTrustStore()[trustKey(plugin.scope, plugin.name)];
70
- return Boolean(entry && entry.version === plugin.version);
57
+ try {
58
+ const entry = loadTrustStore()[trustKey(plugin.scope, plugin.name)];
59
+ return Boolean(entry && entry.version === plugin.version);
60
+ } catch {
61
+ // Project code must stay disabled when the trust store is unavailable.
62
+ return false;
63
+ }
71
64
  }
72
65
 
73
66
  /** Trust a plugin (records the exact version). */
74
67
  export function trustPlugin(name, { scope = "project", version } = {}) {
75
68
  if (!version) throw new Error("trustPlugin requires a version");
76
- const store = loadTrustStore();
77
- store[trustKey(scope, name)] = { version, trustedAt: _deps.now() };
78
- saveTrustStore(store);
79
- return { name, scope, version };
69
+ const file = _deps.storePath();
70
+ return mutateSecurityStore(
71
+ file,
72
+ "plugin trust",
73
+ (store) => {
74
+ store[trustKey(scope, name)] = { version, trustedAt: _deps.now() };
75
+ return { name, scope, version };
76
+ },
77
+ { lock: _deps.withFileLock },
78
+ );
80
79
  }
81
80
 
82
81
  /** Revoke trust for a plugin at a scope. */
83
82
  export function untrustPlugin(name, { scope = "project" } = {}) {
84
- const store = loadTrustStore();
85
- const key = trustKey(scope, name);
86
- const existed = Object.prototype.hasOwnProperty.call(store, key);
87
- delete store[key];
88
- saveTrustStore(store);
89
- return { name, scope, removed: existed };
83
+ const file = _deps.storePath();
84
+ return mutateSecurityStore(
85
+ file,
86
+ "plugin trust",
87
+ (store) => {
88
+ const key = trustKey(scope, name);
89
+ const existed = Object.prototype.hasOwnProperty.call(store, key);
90
+ delete store[key];
91
+ return { name, scope, removed: existed };
92
+ },
93
+ { lock: _deps.withFileLock },
94
+ );
90
95
  }
91
96
 
92
97
  /** All trust entries (for `cc plugin trust --list`). */