chainlesschain 0.165.4 → 0.165.6

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 (214) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/.build-hash +1 -1
  3. package/src/assets/web-panel/assets/{AIOps-C__nnraW.js → AIOps-vfoDb6HZ.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-CsKWHEZ-.js → ActionButton-Cm5f7p93.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-BhIjfjWO.js → Analytics-yRuvgWxa.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-BjuXFzWZ.js → AppLayout-BROsC4h1.js} +4 -4
  7. package/src/assets/web-panel/assets/{Artifacts-k6whDkZJ.js → Artifacts-CimHApb1.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-C4FBMYRh.js → Audit-DI8kr8zI.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-C_vRrSXk.js → BackgroundAgents-DSLzKy-n.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-CngFZeVp.js → Backup-DkH_n2r1.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-B_H9EBRm.js → BaseInput-CKSrUoRA.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-DLEC5kt7.js → Chat-ClwfMXUS.js} +3 -3
  13. package/src/assets/web-panel/assets/ChatBubbleRenderer-CjMaqfL7.js +1 -0
  14. package/src/assets/web-panel/assets/{Checkbox-m3ClR4xh.js → Checkbox-BYTehcQG.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-CmLSFrgp.js → Codegen-B8AMcp6J.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-DFGQteHN.js → Col-BNSogPo3.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-EUUVORHE.js → Community-JxPvGb8O.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-2PSg0Yr7.js → Compact-DF7bFAgE.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-CcKur7gB.js → Compliance-Bvhqnwrq.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-DK_Fezfa.js → Cowork-BDS0CJvM.js} +3 -3
  21. package/src/assets/web-panel/assets/{Cron-Dbw89xl7.js → Cron-DqvRfxoQ.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-CH66h_Ec.js → Crosschain-CDcIvnqS.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-D1igRb17.js → DID-D7jaUxU3.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-DVAsrobk.js → Dashboard-B5A18wEV.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-Dl7W8AQs.js → Dropdown-_6IVkGag.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-D5tpaEQC.js → EmailListRenderer-C9PeiKCG.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard-O_VQf8gq.js → FamilyGuardDashboard-DXjuEHrX.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-BTVcgS9n.js → Federation-B4IAR9zv.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-BRnkJAIz.js → FormItemContext-CxQeSNx1.js} +1 -1
  30. package/src/assets/web-panel/assets/{GenericCardRenderer-8OWSCkDj.js → GenericCardRenderer-B8GS-Y3N.js} +1 -1
  31. package/src/assets/web-panel/assets/{Git-WXLYTQj2.js → Git-BS8SouUX.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-BezaUhtc.js → Governance-Dq9aYb5Q.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-CuRay3Gu.js → Inference-BrCEe9AJ.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-DfWLDW1m.js → KnowledgeGraph-DybOpiY2.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-C55y2pPY.js → Logs-DBpzbRfx.js} +2 -2
  36. package/src/assets/web-panel/assets/MarkdownRenderer-CFyt8iUd.js +1 -0
  37. package/src/assets/web-panel/assets/{Marketplace-Dk08Uycg.js → Marketplace-Cc7CCSCu.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-C11fSB5V.js → McpTools-DFaIhOfu.js} +3 -3
  39. package/src/assets/web-panel/assets/{Memory-mr0eZc97.js → Memory-KCqlp9ol.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-C0iCSRbb.js → MobileBridge-Bys84ySN.js} +1 -1
  41. package/src/assets/web-panel/assets/{MobileProjects-CY-xMG8Z.js → MobileProjects-B-6qU-je.js} +1 -1
  42. package/src/assets/web-panel/assets/{Mtc-Bplqc_Wc.js → Mtc-BgY-fvCq.js} +4 -4
  43. package/src/assets/web-panel/assets/{MtcAudit-BlzwsoSM.js → MtcAudit-B8pCmqQJ.js} +4 -4
  44. package/src/assets/web-panel/assets/{Multisig-BBLmTty6.js → Multisig-BbOmYutA.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-DtT1uf1W.js → NLProgramming-BocLQz_M.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-DcqQAxTK.js → Notes-CSwbxEop.js} +3 -3
  47. package/src/assets/web-panel/assets/{NotificationSettings-cb0kWoZe.js → NotificationSettings-CqFNSYG3.js} +1 -1
  48. package/src/assets/web-panel/assets/{OrderTableRenderer-kw9HZQNN.js → OrderTableRenderer-C6gMfAk7.js} +1 -1
  49. package/src/assets/web-panel/assets/{Organization-DlTlbkUN.js → Organization-QrDXVdMJ.js} +4 -4
  50. package/src/assets/web-panel/assets/{Overflow-pp1qs-oY.js → Overflow-Cxntotjt.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-BESLnyYz.js → P2P-CIdBOwNq.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-B-J1mGuf.js → PdhVaultBrowser-CT5aP8rD.js} +3 -3
  53. package/src/assets/web-panel/assets/{Permissions-B36PeT1_.js → Permissions-DH7OM8XU.js} +4 -4
  54. package/src/assets/web-panel/assets/{PersonalDataHub-CTK2ad-3.js → PersonalDataHub-CnJqbWce.js} +3 -3
  55. package/src/assets/web-panel/assets/{Pipeline-zJNGXsac.js → Pipeline-5C3HG1kH.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-b9fz0Qf0.js → Privacy-B4yIp7xK.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-DjZbZgiB.js → ProjectInit-BMvt-2M0.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-C-hHJXlD.js → ProjectSettings-CvSTEMRG.js} +2 -2
  59. package/src/assets/web-panel/assets/Projects-BKBJxEek.js +1 -0
  60. package/src/assets/web-panel/assets/Providers-BdwUqFWN.js +1 -0
  61. package/src/assets/web-panel/assets/{QrScannerModal-A0yoQ3-3.js → QrScannerModal-DtnCKlTm.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-DrFgFJNC.js → QuickAsk-sTbgwyNr.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend-KC8hF1g4.js → Recommend-Bzr14gSb.js} +1 -1
  64. package/src/assets/web-panel/assets/{RemoteSession-DGTPIk6u.js → RemoteSession-C_TF5IaJ.js} +2 -2
  65. package/src/assets/web-panel/assets/{Reputation-QmbwM7Yk.js → Reputation-GCAM4H2K.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-BxjJylia.js → Row-Dir0r6OQ.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-B7Wda1J6.js → RssFeed-CpGnlecX.js} +2 -2
  68. package/src/assets/web-panel/assets/{Search-_plQ_YSA.js → Search-DMMamC6u.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-CD2YJZfx.js → Security-yqay5yG-.js} +4 -4
  70. package/src/assets/web-panel/assets/{Services-qQE7NmwE.js → Services-C5i2wh9G.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-DgQqkFf7.js → Skeleton-vUqk35yj.js} +1 -1
  72. package/src/assets/web-panel/assets/{Skills-C4C0oFFt.js → Skills-DzcSkhot.js} +1 -1
  73. package/src/assets/web-panel/assets/{Sla-Px2N2B5c.js → Sla-CB6qbYNr.js} +1 -1
  74. package/src/assets/web-panel/assets/{SpeechSettings-DN6C3lQd.js → SpeechSettings-BHUI7cox.js} +1 -1
  75. package/src/assets/web-panel/assets/{SyncSettings-jm5aH_m7.js → SyncSettings-D-RrsxTJ.js} +2 -2
  76. package/src/assets/web-panel/assets/{Tasks-DlkJcv67.js → Tasks-DFxdOJiq.js} +1 -1
  77. package/src/assets/web-panel/assets/{Templates-DyrTHUBs.js → Templates-SKAob_Aq.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-mC434PtL.js → Tenant-BPfsfHQ-.js} +1 -1
  79. package/src/assets/web-panel/assets/{Terminal-o0_s3NgK.js → Terminal-8iw7FpUf.js} +2 -2
  80. package/src/assets/web-panel/assets/{TimelineRenderer-DAGlAXOw.js → TimelineRenderer-C4Gjj5Su.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-BnulS_bs.js → Tokens-COYhN18e.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-suQbVXYM.js → Trigger-B-JzXcf6.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-DbIJAPo5.js → Trust-BJ5bg0nI.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-CQNpbIHi.js → UkeySign-BG_ByRMf.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-D8aWCERk.js → VideoEditing-B3kOnSiU.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-CuLpYfZc.js → Wallet-CcoGFnK7.js} +2 -2
  87. package/src/assets/web-panel/assets/{WebAuthn-CsfG8ZMc.js → WebAuthn-DdT8vRC_.js} +4 -4
  88. package/src/assets/web-panel/assets/{WorkflowEditor-BYsEAZbd.js → WorkflowEditor-CZu3M9N8.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-FT4Um3-I.js → chat-DxJt3Qba.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-CKbS_Wlt.js → colors-DdYfwJaB.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-CFJtzuJM.js → compact-item-BG3SUzwj.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-B9kSRW6K.js → createContext-By51z2-1.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-DorRZcI9.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-DR-x0Xpi.js → hasIn-B0apZ3KJ.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-DjEP7WkH.js → index-3jWkIu5j.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-7jHr_A_k.js → index-B3rWuPMW.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-DcfxhKXR.js → index-B5rLiEo0.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-tqSEHPRT.js → index-BBPf3TpM.js} +1 -1
  99. package/src/assets/web-panel/assets/index-BETiL0a3.js +1 -0
  100. package/src/assets/web-panel/assets/{index-Cr2FLUsD.js → index-BIrJfqO4.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-Bt4fS2eL.js → index-BLIbGOLX.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-BwR7yc2h.js → index-BP94CrBV.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BVPU43b1.js → index-BWF8_mkx.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-DShSkww-.js → index-BYINoRLK.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-Bzz0C1BZ.js → index-BZ_0qm4g.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-KqDaCApw.js → index-BewKYrX9.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-BW-t9n-q.js → index-BfWYsB9t.js} +1 -1
  108. package/src/assets/web-panel/assets/index-BhAVHuW8.js +1 -0
  109. package/src/assets/web-panel/assets/{index-B7osrXqy.js → index-Bissefox.js} +3 -3
  110. package/src/assets/web-panel/assets/{index-DW4BWjTk.js → index-BkvcEo4p.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-DdkIhfi-.js → index-Bos5_aMV.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-DTxNy0ZU.js → index-C1C9i79A.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-QBSeNVO3.js → index-CAhHirVH.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-D4LfPvWA.js → index-CNIxXMmN.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-C_enk9I_.js → index-CW93tZDv.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-WE08gMJP.js → index-CWEuZWCK.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-r2VI1Ikk.js → index-Cp6e-hGw.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-Dap9c3eD.js → index-CpjZhgNd.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-DWdqx7zI.js → index-CzmQElZy.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-BGbPnC5x.js → index-DCn8IcxV.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-DiNUEpSQ.js → index-DE76D-kA.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-DtkFqPVA.js → index-DaIz0NAW.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-CGaXUsIs.js → index-Da_WBdLX.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-B3ZX81mK.js → index-Dz49VOyQ.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-BK3TiKVq.js → index-Q2SCX-MI.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-CJmIQ9XR.js → index-RD6O-0C6.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-CvrCCqJt.js → index-SQqOlR3d.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-BI5hP_qy.js → index-ZFbps9po.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-DeSgw-WV.js → index-ZxtP8jG7.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-DMGmg497.js → index-bP_VlDb4.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-BfFCQHL3.js → index-kf57LJ93.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-OSzjTzGM.js → index-oxRrmFO9.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-C2JvmYRc.js → index-p1_8SbI1.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-Dd7n7VgI.js → initDefaultProps-BWJktcg8.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-BwxouRw1.js → motion-BEXBzUFV.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-DObN0PG9.js → move-BUKwn2sx.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-B3nOUQc7.js → mtc-parser-FTI7btqQ.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-o9WU2Nbl.js → omit-CsLtSPH3.js} +1 -1
  139. package/src/assets/web-panel/assets/parsers-YNLm7sQ0.js +4 -0
  140. package/src/assets/web-panel/assets/{pickAttrs-CL_vvfQ_.js → pickAttrs-DWZxsT_S.js} +1 -1
  141. package/src/assets/web-panel/assets/{placementArrow-CYrM2tyK.js → placementArrow-Bcfs43CX.js} +1 -1
  142. package/src/assets/web-panel/assets/{responsiveObserve-k_06cQ96.js → responsiveObserve-a9bcC1p-.js} +1 -1
  143. package/src/assets/web-panel/assets/{slide-CPKG0pxS.js → slide-BDTzgOXN.js} +1 -1
  144. package/src/assets/web-panel/assets/{statusUtils-BDDEeLTw.js → statusUtils-Iq1j_HUg.js} +1 -1
  145. package/src/assets/web-panel/assets/{styleChecker-Cmb7RTh7.js → styleChecker-DAZEYxeh.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFlexGapSupport-e2IedC4N.js → useFlexGapSupport-DVkjyDrh.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFs-CE_gxVnm.js → useFs-wXTpNTHt.js} +1 -1
  148. package/src/assets/web-panel/assets/{usePersonalDataHub-BkMIIKMz.js → usePersonalDataHub-CtQM_aZr.js} +1 -1
  149. package/src/assets/web-panel/assets/{vnode-DW886XV1.js → vnode-hjEoG85v.js} +1 -1
  150. package/src/assets/web-panel/assets/{zoom-Dwo_adaf.js → zoom-BHVpyKg_.js} +1 -1
  151. package/src/assets/web-panel/index.html +1 -1
  152. package/src/command-help-index.json +3 -3
  153. package/src/commands/agent.js +14 -2
  154. package/src/commands/artifacts.js +235 -0
  155. package/src/commands/background-session.js +100 -10
  156. package/src/commands/cowork.js +86 -57
  157. package/src/commands/mcp.js +5 -0
  158. package/src/commands/plugin.js +145 -29
  159. package/src/commands/remote-control.js +295 -110
  160. package/src/commands/session-location.js +20 -1
  161. package/src/commands/session-message.js +171 -0
  162. package/src/commands/session.js +75 -69
  163. package/src/data/changelog.json +29 -3
  164. package/src/gateways/ws/message-dispatcher.js +57 -0
  165. package/src/harness/mcp-client.js +141 -10
  166. package/src/lib/artifact-access-ledger.js +1 -0
  167. package/src/lib/artifact-deletion-ledger.js +1 -0
  168. package/src/lib/artifact-recovery.js +970 -0
  169. package/src/lib/artifact-workbench-projection.js +171 -0
  170. package/src/lib/background-session-transport.js +153 -27
  171. package/src/lib/dynamic-workflow-runtime.js +408 -1
  172. package/src/lib/execution-location-target.js +4 -2
  173. package/src/lib/mcp-client.js +2 -0
  174. package/src/lib/mcp-headers-helper.js +47 -5
  175. package/src/lib/mcp-oauth.js +55 -6
  176. package/src/lib/mcp-stdio-executable-identity.js +16 -0
  177. package/src/lib/mcp-stdio-native-code-policy.js +74 -0
  178. package/src/lib/mcp-stdio-package-materialization.js +12 -3
  179. package/src/lib/mcp-tls.js +230 -0
  180. package/src/lib/output-styles.js +12 -0
  181. package/src/lib/plugin-runtime/install.js +614 -71
  182. package/src/lib/plugin-runtime/marketplace-archive-source.js +331 -0
  183. package/src/lib/plugin-runtime/marketplace-catalog.js +52 -6
  184. package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +1 -0
  185. package/src/lib/plugin-runtime/marketplace-source-adapter.js +163 -0
  186. package/src/lib/plugin-runtime/marketplace-source-cache.js +11 -1
  187. package/src/lib/plugin-runtime/remote-source.js +435 -55
  188. package/src/lib/plugin-security.js +393 -41
  189. package/src/lib/plugin-source-identity.js +850 -0
  190. package/src/lib/process-execution-broker/index.js +112 -0
  191. package/src/lib/process-execution-broker/platform-sandbox.js +57 -3
  192. package/src/lib/process-execution-broker/workspace-transaction.js +26 -0
  193. package/src/lib/remote-approval-bridge.js +136 -46
  194. package/src/lib/remote-control.js +217 -31
  195. package/src/lib/session-message-fabric.js +1105 -0
  196. package/src/lib/session-projection.js +171 -12
  197. package/src/lib/session-runtime-retention.js +155 -0
  198. package/src/lib/settings-loader.cjs +29 -0
  199. package/src/repl/agent-repl.js +51 -14
  200. package/src/repl/permission-prompt.js +31 -8
  201. package/src/repl/repl-keybindings.js +55 -0
  202. package/src/runtime/agent-core.js +63 -2
  203. package/src/runtime/headless-runner.js +47 -66
  204. package/src/runtime/headless-stream.js +18 -24
  205. package/src/runtime/mcp-config.js +2 -0
  206. package/src/runtime/policies/agent-policy.js +2 -0
  207. package/src/assets/web-panel/assets/ChatBubbleRenderer-xijcWkJe.js +0 -1
  208. package/src/assets/web-panel/assets/MarkdownRenderer-hDpWdiBc.js +0 -1
  209. package/src/assets/web-panel/assets/Projects-BC9KSDM6.js +0 -1
  210. package/src/assets/web-panel/assets/Providers-Dz-CAYYU.js +0 -1
  211. package/src/assets/web-panel/assets/devWarning-DJZ0gAMu.js +0 -1
  212. package/src/assets/web-panel/assets/index-Bizb4hkw.js +0 -1
  213. package/src/assets/web-panel/assets/index-OHSl-xCh.js +0 -1
  214. package/src/assets/web-panel/assets/parsers-UEvh_ShA.js +0 -4
@@ -1,55 +1,370 @@
1
1
  import { createHash, createPublicKey, verify } from "node:crypto";
2
2
  import { readFileSync } from "node:fs";
3
- import { loadManagedSettings } from "./settings-loader.cjs";
4
-
5
- function stringSet(value) {
6
- return Array.isArray(value)
7
- ? new Set(
8
- value
9
- .map((v) =>
10
- typeof v === "string" ? v : v?.name || v?.source || v?.url || null,
11
- )
12
- .map((v) => String(v || "").trim())
13
- .filter(Boolean),
14
- )
3
+ import {
4
+ loadManagedSettings,
5
+ managedSettingsPath,
6
+ } from "./settings-loader.cjs";
7
+ import { canonicalizePluginSource } from "./plugin-source-identity.js";
8
+
9
+ export { canonicalizePluginSource } from "./plugin-source-identity.js";
10
+
11
+ const BLOCKED_SOURCE_KEYS = ["blockedPluginSources", "blockedMarketplaces"];
12
+ const ALLOWED_SOURCE_KEYS = [
13
+ "allowedPluginSources",
14
+ "strictKnownMarketplaces",
15
+ "allowedMarketplaces",
16
+ ];
17
+ const KNOWN_MARKETPLACE_KEYS = [
18
+ "extraKnownMarketplaces",
19
+ "additionalMarketplaces",
20
+ ];
21
+ const STANDARD_GITHUB_SSH_PRINCIPAL = createHash("sha256")
22
+ .update("git")
23
+ .digest("hex");
24
+ let managedPolicyCache = new Map();
25
+
26
+ function stringSet(value, label) {
27
+ if (value == null) return null;
28
+ if (!Array.isArray(value)) throw invalidPolicy(`${label} must be an array`);
29
+ const normalized = value.map((entry, index) => {
30
+ let candidate = entry;
31
+ if (entry && typeof entry === "object" && !Array.isArray(entry)) {
32
+ const keys = Object.keys(entry);
33
+ if (keys.length !== 1 || !["name", "source", "url"].includes(keys[0])) {
34
+ throw invalidPolicy(`${label}[${index}] is invalid`);
35
+ }
36
+ candidate = entry[keys[0]];
37
+ }
38
+ if (typeof candidate !== "string") {
39
+ throw invalidPolicy(`${label}[${index}] must name a plugin`);
40
+ }
41
+ const result = candidate.trim();
42
+ if (
43
+ !result ||
44
+ result.length > 256 ||
45
+ /[\u0000-\u001f\u007f]/u.test(result)
46
+ ) {
47
+ throw invalidPolicy(`${label}[${index}] must be a bounded string`);
48
+ }
49
+ return result;
50
+ });
51
+ return new Set(normalized);
52
+ }
53
+
54
+ function invalidPolicy(message) {
55
+ const error = new Error(
56
+ `managed plugin source policy is invalid: ${message}`,
57
+ );
58
+ error.code = "PLUGIN_SOURCE_POLICY_INVALID";
59
+ return error;
60
+ }
61
+
62
+ function listSetting(managed, key) {
63
+ if (!Object.prototype.hasOwnProperty.call(managed, key)) return null;
64
+ if (!Array.isArray(managed[key])) {
65
+ throw invalidPolicy(`${key} must be an array`);
66
+ }
67
+ return managed[key];
68
+ }
69
+
70
+ function canonicalJson(value) {
71
+ if (Array.isArray(value)) return value.map(canonicalJson);
72
+ if (!value || typeof value !== "object") return value;
73
+ return Object.fromEntries(
74
+ Object.keys(value)
75
+ .sort()
76
+ .map((key) => [key, canonicalJson(value[key])]),
77
+ );
78
+ }
79
+
80
+ function immutablePolicySnapshot(value) {
81
+ if (value == null) return null;
82
+ const snapshot = canonicalJson(value);
83
+ const freeze = (entry) => {
84
+ if (!entry || typeof entry !== "object" || Object.isFrozen(entry)) {
85
+ return entry;
86
+ }
87
+ for (const child of Object.values(entry)) freeze(child);
88
+ return Object.freeze(entry);
89
+ };
90
+ return freeze(snapshot);
91
+ }
92
+
93
+ function digest(value) {
94
+ return createHash("sha256")
95
+ .update(JSON.stringify(canonicalJson(value)))
96
+ .digest("hex");
97
+ }
98
+
99
+ function knownMarketplaces(managed, options) {
100
+ const known = new Map();
101
+ for (const setting of KNOWN_MARKETPLACE_KEYS) {
102
+ if (!Object.prototype.hasOwnProperty.call(managed, setting)) continue;
103
+ const declarations = managed[setting];
104
+ // The array form contains anonymous direct sources and therefore has no
105
+ // name to resolve. It remains a valid compatibility form, but every entry
106
+ // must still compile so damaged managed settings cannot become inert.
107
+ if (Array.isArray(declarations)) {
108
+ declarations.forEach((declaration) =>
109
+ canonicalizePluginSource(declaration, {
110
+ policyEntry: true,
111
+ cwd: options.cwd,
112
+ }),
113
+ );
114
+ continue;
115
+ }
116
+ if (!declarations || typeof declarations !== "object") {
117
+ throw invalidPolicy(`${setting} must be an object or array`);
118
+ }
119
+ for (const [rawName, declaration] of Object.entries(declarations)) {
120
+ const name = String(rawName).trim().toLowerCase();
121
+ if (!name)
122
+ throw invalidPolicy(`${setting} has an empty marketplace name`);
123
+ const identity = canonicalizePluginSource(declaration, {
124
+ policyEntry: true,
125
+ cwd: options.cwd,
126
+ });
127
+ const previous = known.get(name);
128
+ if (previous && digest(previous) !== digest(identity)) {
129
+ throw invalidPolicy(
130
+ `${setting} conflicts with its compatibility alias for marketplace ${rawName}`,
131
+ );
132
+ }
133
+ known.set(name, identity);
134
+ }
135
+ }
136
+ return known;
137
+ }
138
+
139
+ function sourceIdentity(value, known, options) {
140
+ if (options.policyEntry === true) {
141
+ let aliasName = typeof value === "string" ? value : null;
142
+ if (value && typeof value === "object" && !Array.isArray(value)) {
143
+ const keys = Object.keys(value);
144
+ if (keys.length === 1 && keys[0] === "name") aliasName = value.name;
145
+ if (keys.length === 1 && keys[0] === "source") {
146
+ aliasName = value.source;
147
+ }
148
+ }
149
+ const alias =
150
+ typeof aliasName === "string"
151
+ ? known.get(aliasName.trim().toLowerCase())
152
+ : null;
153
+ if (alias) return { ...alias };
154
+ }
155
+ return canonicalizePluginSource(value, options);
156
+ }
157
+
158
+ function matchesSource(rule, source) {
159
+ if (rule.kind === "github-owner") {
160
+ return (
161
+ source.kind === "github" &&
162
+ source.authority === "github.com" &&
163
+ ((source.scheme === "https" && !source.principalDigest) ||
164
+ (source.scheme === "ssh" &&
165
+ source.principalDigest === STANDARD_GITHUB_SSH_PRINCIPAL)) &&
166
+ source.owner === rule.owner
167
+ );
168
+ }
169
+ return (
170
+ (rule.identityDigest || rule.key) ===
171
+ (source.identityDigest || source.key) &&
172
+ (rule.ref ?? null) === (source.ref ?? null) &&
173
+ (rule.path ?? null) === (source.path ?? null)
174
+ );
175
+ }
176
+
177
+ function compileSourcePolicy(managed, options) {
178
+ const known = knownMarketplaces(managed, options);
179
+ const blocked = [];
180
+ const allowedGroups = [];
181
+ for (const setting of BLOCKED_SOURCE_KEYS) {
182
+ const entries = listSetting(managed, setting);
183
+ entries?.forEach((entry, index) =>
184
+ blocked.push({
185
+ setting,
186
+ index,
187
+ identity: sourceIdentity(entry, known, {
188
+ policyEntry: true,
189
+ cwd: options.cwd,
190
+ }),
191
+ }),
192
+ );
193
+ }
194
+ for (const setting of ALLOWED_SOURCE_KEYS) {
195
+ const entries = listSetting(managed, setting);
196
+ if (!entries) continue;
197
+ allowedGroups.push({
198
+ setting,
199
+ rules: entries.map((entry, index) => ({
200
+ setting,
201
+ index,
202
+ identity: sourceIdentity(entry, known, {
203
+ policyEntry: true,
204
+ cwd: options.cwd,
205
+ }),
206
+ })),
207
+ });
208
+ }
209
+ const projection = {
210
+ blocked,
211
+ allowedGroups,
212
+ };
213
+ return { known, blocked, allowedGroups, policyDigest: digest(projection) };
214
+ }
215
+
216
+ /** Pure, deterministic projection for audit logs and policy rollback checks. */
217
+ export function evaluatePluginSourcePolicy(source, managed, options = {}) {
218
+ if (!managed) {
219
+ return {
220
+ allowed: true,
221
+ status: "unmanaged",
222
+ source: null,
223
+ policyDigest: null,
224
+ matchedRule: null,
225
+ allowedBy: [],
226
+ };
227
+ }
228
+ if (typeof managed !== "object" || Array.isArray(managed)) {
229
+ throw invalidPolicy("settings root must be an object");
230
+ }
231
+ const policy = compileSourcePolicy(managed, options);
232
+ const restricted =
233
+ policy.blocked.length > 0 ||
234
+ (!options.blockedOnly && policy.allowedGroups.length > 0);
235
+ if (!restricted) {
236
+ return {
237
+ allowed: true,
238
+ status: "unrestricted",
239
+ source: null,
240
+ policyDigest: policy.policyDigest,
241
+ matchedRule: null,
242
+ allowedBy: [],
243
+ };
244
+ }
245
+ if (source == null || (typeof source === "string" && !source.trim())) {
246
+ const requiresAllowlist =
247
+ !options.blockedOnly && policy.allowedGroups.length > 0;
248
+ return {
249
+ allowed: !requiresAllowlist,
250
+ status: requiresAllowlist ? "not-allowed" : "unrestricted",
251
+ source: null,
252
+ policyDigest: policy.policyDigest,
253
+ matchedRule: null,
254
+ allowedBy: [],
255
+ };
256
+ }
257
+ const identity = sourceIdentity(source, policy.known, {
258
+ cwd: options.cwd,
259
+ kindHint: options.kindHint,
260
+ });
261
+ const blocked = policy.blocked.find((rule) =>
262
+ matchesSource(rule.identity, identity),
263
+ );
264
+ if (blocked) {
265
+ return {
266
+ allowed: false,
267
+ status: "blocked",
268
+ source: identity,
269
+ policyDigest: policy.policyDigest,
270
+ matchedRule: blocked,
271
+ allowedBy: [],
272
+ };
273
+ }
274
+ if (options.blockedOnly) {
275
+ return {
276
+ allowed: true,
277
+ status: "not-blocked",
278
+ source: identity,
279
+ policyDigest: policy.policyDigest,
280
+ matchedRule: null,
281
+ allowedBy: [],
282
+ };
283
+ }
284
+ const allowedBy = [];
285
+ for (const group of policy.allowedGroups) {
286
+ const match = group.rules.find((rule) =>
287
+ matchesSource(rule.identity, identity),
288
+ );
289
+ if (!match) {
290
+ return {
291
+ allowed: false,
292
+ status: "not-allowed",
293
+ source: identity,
294
+ policyDigest: policy.policyDigest,
295
+ matchedRule: { setting: group.setting, index: null, identity: null },
296
+ allowedBy,
297
+ };
298
+ }
299
+ allowedBy.push(match);
300
+ }
301
+ return {
302
+ allowed: true,
303
+ status: "allowed",
304
+ source: identity,
305
+ policyDigest: policy.policyDigest,
306
+ matchedRule: null,
307
+ allowedBy,
308
+ };
309
+ }
310
+
311
+ /** Enforce source policy before registry transport or git materialization. */
312
+ export function enforcePluginSourcePolicy(source, managed, options = {}) {
313
+ const decision = evaluatePluginSourcePolicy(source, managed, options);
314
+ if (decision.allowed) return decision;
315
+ const error = new Error(
316
+ decision.status === "blocked"
317
+ ? `plugin source "${decision.source?.key || "(missing)"}" is blocked by managed settings`
318
+ : source == null
319
+ ? "managed settings require --source for plugin installation"
320
+ : `plugin source "${decision.source?.key || "(invalid)"}" is not in the managed allowlist`,
321
+ );
322
+ error.code =
323
+ decision.status === "blocked"
324
+ ? "PLUGIN_SOURCE_POLICY_BLOCKED"
325
+ : "PLUGIN_SOURCE_POLICY_NOT_ALLOWED";
326
+ error.sourceIdentity = decision.source?.key || null;
327
+ error.sourceDigest = decision.source
328
+ ? digest({
329
+ identity: decision.source.identityDigest || decision.source.key || null,
330
+ ref: decision.source.ref ?? null,
331
+ path: decision.source.path ?? null,
332
+ })
15
333
  : null;
334
+ error.policyDigest = decision.policyDigest;
335
+ error.policySetting = decision.matchedRule?.setting || null;
336
+ throw error;
16
337
  }
17
338
 
18
339
  export function enforcePluginPolicy(
19
- { name, source = null, action = "install" },
340
+ {
341
+ name,
342
+ source = null,
343
+ sourceKind = null,
344
+ sourcePolicyPreflighted = false,
345
+ action = "install",
346
+ },
20
347
  managed,
21
348
  ) {
22
349
  if (!managed) return { allowed: true };
23
- const denied = stringSet(managed.deniedPlugins) || new Set();
24
- const allowed = stringSet(managed.allowedPlugins);
350
+ const denied = stringSet(managed.deniedPlugins, "deniedPlugins") || new Set();
351
+ const allowed = stringSet(managed.allowedPlugins, "allowedPlugins");
25
352
  if (denied.has(name)) {
26
353
  throw new Error(`plugin "${name}" is denied by managed settings`);
27
354
  }
28
355
  if (allowed && !allowed.has(name)) {
29
356
  throw new Error(`plugin "${name}" is not in the managed allowlist`);
30
357
  }
31
-
32
- const blockedSources = new Set([
33
- ...(stringSet(managed.blockedPluginSources) || []),
34
- ...(stringSet(managed.blockedMarketplaces) || []),
35
- ]);
36
- const allowedSources = stringSet(managed.allowedPluginSources);
37
- if (source && blockedSources.has(source)) {
38
- throw new Error(`plugin source "${source}" is blocked by managed settings`);
39
- }
40
- if (action === "install" && allowedSources) {
41
- if (!source) {
42
- throw new Error(
43
- "managed settings require --source for plugin installation",
44
- );
45
- }
46
- if (!allowedSources.has(source)) {
47
- throw new Error(
48
- `plugin source "${source}" is not in the managed allowlist`,
49
- );
50
- }
51
- }
52
- return { allowed: true };
358
+ const sourceDecision =
359
+ sourcePolicyPreflighted ||
360
+ action === "load" ||
361
+ (source == null && action !== "install")
362
+ ? null
363
+ : enforcePluginSourcePolicy(source, managed, {
364
+ action,
365
+ kindHint: sourceKind,
366
+ });
367
+ return { allowed: true, sourceDecision };
53
368
  }
54
369
 
55
370
  export function verifyPluginManifest({
@@ -158,9 +473,8 @@ export function verifyPluginManifest({
158
473
  publicKeySha256: signatureVerified ? publicKeySha256 : null,
159
474
  signatureSha256: signatureVerified ? signatureSha256 : null,
160
475
  publicKeyDocumentSha256: signatureVerified ? publicKeyDocumentSha256 : null,
161
- // The raw signature material, so the installer can persist it and load-time
162
- // enforcement can CRYPTOGRAPHICALLY re-verify (not merely trust a recorded
163
- // boolean, which a hand-written lock file could forge).
476
+ // Persist exact verified material so load-time enforcement can re-check it
477
+ // cryptographically instead of trusting a forgeable boolean in a lock file.
164
478
  signatureBase64: signatureVerified ? signature.toString("base64") : null,
165
479
  publicKeyPem: signatureVerified ? publicKeyPem : null,
166
480
  };
@@ -180,5 +494,43 @@ function assertExpectedDigest(actual, expected, label) {
180
494
  }
181
495
 
182
496
  export function loadPluginManagedPolicy(options = {}) {
183
- return loadManagedSettings(options).settings;
497
+ const key = managedSettingsPath(options);
498
+ if (managedPolicyCache.has(key)) {
499
+ const cached = managedPolicyCache.get(key);
500
+ if (cached?.error) throw cached.error;
501
+ return cached?.settings ?? null;
502
+ }
503
+ try {
504
+ const settings = immutablePolicySnapshot(
505
+ loadManagedSettings(options).settings,
506
+ );
507
+ managedPolicyCache.set(key, { settings });
508
+ return settings;
509
+ } catch (error) {
510
+ managedPolicyCache.set(key, { error });
511
+ throw error;
512
+ }
513
+ }
514
+
515
+ /**
516
+ * Resolve the non-bypassable process policy. A caller-provided policy is a
517
+ * test/internal fallback only when no organization policy exists on disk; it
518
+ * can never replace (including with null) a loaded managed policy.
519
+ */
520
+ export function resolvePluginManagedPolicy(options = {}) {
521
+ const managed = loadPluginManagedPolicy({
522
+ env: options.env,
523
+ managedSettingsFile: options.managedSettingsFile,
524
+ onWarn: options.onWarn,
525
+ });
526
+ if (managed != null) return managed;
527
+ if (!Object.prototype.hasOwnProperty.call(options, "managedPolicy")) {
528
+ return null;
529
+ }
530
+ return immutablePolicySnapshot(options.managedPolicy);
531
+ }
532
+
533
+ /** Test/session hook: managed org policy is otherwise immutable per process. */
534
+ export function _resetPluginManagedPolicyCache() {
535
+ managedPolicyCache = new Map();
184
536
  }