chainlesschain 0.162.176 → 0.162.178
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/README.md +10 -0
- package/package.json +1 -1
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-BDLu5Elz.js → AIOps-DRftcSue.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-DH5us-CK.js → ActionButton-BFvUaMKR.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-BZ0u8IFG.js → Analytics-C0-Rru4P.js} +3 -3
- package/src/assets/web-panel/assets/AppLayout-bx-BCljj.js +9 -0
- package/src/assets/web-panel/assets/{Artifacts-Br2YBbh_.js → Artifacts-DAJ8B3Un.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-C3C6a482.js → Audit-hOk4L1lr.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-CzHvebcj.js → BackgroundAgents-3pbDpM9z.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-DZNHYDFd.js → Backup-BtziGDn9.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-VRiC4fIx.js → BaseInput-kmshphJ3.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-Cm08WWAD.js → Chat-d7tGSosA.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-CGHYrugQ.js → ChatBubbleRenderer-p-_PBpX_.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-DtByk7d7.js → Checkbox-C4Eh4Tz5.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-CphXXOfD.js → Codegen-r7gmhZyA.js} +1 -1
- package/src/assets/web-panel/assets/{Col-Hz86TnLR.js → Col-U7mDaGlL.js} +1 -1
- package/src/assets/web-panel/assets/{Community-HP03ltpD.js → Community-Bpu8aH1T.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-B_N1mqQz.js → Compact-CHb2XBJe.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CVztRpi8.js → Compliance-Cn_r4dey.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-wUVOyZih.js → Cowork-CdMWfDcz.js} +4 -4
- package/src/assets/web-panel/assets/{Cron-DW5TLJKw.js → Cron-BtnREHWy.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CrAFGhWH.js → Crosschain-BKI9TSzr.js} +1 -1
- package/src/assets/web-panel/assets/{DID-pA-oD8ke.js → DID-pkNubzzJ.js} +2 -2
- package/src/assets/web-panel/assets/Dashboard-1rrz1snN.js +3 -0
- package/src/assets/web-panel/assets/{Dropdown-EweJcsek.js → Dropdown-DLyFVxDc.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-C9xVLPG4.js → EmailListRenderer-CtUWfYVq.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-CDcEEqlu.js → FamilyGuardDashboard-B8eX2Qe4.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-DtZda9A_.js → Federation-D8lsDGus.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-CiYdcVz3.js → FormItemContext-CRYt_aIw.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-DA13uwA0.js → GenericCardRenderer-ClKzY8_N.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DzRhZD1O.js → Git-BXj5Dney.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-D5RMgOSb.js → Governance-Cm-I8RMz.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BgrPfSNk.js → Inference-CPvbhvgt.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DzjnD571.js → KnowledgeGraph-sYNDZaoi.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-BhWzVDtN.js → Logs-BZY_3CRZ.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-BDape9cx.js → MarkdownRenderer-up0BW6pv.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-DJtL5GV7.js → Marketplace-C5MEJ2Qe.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CZcQygI7.js → McpTools-ihdrn43I.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-DUWSDUUu.js → Memory-Br8bPMlh.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BTwq2WKY.js → MobileBridge-BNntgrYW.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-BdV915mw.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-BiGugEQm.js → Mtc-A3wDmlqL.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-DY7a6gUe.js → MtcAudit-CF-mBLWM.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-BQbDu_w7.js → Multisig-Iy2k_MSo.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-CM2wXTLv.js → NLProgramming-kk0W7HUb.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-DI6gGs1v.js → Notes-B5u5t_4S.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-BsZOLWAB.js → NotificationSettings-BN0POf6_.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-CHkSUrXB.js +1 -0
- package/src/assets/web-panel/assets/{Organization-Cds0_tXr.js → Organization-DwWQESuN.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-WunYMD87.js → Overflow-DG6klrcC.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-Bo6j4DDv.js → P2P-BwJcKkgZ.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-Bh2XPD5f.js → PdhVaultBrowser-BwOHG0in.js} +5 -5
- package/src/assets/web-panel/assets/{Permissions-EMvMMC8N.js → Permissions-CGMXe4TX.js} +4 -4
- package/src/assets/web-panel/assets/PersonalDataHub-ziYqg7-A.js +8 -0
- package/src/assets/web-panel/assets/{Pipeline-BOx8HOgL.js → Pipeline-BzJfeoGt.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-tBeTVQVM.js → Privacy-DLh3Bblx.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-CVYg1W4M.js → ProjectInit-USVWW36c.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-Dvt5I7y1.js → ProjectSettings-CiiOn62h.js} +2 -2
- package/src/assets/web-panel/assets/Projects-6V-PNmcA.js +1 -0
- package/src/assets/web-panel/assets/{Providers-Ct8xqY-E.js → Providers-CBPWWzpu.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-Cni8Ooja.js → QrScannerModal-QVwoRUq3.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-BJVLKdxr.js → QuickAsk-CXnR-2Vn.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DPG8Rbbm.js → Recommend-ClaNzjmF.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-DsdR7dCt.js → RemoteSession-C3rGw8vJ.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-Csg1YM-b.js → Reputation-Ci-OWAoP.js} +1 -1
- package/src/assets/web-panel/assets/{Row-D9DoFoEf.js → Row-DRhAwXOS.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-BsvKrXMS.js → RssFeed-BQLJQ2_y.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DFUStfgQ.js → Search-QQUpkfFd.js} +1 -1
- package/src/assets/web-panel/assets/{Security-ILg1zxdK.js → Security-DdXKzuKT.js} +4 -4
- package/src/assets/web-panel/assets/{Services-Dd41PCaY.js → Services-x2Zh62Qd.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-Bzo1cN80.js → Skeleton-GdY4KwRz.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-BDHh17P0.js → Skills-Bv4tY1Fd.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-jl7UTiRY.js → Sla-C3QnM-11.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-BePa-RF6.js → SpeechSettings-Bl3ytvmI.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DiqqDKGZ.js → SyncSettings-Wp9IwTsP.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-DYQ_6lxj.js → Tasks-CF3rIrDe.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-JiDeI06L.js → Templates-CGfvVVM9.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-hhgI6zwS.js → Tenant-CVXmwQ3U.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-bvwrt03E.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-B8uB5Llk.js → TimelineRenderer-D0g74KhH.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-C3b_6r2z.js → Tokens-BH4IwzlT.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-tIP7HKVe.js → Trigger-DJOpM533.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-vjoc11vJ.js → Trust-B43EPRLr.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-DUPBnGuH.js → UkeySign-BmBFG-em.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-CBvhUY5T.js → VideoEditing-n9oJwB8k.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-DUaQ0uA5.js → Wallet-D5QeivHp.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DllSivjE.js → WebAuthn-DcNy7igO.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-xc8D3uO6.js → WorkflowEditor-BVjc7-5-.js} +1 -1
- package/src/assets/web-panel/assets/{chat-BVicU7oA.js → chat-Dy5Tfj3m.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DJzLmhLm.js → colors-C4c2CNZU.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BvYRfThE.js → compact-item-DPa3O5vN.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DGXxCBKR.js → createContext-TLcfNA6_.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-BAwdDA_5.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-SBDJB1y4.js → hasIn-D41LVFkp.js} +1 -1
- package/src/assets/web-panel/assets/{index-D7HimK0M.js → index-0oevYjfT.js} +1 -1
- package/src/assets/web-panel/assets/{index-DCdRAgjy.js → index-388pLGJ1.js} +1 -1
- package/src/assets/web-panel/assets/{index-BO1itZaY.js → index-B8nLBZbv.js} +3 -3
- package/src/assets/web-panel/assets/{index-DvUTDYXX.js → index-BPTGAjee.js} +1 -1
- package/src/assets/web-panel/assets/{index-hxTODbM1.js → index-BPtrOBmW.js} +1 -1
- package/src/assets/web-panel/assets/{index-wcCL-miV.js → index-BQiIxHBy.js} +1 -1
- package/src/assets/web-panel/assets/{index-CKyEivf8.js → index-BSM1cHVK.js} +1 -1
- package/src/assets/web-panel/assets/{index-BJZf9DhV.js → index-BYPr9fkz.js} +1 -1
- package/src/assets/web-panel/assets/{index-DHVLJ8q0.js → index-BsQ7Ev6i.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cs2rmLFt.js → index-Btk9qLL2.js} +1 -1
- package/src/assets/web-panel/assets/{index-z1ZylsLq.js → index-BvmziZSG.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cf-O_g_8.js → index-BvopLC_T.js} +1 -1
- package/src/assets/web-panel/assets/{index-DMarmfrv.js → index-C7xhTVyP.js} +1 -1
- package/src/assets/web-panel/assets/{index-CoJAO1Lm.js → index-CNk_ZooP.js} +1 -1
- package/src/assets/web-panel/assets/{index-9gdI7uUW.js → index-CQrEHoOG.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bf-ctERC.js → index-CSxex23J.js} +1 -1
- package/src/assets/web-panel/assets/{index-MjC4G09d.js → index-CVjgm992.js} +1 -1
- package/src/assets/web-panel/assets/{index-e4fXH_WO.js → index-CWK4zOPe.js} +1 -1
- package/src/assets/web-panel/assets/{index-xfluRkCT.js → index-CX0VsoP4.js} +1 -1
- package/src/assets/web-panel/assets/{index-DRfiXB_p.js → index-CXl0YPNG.js} +1 -1
- package/src/assets/web-panel/assets/{index-d5BVd-cL.js → index-Cip7LWml.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dm_77jgR.js → index-Cq_hlWNt.js} +1 -1
- package/src/assets/web-panel/assets/{index-YJkzy8ZF.js → index-CzZ49YZL.js} +1 -1
- package/src/assets/web-panel/assets/{index-CtwqO5qo.js → index-D2Nkivlm.js} +1 -1
- package/src/assets/web-panel/assets/{index-BYqz4Wrr.js → index-DBUgRs4D.js} +1 -1
- package/src/assets/web-panel/assets/index-DEjVkdzq.js +1 -0
- package/src/assets/web-panel/assets/{index-CdGY9P8a.js → index-DNsBj2Ob.js} +1 -1
- package/src/assets/web-panel/assets/{index-DonCnfMr.js → index-Di4X8cfI.js} +1 -1
- package/src/assets/web-panel/assets/{index-1SdDS6lR.js → index-DljFsVGI.js} +1 -1
- package/src/assets/web-panel/assets/{index-DnjPdvR6.js → index-Korc3QIe.js} +1 -1
- package/src/assets/web-panel/assets/index-LMOc5xrS.js +1 -0
- package/src/assets/web-panel/assets/{index-VMfwIH5G.js → index-MKZDje0H.js} +1 -1
- package/src/assets/web-panel/assets/{index-DKrvvWm4.js → index-OHAfRu_3.js} +1 -1
- package/src/assets/web-panel/assets/{index-FxZzRyE1.js → index-WEJr8PL5.js} +1 -1
- package/src/assets/web-panel/assets/{index-Crk5NTb0.js → index-WinCp6du.js} +1 -1
- package/src/assets/web-panel/assets/{index-DCqRS6da.js → index-Yjr6cqSK.js} +1 -1
- package/src/assets/web-panel/assets/{index-BTrBGBJs.js → index-iQ6gtFih.js} +1 -1
- package/src/assets/web-panel/assets/{index-lpaGoTH3.js → index-pt3s7yvV.js} +1 -1
- package/src/assets/web-panel/assets/{index-CloCgBUR.js → index-tQ3igERQ.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-C1zO1KnY.js → initDefaultProps-BFZu87WZ.js} +1 -1
- package/src/assets/web-panel/assets/{motion-CWLtEGmC.js → motion-DJIo7qvt.js} +1 -1
- package/src/assets/web-panel/assets/{move-DzD_C3Vm.js → move-Cfr5qknL.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-D880PYJl.js → mtc-parser-Bgc-OadH.js} +1 -1
- package/src/assets/web-panel/assets/{omit-CFR_z2ov.js → omit-X3WI-TNp.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-srIhgrSC.js → pickAttrs-pJhU9IxK.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-C1rXpibP.js → placementArrow-BNg_Vj3T.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-C30gRcSS.js → responsiveObserve-TeSEGQ5-.js} +1 -1
- package/src/assets/web-panel/assets/{slide-CvtKiMfV.js → slide-D_t_P0bv.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-DNHO7ITG.js → statusUtils-DrrIMwAT.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-Dt_Sl-g4.js → styleChecker-BjZCuFRm.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-Cjev42Gh.js → useFlexGapSupport-rTFdlqdQ.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-Baxglj2V.js → useFs-BidCpfLX.js} +1 -1
- package/src/assets/web-panel/assets/usePersonalDataHub-C5mHttA9.js +1 -0
- package/src/assets/web-panel/assets/{vnode-mIRkdT7o.js → vnode-BrbcRiHZ.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-HzI5DlH_.js → zoom-PISX7AkR.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/__tests__/hub-wechat.test.js +45 -0
- package/src/commands/agenda.js +22 -6
- package/src/commands/agent.js +3 -3
- package/src/commands/background-session.js +16 -6
- package/src/commands/batch.js +79 -27
- package/src/commands/changelog.js +15 -4
- package/src/commands/context.js +33 -1
- package/src/commands/eval.js +21 -6
- package/src/commands/hook.js +2 -2
- package/src/commands/hub.js +473 -39
- package/src/commands/init.js +212 -110
- package/src/commands/llm.js +22 -6
- package/src/commands/loop.js +9 -2
- package/src/commands/skill.js +13 -1
- package/src/commands/statusline.js +3 -3
- package/src/data/changelog.json +53 -5
- package/src/gateways/ws/personal-data-hub-protocol.js +22 -2
- package/src/harness/background-task-manager.js +18 -6
- package/src/harness/background-task-worker.js +11 -18
- package/src/harness/golden-transcript.js +3 -0
- package/src/harness/mcp-client.js +9 -15
- package/src/harness/worktree-isolator.js +18 -21
- package/src/index.js +18 -7
- package/src/lib/agent-core.js +5 -0
- package/src/lib/agent-ipc-bus.js +12 -3
- package/src/lib/agent-team/team-worktree.js +28 -6
- package/src/lib/agent-worktree.js +20 -19
- package/src/lib/approval-authority-store.js +891 -0
- package/src/lib/async-hook-supervisor.cjs +134 -24
- package/src/lib/async-hook-supervisor.js +47 -0
- package/src/lib/background-agent-supervisor.js +35 -12
- package/src/lib/background-interaction-resolver.js +399 -54
- package/src/lib/background-session-transport.js +3 -1
- package/src/lib/background-task-manager.js +5 -1
- package/src/lib/changelog.js +57 -0
- package/src/lib/chrome-connector.js +6 -2
- package/src/lib/claude-code-bridge.js +24 -8
- package/src/lib/cli-anything-bridge.js +82 -25
- package/src/lib/context-breakdown.js +82 -3
- package/src/lib/doctor-checkup.js +18 -6
- package/src/lib/eval/tasks.js +25 -31
- package/src/lib/event-runtime-host.js +225 -0
- package/src/lib/event-runtime-store.js +102 -21
- package/src/lib/event-runtime-worker.js +70 -2
- package/src/lib/hook-runner.cjs +71 -36
- package/src/lib/hook-runner.js +55 -0
- package/src/lib/hooks-v2-producers.js +33 -8
- package/src/lib/hooks-v2-runtime.js +360 -40
- package/src/lib/host-adb-bridge.js +18 -3
- package/src/lib/interaction-adapter.js +66 -0
- package/src/lib/lsp/__tests__/benchmark.test.js +61 -0
- package/src/lib/lsp/__tests__/lsp-client.test.js +6 -1
- package/src/lib/lsp/benchmark.js +20 -4
- package/src/lib/lsp/lsp-client.js +6 -4
- package/src/lib/lsp/lsp-server-registry.js +0 -2
- package/src/lib/operation-fingerprint.js +107 -2
- package/src/lib/orchestrator.js +8 -2
- package/src/lib/packer/pack-update-applier.js +14 -2
- package/src/lib/packer/smoke-runner.js +18 -5
- package/src/lib/paths.js +1 -1
- package/src/lib/pdh-dedicated-batch-collectors.js +124 -0
- package/src/lib/personal-data-hub-wiring.js +327 -52
- package/src/lib/plugin-monitor-supervisor.js +20 -13
- package/src/lib/plugin-runtime/install.js +10 -3
- package/src/lib/process-execution-broker/credential-agent.js +954 -111
- package/src/lib/process-execution-broker/index.js +369 -85
- package/src/lib/process-execution-broker/platform-sandbox.js +320 -140
- package/src/lib/provider-http-error.js +94 -0
- package/src/lib/remote-approval-bridge.js +222 -26
- package/src/lib/repl-bang-memorize.js +10 -2
- package/src/lib/repl-goal.js +19 -2
- package/src/lib/settings-hook-events.cjs +13 -8
- package/src/lib/settings-hook-events.js +20 -0
- package/src/lib/side-effect-ledger-store.js +65 -14
- package/src/lib/skill-loader.js +215 -12
- package/src/lib/skill-packs/generator.js +18 -9
- package/src/lib/skill-process-broker.js +85 -0
- package/src/lib/slash-commands.js +10 -2
- package/src/lib/status-line.cjs +28 -7
- package/src/lib/status-line.js +33 -0
- package/src/lib/sub-agent-context.js +42 -0
- package/src/lib/turn-binding-store.js +64 -15
- package/src/lib/turn-binding.js +85 -16
- package/src/repl/agent-repl.js +88 -49
- package/src/repl/remote-approval.js +13 -13
- package/src/repl/repl-turn-binding.js +46 -16
- package/src/runtime/agent-core.js +419 -84
- package/src/runtime/coding-agent-contract-shared.cjs +16 -0
- package/src/runtime/headless-runner.js +172 -44
- package/src/runtime/headless-stream.js +221 -11
- package/src/runtime/session-slash-commands.js +506 -0
- package/src/skills/video-editing/extractors/audio-extractor.js +13 -5
- package/src/skills/video-editing/extractors/video-extractor.js +13 -3
- package/src/skills/video-editing/media-process.js +20 -0
- package/src/skills/video-editing/render/audio-mix.js +13 -3
- package/src/skills/video-editing/render/ffmpeg-concat.js +7 -2
- package/src/skills/video-editing/render/ffmpeg-extract.js +7 -2
- package/src/workers/background-agent-worker.js +76 -40
- package/src/assets/web-panel/assets/AppLayout-Duu8xR14.js +0 -9
- package/src/assets/web-panel/assets/Dashboard-CXrd5gAw.js +0 -3
- package/src/assets/web-panel/assets/MobileProjects-NZvvfDME.js +0 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-C48mu09U.js +0 -1
- package/src/assets/web-panel/assets/PersonalDataHub-AX3ypUDV.js +0 -9
- package/src/assets/web-panel/assets/Projects-Cc7FC9-e.js +0 -1
- package/src/assets/web-panel/assets/Terminal-CjTZPa37.js +0 -3
- package/src/assets/web-panel/assets/devWarning-BT46Y_QI.js +0 -1
- package/src/assets/web-panel/assets/index-B7nuIywP.js +0 -1
- package/src/assets/web-panel/assets/index-ycwAfC-i.js +0 -1
- package/src/assets/web-panel/assets/usePersonalDataHub-B4NkcLaP.js +0 -1
|
@@ -1,30 +1,109 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Platform-specific sandbox enforcement for ProcessExecutionBroker (P0-1)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* -
|
|
6
|
-
* -
|
|
7
|
-
* -
|
|
4
|
+
* Platform enforcement currently available:
|
|
5
|
+
* - macOS: Seatbelt sandbox-exec profiles
|
|
6
|
+
* - Linux: prlimit resource-limit wrapper
|
|
7
|
+
* - Windows: explicitly unavailable until a native Job Object + restricted
|
|
8
|
+
* token adapter is installed
|
|
8
9
|
*
|
|
9
10
|
* Security model:
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* 4. Privilege escalation is prevented (NO_NEW_PRIVS, restricted tokens)
|
|
14
|
-
* 5. Resource limits prevent DoS (CPU, memory, process count)
|
|
11
|
+
* Adapters return a truthful spawn plan. An unavailable primitive is never
|
|
12
|
+
* represented as applied; ProcessExecutionBroker decides whether to fail
|
|
13
|
+
* closed (strict mode) or record the unavailable boundary.
|
|
15
14
|
*
|
|
16
15
|
* Part of Phase 1 Implementation - 2026-07-22
|
|
17
16
|
*/
|
|
18
17
|
|
|
19
18
|
import os from "node:os";
|
|
20
19
|
import path from "node:path";
|
|
21
|
-
import fs from "node:fs";
|
|
20
|
+
import * as fs from "node:fs";
|
|
22
21
|
import crypto from "node:crypto";
|
|
23
|
-
|
|
22
|
+
const DEFAULT_RUNTIME = Object.freeze({
|
|
23
|
+
platform: os.platform(),
|
|
24
|
+
fs,
|
|
25
|
+
tmpdir: () => os.tmpdir(),
|
|
26
|
+
homedir: () => os.homedir(),
|
|
27
|
+
randomBytes: (size) => crypto.randomBytes(size),
|
|
28
|
+
resolvePath: (value) => path.resolve(value),
|
|
29
|
+
joinPath: (...parts) => path.join(...parts),
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
function resolveRuntime(overrides = {}) {
|
|
33
|
+
return { ...DEFAULT_RUNTIME, ...overrides };
|
|
34
|
+
}
|
|
24
35
|
|
|
25
|
-
|
|
36
|
+
/**
|
|
37
|
+
* A native `spawn(..., { shell: true })` asks Node to execute one command
|
|
38
|
+
* string through the platform shell. Once a sandbox wrapper becomes the
|
|
39
|
+
* executable, leaving `shell: true` makes the host shell parse the wrapper
|
|
40
|
+
* argv instead, and the original command is no longer one atomic `-c`
|
|
41
|
+
* payload. Linux `prlimit` then tries to exec a file literally named
|
|
42
|
+
* "node script.js"; macOS Seatbelt has the same ambiguity.
|
|
43
|
+
*
|
|
44
|
+
* Materialize the requested POSIX shell before adding either wrapper. The
|
|
45
|
+
* sandbox executable itself is always spawned directly.
|
|
46
|
+
*/
|
|
47
|
+
function normalizeWrappedInvocation(command, args, spawnOpts, platform) {
|
|
48
|
+
if (!spawnOpts?.shell || platform === "win32") {
|
|
49
|
+
return {
|
|
50
|
+
command,
|
|
51
|
+
args: [...(args || [])],
|
|
52
|
+
options: { ...(spawnOpts || {}) },
|
|
53
|
+
};
|
|
54
|
+
}
|
|
26
55
|
|
|
27
|
-
const
|
|
56
|
+
const shell =
|
|
57
|
+
typeof spawnOpts.shell === "string" ? spawnOpts.shell : "/bin/sh";
|
|
58
|
+
const shellCommand = [command, ...(args || [])].map(String).join(" ");
|
|
59
|
+
return {
|
|
60
|
+
command: shell,
|
|
61
|
+
args: ["-c", shellCommand],
|
|
62
|
+
options: { ...spawnOpts, shell: false },
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Every platform adapter returns the same immutable spawn-plan shape. The
|
|
68
|
+
* broker must consume `command`, `args`, and `options` from this object rather
|
|
69
|
+
* than relying on adapters to mutate caller-owned values.
|
|
70
|
+
*
|
|
71
|
+
* A required post-spawn enforcement step must declare whether it is
|
|
72
|
+
* synchronous. ProcessExecutionBroker.spawn() is synchronous, so strict mode
|
|
73
|
+
* rejects an asynchronous required step before starting the child.
|
|
74
|
+
*
|
|
75
|
+
* @param {Object} input
|
|
76
|
+
* @returns {{
|
|
77
|
+
* contractVersion: 1,
|
|
78
|
+
* applied: boolean,
|
|
79
|
+
* platform: string,
|
|
80
|
+
* profile: string,
|
|
81
|
+
* command: string,
|
|
82
|
+
* args: string[],
|
|
83
|
+
* options: Object,
|
|
84
|
+
* enforcement: string|null,
|
|
85
|
+
* reason: string|null,
|
|
86
|
+
* cleanup?: Function,
|
|
87
|
+
* postSpawn: {required: boolean, mode: "none"|"sync"|"async"}
|
|
88
|
+
* }}
|
|
89
|
+
*/
|
|
90
|
+
function createSandboxPlan(input) {
|
|
91
|
+
const postSpawn = Object.freeze({
|
|
92
|
+
required: false,
|
|
93
|
+
mode: "none",
|
|
94
|
+
...(input.postSpawn || {}),
|
|
95
|
+
});
|
|
96
|
+
return Object.freeze({
|
|
97
|
+
contractVersion: 1,
|
|
98
|
+
applied: false,
|
|
99
|
+
enforcement: null,
|
|
100
|
+
reason: null,
|
|
101
|
+
...input,
|
|
102
|
+
args: Object.freeze([...(input.args || [])]),
|
|
103
|
+
options: Object.freeze({ ...(input.options || {}) }),
|
|
104
|
+
postSpawn,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
28
107
|
|
|
29
108
|
// ---------------------------------------------------------------------------
|
|
30
109
|
// macOS Seatbelt Sandbox
|
|
@@ -41,7 +120,8 @@ const platform = os.platform();
|
|
|
41
120
|
* @param {boolean} [opts.allowExec=true] - Allow process exec (subprocess spawning)
|
|
42
121
|
* @returns {string} sandbox profile content
|
|
43
122
|
*/
|
|
44
|
-
export function generateMacSeatbeltProfile(opts = {}) {
|
|
123
|
+
export function generateMacSeatbeltProfile(opts = {}, runtimeOverrides = {}) {
|
|
124
|
+
const runtime = resolveRuntime(runtimeOverrides);
|
|
45
125
|
const {
|
|
46
126
|
allowRead = [],
|
|
47
127
|
allowWrite = [],
|
|
@@ -54,9 +134,9 @@ export function generateMacSeatbeltProfile(opts = {}) {
|
|
|
54
134
|
"(deny default)",
|
|
55
135
|
// Basic system operations always allowed
|
|
56
136
|
"(allow signal (target self))",
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
137
|
+
'(allow process-exec (literal "/usr/bin/env"))',
|
|
138
|
+
'(allow process-exec (literal "/bin/sh"))',
|
|
139
|
+
'(allow process-exec (literal "/bin/bash"))',
|
|
60
140
|
"(allow sysctl-read)",
|
|
61
141
|
"(allow mach-lookup)",
|
|
62
142
|
];
|
|
@@ -72,12 +152,12 @@ export function generateMacSeatbeltProfile(opts = {}) {
|
|
|
72
152
|
|
|
73
153
|
// Allow read/write to specific paths
|
|
74
154
|
for (const p of allowRead) {
|
|
75
|
-
const abs =
|
|
155
|
+
const abs = runtime.resolvePath(p);
|
|
76
156
|
lines.push(`(allow file-read* (subpath "${abs}"))`);
|
|
77
157
|
}
|
|
78
158
|
|
|
79
159
|
for (const p of allowWrite) {
|
|
80
|
-
const abs =
|
|
160
|
+
const abs = runtime.resolvePath(p);
|
|
81
161
|
lines.push(`(allow file-read* file-write* (subpath "${abs}"))`);
|
|
82
162
|
}
|
|
83
163
|
|
|
@@ -99,165 +179,235 @@ export function generateMacSeatbeltProfile(opts = {}) {
|
|
|
99
179
|
*
|
|
100
180
|
* @param {string} command - Original command
|
|
101
181
|
* @param {string[]} args - Original args
|
|
102
|
-
* @param {Object} spawnOpts -
|
|
182
|
+
* @param {Object} spawnOpts - Original spawn options
|
|
103
183
|
* @param {Object} sandboxOpts - Sandbox options
|
|
104
184
|
*/
|
|
105
|
-
export function applyMacSandbox(
|
|
106
|
-
|
|
185
|
+
export function applyMacSandbox(
|
|
186
|
+
command,
|
|
187
|
+
args,
|
|
188
|
+
spawnOpts,
|
|
189
|
+
sandboxOpts = {},
|
|
190
|
+
runtimeOverrides = {},
|
|
191
|
+
) {
|
|
192
|
+
const runtime = resolveRuntime(runtimeOverrides);
|
|
193
|
+
const invocation = normalizeWrappedInvocation(
|
|
194
|
+
command,
|
|
195
|
+
args,
|
|
196
|
+
spawnOpts,
|
|
197
|
+
runtime.platform,
|
|
198
|
+
);
|
|
199
|
+
const base = {
|
|
200
|
+
platform: runtime.platform,
|
|
201
|
+
profile: sandboxOpts.profileName || "default",
|
|
202
|
+
command,
|
|
203
|
+
args,
|
|
204
|
+
options: { ...(spawnOpts || {}) },
|
|
205
|
+
};
|
|
206
|
+
if (runtime.platform !== "darwin") {
|
|
207
|
+
return createSandboxPlan({
|
|
208
|
+
...base,
|
|
209
|
+
reason: "platform_mismatch",
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// A deny-by-default Seatbelt profile cannot safely infer the filesystem,
|
|
214
|
+
// IPC, and inherited-descriptor access required by an arbitrary command.
|
|
215
|
+
// Keep the boundary truthful for the broker's implicit default profile:
|
|
216
|
+
// non-strict mode records the unavailable primitive and executes the
|
|
217
|
+
// original invocation, while strict mode fails closed. Explicit strict or
|
|
218
|
+
// network-only profiles still opt in to the sandbox-exec wrapper below.
|
|
219
|
+
if ((sandboxOpts.profileName || "default") === "default") {
|
|
220
|
+
return createSandboxPlan({
|
|
221
|
+
...base,
|
|
222
|
+
reason: "macos_default_profile_requires_explicit_policy",
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const sandboxExecutable = "/usr/bin/sandbox-exec";
|
|
227
|
+
if (!runtime.fs.existsSync(sandboxExecutable)) {
|
|
228
|
+
return createSandboxPlan({
|
|
229
|
+
...base,
|
|
230
|
+
reason: "macos_sandbox_exec_unavailable",
|
|
231
|
+
});
|
|
232
|
+
}
|
|
107
233
|
|
|
108
234
|
// Generate temporary profile file
|
|
109
|
-
const profileContent = generateMacSeatbeltProfile(
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
235
|
+
const profileContent = generateMacSeatbeltProfile(
|
|
236
|
+
sandboxOpts,
|
|
237
|
+
runtimeOverrides,
|
|
238
|
+
);
|
|
239
|
+
const profilePath = runtime.joinPath(
|
|
240
|
+
runtime.tmpdir(),
|
|
241
|
+
`chainless-sb-${runtime.randomBytes(8).toString("hex")}.sb`,
|
|
113
242
|
);
|
|
114
243
|
|
|
115
|
-
fs.writeFileSync(profilePath, profileContent, { mode: 0o600 });
|
|
244
|
+
runtime.fs.writeFileSync(profilePath, profileContent, { mode: 0o600 });
|
|
116
245
|
|
|
117
246
|
// Wrap command with sandbox-exec
|
|
118
|
-
const newArgs = ["-f", profilePath, command, ...args];
|
|
247
|
+
const newArgs = ["-f", profilePath, invocation.command, ...invocation.args];
|
|
119
248
|
|
|
120
|
-
return {
|
|
249
|
+
return createSandboxPlan({
|
|
250
|
+
...base,
|
|
121
251
|
applied: true,
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
252
|
+
enforcement: "macos-seatbelt",
|
|
253
|
+
command: sandboxExecutable,
|
|
254
|
+
args: newArgs,
|
|
255
|
+
options: invocation.options,
|
|
126
256
|
cleanup: () => {
|
|
127
257
|
try {
|
|
128
|
-
fs.unlinkSync(profilePath);
|
|
258
|
+
runtime.fs.unlinkSync(profilePath);
|
|
129
259
|
} catch {
|
|
130
260
|
// ignore cleanup errors
|
|
131
261
|
}
|
|
132
262
|
},
|
|
133
|
-
};
|
|
263
|
+
});
|
|
134
264
|
}
|
|
135
265
|
|
|
136
266
|
// ---------------------------------------------------------------------------
|
|
137
|
-
// Windows Job Object
|
|
267
|
+
// Windows Job Object availability
|
|
138
268
|
// ---------------------------------------------------------------------------
|
|
139
269
|
|
|
140
270
|
/**
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
* On Windows we:
|
|
144
|
-
* 1. Set CREATE_BREAKAWAY_FROM_JOB to ensure child can be placed into our own job
|
|
145
|
-
* 2. Add JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE so children die when parent exits
|
|
146
|
-
* 3. Set basic process memory/CPU limits if specified
|
|
147
|
-
* 4. Set creation flags for restricted token (best-effort)
|
|
148
|
-
*
|
|
149
|
-
* Note: Full Win32 Job Object API requires ffi/n-rap invocation.
|
|
150
|
-
* This function sets the spawn flags and returns metadata for post-spawn association.
|
|
271
|
+
* Report Windows sandbox availability. Node's child_process API cannot create
|
|
272
|
+
* and synchronously assign a Job Object or restricted token by itself.
|
|
151
273
|
*
|
|
152
274
|
* @param {string} command
|
|
153
275
|
* @param {string[]} args
|
|
154
276
|
* @param {Object} spawnOpts
|
|
155
277
|
* @param {Object} sandboxOpts
|
|
156
278
|
*/
|
|
157
|
-
export function applyWindowsSandbox(
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
// Set environment variable to signal sandboxed mode to any child-aware tools
|
|
172
|
-
const env = { ...(spawnOpts.env || process.env) };
|
|
173
|
-
env.CHAINLESS_SANDBOXED = "1";
|
|
174
|
-
spawnOpts.env = env;
|
|
175
|
-
|
|
176
|
-
return {
|
|
177
|
-
applied: true,
|
|
178
|
-
needsPostSpawn: true,
|
|
179
|
-
jobFlags: CREATE_BREAKAWAY_FROM_JOB | existingFlags,
|
|
180
|
-
limits: sandboxOpts.limits || null,
|
|
279
|
+
export function applyWindowsSandbox(
|
|
280
|
+
command,
|
|
281
|
+
args,
|
|
282
|
+
spawnOpts,
|
|
283
|
+
sandboxOpts = {},
|
|
284
|
+
runtimeOverrides = {},
|
|
285
|
+
) {
|
|
286
|
+
const runtime = resolveRuntime(runtimeOverrides);
|
|
287
|
+
const base = {
|
|
288
|
+
platform: runtime.platform,
|
|
289
|
+
profile: sandboxOpts.profileName || "default",
|
|
290
|
+
command,
|
|
291
|
+
args,
|
|
292
|
+
options: spawnOpts,
|
|
181
293
|
};
|
|
294
|
+
if (runtime.platform !== "win32") {
|
|
295
|
+
return createSandboxPlan({
|
|
296
|
+
...base,
|
|
297
|
+
reason: "platform_mismatch",
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Node does not expose Job Object or restricted-token primitives. Mark the
|
|
302
|
+
// platform unavailable instead of treating CREATE_NO_WINDOW or an
|
|
303
|
+
// environment marker as a security boundary. A future native adapter may
|
|
304
|
+
// return an applied plan with a synchronous postSpawn step.
|
|
305
|
+
return createSandboxPlan({
|
|
306
|
+
...base,
|
|
307
|
+
reason: "windows_native_job_object_unavailable",
|
|
308
|
+
});
|
|
182
309
|
}
|
|
183
310
|
|
|
184
311
|
/**
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
* requires koffi/n-rap).
|
|
312
|
+
* Reject an attempted Windows post-spawn association until a native adapter is
|
|
313
|
+
* available.
|
|
188
314
|
*
|
|
189
315
|
* @param {ChildProcess} proc - The spawned child process
|
|
190
316
|
* @param {Object} sandboxResult - Result from applyWindowsSandbox
|
|
191
317
|
*/
|
|
192
|
-
export
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
318
|
+
export function postSpawnWindowsSandbox(
|
|
319
|
+
proc,
|
|
320
|
+
sandboxResult,
|
|
321
|
+
runtimeOverrides = {},
|
|
322
|
+
) {
|
|
323
|
+
const runtime = resolveRuntime(runtimeOverrides);
|
|
324
|
+
if (runtime.platform !== "win32" || !sandboxResult?.postSpawn?.required) {
|
|
325
|
+
return;
|
|
200
326
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
// 3. Environment variable signaling sandbox mode
|
|
327
|
+
const error = new Error(
|
|
328
|
+
"Windows native Job Object enforcement is unavailable",
|
|
329
|
+
);
|
|
330
|
+
error.code = "ERR_WINDOWS_SANDBOX_UNAVAILABLE";
|
|
331
|
+
throw error;
|
|
207
332
|
}
|
|
208
333
|
|
|
209
334
|
// ---------------------------------------------------------------------------
|
|
210
|
-
// Linux
|
|
335
|
+
// Linux resource-limit enforcement
|
|
211
336
|
// ---------------------------------------------------------------------------
|
|
212
337
|
|
|
213
338
|
/**
|
|
214
|
-
* Apply Linux
|
|
215
|
-
*
|
|
216
|
-
* For Node.js spawned children, the most portable approach without native deps
|
|
217
|
-
* is to use `prlimit` (util-linux) wrapper and set `child_process` uid/gid/groups.
|
|
339
|
+
* Apply Linux resource limits through the util-linux `prlimit` wrapper.
|
|
218
340
|
*
|
|
219
341
|
* @param {string} command
|
|
220
342
|
* @param {string[]} args
|
|
221
343
|
* @param {Object} spawnOpts
|
|
222
344
|
* @param {Object} sandboxOpts
|
|
223
345
|
*/
|
|
224
|
-
export function applyLinuxSandbox(
|
|
225
|
-
|
|
346
|
+
export function applyLinuxSandbox(
|
|
347
|
+
command,
|
|
348
|
+
args,
|
|
349
|
+
spawnOpts,
|
|
350
|
+
sandboxOpts = {},
|
|
351
|
+
runtimeOverrides = {},
|
|
352
|
+
) {
|
|
353
|
+
const runtime = resolveRuntime(runtimeOverrides);
|
|
354
|
+
const invocation = normalizeWrappedInvocation(
|
|
355
|
+
command,
|
|
356
|
+
args,
|
|
357
|
+
spawnOpts,
|
|
358
|
+
runtime.platform,
|
|
359
|
+
);
|
|
360
|
+
const base = {
|
|
361
|
+
platform: runtime.platform,
|
|
362
|
+
profile: sandboxOpts.profileName || "default",
|
|
363
|
+
command,
|
|
364
|
+
args,
|
|
365
|
+
options: { ...(spawnOpts || {}) },
|
|
366
|
+
};
|
|
367
|
+
if (runtime.platform !== "linux") {
|
|
368
|
+
return createSandboxPlan({
|
|
369
|
+
...base,
|
|
370
|
+
reason: "platform_mismatch",
|
|
371
|
+
});
|
|
372
|
+
}
|
|
226
373
|
|
|
227
374
|
const { limits = {} } = sandboxOpts;
|
|
228
375
|
|
|
229
|
-
// Apply resource limits via spawn options (if supported by Node version)
|
|
230
|
-
// Node 19+ supports `gid`, `uid` in spawn options for privilege dropping
|
|
231
|
-
spawnOpts.gid = spawnOpts.gid || undefined;
|
|
232
|
-
spawnOpts.uid = spawnOpts.uid || undefined;
|
|
233
|
-
|
|
234
|
-
// Mark environment
|
|
235
|
-
const env = { ...(spawnOpts.env || process.env) };
|
|
236
|
-
env.CHAINLESS_SANDBOXED = "1";
|
|
237
|
-
spawnOpts.env = env;
|
|
238
|
-
|
|
239
|
-
// If we want hard limits and prlimit is available, wrap the command.
|
|
240
|
-
// Prlimit path: /usr/bin/prlimit
|
|
241
|
-
let newCommand = command;
|
|
242
|
-
let newArgs = [...args];
|
|
243
|
-
|
|
244
376
|
const prlimitParts = [];
|
|
245
377
|
if (limits.cpu) prlimitParts.push(`--cpu=${limits.cpu}`);
|
|
246
378
|
if (limits.as) prlimitParts.push(`--as=${limits.as}`);
|
|
247
379
|
if (limits.nofile) prlimitParts.push(`--nofile=${limits.nofile}`);
|
|
248
380
|
if (limits.nproc) prlimitParts.push(`--nproc=${limits.nproc}`);
|
|
249
381
|
|
|
250
|
-
if (prlimitParts.length
|
|
251
|
-
|
|
252
|
-
|
|
382
|
+
if (prlimitParts.length === 0) {
|
|
383
|
+
return createSandboxPlan({
|
|
384
|
+
...base,
|
|
385
|
+
reason: "linux_resource_limits_not_configured",
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
if (!runtime.fs.existsSync("/usr/bin/prlimit")) {
|
|
389
|
+
return createSandboxPlan({
|
|
390
|
+
...base,
|
|
391
|
+
reason: "linux_prlimit_unavailable",
|
|
392
|
+
});
|
|
253
393
|
}
|
|
254
394
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
395
|
+
const options = {
|
|
396
|
+
...invocation.options,
|
|
397
|
+
env: {
|
|
398
|
+
...(invocation.options.env || process.env),
|
|
399
|
+
CHAINLESS_SANDBOXED: "1",
|
|
400
|
+
},
|
|
260
401
|
};
|
|
402
|
+
|
|
403
|
+
return createSandboxPlan({
|
|
404
|
+
...base,
|
|
405
|
+
applied: true,
|
|
406
|
+
enforcement: "linux-prlimit",
|
|
407
|
+
command: "/usr/bin/prlimit",
|
|
408
|
+
args: [...prlimitParts, "--", invocation.command, ...invocation.args],
|
|
409
|
+
options,
|
|
410
|
+
});
|
|
261
411
|
}
|
|
262
412
|
|
|
263
413
|
// ---------------------------------------------------------------------------
|
|
@@ -269,75 +419,105 @@ export function applyLinuxSandbox(command, args, spawnOpts, sandboxOpts = {}) {
|
|
|
269
419
|
*
|
|
270
420
|
* @param {string} command
|
|
271
421
|
* @param {string[]} args
|
|
272
|
-
* @param {Object} spawnOpts -
|
|
422
|
+
* @param {Object} spawnOpts - Original spawn options
|
|
273
423
|
* @param {"default"|"strict"|"network-only"} profileName
|
|
274
|
-
* @returns {
|
|
424
|
+
* @returns {ReturnType<typeof createSandboxPlan>}
|
|
275
425
|
*/
|
|
276
|
-
export function applySandbox(
|
|
426
|
+
export function applySandbox(
|
|
427
|
+
command,
|
|
428
|
+
args,
|
|
429
|
+
spawnOpts,
|
|
430
|
+
profileName = "default",
|
|
431
|
+
runtimeOverrides = {},
|
|
432
|
+
) {
|
|
433
|
+
const runtime = resolveRuntime(runtimeOverrides);
|
|
277
434
|
const profiles = {
|
|
278
435
|
default: {
|
|
279
436
|
allowNetwork: false,
|
|
280
437
|
allowExec: true,
|
|
281
|
-
allowRead: [
|
|
282
|
-
allowWrite: [
|
|
438
|
+
allowRead: [runtime.homedir(), "/tmp"],
|
|
439
|
+
allowWrite: [runtime.tmpdir()],
|
|
283
440
|
limits: {
|
|
441
|
+
// RLIMIT_NPROC is intentionally omitted. Linux applies it per real
|
|
442
|
+
// user ID rather than to this child tree, so it can starve unrelated
|
|
443
|
+
// CI workers and prevent Node from creating its own helper threads.
|
|
284
444
|
cpu: 30, // seconds
|
|
285
445
|
nofile: 256,
|
|
286
|
-
nproc: 64,
|
|
287
446
|
},
|
|
288
447
|
},
|
|
289
448
|
strict: {
|
|
290
449
|
allowNetwork: false,
|
|
291
450
|
allowExec: false,
|
|
292
451
|
allowRead: [],
|
|
293
|
-
allowWrite: [
|
|
452
|
+
allowWrite: [runtime.tmpdir()],
|
|
294
453
|
limits: {
|
|
295
454
|
cpu: 10,
|
|
296
455
|
as: 256 * 1024 * 1024, // 256MB address space
|
|
297
456
|
nofile: 64,
|
|
298
|
-
nproc: 8,
|
|
299
457
|
},
|
|
300
458
|
},
|
|
301
459
|
"network-only": {
|
|
302
460
|
allowNetwork: true,
|
|
303
461
|
allowExec: true,
|
|
304
|
-
allowRead: [
|
|
305
|
-
allowWrite: [
|
|
462
|
+
allowRead: [runtime.homedir()],
|
|
463
|
+
allowWrite: [runtime.tmpdir()],
|
|
306
464
|
limits: {
|
|
307
465
|
cpu: 60,
|
|
308
466
|
nofile: 512,
|
|
309
|
-
nproc: 128,
|
|
310
467
|
},
|
|
311
468
|
},
|
|
312
469
|
};
|
|
313
470
|
|
|
314
|
-
const profile =
|
|
471
|
+
const profile = {
|
|
472
|
+
...(profiles[profileName] || profiles.default),
|
|
473
|
+
profileName: profiles[profileName] ? profileName : "default",
|
|
474
|
+
};
|
|
315
475
|
|
|
316
476
|
// Dispatch to platform handler
|
|
317
|
-
if (platform === "darwin") {
|
|
318
|
-
return applyMacSandbox(command, args, spawnOpts, profile);
|
|
477
|
+
if (runtime.platform === "darwin") {
|
|
478
|
+
return applyMacSandbox(command, args, spawnOpts, profile, runtimeOverrides);
|
|
319
479
|
}
|
|
320
|
-
if (platform === "win32") {
|
|
321
|
-
return applyWindowsSandbox(
|
|
480
|
+
if (runtime.platform === "win32") {
|
|
481
|
+
return applyWindowsSandbox(
|
|
482
|
+
command,
|
|
483
|
+
args,
|
|
484
|
+
spawnOpts,
|
|
485
|
+
profile,
|
|
486
|
+
runtimeOverrides,
|
|
487
|
+
);
|
|
322
488
|
}
|
|
323
|
-
if (platform === "linux") {
|
|
324
|
-
return applyLinuxSandbox(
|
|
489
|
+
if (runtime.platform === "linux") {
|
|
490
|
+
return applyLinuxSandbox(
|
|
491
|
+
command,
|
|
492
|
+
args,
|
|
493
|
+
spawnOpts,
|
|
494
|
+
profile,
|
|
495
|
+
runtimeOverrides,
|
|
496
|
+
);
|
|
325
497
|
}
|
|
326
498
|
|
|
327
499
|
// Unknown platform - no sandbox applied
|
|
328
|
-
return {
|
|
500
|
+
return createSandboxPlan({
|
|
501
|
+
platform: runtime.platform,
|
|
502
|
+
profile: profile.profileName,
|
|
503
|
+
command,
|
|
504
|
+
args,
|
|
505
|
+
options: spawnOpts,
|
|
506
|
+
reason: "unsupported_platform",
|
|
507
|
+
});
|
|
329
508
|
}
|
|
330
509
|
|
|
331
510
|
/**
|
|
332
511
|
* Post-spawn sandbox setup (called after child process starts).
|
|
333
|
-
*
|
|
512
|
+
* Reserved for adapters that require a synchronous native association step.
|
|
334
513
|
*
|
|
335
514
|
* @param {ChildProcess} proc
|
|
336
515
|
* @param {Object} sandboxResult
|
|
337
516
|
*/
|
|
338
|
-
export
|
|
339
|
-
|
|
340
|
-
|
|
517
|
+
export function postSpawnSandbox(proc, sandboxResult, runtimeOverrides = {}) {
|
|
518
|
+
const runtime = resolveRuntime(runtimeOverrides);
|
|
519
|
+
if (runtime.platform === "win32" && sandboxResult?.postSpawn?.required) {
|
|
520
|
+
return postSpawnWindowsSandbox(proc, sandboxResult, runtimeOverrides);
|
|
341
521
|
}
|
|
342
522
|
}
|
|
343
523
|
|