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.
- package/package.json +1 -1
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-C__nnraW.js → AIOps-vfoDb6HZ.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CsKWHEZ-.js → ActionButton-Cm5f7p93.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-BhIjfjWO.js → Analytics-yRuvgWxa.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-BjuXFzWZ.js → AppLayout-BROsC4h1.js} +4 -4
- package/src/assets/web-panel/assets/{Artifacts-k6whDkZJ.js → Artifacts-CimHApb1.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-C4FBMYRh.js → Audit-DI8kr8zI.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-C_vRrSXk.js → BackgroundAgents-DSLzKy-n.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-CngFZeVp.js → Backup-DkH_n2r1.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-B_H9EBRm.js → BaseInput-CKSrUoRA.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-DLEC5kt7.js → Chat-ClwfMXUS.js} +3 -3
- package/src/assets/web-panel/assets/ChatBubbleRenderer-CjMaqfL7.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-m3ClR4xh.js → Checkbox-BYTehcQG.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-CmLSFrgp.js → Codegen-B8AMcp6J.js} +1 -1
- package/src/assets/web-panel/assets/{Col-DFGQteHN.js → Col-BNSogPo3.js} +1 -1
- package/src/assets/web-panel/assets/{Community-EUUVORHE.js → Community-JxPvGb8O.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-2PSg0Yr7.js → Compact-DF7bFAgE.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CcKur7gB.js → Compliance-Bvhqnwrq.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DK_Fezfa.js → Cowork-BDS0CJvM.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-Dbw89xl7.js → Cron-DqvRfxoQ.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CH66h_Ec.js → Crosschain-CDcIvnqS.js} +1 -1
- package/src/assets/web-panel/assets/{DID-D1igRb17.js → DID-D7jaUxU3.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-DVAsrobk.js → Dashboard-B5A18wEV.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-Dl7W8AQs.js → Dropdown-_6IVkGag.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-D5tpaEQC.js → EmailListRenderer-C9PeiKCG.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-O_VQf8gq.js → FamilyGuardDashboard-DXjuEHrX.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-BTVcgS9n.js → Federation-B4IAR9zv.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-BRnkJAIz.js → FormItemContext-CxQeSNx1.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-8OWSCkDj.js → GenericCardRenderer-B8GS-Y3N.js} +1 -1
- package/src/assets/web-panel/assets/{Git-WXLYTQj2.js → Git-BS8SouUX.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BezaUhtc.js → Governance-Dq9aYb5Q.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CuRay3Gu.js → Inference-BrCEe9AJ.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DfWLDW1m.js → KnowledgeGraph-DybOpiY2.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-C55y2pPY.js → Logs-DBpzbRfx.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-CFyt8iUd.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-Dk08Uycg.js → Marketplace-Cc7CCSCu.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-C11fSB5V.js → McpTools-DFaIhOfu.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-mr0eZc97.js → Memory-KCqlp9ol.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-C0iCSRbb.js → MobileBridge-Bys84ySN.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-CY-xMG8Z.js → MobileProjects-B-6qU-je.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-Bplqc_Wc.js → Mtc-BgY-fvCq.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-BlzwsoSM.js → MtcAudit-B8pCmqQJ.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-BBLmTty6.js → Multisig-BbOmYutA.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-DtT1uf1W.js → NLProgramming-BocLQz_M.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-DcqQAxTK.js → Notes-CSwbxEop.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-cb0kWoZe.js → NotificationSettings-CqFNSYG3.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-kw9HZQNN.js → OrderTableRenderer-C6gMfAk7.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-DlTlbkUN.js → Organization-QrDXVdMJ.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-pp1qs-oY.js → Overflow-Cxntotjt.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-BESLnyYz.js → P2P-CIdBOwNq.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-B-J1mGuf.js → PdhVaultBrowser-CT5aP8rD.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-B36PeT1_.js → Permissions-DH7OM8XU.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-CTK2ad-3.js → PersonalDataHub-CnJqbWce.js} +3 -3
- package/src/assets/web-panel/assets/{Pipeline-zJNGXsac.js → Pipeline-5C3HG1kH.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-b9fz0Qf0.js → Privacy-B4yIp7xK.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-DjZbZgiB.js → ProjectInit-BMvt-2M0.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-C-hHJXlD.js → ProjectSettings-CvSTEMRG.js} +2 -2
- package/src/assets/web-panel/assets/Projects-BKBJxEek.js +1 -0
- package/src/assets/web-panel/assets/Providers-BdwUqFWN.js +1 -0
- package/src/assets/web-panel/assets/{QrScannerModal-A0yoQ3-3.js → QrScannerModal-DtnCKlTm.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-DrFgFJNC.js → QuickAsk-sTbgwyNr.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-KC8hF1g4.js → Recommend-Bzr14gSb.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-DGTPIk6u.js → RemoteSession-C_TF5IaJ.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-QmbwM7Yk.js → Reputation-GCAM4H2K.js} +1 -1
- package/src/assets/web-panel/assets/{Row-BxjJylia.js → Row-Dir0r6OQ.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-B7Wda1J6.js → RssFeed-CpGnlecX.js} +2 -2
- package/src/assets/web-panel/assets/{Search-_plQ_YSA.js → Search-DMMamC6u.js} +1 -1
- package/src/assets/web-panel/assets/{Security-CD2YJZfx.js → Security-yqay5yG-.js} +4 -4
- package/src/assets/web-panel/assets/{Services-qQE7NmwE.js → Services-C5i2wh9G.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DgQqkFf7.js → Skeleton-vUqk35yj.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-C4C0oFFt.js → Skills-DzcSkhot.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-Px2N2B5c.js → Sla-CB6qbYNr.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-DN6C3lQd.js → SpeechSettings-BHUI7cox.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-jm5aH_m7.js → SyncSettings-D-RrsxTJ.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-DlkJcv67.js → Tasks-DFxdOJiq.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-DyrTHUBs.js → Templates-SKAob_Aq.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-mC434PtL.js → Tenant-BPfsfHQ-.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-o0_s3NgK.js → Terminal-8iw7FpUf.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-DAGlAXOw.js → TimelineRenderer-C4Gjj5Su.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-BnulS_bs.js → Tokens-COYhN18e.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-suQbVXYM.js → Trigger-B-JzXcf6.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DbIJAPo5.js → Trust-BJ5bg0nI.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CQNpbIHi.js → UkeySign-BG_ByRMf.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-D8aWCERk.js → VideoEditing-B3kOnSiU.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-CuLpYfZc.js → Wallet-CcoGFnK7.js} +2 -2
- package/src/assets/web-panel/assets/{WebAuthn-CsfG8ZMc.js → WebAuthn-DdT8vRC_.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-BYsEAZbd.js → WorkflowEditor-CZu3M9N8.js} +1 -1
- package/src/assets/web-panel/assets/{chat-FT4Um3-I.js → chat-DxJt3Qba.js} +1 -1
- package/src/assets/web-panel/assets/{colors-CKbS_Wlt.js → colors-DdYfwJaB.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-CFJtzuJM.js → compact-item-BG3SUzwj.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-B9kSRW6K.js → createContext-By51z2-1.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-DorRZcI9.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DR-x0Xpi.js → hasIn-B0apZ3KJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DjEP7WkH.js → index-3jWkIu5j.js} +1 -1
- package/src/assets/web-panel/assets/{index-7jHr_A_k.js → index-B3rWuPMW.js} +1 -1
- package/src/assets/web-panel/assets/{index-DcfxhKXR.js → index-B5rLiEo0.js} +1 -1
- package/src/assets/web-panel/assets/{index-tqSEHPRT.js → index-BBPf3TpM.js} +1 -1
- package/src/assets/web-panel/assets/index-BETiL0a3.js +1 -0
- package/src/assets/web-panel/assets/{index-Cr2FLUsD.js → index-BIrJfqO4.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bt4fS2eL.js → index-BLIbGOLX.js} +1 -1
- package/src/assets/web-panel/assets/{index-BwR7yc2h.js → index-BP94CrBV.js} +1 -1
- package/src/assets/web-panel/assets/{index-BVPU43b1.js → index-BWF8_mkx.js} +1 -1
- package/src/assets/web-panel/assets/{index-DShSkww-.js → index-BYINoRLK.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bzz0C1BZ.js → index-BZ_0qm4g.js} +1 -1
- package/src/assets/web-panel/assets/{index-KqDaCApw.js → index-BewKYrX9.js} +1 -1
- package/src/assets/web-panel/assets/{index-BW-t9n-q.js → index-BfWYsB9t.js} +1 -1
- package/src/assets/web-panel/assets/index-BhAVHuW8.js +1 -0
- package/src/assets/web-panel/assets/{index-B7osrXqy.js → index-Bissefox.js} +3 -3
- package/src/assets/web-panel/assets/{index-DW4BWjTk.js → index-BkvcEo4p.js} +1 -1
- package/src/assets/web-panel/assets/{index-DdkIhfi-.js → index-Bos5_aMV.js} +1 -1
- package/src/assets/web-panel/assets/{index-DTxNy0ZU.js → index-C1C9i79A.js} +1 -1
- package/src/assets/web-panel/assets/{index-QBSeNVO3.js → index-CAhHirVH.js} +1 -1
- package/src/assets/web-panel/assets/{index-D4LfPvWA.js → index-CNIxXMmN.js} +1 -1
- package/src/assets/web-panel/assets/{index-C_enk9I_.js → index-CW93tZDv.js} +1 -1
- package/src/assets/web-panel/assets/{index-WE08gMJP.js → index-CWEuZWCK.js} +1 -1
- package/src/assets/web-panel/assets/{index-r2VI1Ikk.js → index-Cp6e-hGw.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dap9c3eD.js → index-CpjZhgNd.js} +1 -1
- package/src/assets/web-panel/assets/{index-DWdqx7zI.js → index-CzmQElZy.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGbPnC5x.js → index-DCn8IcxV.js} +1 -1
- package/src/assets/web-panel/assets/{index-DiNUEpSQ.js → index-DE76D-kA.js} +1 -1
- package/src/assets/web-panel/assets/{index-DtkFqPVA.js → index-DaIz0NAW.js} +1 -1
- package/src/assets/web-panel/assets/{index-CGaXUsIs.js → index-Da_WBdLX.js} +1 -1
- package/src/assets/web-panel/assets/{index-B3ZX81mK.js → index-Dz49VOyQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BK3TiKVq.js → index-Q2SCX-MI.js} +1 -1
- package/src/assets/web-panel/assets/{index-CJmIQ9XR.js → index-RD6O-0C6.js} +1 -1
- package/src/assets/web-panel/assets/{index-CvrCCqJt.js → index-SQqOlR3d.js} +1 -1
- package/src/assets/web-panel/assets/{index-BI5hP_qy.js → index-ZFbps9po.js} +1 -1
- package/src/assets/web-panel/assets/{index-DeSgw-WV.js → index-ZxtP8jG7.js} +1 -1
- package/src/assets/web-panel/assets/{index-DMGmg497.js → index-bP_VlDb4.js} +1 -1
- package/src/assets/web-panel/assets/{index-BfFCQHL3.js → index-kf57LJ93.js} +1 -1
- package/src/assets/web-panel/assets/{index-OSzjTzGM.js → index-oxRrmFO9.js} +1 -1
- package/src/assets/web-panel/assets/{index-C2JvmYRc.js → index-p1_8SbI1.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-Dd7n7VgI.js → initDefaultProps-BWJktcg8.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BwxouRw1.js → motion-BEXBzUFV.js} +1 -1
- package/src/assets/web-panel/assets/{move-DObN0PG9.js → move-BUKwn2sx.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-B3nOUQc7.js → mtc-parser-FTI7btqQ.js} +1 -1
- package/src/assets/web-panel/assets/{omit-o9WU2Nbl.js → omit-CsLtSPH3.js} +1 -1
- package/src/assets/web-panel/assets/parsers-YNLm7sQ0.js +4 -0
- package/src/assets/web-panel/assets/{pickAttrs-CL_vvfQ_.js → pickAttrs-DWZxsT_S.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-CYrM2tyK.js → placementArrow-Bcfs43CX.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-k_06cQ96.js → responsiveObserve-a9bcC1p-.js} +1 -1
- package/src/assets/web-panel/assets/{slide-CPKG0pxS.js → slide-BDTzgOXN.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BDDEeLTw.js → statusUtils-Iq1j_HUg.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-Cmb7RTh7.js → styleChecker-DAZEYxeh.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-e2IedC4N.js → useFlexGapSupport-DVkjyDrh.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-CE_gxVnm.js → useFs-wXTpNTHt.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BkMIIKMz.js → usePersonalDataHub-CtQM_aZr.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-DW886XV1.js → vnode-hjEoG85v.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-Dwo_adaf.js → zoom-BHVpyKg_.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +3 -3
- package/src/commands/agent.js +14 -2
- package/src/commands/artifacts.js +235 -0
- package/src/commands/background-session.js +100 -10
- package/src/commands/cowork.js +86 -57
- package/src/commands/mcp.js +5 -0
- package/src/commands/plugin.js +145 -29
- package/src/commands/remote-control.js +295 -110
- package/src/commands/session-location.js +20 -1
- package/src/commands/session-message.js +171 -0
- package/src/commands/session.js +75 -69
- package/src/data/changelog.json +29 -3
- package/src/gateways/ws/message-dispatcher.js +57 -0
- package/src/harness/mcp-client.js +141 -10
- package/src/lib/artifact-access-ledger.js +1 -0
- package/src/lib/artifact-deletion-ledger.js +1 -0
- package/src/lib/artifact-recovery.js +970 -0
- package/src/lib/artifact-workbench-projection.js +171 -0
- package/src/lib/background-session-transport.js +153 -27
- package/src/lib/dynamic-workflow-runtime.js +408 -1
- package/src/lib/execution-location-target.js +4 -2
- package/src/lib/mcp-client.js +2 -0
- package/src/lib/mcp-headers-helper.js +47 -5
- package/src/lib/mcp-oauth.js +55 -6
- package/src/lib/mcp-stdio-executable-identity.js +16 -0
- package/src/lib/mcp-stdio-native-code-policy.js +74 -0
- package/src/lib/mcp-stdio-package-materialization.js +12 -3
- package/src/lib/mcp-tls.js +230 -0
- package/src/lib/output-styles.js +12 -0
- package/src/lib/plugin-runtime/install.js +614 -71
- package/src/lib/plugin-runtime/marketplace-archive-source.js +331 -0
- package/src/lib/plugin-runtime/marketplace-catalog.js +52 -6
- package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +1 -0
- package/src/lib/plugin-runtime/marketplace-source-adapter.js +163 -0
- package/src/lib/plugin-runtime/marketplace-source-cache.js +11 -1
- package/src/lib/plugin-runtime/remote-source.js +435 -55
- package/src/lib/plugin-security.js +393 -41
- package/src/lib/plugin-source-identity.js +850 -0
- package/src/lib/process-execution-broker/index.js +112 -0
- package/src/lib/process-execution-broker/platform-sandbox.js +57 -3
- package/src/lib/process-execution-broker/workspace-transaction.js +26 -0
- package/src/lib/remote-approval-bridge.js +136 -46
- package/src/lib/remote-control.js +217 -31
- package/src/lib/session-message-fabric.js +1105 -0
- package/src/lib/session-projection.js +171 -12
- package/src/lib/session-runtime-retention.js +155 -0
- package/src/lib/settings-loader.cjs +29 -0
- package/src/repl/agent-repl.js +51 -14
- package/src/repl/permission-prompt.js +31 -8
- package/src/repl/repl-keybindings.js +55 -0
- package/src/runtime/agent-core.js +63 -2
- package/src/runtime/headless-runner.js +47 -66
- package/src/runtime/headless-stream.js +18 -24
- package/src/runtime/mcp-config.js +2 -0
- package/src/runtime/policies/agent-policy.js +2 -0
- package/src/assets/web-panel/assets/ChatBubbleRenderer-xijcWkJe.js +0 -1
- package/src/assets/web-panel/assets/MarkdownRenderer-hDpWdiBc.js +0 -1
- package/src/assets/web-panel/assets/Projects-BC9KSDM6.js +0 -1
- package/src/assets/web-panel/assets/Providers-Dz-CAYYU.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DJZ0gAMu.js +0 -1
- package/src/assets/web-panel/assets/index-Bizb4hkw.js +0 -1
- package/src/assets/web-panel/assets/index-OHSl-xCh.js +0 -1
- 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 {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
{
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
-
//
|
|
162
|
-
//
|
|
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
|
-
|
|
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
|
}
|