chainlesschain 0.162.198 → 0.162.200
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/bin/chainlesschain.js +14 -6
- package/package.json +4 -1
- package/scripts/command-lifecycle-report.mjs +94 -0
- package/src/assets/web-panel/assets/{AIOps-CSN-D2xb.js → AIOps-DcQ0bWKy.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CBSMlGzv.js → ActionButton-GecwfFPt.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-3yr3Nt2t.js → Analytics-CD6iSt9v.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-1b-o3lMH.js → AppLayout-CDEtuEYf.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-Dr8rJi17.js → Artifacts-DS3jAjeW.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-2V689HC2.js → Audit-CcSJA048.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-DIxkNrD_.js → BackgroundAgents-DRo9Morb.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-Pg6BcwrE.js → Backup-Vw5MrWft.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-CLUpqyfH.js → BaseInput-DNHIu823.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-qVS8rD4G.js → Chat-DvAsO8-b.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-ti49X12Q.js → ChatBubbleRenderer-9aDuObay.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-Bs9AaEay.js → Checkbox-CKCa7tvn.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-Dvc1mq8q.js → Codegen-CIFvZdaT.js} +1 -1
- package/src/assets/web-panel/assets/{Col-C4_biO7A.js → Col-C79yz7bK.js} +1 -1
- package/src/assets/web-panel/assets/{Community-al25XQUV.js → Community-DVvZskLJ.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-D-ZDB8M1.js → Compact-oaew61hV.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-6lIfDz1W.js → Compliance-DqA7wmRx.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DdI48XMJ.js → Cowork-B-qGadxa.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-DF5HZd2g.js → Cron-CUlCl4sS.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-DuxeSvt3.js → Crosschain-CNOlr9DU.js} +1 -1
- package/src/assets/web-panel/assets/{DID-B9yHkUTd.js → DID-DJqFCT_3.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-Z5EuI3IM.js → Dashboard-CznGpphf.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-vuRfO3dY.js → Dropdown-_cJw218E.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-QFLCc1uL.js → EmailListRenderer-Dr-1BZ9C.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-BZ7EXkFJ.js → FamilyGuardDashboard-Dxf4xtSk.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-DycIEg2s.js → Federation-DOiG3i_1.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-Ba0H_7yG.js → FormItemContext-BzbMcFB9.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer--JgSTK-C.js → GenericCardRenderer-VbBrYttP.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DEvTbldE.js → Git-CLG8E6ED.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BJIljy18.js → Governance-LGJQfk_q.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CVyW3G3q.js → Inference-DlQKx9lF.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-v8-borge.js → KnowledgeGraph-DU8vEouV.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-BCdS7gGo.js → Logs-FZIQOdln.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-BJNWIrbw.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-AN6tGA2B.js → Marketplace-C_xd-zZI.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DGViXASN.js → McpTools-q-YktphS.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-Bpvmx9X4.js → Memory-Cq9OhDin.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-CTP-DOTC.js → MobileBridge-B03_R98T.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-C8qfktxn.js → MobileProjects-DZrk-qmF.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-ndYr0M1s.js → Mtc-BidCKW28.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-Ci0-YK7W.js → MtcAudit-r-iaMVM7.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-BehSTFW7.js → Multisig-CgTUFvff.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-B91_YBLv.js → NLProgramming-B7NvzfAV.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-BQlJ0-gq.js → Notes-80CWNqJI.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-CDgYMjYK.js → NotificationSettings-0H6xdiY3.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-BJkSlKeH.js → OrderTableRenderer-CKP4AFWy.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-B-b3cWCp.js → Organization-B8sxCV_h.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-CILUL4nL.js → Overflow-CW9JBBhQ.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-BTCFBkF0.js → P2P-bdSQV7oZ.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-BAR6AUx5.js → PdhVaultBrowser-DQad42nW.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-RRf6HbWJ.js → Permissions-CueexxTR.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-BGTMiICa.js → PersonalDataHub-fqxflhR8.js} +6 -6
- package/src/assets/web-panel/assets/{Pipeline-945qY9YF.js → Pipeline-KFwwnIMC.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-DPZwI6lJ.js → Privacy-ClnD9buY.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-BPH2NRKc.js → ProjectInit-CZEz6sm3.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BZCRNCvb.js → ProjectSettings-B6NzpmOI.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-BTI__tBt.js → Projects-DYyuwPCs.js} +1 -1
- package/src/assets/web-panel/assets/Providers-C3tz_jdh.js +1 -0
- package/src/assets/web-panel/assets/{QrScannerModal-N6rbqt1r.js → QrScannerModal-BzuOBbqB.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-DrwjPS7M.js → QuickAsk-CmNO9qSj.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-Cog9Wd99.js → Recommend-VJNj3_NF.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-DC9pynjM.js → RemoteSession-CrbdbSBF.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-D4th4gKS.js → Reputation-DTyMd45j.js} +1 -1
- package/src/assets/web-panel/assets/{Row-ogiWR6v9.js → Row-DHrQ-Icz.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-uYlk-2Oj.js → RssFeed-DqWxY9c5.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DYzzwvtM.js → Search-ctF1Ks3J.js} +1 -1
- package/src/assets/web-panel/assets/{Security-Da7YOyX6.js → Security-BrQz8uo5.js} +4 -4
- package/src/assets/web-panel/assets/{Services-CLI1VM1X.js → Services-D4scVFar.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DK77dzDC.js → Skeleton-oUScaOjv.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-C_z7Lmhl.js → Skills-CL-y0eLt.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-D6413Q8L.js → Sla-DQExhwXj.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-C07ydbj2.js → SpeechSettings-iNp_I7kN.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DGOm2W22.js → SyncSettings-CTDlMo0A.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-Cr_PVyLM.js → Tasks-4kb8l3sc.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BhL2mZ0t.js → Templates-BXcL9oXW.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CPk5oyUr.js → Tenant-DLE8eS0D.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-ClhqUsqV.js → Terminal-DGpUZPPK.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-BCC7MV5a.js → TimelineRenderer-C1pWXGPC.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-DD1Jt4oO.js → Tokens-BYfbfqhZ.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BCydFvN2.js → Trigger-K9YfLOCw.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DDHT1noa.js → Trust-Ctkq77Hy.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CWPZC7oI.js → UkeySign-C6_CSe9J.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-9Ea0nJR0.js → VideoEditing-Be3rpOWs.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BjxhLxTf.js → Wallet-D0UIplxk.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-C6uCye67.js → WebAuthn-CF9bM9I3.js} +3 -3
- package/src/assets/web-panel/assets/{WorkflowEditor-d2g4reYo.js → WorkflowEditor-D0H1XVPY.js} +1 -1
- package/src/assets/web-panel/assets/{chat-frTc6ScX.js → chat-Cgzzbe0o.js} +1 -1
- package/src/assets/web-panel/assets/{colors-B5K6lG3v.js → colors-BwNxEVS0.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-Cdn46r8D.js → compact-item-D60Z4Hhs.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DU1jqVQi.js → createContext-MFk58XB0.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-BJiw369i.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DdNH-aW_.js → hasIn-CRj2SvGO.js} +1 -1
- package/src/assets/web-panel/assets/{index-DM5FmPZU.js → index--s45_1cb.js} +1 -1
- package/src/assets/web-panel/assets/{index-D4l82Me1.js → index--tquQ2ZG.js} +1 -1
- package/src/assets/web-panel/assets/{index-CQorP1Ng.js → index-1T1rhokn.js} +1 -1
- package/src/assets/web-panel/assets/{index-CHmkkdfT.js → index-B-M82_rx.js} +1 -1
- package/src/assets/web-panel/assets/{index-CGiwfwB9.js → index-BE_el1Zs.js} +1 -1
- package/src/assets/web-panel/assets/{index-BwlIxAmX.js → index-BhRkR7IO.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cj6P9Nst.js → index-Bo0y96-K.js} +1 -1
- package/src/assets/web-panel/assets/{index-BoFak7le.js → index-CJgu5JUK.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dca_i7H8.js → index-CLWwdebO.js} +1 -1
- package/src/assets/web-panel/assets/{index-BVLL-mq_.js → index-CNAK5QG_.js} +1 -1
- package/src/assets/web-panel/assets/{index-LaivuXyF.js → index-CQjJjPRD.js} +1 -1
- package/src/assets/web-panel/assets/{index-t_OBzIP4.js → index-CTDbAfae.js} +1 -1
- package/src/assets/web-panel/assets/{index-BcGwGIaR.js → index-CVI_9sRK.js} +1 -1
- package/src/assets/web-panel/assets/{index-D23xGYjM.js → index-CY14oMQK.js} +1 -1
- package/src/assets/web-panel/assets/{index-VDM2KKo9.js → index-CbiTJkZf.js} +1 -1
- package/src/assets/web-panel/assets/index-CiMouosn.js +1 -0
- package/src/assets/web-panel/assets/{index-32ajXmTb.js → index-CqWpxMqx.js} +1 -1
- package/src/assets/web-panel/assets/{index-PjAS0sIZ.js → index-CvB8lYUR.js} +1 -1
- package/src/assets/web-panel/assets/{index-7ehytj1K.js → index-D51XwtCY.js} +1 -1
- package/src/assets/web-panel/assets/{index-DtBCCkC4.js → index-D6HvK_1O.js} +1 -1
- package/src/assets/web-panel/assets/{index-Be4OtL-N.js → index-D9jVIwLJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CUoNAmE8.js → index-DA4tE98u.js} +1 -1
- package/src/assets/web-panel/assets/{index-cYaWV4Mq.js → index-DBwOtXw0.js} +1 -1
- package/src/assets/web-panel/assets/{index-MM4Zz2OE.js → index-DKdNzTIb.js} +1 -1
- package/src/assets/web-panel/assets/{index-DIVyTmZ3.js → index-DRySdmvN.js} +1 -1
- package/src/assets/web-panel/assets/{index-CtRPi4YC.js → index-DWzyTev7.js} +1 -1
- package/src/assets/web-panel/assets/index-DXcKlwy7.js +1 -0
- package/src/assets/web-panel/assets/{index-kVO_MDm-.js → index-DYjs7jAP.js} +1 -1
- package/src/assets/web-panel/assets/{index-D4miNkWv.js → index-DbROzMBp.js} +1 -1
- package/src/assets/web-panel/assets/{index-yZRuZpwK.js → index-DhFtk5PR.js} +1 -1
- package/src/assets/web-panel/assets/{index-BXKhhx9V.js → index-Di2AbMLg.js} +1 -1
- package/src/assets/web-panel/assets/{index-BC4eGkar.js → index-DvmocQsM.js} +1 -1
- package/src/assets/web-panel/assets/{index-NmEXVjzt.js → index-Dw-o0zEF.js} +1 -1
- package/src/assets/web-panel/assets/{index-DRzBBdQ0.js → index-DysPoP38.js} +1 -1
- package/src/assets/web-panel/assets/{index-HjCvXHf5.js → index-LX9pJxm_.js} +1 -1
- package/src/assets/web-panel/assets/{index-gg3QPC3i.js → index-OI_fXWx0.js} +3 -3
- package/src/assets/web-panel/assets/{index-mgU3Q-lN.js → index-eDTOX8Xj.js} +1 -1
- package/src/assets/web-panel/assets/{index-D1qIC4GR.js → index-gWKDsTzF.js} +1 -1
- package/src/assets/web-panel/assets/{index-DftZuyA7.js → index-q_GDUVAA.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-DwLTRNdo.js → initDefaultProps-C61kZqEd.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BchZDXnh.js → motion-DZnT5U1L.js} +1 -1
- package/src/assets/web-panel/assets/{move-e8M-zZFl.js → move-L8wzwbel.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-Ci40fQb3.js → mtc-parser-DLdYSejc.js} +1 -1
- package/src/assets/web-panel/assets/{omit-C7110_f2.js → omit-D53cbS59.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-skteMgnM.js → pickAttrs-Bbc5HPtu.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-MGZ-lh2B.js → placementArrow-BkvmO860.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-N4Sd7uy-.js → responsiveObserve-u2y1ryS1.js} +1 -1
- package/src/assets/web-panel/assets/{slide-C7HDGRaa.js → slide-BBqj7svU.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BhRexlgy.js → statusUtils-GN0mqu2d.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-ChEoQkN2.js → styleChecker-BvwPKoBT.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-CDbG1s2Y.js → useFlexGapSupport-CCt8tnfY.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-CUIx0tcJ.js → useFs-DXAxl2SV.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-bkO7L7ec.js → usePersonalDataHub-DihlR2dj.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-B_ZvABIG.js → vnode-D7BOX2gi.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-D5shjpS8.js → zoom-CVbO-nL7.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +1 -1
- package/src/commands/mcp.js +119 -0
- package/src/commands/session-show.js +8 -10
- package/src/commands/session.js +60 -52
- package/src/data/changelog.json +27 -1
- package/src/gateways/ws/session-protocol.js +14 -4
- package/src/gateways/ws/ws-agent-handler.js +31 -0
- package/src/harness/jsonl-session-store.js +1147 -130
- package/src/harness/mcp-client.js +44 -11
- package/src/harness/session-index.js +80 -80
- package/src/harness/session-list-index.js +147 -2
- package/src/lib/background-interaction-journal.js +2 -2
- package/src/lib/command-lifecycle-report.js +516 -0
- package/src/lib/mcp-stdio-environment.js +48 -0
- package/src/lib/mcp-stdio-executable-identity.js +552 -17
- package/src/lib/mcp-stdio-package-materialization.js +1424 -0
- package/src/lib/packer/native-update-state.js +979 -1
- package/src/lib/packer/pack-update-applier.js +1050 -125
- package/src/lib/packer/pkg-config-generator.js +1 -0
- package/src/lib/paths.js +53 -0
- package/src/lib/process-execution-broker/index.js +180 -37
- package/src/lib/process-execution-broker/platform-sandbox.js +291 -24
- package/src/lib/recent-session.js +17 -17
- package/src/lib/secure-file-identity.js +47 -0
- package/src/lib/secure-fs.js +21 -2
- package/src/lib/session-anti-rollback-anchor.js +766 -0
- package/src/lib/session-host-lease.js +492 -0
- package/src/lib/session-persistence-failure.js +109 -0
- package/src/lib/session-picker.js +26 -3
- package/src/lib/session-search.js +25 -11
- package/src/lib/side-effect-ledger-store.js +2 -2
- package/src/lib/skill-execution-authority.js +13 -9
- package/src/lib/turn-binding-store.js +2 -2
- package/src/repl/agent-repl.js +309 -39
- package/src/runtime/agent-core.js +88 -5
- package/src/runtime/cleanup-deadline.js +143 -0
- package/src/runtime/headless-runner.js +357 -139
- package/src/runtime/headless-stream.js +207 -28
- package/src/runtime/output-backpressure.js +53 -0
- package/src/assets/web-panel/assets/MarkdownRenderer-CU-JB2Ns.js +0 -1
- package/src/assets/web-panel/assets/Providers-DDCf_nIw.js +0 -1
- package/src/assets/web-panel/assets/devWarning-CP-jEUyw.js +0 -1
- package/src/assets/web-panel/assets/index-CzrCHrFy.js +0 -1
- package/src/assets/web-panel/assets/index-OJsGskZw.js +0 -1
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
* the selected backend; it does not merely describe a configured intent.
|
|
38
38
|
*/
|
|
39
39
|
export const SANDBOX_BOUNDARIES = Object.freeze({
|
|
40
|
+
CODE_SNAPSHOT: "code-snapshot",
|
|
40
41
|
FILESYSTEM: "filesystem",
|
|
41
42
|
NETWORK: "network",
|
|
42
43
|
PROCESS_EXEC: "process-exec",
|
|
@@ -105,6 +106,7 @@ const WINDOWS_IDENTITY_WAIT = new Int32Array(new SharedArrayBuffer(4));
|
|
|
105
106
|
const WINDOWS_RESTRICTED_TOKEN_BACKEND = "windows-job-restricted-token";
|
|
106
107
|
const WINDOWS_APPCONTAINER_BACKEND =
|
|
107
108
|
"windows-appcontainer-job-restricted-token";
|
|
109
|
+
const MCP_STDIO_CAPSULE_SANDBOX_CONTRACT_KIND = "strict-mcp-node-capsule";
|
|
108
110
|
const WINDOWS_ADAPTER_IDLE_TTL_MS = 60_000;
|
|
109
111
|
// Every native helper operation starts a trusted System32 PowerShell host and
|
|
110
112
|
// byte-loads the checked-in assembly. Hosted Windows runners can spend well
|
|
@@ -163,6 +165,11 @@ const LINUX_ATTESTATION_HASH_CHUNK_BYTES = 1024 * 1024;
|
|
|
163
165
|
const LINUX_ENTRY_SNAPSHOT_MECHANISM =
|
|
164
166
|
"verified-o_tmpfile-copy-bwrap-ro-bind-data-v1";
|
|
165
167
|
const LINUX_ENTRY_SNAPSHOT_SOURCE_MODE = 0o400;
|
|
168
|
+
const LINUX_EXECUTABLE_SNAPSHOT_SOURCE_MODE = 0o500;
|
|
169
|
+
const LINUX_MCP_CAPSULE_BACKEND = "linux-fd-code-snapshot";
|
|
170
|
+
const LINUX_MCP_RUNTIME_SNAPSHOT_SCOPE = "mcp-node-runtime-executable";
|
|
171
|
+
const LINUX_MCP_CAPSULE_SNAPSHOT_MECHANISM =
|
|
172
|
+
"verified-o_tmpfile-copy-inherited-fd-exec-v1";
|
|
166
173
|
const LINUX_NODE_ENTRY_SNAPSHOT_SCOPE = "plugin-entry-source";
|
|
167
174
|
const LINUX_NATIVE_ENTRY_SNAPSHOT_SCOPE = "plugin-entry-executable";
|
|
168
175
|
const LINUX_NODE_PLUGIN_TREE_SNAPSHOT_SCOPE = "all-pinned-plugin-regular-files";
|
|
@@ -1884,13 +1891,18 @@ function windowsSandboxHostEnvironment(runtime) {
|
|
|
1884
1891
|
function windowsPluginNodeEntrySnapshot(invocation, sandboxOpts, spawnOpts) {
|
|
1885
1892
|
const contract = sandboxOpts.executionContract;
|
|
1886
1893
|
if (!contract) return { locks: null, reason: null };
|
|
1887
|
-
|
|
1894
|
+
const capsuleContract =
|
|
1895
|
+
contract.kind === MCP_STDIO_CAPSULE_SANDBOX_CONTRACT_KIND;
|
|
1896
|
+
if (contract.kind !== "strict-plugin-node-bin" && !capsuleContract) {
|
|
1888
1897
|
return {
|
|
1889
1898
|
locks: null,
|
|
1890
1899
|
reason: "windows_plugin_execution_contract_unsupported",
|
|
1891
1900
|
};
|
|
1892
1901
|
}
|
|
1893
|
-
if (
|
|
1902
|
+
if (
|
|
1903
|
+
(!capsuleContract && sandboxOpts.sync !== true) ||
|
|
1904
|
+
spawnOpts?.detached === true
|
|
1905
|
+
) {
|
|
1894
1906
|
return {
|
|
1895
1907
|
locks: null,
|
|
1896
1908
|
reason: "windows_plugin_launch_path_lock_requires_sync_foreground",
|
|
@@ -2586,10 +2598,34 @@ export function applyWindowsSandbox(
|
|
|
2586
2598
|
? {
|
|
2587
2599
|
...(appContainerRuntimeProbe || nodeSnapshotRuntimeProbe),
|
|
2588
2600
|
contentSnapshot: true,
|
|
2589
|
-
contentSnapshotScope:
|
|
2601
|
+
contentSnapshotScope:
|
|
2602
|
+
sandboxOpts.executionContract?.kind ===
|
|
2603
|
+
MCP_STDIO_CAPSULE_SANDBOX_CONTRACT_KIND
|
|
2604
|
+
? "mcp-capsule-entry-source"
|
|
2605
|
+
: "plugin-entry-source",
|
|
2590
2606
|
contentSnapshotMechanism:
|
|
2591
2607
|
"verified-handle-inherited-pipe-module-compile-v1",
|
|
2592
2608
|
handleAtomic: false,
|
|
2609
|
+
...(sandboxOpts.executionContract?.kind ===
|
|
2610
|
+
MCP_STDIO_CAPSULE_SANDBOX_CONTRACT_KIND
|
|
2611
|
+
? {
|
|
2612
|
+
runtimeAttestedSha256: entrySnapshot.locks.find(
|
|
2613
|
+
({ role }) => role === "runtime",
|
|
2614
|
+
)?.sha256,
|
|
2615
|
+
runtimeAttestedBytes: entrySnapshot.locks.find(
|
|
2616
|
+
({ role }) => role === "runtime",
|
|
2617
|
+
)?.bytes,
|
|
2618
|
+
entrySnapshotSha256: entrySnapshot.locks.find(
|
|
2619
|
+
({ role }) => role === "entry",
|
|
2620
|
+
)?.sha256,
|
|
2621
|
+
entrySnapshotBytes: entrySnapshot.locks.find(
|
|
2622
|
+
({ role }) => role === "entry",
|
|
2623
|
+
)?.bytes,
|
|
2624
|
+
entrySnapshotAtomic: true,
|
|
2625
|
+
runtimeLaunchAtomic: false,
|
|
2626
|
+
sharedLibraryClosure: false,
|
|
2627
|
+
}
|
|
2628
|
+
: {}),
|
|
2593
2629
|
}
|
|
2594
2630
|
: appContainerRuntimeProbe;
|
|
2595
2631
|
return createSandboxPlan({
|
|
@@ -2599,13 +2635,20 @@ export function applyWindowsSandbox(
|
|
|
2599
2635
|
policyAttested: requiresAppContainer ? true : null,
|
|
2600
2636
|
policyDigest: appContainerPolicyDigest,
|
|
2601
2637
|
runtimeProbe: entrySnapshotRuntimeProbe,
|
|
2602
|
-
guarantees:
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2638
|
+
guarantees: [
|
|
2639
|
+
...(requiresAppContainer
|
|
2640
|
+
? appContainerGuarantees
|
|
2641
|
+
: [
|
|
2642
|
+
SANDBOX_BOUNDARIES.PROCESS_TREE,
|
|
2643
|
+
SANDBOX_BOUNDARIES.RESOURCE_LIMITS,
|
|
2644
|
+
SANDBOX_BOUNDARIES.PRIVILEGE_REDUCTION,
|
|
2645
|
+
]),
|
|
2646
|
+
...(entrySnapshot.locks &&
|
|
2647
|
+
sandboxOpts.executionContract?.kind ===
|
|
2648
|
+
MCP_STDIO_CAPSULE_SANDBOX_CONTRACT_KIND
|
|
2649
|
+
? [SANDBOX_BOUNDARIES.CODE_SNAPSHOT]
|
|
2650
|
+
: []),
|
|
2651
|
+
],
|
|
2609
2652
|
command: helperInvocation.command,
|
|
2610
2653
|
args: helperInvocation.args,
|
|
2611
2654
|
options,
|
|
@@ -3042,7 +3085,10 @@ function validateLinuxPluginContract(
|
|
|
3042
3085
|
sync,
|
|
3043
3086
|
{ sealedEntry = false } = {},
|
|
3044
3087
|
) {
|
|
3045
|
-
const
|
|
3088
|
+
const capsuleContract =
|
|
3089
|
+
contract?.kind === MCP_STDIO_CAPSULE_SANDBOX_CONTRACT_KIND;
|
|
3090
|
+
const nodeContract =
|
|
3091
|
+
contract?.kind === "strict-plugin-node-bin" || capsuleContract;
|
|
3046
3092
|
const legacyStaticNativeContract =
|
|
3047
3093
|
contract?.kind === "strict-plugin-native-static-elf-bin";
|
|
3048
3094
|
const nativeContract =
|
|
@@ -3060,7 +3106,7 @@ function validateLinuxPluginContract(
|
|
|
3060
3106
|
if (
|
|
3061
3107
|
(sync !== true && sync !== false) ||
|
|
3062
3108
|
spawnOpts?.shell !== false ||
|
|
3063
|
-
spawnOpts?.detached === true ||
|
|
3109
|
+
(spawnOpts?.detached === true && !capsuleContract) ||
|
|
3064
3110
|
!linuxStdioIsNarrow(spawnOpts?.stdio) ||
|
|
3065
3111
|
spawnOpts?.serialization !== undefined ||
|
|
3066
3112
|
spawnOpts?.argv0 !== undefined ||
|
|
@@ -3274,6 +3320,7 @@ function linuxEntrySnapshotContract(targetRuntime) {
|
|
|
3274
3320
|
return {
|
|
3275
3321
|
scope: LINUX_NATIVE_ENTRY_SNAPSHOT_SCOPE,
|
|
3276
3322
|
targetMode: LINUX_NATIVE_ENTRY_SNAPSHOT_TARGET_MODE,
|
|
3323
|
+
sourceMode: LINUX_ENTRY_SNAPSHOT_SOURCE_MODE,
|
|
3277
3324
|
minimumBytes: LINUX_ELF64_HEADER_BYTES,
|
|
3278
3325
|
errorPrefix: "native_entry_snapshot",
|
|
3279
3326
|
};
|
|
@@ -3282,6 +3329,7 @@ function linuxEntrySnapshotContract(targetRuntime) {
|
|
|
3282
3329
|
return {
|
|
3283
3330
|
scope: LINUX_NODE_ENTRY_SNAPSHOT_SCOPE,
|
|
3284
3331
|
targetMode: LINUX_NODE_ENTRY_SNAPSHOT_TARGET_MODE,
|
|
3332
|
+
sourceMode: LINUX_ENTRY_SNAPSHOT_SOURCE_MODE,
|
|
3285
3333
|
minimumBytes: 0,
|
|
3286
3334
|
errorPrefix: "node_entry_snapshot",
|
|
3287
3335
|
};
|
|
@@ -3296,11 +3344,22 @@ function linuxNodePluginTreeFileSnapshotContract(sourceMode) {
|
|
|
3296
3344
|
return {
|
|
3297
3345
|
scope: LINUX_NODE_PLUGIN_TREE_SNAPSHOT_SCOPE,
|
|
3298
3346
|
targetMode: (sourceMode & 0o111) !== 0 ? "0500" : "0400",
|
|
3347
|
+
sourceMode: LINUX_ENTRY_SNAPSHOT_SOURCE_MODE,
|
|
3299
3348
|
minimumBytes: 0,
|
|
3300
3349
|
errorPrefix: "node_plugin_tree_snapshot",
|
|
3301
3350
|
};
|
|
3302
3351
|
}
|
|
3303
3352
|
|
|
3353
|
+
function linuxMcpRuntimeSnapshotContract() {
|
|
3354
|
+
return {
|
|
3355
|
+
scope: LINUX_MCP_RUNTIME_SNAPSHOT_SCOPE,
|
|
3356
|
+
targetMode: "0500",
|
|
3357
|
+
sourceMode: LINUX_EXECUTABLE_SNAPSHOT_SOURCE_MODE,
|
|
3358
|
+
minimumBytes: 1,
|
|
3359
|
+
errorPrefix: "mcp_node_runtime_snapshot",
|
|
3360
|
+
};
|
|
3361
|
+
}
|
|
3362
|
+
|
|
3304
3363
|
function createLinuxRegularFileSnapshot(
|
|
3305
3364
|
runtime,
|
|
3306
3365
|
entryMount,
|
|
@@ -3311,10 +3370,16 @@ function createLinuxRegularFileSnapshot(
|
|
|
3311
3370
|
let probeFd;
|
|
3312
3371
|
let finalFd;
|
|
3313
3372
|
try {
|
|
3373
|
+
const snapshotSourceMode = snapshotContract?.sourceMode;
|
|
3314
3374
|
if (
|
|
3315
3375
|
!snapshotContract ||
|
|
3316
3376
|
typeof snapshotContract.scope !== "string" ||
|
|
3317
3377
|
typeof snapshotContract.targetMode !== "string" ||
|
|
3378
|
+
!Number.isSafeInteger(snapshotSourceMode) ||
|
|
3379
|
+
![
|
|
3380
|
+
LINUX_ENTRY_SNAPSHOT_SOURCE_MODE,
|
|
3381
|
+
LINUX_EXECUTABLE_SNAPSHOT_SOURCE_MODE,
|
|
3382
|
+
].includes(snapshotSourceMode) ||
|
|
3318
3383
|
!Number.isSafeInteger(snapshotContract.minimumBytes) ||
|
|
3319
3384
|
typeof snapshotContract.errorPrefix !== "string"
|
|
3320
3385
|
) {
|
|
@@ -3369,7 +3434,8 @@ function createLinuxRegularFileSnapshot(
|
|
|
3369
3434
|
throw snapshotError("source_mode_changed");
|
|
3370
3435
|
}
|
|
3371
3436
|
if (
|
|
3372
|
-
snapshotContract.scope === LINUX_NATIVE_ENTRY_SNAPSHOT_SCOPE
|
|
3437
|
+
(snapshotContract.scope === LINUX_NATIVE_ENTRY_SNAPSHOT_SCOPE ||
|
|
3438
|
+
snapshotContract.scope === LINUX_MCP_RUNTIME_SNAPSHOT_SCOPE) &&
|
|
3373
3439
|
(sourceFileMode & 0o111) === 0
|
|
3374
3440
|
) {
|
|
3375
3441
|
throw snapshotError("source_mode_changed");
|
|
@@ -3382,11 +3448,7 @@ function createLinuxRegularFileSnapshot(
|
|
|
3382
3448
|
Number(constants.O_TMPFILE ?? LINUX_O_TMPFILE) |
|
|
3383
3449
|
Number(constants.O_NOFOLLOW || 0) |
|
|
3384
3450
|
Number(constants.O_NONBLOCK || 0);
|
|
3385
|
-
writerFd = runtime.fs.openSync(
|
|
3386
|
-
"/tmp",
|
|
3387
|
-
writerFlags,
|
|
3388
|
-
LINUX_ENTRY_SNAPSHOT_SOURCE_MODE,
|
|
3389
|
-
);
|
|
3451
|
+
writerFd = runtime.fs.openSync("/tmp", writerFlags, snapshotSourceMode);
|
|
3390
3452
|
|
|
3391
3453
|
const sourceDigest = crypto.createHash("sha256");
|
|
3392
3454
|
const chunk = Buffer.allocUnsafe(
|
|
@@ -3455,15 +3517,14 @@ function createLinuxRegularFileSnapshot(
|
|
|
3455
3517
|
throw snapshotError("identity_changed");
|
|
3456
3518
|
}
|
|
3457
3519
|
|
|
3458
|
-
runtime.fs.fchmodSync(writerFd,
|
|
3520
|
+
runtime.fs.fchmodSync(writerFd, snapshotSourceMode);
|
|
3459
3521
|
runtime.fs.fsyncSync(writerFd);
|
|
3460
3522
|
const sealedBeforeRead = runtime.fs.fstatSync(writerFd);
|
|
3461
3523
|
if (
|
|
3462
3524
|
!sealedBeforeRead.isFile() ||
|
|
3463
3525
|
Number(sealedBeforeRead.nlink) !== 0 ||
|
|
3464
3526
|
Number(sealedBeforeRead.size) !== entryIdentity.bytes ||
|
|
3465
|
-
(Number(sealedBeforeRead.mode) & 0o777) !==
|
|
3466
|
-
LINUX_ENTRY_SNAPSHOT_SOURCE_MODE
|
|
3527
|
+
(Number(sealedBeforeRead.mode) & 0o777) !== snapshotSourceMode
|
|
3467
3528
|
) {
|
|
3468
3529
|
throw snapshotError("readonly_mode_unattested");
|
|
3469
3530
|
}
|
|
@@ -3513,7 +3574,7 @@ function createLinuxRegularFileSnapshot(
|
|
|
3513
3574
|
}),
|
|
3514
3575
|
sourceMtimeMs: Number(entryIdentity.mtimeMs),
|
|
3515
3576
|
sourceFileMode: sourceFileMode.toString(8).padStart(4, "0"),
|
|
3516
|
-
sourceMode:
|
|
3577
|
+
sourceMode: snapshotSourceMode.toString(8).padStart(4, "0"),
|
|
3517
3578
|
targetMode: snapshotContract.targetMode,
|
|
3518
3579
|
});
|
|
3519
3580
|
const descriptor = (fd) => {
|
|
@@ -3581,12 +3642,13 @@ function attestLinuxRegularFileSnapshot(
|
|
|
3581
3642
|
snapshotContract,
|
|
3582
3643
|
) {
|
|
3583
3644
|
const errorPrefix = snapshotContract.errorPrefix;
|
|
3645
|
+
const snapshotSourceMode = snapshotContract.sourceMode;
|
|
3584
3646
|
const before = runtime.fs.fstatSync(mount?.fd);
|
|
3585
3647
|
if (
|
|
3586
3648
|
attestation?.scope !== snapshotContract.scope ||
|
|
3587
3649
|
attestation?.mechanism !== LINUX_ENTRY_SNAPSHOT_MECHANISM ||
|
|
3588
3650
|
attestation?.sourceMode !==
|
|
3589
|
-
|
|
3651
|
+
snapshotSourceMode.toString(8).padStart(4, "0") ||
|
|
3590
3652
|
typeof attestation?.sourceFileMode !== "string" ||
|
|
3591
3653
|
!/^[0-7]{4}$/.test(attestation.sourceFileMode) ||
|
|
3592
3654
|
attestation?.targetMode !== snapshotContract.targetMode ||
|
|
@@ -3595,7 +3657,7 @@ function attestLinuxRegularFileSnapshot(
|
|
|
3595
3657
|
mount?.contentSnapshot !== attestation ||
|
|
3596
3658
|
!before.isFile() ||
|
|
3597
3659
|
Number(before.nlink) !== 0 ||
|
|
3598
|
-
(Number(before.mode) & 0o777) !==
|
|
3660
|
+
(Number(before.mode) & 0o777) !== snapshotSourceMode ||
|
|
3599
3661
|
String(before.dev) !== String(mount?.snapshotIdentity?.fileId?.dev) ||
|
|
3600
3662
|
String(before.ino) !== String(mount?.snapshotIdentity?.fileId?.ino) ||
|
|
3601
3663
|
Number(before.size) !== Number(attestation?.bytes) ||
|
|
@@ -3624,6 +3686,200 @@ function attestLinuxEntrySnapshot(runtime, mount, attestation, targetRuntime) {
|
|
|
3624
3686
|
);
|
|
3625
3687
|
}
|
|
3626
3688
|
|
|
3689
|
+
function linuxIdentityExpectedStat(identity) {
|
|
3690
|
+
return {
|
|
3691
|
+
dev: identity?.fileId?.dev,
|
|
3692
|
+
ino: identity?.fileId?.ino,
|
|
3693
|
+
size: identity?.bytes,
|
|
3694
|
+
mtimeMs: identity?.mtimeMs,
|
|
3695
|
+
};
|
|
3696
|
+
}
|
|
3697
|
+
|
|
3698
|
+
function applyLinuxMcpCapsuleCodeSnapshot(
|
|
3699
|
+
command,
|
|
3700
|
+
args,
|
|
3701
|
+
spawnOpts,
|
|
3702
|
+
sandboxOpts,
|
|
3703
|
+
runtime,
|
|
3704
|
+
base,
|
|
3705
|
+
) {
|
|
3706
|
+
const contract = sandboxOpts.executionContract;
|
|
3707
|
+
const validation = validateLinuxPluginContract(
|
|
3708
|
+
command,
|
|
3709
|
+
args,
|
|
3710
|
+
spawnOpts,
|
|
3711
|
+
contract,
|
|
3712
|
+
runtime,
|
|
3713
|
+
sandboxOpts.sync,
|
|
3714
|
+
);
|
|
3715
|
+
const unavailable = (reason, runtimeProbe = null) =>
|
|
3716
|
+
createSandboxPlan({
|
|
3717
|
+
...base,
|
|
3718
|
+
backend: null,
|
|
3719
|
+
candidateBackend: LINUX_MCP_CAPSULE_BACKEND,
|
|
3720
|
+
policyAttested: false,
|
|
3721
|
+
runtimeProbe: runtimeProbe
|
|
3722
|
+
? {
|
|
3723
|
+
kind: "linux-mcp-capsule-code-snapshot-v1",
|
|
3724
|
+
attempted: runtimeProbe.attempted !== false,
|
|
3725
|
+
probeRuntime: "node",
|
|
3726
|
+
targetRuntime: "node",
|
|
3727
|
+
...runtimeProbe,
|
|
3728
|
+
}
|
|
3729
|
+
: null,
|
|
3730
|
+
reason,
|
|
3731
|
+
guarantees: [],
|
|
3732
|
+
});
|
|
3733
|
+
if (
|
|
3734
|
+
contract?.kind !== MCP_STDIO_CAPSULE_SANDBOX_CONTRACT_KIND ||
|
|
3735
|
+
!validation.ok
|
|
3736
|
+
) {
|
|
3737
|
+
return unavailable("linux_mcp_capsule_execution_contract_invalid", {
|
|
3738
|
+
attempted: false,
|
|
3739
|
+
runnable: false,
|
|
3740
|
+
reason: validation.reason,
|
|
3741
|
+
contentSnapshot: false,
|
|
3742
|
+
handleAtomic: false,
|
|
3743
|
+
});
|
|
3744
|
+
}
|
|
3745
|
+
|
|
3746
|
+
const invocation = normalizeWrappedInvocation(
|
|
3747
|
+
command,
|
|
3748
|
+
args,
|
|
3749
|
+
spawnOpts,
|
|
3750
|
+
runtime.platform,
|
|
3751
|
+
);
|
|
3752
|
+
let runtimePin;
|
|
3753
|
+
let entryPin;
|
|
3754
|
+
let runtimeSnapshot;
|
|
3755
|
+
let entrySnapshot;
|
|
3756
|
+
try {
|
|
3757
|
+
runtimePin = pinLinuxRegularFile(
|
|
3758
|
+
runtime,
|
|
3759
|
+
contract.runtimeIdentity.realPath,
|
|
3760
|
+
contract.runtimeIdentity.realPath,
|
|
3761
|
+
linuxIdentityExpectedStat(contract.runtimeIdentity),
|
|
3762
|
+
{ requireSingleLink: true },
|
|
3763
|
+
);
|
|
3764
|
+
entryPin = pinLinuxRegularFile(
|
|
3765
|
+
runtime,
|
|
3766
|
+
contract.entryIdentity.realPath,
|
|
3767
|
+
contract.entryIdentity.realPath,
|
|
3768
|
+
linuxIdentityExpectedStat(contract.entryIdentity),
|
|
3769
|
+
{ requireSingleLink: true },
|
|
3770
|
+
);
|
|
3771
|
+
runtimeSnapshot = createLinuxRegularFileSnapshot(
|
|
3772
|
+
runtime,
|
|
3773
|
+
runtimePin,
|
|
3774
|
+
contract.runtimeIdentity,
|
|
3775
|
+
linuxMcpRuntimeSnapshotContract(),
|
|
3776
|
+
);
|
|
3777
|
+
entrySnapshot = createLinuxEntrySnapshot(
|
|
3778
|
+
runtime,
|
|
3779
|
+
entryPin,
|
|
3780
|
+
contract.entryIdentity,
|
|
3781
|
+
"node",
|
|
3782
|
+
);
|
|
3783
|
+
attestLinuxRegularFileSnapshot(
|
|
3784
|
+
runtime,
|
|
3785
|
+
runtimeSnapshot.finalMount,
|
|
3786
|
+
runtimeSnapshot.attestation,
|
|
3787
|
+
linuxMcpRuntimeSnapshotContract(),
|
|
3788
|
+
);
|
|
3789
|
+
attestLinuxEntrySnapshot(
|
|
3790
|
+
runtime,
|
|
3791
|
+
entrySnapshot.finalMount,
|
|
3792
|
+
entrySnapshot.attestation,
|
|
3793
|
+
"node",
|
|
3794
|
+
);
|
|
3795
|
+
} catch (error) {
|
|
3796
|
+
closeLinuxPinnedMounts(runtime, [
|
|
3797
|
+
runtimePin,
|
|
3798
|
+
entryPin,
|
|
3799
|
+
runtimeSnapshot?.probeMount,
|
|
3800
|
+
runtimeSnapshot?.finalMount,
|
|
3801
|
+
entrySnapshot?.probeMount,
|
|
3802
|
+
entrySnapshot?.finalMount,
|
|
3803
|
+
]);
|
|
3804
|
+
return unavailable("linux_mcp_capsule_code_snapshot_unavailable", {
|
|
3805
|
+
runnable: false,
|
|
3806
|
+
reason: error.message || "snapshot_unattested",
|
|
3807
|
+
contentSnapshot: false,
|
|
3808
|
+
handleAtomic: false,
|
|
3809
|
+
});
|
|
3810
|
+
}
|
|
3811
|
+
|
|
3812
|
+
closeLinuxPinnedMounts(runtime, [
|
|
3813
|
+
runtimePin,
|
|
3814
|
+
entryPin,
|
|
3815
|
+
runtimeSnapshot.probeMount,
|
|
3816
|
+
entrySnapshot.probeMount,
|
|
3817
|
+
]);
|
|
3818
|
+
const descriptors = [runtimeSnapshot.finalMount, entrySnapshot.finalMount];
|
|
3819
|
+
const runtimeFd = 3;
|
|
3820
|
+
const entryFd = 4;
|
|
3821
|
+
const snapshotIdentity = Object.freeze({
|
|
3822
|
+
runtimeSnapshotSha256: runtimeSnapshot.attestation.sha256,
|
|
3823
|
+
runtimeSnapshotBytes: runtimeSnapshot.attestation.bytes,
|
|
3824
|
+
entrySnapshotSha256: entrySnapshot.attestation.sha256,
|
|
3825
|
+
entrySnapshotBytes: entrySnapshot.attestation.bytes,
|
|
3826
|
+
});
|
|
3827
|
+
const policyDigest = sha256(
|
|
3828
|
+
JSON.stringify({
|
|
3829
|
+
version: 1,
|
|
3830
|
+
backend: LINUX_MCP_CAPSULE_BACKEND,
|
|
3831
|
+
contractKind: contract.kind,
|
|
3832
|
+
requiredBoundaries: [
|
|
3833
|
+
...new Set(sandboxOpts.requiredBoundaries || []),
|
|
3834
|
+
].sort(),
|
|
3835
|
+
identity: snapshotIdentity,
|
|
3836
|
+
cwd: invocation.options.cwd,
|
|
3837
|
+
passthroughArgsDigest: sha256(JSON.stringify(invocation.args.slice(1))),
|
|
3838
|
+
}),
|
|
3839
|
+
);
|
|
3840
|
+
let closed = false;
|
|
3841
|
+
const cleanup = () => {
|
|
3842
|
+
if (closed) return;
|
|
3843
|
+
closed = true;
|
|
3844
|
+
closeLinuxPinnedMounts(runtime, descriptors);
|
|
3845
|
+
};
|
|
3846
|
+
return createSandboxPlan({
|
|
3847
|
+
...base,
|
|
3848
|
+
applied: true,
|
|
3849
|
+
enforcement: LINUX_MCP_CAPSULE_BACKEND,
|
|
3850
|
+
backend: LINUX_MCP_CAPSULE_BACKEND,
|
|
3851
|
+
candidateBackend: null,
|
|
3852
|
+
policyAttested: true,
|
|
3853
|
+
policyDigest,
|
|
3854
|
+
runtimeProbe: {
|
|
3855
|
+
kind: "linux-mcp-capsule-code-snapshot-v1",
|
|
3856
|
+
attempted: true,
|
|
3857
|
+
runnable: true,
|
|
3858
|
+
reason: null,
|
|
3859
|
+
probeRuntime: "node",
|
|
3860
|
+
targetRuntime: "node",
|
|
3861
|
+
contentSnapshot: true,
|
|
3862
|
+
contentSnapshotScope: "mcp-capsule-entry-and-node-runtime",
|
|
3863
|
+
contentSnapshotMechanism: LINUX_MCP_CAPSULE_SNAPSHOT_MECHANISM,
|
|
3864
|
+
handleAtomic: true,
|
|
3865
|
+
sharedLibraryClosure: false,
|
|
3866
|
+
...snapshotIdentity,
|
|
3867
|
+
},
|
|
3868
|
+
reason: null,
|
|
3869
|
+
guarantees: [SANDBOX_BOUNDARIES.CODE_SNAPSHOT],
|
|
3870
|
+
command: `/proc/self/fd/${runtimeFd}`,
|
|
3871
|
+
args: [`/proc/self/fd/${entryFd}`, ...invocation.args.slice(1)],
|
|
3872
|
+
options: {
|
|
3873
|
+
...invocation.options,
|
|
3874
|
+
shell: false,
|
|
3875
|
+
stdio: Object.freeze(
|
|
3876
|
+
linuxStdioWithPinnedMounts(invocation.options.stdio, descriptors),
|
|
3877
|
+
),
|
|
3878
|
+
},
|
|
3879
|
+
cleanup,
|
|
3880
|
+
});
|
|
3881
|
+
}
|
|
3882
|
+
|
|
3627
3883
|
function buildLinuxNodePluginTreeSnapshotAttestation(mounts, entryDestination) {
|
|
3628
3884
|
const members = [];
|
|
3629
3885
|
const destinations = new Set();
|
|
@@ -5439,6 +5695,17 @@ export function applyLinuxSandbox(
|
|
|
5439
5695
|
boundary === SANDBOX_BOUNDARIES.PROCESS_TREE,
|
|
5440
5696
|
);
|
|
5441
5697
|
|
|
5698
|
+
if (requiredBoundaries.includes(SANDBOX_BOUNDARIES.CODE_SNAPSHOT)) {
|
|
5699
|
+
return applyLinuxMcpCapsuleCodeSnapshot(
|
|
5700
|
+
command,
|
|
5701
|
+
args,
|
|
5702
|
+
spawnOpts,
|
|
5703
|
+
sandboxOpts,
|
|
5704
|
+
runtime,
|
|
5705
|
+
base,
|
|
5706
|
+
);
|
|
5707
|
+
}
|
|
5708
|
+
|
|
5442
5709
|
if (requiresStrongLinuxBoundary) {
|
|
5443
5710
|
if (isLinuxGenericWorkspaceContract(sandboxOpts.executionContract)) {
|
|
5444
5711
|
return applyLinuxGenericWorkspaceSandbox(
|
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { listSessions } from "./session-manager.js";
|
|
10
|
-
import {
|
|
11
|
-
|
|
10
|
+
import {
|
|
11
|
+
listSessionAuthoritySummaries,
|
|
12
|
+
listSessionEvidenceIds,
|
|
13
|
+
} from "../harness/jsonl-session-store.js";
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* Merge both stores into a single newest-first, id-deduped list.
|
|
@@ -21,15 +23,18 @@ import { feature } from "./feature-flags.js";
|
|
|
21
23
|
export function listRecentSessions(ctx, opts = {}) {
|
|
22
24
|
const scan = Math.max(1, opts.scan || 20);
|
|
23
25
|
const sessions = [];
|
|
26
|
+
const canonicalIds = new Set(listSessionEvidenceIds());
|
|
24
27
|
|
|
25
28
|
if (ctx && ctx.db) {
|
|
26
29
|
try {
|
|
27
30
|
const db = ctx.db.getDatabase();
|
|
28
31
|
sessions.push(
|
|
29
|
-
...listSessions(db, { limit: scan })
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
...listSessions(db, { limit: scan })
|
|
33
|
+
.filter((s) => !canonicalIds.has(s?.id))
|
|
34
|
+
.map((s) => ({
|
|
35
|
+
...s,
|
|
36
|
+
_store: "db",
|
|
37
|
+
})),
|
|
33
38
|
);
|
|
34
39
|
} catch (err) {
|
|
35
40
|
/* db unavailable — fall through to JSONL */
|
|
@@ -37,17 +42,12 @@ export function listRecentSessions(ctx, opts = {}) {
|
|
|
37
42
|
}
|
|
38
43
|
}
|
|
39
44
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
})),
|
|
47
|
-
);
|
|
48
|
-
} catch (err) {
|
|
49
|
-
void err;
|
|
50
|
-
}
|
|
45
|
+
try {
|
|
46
|
+
// Existing canonical history remains authoritative even when the feature
|
|
47
|
+
// flag that controls new JSONL adoption is disabled.
|
|
48
|
+
sessions.push(...listSessionAuthoritySummaries({ limit: scan }));
|
|
49
|
+
} catch (err) {
|
|
50
|
+
void err;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
// Dedup by id (JSONL precedence via sort+seen), newest updated_at first.
|
|
@@ -33,6 +33,10 @@ const IDENTITY_FIELDS = Object.freeze([
|
|
|
33
33
|
const IDENTITY_FIELDS_EXCEPT_DEVICE = Object.freeze(
|
|
34
34
|
IDENTITY_FIELDS.filter((field) => field !== "dev"),
|
|
35
35
|
);
|
|
36
|
+
const STABLE_FILE_IDENTITY_FIELDS = Object.freeze(["dev", "ino", "mode"]);
|
|
37
|
+
const STABLE_FILE_IDENTITY_FIELDS_EXCEPT_DEVICE = Object.freeze(
|
|
38
|
+
STABLE_FILE_IDENTITY_FIELDS.filter((field) => field !== "dev"),
|
|
39
|
+
);
|
|
36
40
|
const DIRECTORY_IDENTITY_FIELDS = Object.freeze(["dev", "ino", "mode"]);
|
|
37
41
|
const DIRECTORY_IDENTITY_FIELDS_EXCEPT_DEVICE = Object.freeze(
|
|
38
42
|
DIRECTORY_IDENTITY_FIELDS.filter((field) => field !== "dev"),
|
|
@@ -184,6 +188,49 @@ export function samePathHandleFileIdentity(
|
|
|
184
188
|
);
|
|
185
189
|
}
|
|
186
190
|
|
|
191
|
+
/**
|
|
192
|
+
* Compare only the immutable/type portion of a path/handle file identity.
|
|
193
|
+
*
|
|
194
|
+
* This is for appenders: size and timestamps are expected to change while the
|
|
195
|
+
* descriptor is held, but the published name must continue to designate that
|
|
196
|
+
* exact regular file. The independently opened parent/volume device keeps the
|
|
197
|
+
* narrow Node 22.12 Windows device-projection bridge fail-closed.
|
|
198
|
+
*/
|
|
199
|
+
export function samePathHandleStableFileIdentity(
|
|
200
|
+
pathStat,
|
|
201
|
+
handleStat,
|
|
202
|
+
expectedDevice,
|
|
203
|
+
runtime = undefined,
|
|
204
|
+
) {
|
|
205
|
+
const pathIdentity = fileStatIdentity(pathStat);
|
|
206
|
+
const handleIdentity = fileStatIdentity(handleStat);
|
|
207
|
+
const trustedDevice =
|
|
208
|
+
expectedDevice === undefined || expectedDevice === null
|
|
209
|
+
? null
|
|
210
|
+
: String(expectedDevice);
|
|
211
|
+
if (
|
|
212
|
+
!hasFields(pathIdentity, STABLE_FILE_IDENTITY_FIELDS) ||
|
|
213
|
+
!hasFields(handleIdentity, STABLE_FILE_IDENTITY_FIELDS) ||
|
|
214
|
+
trustedDevice === null ||
|
|
215
|
+
handleIdentity.dev !== trustedDevice
|
|
216
|
+
) {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
if (sameFields(pathIdentity, handleIdentity, STABLE_FILE_IDENTITY_FIELDS)) {
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
return (
|
|
223
|
+
isAffectedWindowsZeroDeviceStatRuntime(runtime) &&
|
|
224
|
+
pathIdentity.dev !== handleIdentity.dev &&
|
|
225
|
+
handleIdentity.dev !== "0" &&
|
|
226
|
+
sameFields(
|
|
227
|
+
pathIdentity,
|
|
228
|
+
handleIdentity,
|
|
229
|
+
STABLE_FILE_IDENTITY_FIELDS_EXCEPT_DEVICE,
|
|
230
|
+
)
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
|
|
187
234
|
/**
|
|
188
235
|
* Directory contents can legitimately change while a child is written, so a
|
|
189
236
|
* parent recheck excludes content-derived metadata and the directory link
|
package/src/lib/secure-fs.js
CHANGED
|
@@ -1004,6 +1004,7 @@ export function ensurePrivateDirectory(target, options = {}) {
|
|
|
1004
1004
|
platform,
|
|
1005
1005
|
);
|
|
1006
1006
|
let existed = deps.fs.existsSync(target);
|
|
1007
|
+
let existingMode = null;
|
|
1007
1008
|
if (existed) {
|
|
1008
1009
|
const pathEntry = readPrivatePathEntry(
|
|
1009
1010
|
target,
|
|
@@ -1013,6 +1014,7 @@ export function ensurePrivateDirectory(target, options = {}) {
|
|
|
1013
1014
|
);
|
|
1014
1015
|
existed = pathEntry.exists;
|
|
1015
1016
|
const existing = pathEntry.entry;
|
|
1017
|
+
existingMode = existing ? Number(existing.mode) : null;
|
|
1016
1018
|
if (existed && existing.isSymbolicLink()) {
|
|
1017
1019
|
throw new Error(
|
|
1018
1020
|
`Refusing owner-only directory through a symbolic link: ${target}`,
|
|
@@ -1031,7 +1033,16 @@ export function ensurePrivateDirectory(target, options = {}) {
|
|
|
1031
1033
|
mode: PRIVATE_DIRECTORY_MODE,
|
|
1032
1034
|
});
|
|
1033
1035
|
if ((options.platform || deps.platform()) !== "win32") {
|
|
1034
|
-
|
|
1036
|
+
// chmod updates ctime even when the mode is already correct. Session and
|
|
1037
|
+
// security stores use ctime as part of their physical witness, so avoid
|
|
1038
|
+
// invalidating an otherwise unchanged owner-only directory.
|
|
1039
|
+
if (
|
|
1040
|
+
!existed ||
|
|
1041
|
+
!Number.isFinite(existingMode) ||
|
|
1042
|
+
(existingMode & 0o7777) !== PRIVATE_DIRECTORY_MODE
|
|
1043
|
+
) {
|
|
1044
|
+
deps.fs.chmodSync(target, PRIVATE_DIRECTORY_MODE);
|
|
1045
|
+
}
|
|
1035
1046
|
} else if (
|
|
1036
1047
|
options.applyWindowsAcl === true ||
|
|
1037
1048
|
(!existed && options.applyWindowsAcl !== false)
|
|
@@ -1071,7 +1082,15 @@ export function ensurePrivateFile(target, options = {}) {
|
|
|
1071
1082
|
throw new Error(`Expected a file for owner-only storage: ${target}`);
|
|
1072
1083
|
}
|
|
1073
1084
|
if (platform !== "win32") {
|
|
1074
|
-
|
|
1085
|
+
// Preserve ctime for an already-secure file. Rejected CAS writes and
|
|
1086
|
+
// read-only preflights must not make a persisted physical witness stale.
|
|
1087
|
+
const existingMode = Number(existing.mode);
|
|
1088
|
+
if (
|
|
1089
|
+
!Number.isFinite(existingMode) ||
|
|
1090
|
+
(existingMode & 0o7777) !== PRIVATE_FILE_MODE
|
|
1091
|
+
) {
|
|
1092
|
+
deps.fs.chmodSync(target, PRIVATE_FILE_MODE);
|
|
1093
|
+
}
|
|
1075
1094
|
} else if (
|
|
1076
1095
|
options.applyWindowsAcl === true &&
|
|
1077
1096
|
(options.deps || !securedWindowsPaths.has(target))
|