chainlesschain 0.165.1 → 0.165.2

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 (202) hide show
  1. package/README.md +248 -2
  2. package/package.json +4 -1
  3. package/src/assets/web-panel/assets/{AIOps-CYxFDrcm.js → AIOps-lS1R0Cza.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-CPBtdiU2.js → ActionButton-BmlgBPsj.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-Dayq7Dp7.js → Analytics-CNKczv1S.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-6U7bPb2s.js → AppLayout-BuZGJARQ.js} +4 -4
  7. package/src/assets/web-panel/assets/{Artifacts-D2Iqg_3D.js → Artifacts-Dm73Sl-O.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-CdoOB7WV.js → Audit-BGMW7A5e.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-DrnAVB8w.js → BackgroundAgents-BQ6M54JR.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-CesMi5cy.js → Backup-DBzGP0bR.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-DaX9ptax.js → BaseInput-D1mLCoOV.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-OrwOPxDS.js → Chat-BUfcN7p8.js} +4 -4
  13. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CvPZFRxM.js → ChatBubbleRenderer-CY5m8ZHg.js} +1 -1
  14. package/src/assets/web-panel/assets/{Checkbox-DiHbcysC.js → Checkbox-Du0Yg5Pi.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-CbgCkaBJ.js → Codegen-B2RXziHW.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-Du5hgrh4.js → Col-DWhekOrR.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-DsPOBW-p.js → Community-HQhrkon4.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-BwHIFkNC.js → Compact-izHNb4uz.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-BvrDQSgd.js → Compliance-BDwLy41-.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-gwAE6arx.js → Cowork-DFJhLa7K.js} +3 -3
  21. package/src/assets/web-panel/assets/{Cron-DW-0l4uF.js → Cron-DYY9RG7-.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-j-NsLesB.js → Crosschain-rr7tJTtv.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-CibVEBOI.js → DID-D2sfHRLi.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-W4z9vSfe.js → Dashboard-q_eGdhha.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-DAcrkKxG.js → Dropdown-Cufrh2Bz.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-6GXah-89.js → EmailListRenderer-B-kdv10f.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard-TKDCq8Ku.js → FamilyGuardDashboard-D21XjgfG.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-BXBLlcNm.js → Federation-CAwRTLZH.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-BoJJBkG3.js → FormItemContext-vx3daNDF.js} +1 -1
  30. package/src/assets/web-panel/assets/{GenericCardRenderer-okjsl46v.js → GenericCardRenderer-CRWY2wU4.js} +1 -1
  31. package/src/assets/web-panel/assets/{Git-Rvs7i6nn.js → Git-Q6SwauyD.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-CHSUxXXS.js → Governance-BJ1q4IQZ.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-V3BlfxsB.js → Inference-CSWjROgD.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-C_NlD4aR.js → KnowledgeGraph-fzuQsWuY.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-Nn4LNxhA.js → Logs-DVF8Mnns.js} +2 -2
  36. package/src/assets/web-panel/assets/MarkdownRenderer-BLif4QSg.js +1 -0
  37. package/src/assets/web-panel/assets/{Marketplace-DEmjFcg-.js → Marketplace-BQP7LOA4.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-DlopXipI.js → McpTools-BNlJCmNc.js} +4 -4
  39. package/src/assets/web-panel/assets/{Memory-BG3ynX60.js → Memory-DLLg5WQ4.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-DeRzWOfT.js → MobileBridge-CR2skNAF.js} +1 -1
  41. package/src/assets/web-panel/assets/{MobileProjects-Tyd3o2A0.js → MobileProjects-BxVavObl.js} +1 -1
  42. package/src/assets/web-panel/assets/{Mtc-BoPbOv1C.js → Mtc-B17pgqMI.js} +4 -4
  43. package/src/assets/web-panel/assets/{MtcAudit-un-rTHp7.js → MtcAudit-4UmV5cIL.js} +2 -2
  44. package/src/assets/web-panel/assets/{Multisig-Ds0oveEB.js → Multisig-DoMEXEcU.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-D09JI-yY.js → NLProgramming-h9DMXFX4.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-DTRhiKJn.js → Notes-Cihn-xX8.js} +3 -3
  47. package/src/assets/web-panel/assets/{NotificationSettings-BAnnNCim.js → NotificationSettings-BE6ZGa3R.js} +1 -1
  48. package/src/assets/web-panel/assets/{OrderTableRenderer-Yr-1fSYi.js → OrderTableRenderer-CnwojoSI.js} +1 -1
  49. package/src/assets/web-panel/assets/{Organization-S9EAolpj.js → Organization-B2vpwmjb.js} +4 -4
  50. package/src/assets/web-panel/assets/{Overflow-CqcLKqJ8.js → Overflow-C4z28R0-.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-Dw0F9EcU.js → P2P-BVlFkwhW.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-BDRwUevN.js → PdhVaultBrowser-BXbEdL5B.js} +3 -3
  53. package/src/assets/web-panel/assets/{Permissions-D3_c3nKB.js → Permissions-C28xs4lp.js} +4 -4
  54. package/src/assets/web-panel/assets/{PersonalDataHub-CxdMV98x.js → PersonalDataHub-Dgl_rBjM.js} +3 -3
  55. package/src/assets/web-panel/assets/{Pipeline-CgjNQFLI.js → Pipeline-3QUIhrKI.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-BHghIIht.js → Privacy-8Gh33OZ5.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-De6pqaKM.js → ProjectInit-BNmg4tZi.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-Bg4ZkNYQ.js → ProjectSettings-vgMfeCf9.js} +2 -2
  59. package/src/assets/web-panel/assets/Projects-BhtAVilc.js +1 -0
  60. package/src/assets/web-panel/assets/{Providers-CUnHbNf-.js → Providers-CXoOa8eX.js} +1 -1
  61. package/src/assets/web-panel/assets/{QrScannerModal-DA2f3Wts.js → QrScannerModal-BhfTF0oS.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-C1FeHDqp.js → QuickAsk-C746HEAj.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend-B5guaUMN.js → Recommend-BSej8Eo0.js} +1 -1
  64. package/src/assets/web-panel/assets/{RemoteSession-PDADSds3.js → RemoteSession-f3gmnlG3.js} +3 -3
  65. package/src/assets/web-panel/assets/{Reputation-eTlRhgvK.js → Reputation-CyvybpkN.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-D7AqSGY0.js → Row-DwV2PeYn.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-JiuLm4Ja.js → RssFeed-11GrzjZy.js} +3 -3
  68. package/src/assets/web-panel/assets/{Search-CwruahW3.js → Search-BjKXkrAY.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-CdhqaR0b.js → Security-eWiFb9Yk.js} +4 -4
  70. package/src/assets/web-panel/assets/{Services-CU0ZIlcT.js → Services-CdCsMAtt.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-CtduPfAb.js → Skeleton-4Q2UTKQ5.js} +1 -1
  72. package/src/assets/web-panel/assets/{Skills-CROXm6AY.js → Skills-v4rtYrRj.js} +1 -1
  73. package/src/assets/web-panel/assets/{Sla-DiZiABFD.js → Sla-CRhsFvd_.js} +1 -1
  74. package/src/assets/web-panel/assets/SpeechSettings-DLjKsDVu.js +1 -0
  75. package/src/assets/web-panel/assets/{SyncSettings-DBX6J1Oe.js → SyncSettings-D16zonl7.js} +2 -2
  76. package/src/assets/web-panel/assets/{Tasks-BLyRJd3-.js → Tasks-Xxozz0i_.js} +1 -1
  77. package/src/assets/web-panel/assets/{Templates-BKa5qzmk.js → Templates-CXJpPtCT.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-DnD3a4M6.js → Tenant-XRV0L1ZF.js} +1 -1
  79. package/src/assets/web-panel/assets/{Terminal-DEitQeTb.js → Terminal-CYuO1i_w.js} +2 -2
  80. package/src/assets/web-panel/assets/{TimelineRenderer-CjHggTDq.js → TimelineRenderer-BXqitWsu.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-CsGT7sfl.js → Tokens-BvPrDHIy.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-yr4rFDrW.js → Trigger-DhCrSTf5.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-CLvu1Sjp.js → Trust-DmsuZD6K.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-B0m7yUP8.js → UkeySign-D_yrts5C.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-C0VvP4lc.js → VideoEditing-B01ihPrm.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-kllBAG1M.js → Wallet-DpUjKa-N.js} +3 -3
  87. package/src/assets/web-panel/assets/{WebAuthn-C54UQNLx.js → WebAuthn-CL07yON6.js} +3 -3
  88. package/src/assets/web-panel/assets/{WorkflowEditor-B7y8qSvU.js → WorkflowEditor-CLMflnRr.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-DRzTh8CJ.js → chat-DtUqe8h_.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-BSMwSnCx.js → colors-DPKrgVfy.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-BTg602H5.js → compact-item-BTt2GtOm.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-B6EGsdvp.js → createContext-D_VeUc1J.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-Bj5nUW2v.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-DDKqJ8RD.js → hasIn-1kndiylj.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-CUEU48o1.js → index-2eyAXE3d.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-rjzk9z1Q.js → index-4bna2_SR.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-CmAubjDi.js → index-8nz_fmlj.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-Co7oM1qr.js → index-B9KvcS7R.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-BMuGd2--.js → index-BAXfRKfG.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BVTAl5N2.js → index-BHpBMWCh.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-DpTHIRfZ.js → index-BaZAbw9A.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-CWGax2QW.js → index-BepLZwgB.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DiW0sDkz.js → index-Bhudc_Ez.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CGNklbP6.js → index-BlDNVgBt.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-u2YVld9W.js → index-By5n8up9.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-pqfux8vZ.js → index-CHG-KcS4.js} +1 -1
  107. package/src/assets/web-panel/assets/index-CPcM-eqo.js +1 -0
  108. package/src/assets/web-panel/assets/{index-BRqt4fO-.js → index-CX81qSM4.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-BsR7Y2NG.js → index-CauoBQkH.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-C_JzIXUq.js → index-CcO04eDn.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-CQlHFN_g.js → index-CtF7EN49.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-CwPUZbMI.js → index-CzjkKUmR.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-th2ihDc0.js → index-D95OFht7.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-CHfLYwcW.js → index-DFIZ_1Sf.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-C1GFfuqN.js → index-DG2MZQ3f.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-D1naNj4U.js → index-DJ8vXGOa.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-DLdrHhML.js → index-Dbbymxpj.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-DBT3YeQ9.js → index-DdkplL9R.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-BICn3Qh1.js → index-DfGl8CqG.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-DqFXGzzC.js → index-DfKBRdSS.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-Bx044qDj.js → index-DsJCDUJG.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-XFe-1twF.js → index-Dwqmtk65.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-C66NpWy5.js → index-DxdTdBix.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-CmAInUkX.js → index-FzdwcSy2.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-Cf23wVMs.js → index-GsoUQ2M7.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-D5CsBShd.js → index-brCInrzq.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-323Hhxxt.js → index-dVc-CXY4.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-p2HYn89m.js → index-fk2Rjacw.js} +3 -3
  129. package/src/assets/web-panel/assets/{index-Dfv2lKu3.js → index-l1BETrDb.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-CNxg61YP.js → index-m31Ka8hZ.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-CDTvsX8t.js → index-ocf06EVQ.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-Dc77VR3H.js → index-sDoMHTNA.js} +1 -1
  133. package/src/assets/web-panel/assets/index-xeSyVoRe.js +1 -0
  134. package/src/assets/web-panel/assets/{initDefaultProps-C3Djh9fa.js → initDefaultProps-CvyYJd7z.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-BzqFmbSe.js → motion-DYZkhUdz.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-DJo_FFaW.js → move-slnJRVT1.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-_tlTiBvk.js → mtc-parser-DVc0CKmy.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-CB2ZyxUg.js → omit-BCXAtHCq.js} +1 -1
  139. package/src/assets/web-panel/assets/{pickAttrs-DZwIFD4u.js → pickAttrs-DBsemz_K.js} +1 -1
  140. package/src/assets/web-panel/assets/{placementArrow-DxZY0dgk.js → placementArrow-BRtkJ-nv.js} +1 -1
  141. package/src/assets/web-panel/assets/{responsiveObserve-CzzGt7GL.js → responsiveObserve-Cebq7EZn.js} +1 -1
  142. package/src/assets/web-panel/assets/{slide-BaIK52yz.js → slide-DT7qvId2.js} +1 -1
  143. package/src/assets/web-panel/assets/{statusUtils-3-FHu9_M.js → statusUtils-pQiITLkG.js} +1 -1
  144. package/src/assets/web-panel/assets/{styleChecker-BkRT68fK.js → styleChecker-c-19BVKQ.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFlexGapSupport-DHYwKS-s.js → useFlexGapSupport-DsS5-0bE.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFs-DVVUhV8p.js → useFs-CxGiMe5n.js} +1 -1
  147. package/src/assets/web-panel/assets/{usePersonalDataHub-CkrFKAzQ.js → usePersonalDataHub-D9btVID5.js} +1 -1
  148. package/src/assets/web-panel/assets/{vnode-BuBLFz0c.js → vnode-CUYFsFEN.js} +1 -1
  149. package/src/assets/web-panel/assets/{zoom-kpm6LtXU.js → zoom-CXmn_35j.js} +1 -1
  150. package/src/assets/web-panel/index.html +1 -1
  151. package/src/command-help-index.json +1 -1
  152. package/src/commands/cowork.js +280 -5
  153. package/src/commands/plugin.js +819 -64
  154. package/src/commands/session-location.js +318 -7
  155. package/src/constants.js +2 -2
  156. package/src/data/changelog.json +14 -1
  157. package/src/gateways/ws/action-protocol.js +1 -1
  158. package/src/harness/jsonl-session-store.js +638 -2
  159. package/src/harness/prompt-compressor.js +4 -0
  160. package/src/lib/background-agent-keeper-client.js +29 -0
  161. package/src/lib/background-agent-keeper-protocol.js +4 -0
  162. package/src/lib/background-agent-supervisor.js +59 -29
  163. package/src/lib/cowork-task-runner.js +70 -0
  164. package/src/lib/cowork-workflow.js +42 -9
  165. package/src/lib/doctor-checkup.js +34 -10
  166. package/src/lib/dynamic-workflow-draft.js +535 -0
  167. package/src/lib/dynamic-workflow-facade.js +11 -11
  168. package/src/lib/dynamic-workflow-runtime.js +2974 -0
  169. package/src/lib/execution-location-contract.js +111 -7
  170. package/src/lib/execution-location-runtime.js +3 -1
  171. package/src/lib/execution-location-target.js +910 -0
  172. package/src/lib/llm-providers.js +1 -0
  173. package/src/lib/mcp-call-ledger-store.js +35 -0
  174. package/src/lib/mcp-call-ledger.js +30 -0
  175. package/src/lib/plugin-runtime/__tests__/remote-source.test.js +34 -16
  176. package/src/lib/plugin-runtime/install.js +4956 -657
  177. package/src/lib/plugin-runtime/manifest.js +3 -1
  178. package/src/lib/plugin-runtime/marketplace-artifact-readback.js +671 -31
  179. package/src/lib/plugin-runtime/marketplace-catalog.js +68 -2
  180. package/src/lib/plugin-runtime/marketplace-impact.js +208 -15
  181. package/src/lib/plugin-runtime/marketplace-network.js +317 -0
  182. package/src/lib/plugin-runtime/marketplace-pac-worker.js +15 -0
  183. package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +25 -2
  184. package/src/lib/plugin-runtime/marketplace-source-cache.js +359 -0
  185. package/src/lib/plugin-runtime/policy.js +21 -6
  186. package/src/lib/plugin-runtime/publisher-trust.js +332 -0
  187. package/src/lib/plugin-runtime/remote-source.js +323 -27
  188. package/src/lib/plugin-runtime/scopes.js +317 -41
  189. package/src/lib/plugin-runtime/transaction-journal.js +806 -0
  190. package/src/lib/public-ide-capability-manifest.js +1 -1
  191. package/src/lib/remote-membership-coordinator.js +8 -6
  192. package/src/lib/sub-agent-context.js +268 -2
  193. package/src/lib/task-model-selector.js +1 -1
  194. package/src/lib/with-file-lock.js +95 -5
  195. package/src/runtime/agent-core.js +595 -41
  196. package/src/workers/background-agent-keeper.js +40 -10
  197. package/src/assets/web-panel/assets/MarkdownRenderer-SVAgNnkt.js +0 -1
  198. package/src/assets/web-panel/assets/Projects-CP8vPvzs.js +0 -1
  199. package/src/assets/web-panel/assets/SpeechSettings-B5pLcXUw.js +0 -1
  200. package/src/assets/web-panel/assets/devWarning-Dol8jLEP.js +0 -1
  201. package/src/assets/web-panel/assets/index-C3QX5tOl.js +0 -1
  202. package/src/assets/web-panel/assets/index-xYybvEic.js +0 -1
@@ -0,0 +1,332 @@
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { verifyInstalledSignature } from "./signature.js";
5
+
6
+ export const PLUGIN_PUBLISHER_AUTHORITY_SCHEMA =
7
+ "cc-plugin-publisher-authority/v1";
8
+
9
+ const DIGEST_RE = /^[a-f0-9]{64}$/u;
10
+ const MAX_POLICY_ENTRIES = 256;
11
+
12
+ export function normalizePublisherDeclaration(value) {
13
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
14
+ const id = bounded(value.id, 256);
15
+ const organizationId = bounded(
16
+ value.organizationId ?? value.organization,
17
+ 256,
18
+ );
19
+ if (!id || !organizationId) return null;
20
+ return { id, organizationId };
21
+ }
22
+
23
+ export function normalizePublisherAuthority(value) {
24
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
25
+ const publisher = normalizePublisherDeclaration(value.publisher);
26
+ const subject = value.subject;
27
+ const normalized = {
28
+ schemaVersion: value.schemaVersion,
29
+ status: value.status,
30
+ trustSource: value.trustSource,
31
+ publisher,
32
+ subject: {
33
+ name: bounded(subject?.name, 256),
34
+ registryOrigin: normalizeOrigin(subject?.registryOrigin),
35
+ signingKeySha256: String(subject?.signingKeySha256 || "").toLowerCase(),
36
+ },
37
+ trustRootId: bounded(value.trustRootId, 256),
38
+ policyDigest: String(value.policyDigest || "").toLowerCase(),
39
+ verifiedAt: optionalTime(value.verifiedAt, "publisher verifiedAt"),
40
+ claims: {
41
+ publisherIdentityVerified:
42
+ value.claims?.publisherIdentityVerified === true,
43
+ organizationTrustRootMatched:
44
+ value.claims?.organizationTrustRootMatched === true,
45
+ signingKeyNotRevoked: value.claims?.signingKeyNotRevoked === true,
46
+ manifestSignatureVerified:
47
+ value.claims?.manifestSignatureVerified === true,
48
+ },
49
+ };
50
+ if (
51
+ normalized.schemaVersion !== PLUGIN_PUBLISHER_AUTHORITY_SCHEMA ||
52
+ normalized.status !== "verified" ||
53
+ normalized.trustSource !== "managed-settings" ||
54
+ !normalized.publisher ||
55
+ !normalized.subject.name ||
56
+ !normalized.subject.registryOrigin ||
57
+ !DIGEST_RE.test(normalized.subject.signingKeySha256) ||
58
+ !normalized.trustRootId ||
59
+ !DIGEST_RE.test(normalized.policyDigest) ||
60
+ !normalized.verifiedAt ||
61
+ Object.values(normalized.claims).some((claim) => claim !== true)
62
+ ) {
63
+ return null;
64
+ }
65
+ const authorityDigest = String(value.authorityDigest || "").toLowerCase();
66
+ if (
67
+ !DIGEST_RE.test(authorityDigest) ||
68
+ authorityDigest !== sha256Canonical(normalized)
69
+ ) {
70
+ return null;
71
+ }
72
+ const complete = { ...normalized, authorityDigest };
73
+ return canonicalJson(complete) === canonicalJson(value) ? complete : null;
74
+ }
75
+
76
+ export function buildManagedPublisherAuthority({
77
+ name,
78
+ registryUrl,
79
+ declaration,
80
+ signingKeySha256,
81
+ managed,
82
+ verifiedAt = new Date().toISOString(),
83
+ evaluatedAt = verifiedAt,
84
+ } = {}) {
85
+ const required = managed?.requireTrustedPluginPublishers === true;
86
+ const publisher = normalizePublisherDeclaration(declaration);
87
+ if (!publisher) {
88
+ if (required) {
89
+ throw new Error("TRUSTED_PLUGIN_PUBLISHER_REQUIRED: declaration missing");
90
+ }
91
+ return null;
92
+ }
93
+ const key = String(signingKeySha256 || "").toLowerCase();
94
+ if (!DIGEST_RE.test(key)) {
95
+ if (required) {
96
+ throw new Error("TRUSTED_PLUGIN_PUBLISHER_REQUIRED: signed key missing");
97
+ }
98
+ return null;
99
+ }
100
+ const registryOrigin = normalizeOrigin(registryUrl);
101
+ if (!registryOrigin) {
102
+ throw new Error("plugin publisher registry origin is invalid");
103
+ }
104
+ const recordedAt = canonicalTime(verifiedAt, "publisher verification time");
105
+ const now = canonicalTime(evaluatedAt, "publisher policy evaluation time");
106
+ const revocations = normalizeRevocations(managed?.revokedPluginPublisherKeys);
107
+ if (revocations.has(key)) {
108
+ throw new Error(`PLUGIN_PUBLISHER_KEY_REVOKED (${key})`);
109
+ }
110
+ const entries = normalizeTrustEntries(managed?.trustedPluginPublishers);
111
+ const match = entries.find(
112
+ (entry) =>
113
+ entry.publisherId === publisher.id &&
114
+ entry.organizationId === publisher.organizationId &&
115
+ entry.pluginNames.includes(String(name)) &&
116
+ entry.registryOrigins.includes(registryOrigin) &&
117
+ entry.signingKeySha256.includes(key) &&
118
+ (!entry.notBefore || now >= entry.notBefore) &&
119
+ (!entry.notAfter || now <= entry.notAfter),
120
+ );
121
+ if (!match) {
122
+ if (required || entries.length > 0) {
123
+ throw new Error(
124
+ `PLUGIN_PUBLISHER_TRUST_MISMATCH (${publisher.organizationId}/${publisher.id}; ${name}; ${registryOrigin}; ${key})`,
125
+ );
126
+ }
127
+ return null;
128
+ }
129
+ const withoutDigest = {
130
+ schemaVersion: PLUGIN_PUBLISHER_AUTHORITY_SCHEMA,
131
+ status: "verified",
132
+ trustSource: "managed-settings",
133
+ publisher,
134
+ subject: {
135
+ name: String(name),
136
+ registryOrigin,
137
+ signingKeySha256: key,
138
+ },
139
+ trustRootId: match.trustRootId,
140
+ policyDigest: sha256Canonical(match),
141
+ verifiedAt: recordedAt,
142
+ claims: {
143
+ publisherIdentityVerified: true,
144
+ organizationTrustRootMatched: true,
145
+ signingKeyNotRevoked: true,
146
+ manifestSignatureVerified: true,
147
+ },
148
+ };
149
+ return { ...withoutDigest, authorityDigest: sha256Canonical(withoutDigest) };
150
+ }
151
+
152
+ export function verifyInstalledManagedPublisherAuthority(
153
+ { root, name },
154
+ managed,
155
+ ) {
156
+ const required = managed?.requireTrustedPluginPublishers === true;
157
+ let raw;
158
+ try {
159
+ const file = path.join(root, ".plugin-source.json");
160
+ const stat = fs.lstatSync(file);
161
+ if (
162
+ stat.isSymbolicLink() ||
163
+ !stat.isFile() ||
164
+ stat.nlink !== 1 ||
165
+ stat.size <= 0 ||
166
+ stat.size > 96 * 1024
167
+ ) {
168
+ throw new Error("source metadata authority file is unsafe");
169
+ }
170
+ raw = JSON.parse(fs.readFileSync(file, "utf8"));
171
+ } catch (error) {
172
+ return required
173
+ ? { verified: false, present: false, reason: error.message }
174
+ : { verified: false, present: false, reason: null };
175
+ }
176
+ const recorded = raw?.catalogAuthority?.publisherAuthority;
177
+ if (!recorded) {
178
+ return required
179
+ ? {
180
+ verified: false,
181
+ present: false,
182
+ reason: "trusted publisher authority is missing",
183
+ }
184
+ : { verified: false, present: false, reason: null };
185
+ }
186
+ try {
187
+ const signature = verifyInstalledSignature({ root });
188
+ if (!signature.signed) {
189
+ throw new Error(
190
+ `installed manifest signature is invalid: ${signature.reason}`,
191
+ );
192
+ }
193
+ const rebuilt = buildManagedPublisherAuthority({
194
+ name,
195
+ registryUrl: raw.registry,
196
+ declaration: raw.catalogAuthority?.publisherDeclaration,
197
+ signingKeySha256: signature.publicKeySha256,
198
+ managed,
199
+ verifiedAt: recorded.verifiedAt,
200
+ evaluatedAt: new Date().toISOString(),
201
+ });
202
+ if (!rebuilt || canonicalJson(rebuilt) !== canonicalJson(recorded)) {
203
+ throw new Error("persisted publisher authority no longer matches policy");
204
+ }
205
+ return {
206
+ verified: true,
207
+ present: true,
208
+ reason: null,
209
+ authority: rebuilt,
210
+ };
211
+ } catch (error) {
212
+ return { verified: false, present: true, reason: error.message };
213
+ }
214
+ }
215
+
216
+ function normalizeTrustEntries(value) {
217
+ if (value == null) return [];
218
+ if (!Array.isArray(value) || value.length > MAX_POLICY_ENTRIES) {
219
+ throw new Error("trustedPluginPublishers must be a bounded array");
220
+ }
221
+ return value.map((entry, index) => {
222
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
223
+ throw new Error(`trustedPluginPublishers[${index}] is invalid`);
224
+ }
225
+ const trustRootId = bounded(entry.trustRootId, 256);
226
+ const publisherId = bounded(entry.publisherId, 256);
227
+ const organizationId = bounded(entry.organizationId, 256);
228
+ const pluginNames = stringList(entry.pluginNames, 256, 256);
229
+ const registryOrigins = stringList(entry.registryOrigins, 32, 4096).map(
230
+ (url) => normalizeOrigin(url),
231
+ );
232
+ const signingKeySha256 = stringList(entry.signingKeySha256, 32, 64).map(
233
+ (digest) => digest.toLowerCase(),
234
+ );
235
+ if (
236
+ !trustRootId ||
237
+ !publisherId ||
238
+ !organizationId ||
239
+ pluginNames.length === 0 ||
240
+ registryOrigins.some((origin) => !origin) ||
241
+ signingKeySha256.length === 0 ||
242
+ signingKeySha256.some((digest) => !DIGEST_RE.test(digest))
243
+ ) {
244
+ throw new Error(`trustedPluginPublishers[${index}] is incomplete`);
245
+ }
246
+ const notBefore = optionalTime(entry.notBefore, `entry ${index} notBefore`);
247
+ const notAfter = optionalTime(entry.notAfter, `entry ${index} notAfter`);
248
+ if (notBefore && notAfter && notBefore > notAfter) {
249
+ throw new Error(`trustedPluginPublishers[${index}] validity is inverted`);
250
+ }
251
+ return {
252
+ trustRootId,
253
+ publisherId,
254
+ organizationId,
255
+ pluginNames: [...new Set(pluginNames)].sort(),
256
+ registryOrigins: [...new Set(registryOrigins)].sort(),
257
+ signingKeySha256: [...new Set(signingKeySha256)].sort(),
258
+ notBefore,
259
+ notAfter,
260
+ };
261
+ });
262
+ }
263
+
264
+ function normalizeRevocations(value) {
265
+ if (value == null) return new Set();
266
+ if (!Array.isArray(value) || value.length > MAX_POLICY_ENTRIES * 4) {
267
+ throw new Error("revokedPluginPublisherKeys must be a bounded array");
268
+ }
269
+ const result = new Set();
270
+ for (const [index, raw] of value.entries()) {
271
+ const digest = String(
272
+ typeof raw === "string" ? raw : raw?.sha256 || "",
273
+ ).toLowerCase();
274
+ if (!DIGEST_RE.test(digest)) {
275
+ throw new Error(`revokedPluginPublisherKeys[${index}] is invalid`);
276
+ }
277
+ result.add(digest);
278
+ }
279
+ return result;
280
+ }
281
+
282
+ function stringList(value, maxItems, maxLength) {
283
+ if (!Array.isArray(value) || value.length > maxItems) return [];
284
+ return value.map((item) => bounded(item, maxLength)).filter(Boolean);
285
+ }
286
+
287
+ function bounded(value, max) {
288
+ const text = typeof value === "string" ? value.trim() : "";
289
+ const hasControl = [...text].some((character) => {
290
+ const code = character.codePointAt(0);
291
+ return code < 32 || code === 127;
292
+ });
293
+ return text && text.length <= max && !hasControl ? text : null;
294
+ }
295
+
296
+ function normalizeOrigin(value) {
297
+ try {
298
+ const url = new URL(String(value));
299
+ if (!new Set(["https:", "http:"]).has(url.protocol)) return null;
300
+ return url.origin;
301
+ } catch {
302
+ return null;
303
+ }
304
+ }
305
+
306
+ function optionalTime(value, label) {
307
+ return value == null ? null : canonicalTime(value, label);
308
+ }
309
+
310
+ function canonicalTime(value, label) {
311
+ const date = new Date(String(value));
312
+ if (
313
+ !Number.isFinite(date.getTime()) ||
314
+ date.toISOString() !== String(value)
315
+ ) {
316
+ throw new Error(`${label} must be canonical ISO-8601 UTC`);
317
+ }
318
+ return date.toISOString();
319
+ }
320
+
321
+ function sha256Canonical(value) {
322
+ return crypto.createHash("sha256").update(canonicalJson(value)).digest("hex");
323
+ }
324
+
325
+ function canonicalJson(value) {
326
+ if (value === null || typeof value !== "object") return JSON.stringify(value);
327
+ if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
328
+ return `{${Object.keys(value)
329
+ .sort()
330
+ .map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`)
331
+ .join(",")}}`;
332
+ }