chainlesschain 0.166.90 → 0.166.91
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 +9 -7
- package/package.json +3 -3
- package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
- package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
- package/src/assets/web-panel/assets/{AIOps-CZzXRe1-.js → AIOps-DgV7xb8F.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-_AZfbW1Q.js → ActionButton-CgANpkKu.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-CzaUx_wv.js → Analytics-DnvpX7RB.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-xHEeeD-m.js → AppLayout-C2bHccBM.js} +4 -4
- package/src/assets/web-panel/assets/{Artifacts-DmTbtudE.js → Artifacts-BIhijC9g.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-Cn4ng4fo.js → Audit-CKRjWGdp.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-DLUY1VD2.js → BackgroundAgents-CblYtgBE.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-B2v--wB6.js → Backup-Cq35b78a.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-Bgih7yAv.js → BaseInput-DcB7NoRz.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-1MiiA3yA.js → Chat-tc3b-s7i.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-CPLynmbb.js → ChatBubbleRenderer-fcc_Tvqu.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-DsyBa_NO.js → Checkbox-BLD5bH5u.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-B7WCFx9H.js → Codegen-BLOsoazN.js} +1 -1
- package/src/assets/web-panel/assets/{Col-D2x4GBGm.js → Col-Bdr7JwIx.js} +1 -1
- package/src/assets/web-panel/assets/{Community-Rnwg9nea.js → Community-C84BsWE0.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BPczlrRh.js → Compact-Dzdwd04z.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-Br1L_wGU.js → Compliance-CCG-R0EV.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DlsWB_oS.js → Cowork-BYj72SK0.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-BWo_KGpG.js → Cron-B6iKAwOf.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-Cug7N8ge.js → Crosschain-BJ-oDC6u.js} +1 -1
- package/src/assets/web-panel/assets/{DID-CMbyOZJN.js → DID-BnMckGLr.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-C4dl_UaE.js → Dashboard-Cyje-gCO.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-CBrC7M-9.js → Dropdown-BpNlenjK.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-DTq7tU4b.js → EmailListRenderer-BhonO7Nv.js} +1 -1
- package/src/assets/web-panel/assets/{EvolutionSettings-DWP3csxS.js → EvolutionSettings-DVoNU-Id.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-DZl7zuv_.js → FamilyGuardDashboard-tdn-KC67.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-W-GSlVK5.js → Federation--EEVrHhz.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-DMB7xYFV.js → FormItemContext-Cy8zr0-4.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-DNv8GEoq.js → GenericCardRenderer-BuUhpgFi.js} +1 -1
- package/src/assets/web-panel/assets/{Git-BZ0Bbzw6.js → Git-Ctd3E5Pe.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BNEdcOM5.js → Governance-Ce7dV6aU.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-C8249gIz.js → Inference-CD1vExIH.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-ngzebU3e.js → KnowledgeGraph-Dn64OdQ7.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-CP15th-f.js → Logs-PmElVRrT.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-CW3B3JDq.js → MarkdownRenderer-BFiVKf5t.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-CaH59OsY.js → Marketplace-OW4jTXwx.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-C07vnJev.js → McpTools-BEq2Ib4x.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-CqAOkVAS.js → Memory-Can_P2oK.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-qp7mZimq.js → MobileBridge-DJ8R-dn3.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-DKhbqvTw.js → MobileProjects-B7kV9GOt.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-CRYCnWXv.js → Mtc-BfxamolS.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-Z08IrKws.js → MtcAudit-DHtuv7av.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-BWdatUnH.js → Multisig-DLkLpvxc.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-BKWiCZ_m.js → NLProgramming-u4XtJTIt.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-Bgpzk3sm.js → Notes-BwuuPJLS.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-DvtZEktR.js → NotificationSettings-HEeu-E9v.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-CBcy0szc.js → OrderTableRenderer-BtvN-Qwh.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-DRRL6vW1.js → Organization-Yh-czs3b.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-COmfB8Ns.js → Overflow-DmE8mYVM.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-BqMq_DSa.js → P2P-CWVck8WN.js} +2 -2
- package/src/assets/web-panel/assets/PdhVaultBrowser-DgFqekod.js +7 -0
- package/src/assets/web-panel/assets/{Permissions-DzYkjmV_.js → Permissions-BtJBVOHV.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-BBTcxBbN.js → PersonalDataHub-6VBObXzd.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-eRkYFSbO.js → Pipeline-D222FmqY.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-Ch7IFKBh.js → Privacy-Bi9FMikp.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-Ci8EcBYg.js → ProjectInit-Bo52H47H.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-B4lYHFbI.js → ProjectSettings-BPkesfOc.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-zkE5cCo_.js → Projects-GynohSFX.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-BKDVD3_e.js → Providers-DVdMg04n.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-BromrHlf.js → QrScannerModal-DqJCb595.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-CCgoY1gR.js → QuickAsk-J7loQbXi.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DCPZvpq7.js → Recommend-BI5aURVc.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-DPnFP8HU.js → RemoteSession-BN2sqGvz.js} +3 -3
- package/src/assets/web-panel/assets/{Reputation-l6r8ytAs.js → Reputation-BGOND-Fi.js} +1 -1
- package/src/assets/web-panel/assets/{Row-ke9Mk1cx.js → Row-77dfwaUk.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-DQOEzUEn.js → RssFeed-FtBAxS3g.js} +2 -2
- package/src/assets/web-panel/assets/{Search-BqgA0aUz.js → Search-BaYVLFb7.js} +1 -1
- package/src/assets/web-panel/assets/{Security-FeGD_jqV.js → Security-LE3Vv6ab.js} +3 -3
- package/src/assets/web-panel/assets/{Services-4kiYYAjZ.js → Services-C5pP-Whz.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-BbU8Xegs.js → Skeleton-CLqKUVsF.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-Dl2bUMUL.js → Skills-BPjN0SX5.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-xRGALeaZ.js → Sla-14jD70kg.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-DZfd4RDm.js → SpeechSettings-Dr9ij42W.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-BRtCV9Ga.js → SyncSettings-BzLHP7B8.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-DVRQklfG.js → Tasks-YqV9b0rV.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BbhE5jt5.js → Templates-CxxAE4PK.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-qXPDNKbK.js → Tenant-CRb3PcKJ.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-CV48Ks7E.js → Terminal-CTzPpBaP.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-BLGfJIDr.js → TimelineRenderer-DjFUj_hy.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-7G9H6Hrt.js → Tokens-Bbb8tPvx.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger--F64N11F.js → Trigger-CSeWGM0W.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-Cq1r-D_y.js → Trust-JgESMBo3.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-Dqyu4RVh.js → UkeySign-CiObLk0T.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-DuFmWH_B.js → VideoEditing-CFEZaQ2x.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-C3mg7EWP.js → Wallet-DR8ZGDNn.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-CDK-Aj_X.js → WebAuthn-DxZukvu7.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor--K7K-T1F.js → WorkflowEditor-CKgSZQwn.js} +1 -1
- package/src/assets/web-panel/assets/{chat-BQDcS6VP.js → chat-CTxEQE66.js} +1 -1
- package/src/assets/web-panel/assets/{colors-BKxJL2-T.js → colors-CAjKMUu3.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-CFjQAMbY.js → compact-item-BXuz49at.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DbgCsdQd.js → createContext-CFN_Hwr9.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-CfB8DxT2.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-BhkaOBNv.js → hasIn-BwoSBSfP.js} +1 -1
- package/src/assets/web-panel/assets/{index-D-Yh3-1z.js → index-B0QbLlWn.js} +1 -1
- package/src/assets/web-panel/assets/{index-BfGGsAU7.js → index-B2o_BBjg.js} +1 -1
- package/src/assets/web-panel/assets/{index-CoOu7sdP.js → index-B2tEnBPx.js} +1 -1
- package/src/assets/web-panel/assets/{index-BRqlCTrz.js → index-B7kp-zRE.js} +1 -1
- package/src/assets/web-panel/assets/{index-CB4oHynY.js → index-B9yR7zqr.js} +1 -1
- package/src/assets/web-panel/assets/{index-DEwHywz9.js → index-BK4ftQ4d.js} +1 -1
- package/src/assets/web-panel/assets/{index-Du_SxxBY.js → index-Bj4hIiLW.js} +1 -1
- package/src/assets/web-panel/assets/{index-DFt48Z-x.js → index-BmQITjMU.js} +1 -1
- package/src/assets/web-panel/assets/{index-DdcrixaQ.js → index-BmXpdcHI.js} +1 -1
- package/src/assets/web-panel/assets/{index-BuWPqSGT.js → index-Bqv_Cray.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmYK9Tqt.js → index-Bu2P6u8m.js} +1 -1
- package/src/assets/web-panel/assets/{index-T9ka3Xj3.js → index-Bw9s2d3c.js} +1 -1
- package/src/assets/web-panel/assets/{index-COGy6wXn.js → index-C8er4W9u.js} +1 -1
- package/src/assets/web-panel/assets/{index-sKfUUldY.js → index-CB3kVd9c.js} +1 -1
- package/src/assets/web-panel/assets/index-CCsRfd0k.js +1 -0
- package/src/assets/web-panel/assets/{index-Dhfa_BIl.js → index-CF9lWi1o.js} +1 -1
- package/src/assets/web-panel/assets/{index-CRtUDiXx.js → index-CN53dE_u.js} +1 -1
- package/src/assets/web-panel/assets/{index-D2Zb-Kd1.js → index-CSmFby3Q.js} +1 -1
- package/src/assets/web-panel/assets/{index-DP1NrM9J.js → index-CehdwJ_Q.js} +1 -1
- package/src/assets/web-panel/assets/{index-aPdVzagA.js → index-Cgk0YEiq.js} +1 -1
- package/src/assets/web-panel/assets/{index-3YutaXnp.js → index-Cp5y7lX_.js} +1 -1
- package/src/assets/web-panel/assets/index-CsmiZIQ4.js +1 -0
- package/src/assets/web-panel/assets/{index-C0DzhUOX.js → index-DTX9CJPx.js} +1 -1
- package/src/assets/web-panel/assets/{index-bMX8BBLE.js → index-DViK2bkv.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dn2QSsuI.js → index-DY-gBSm8.js} +1 -1
- package/src/assets/web-panel/assets/{index-BNjYPJNU.js → index-DjF5BOZx.js} +1 -1
- package/src/assets/web-panel/assets/{index-CE506mgj.js → index-DmkbAADP.js} +1 -1
- package/src/assets/web-panel/assets/{index-De7daEnc.js → index-DpdDnZX_.js} +1 -1
- package/src/assets/web-panel/assets/{index-3uR0ThJO.js → index-Dv7V2kg6.js} +1 -1
- package/src/assets/web-panel/assets/{index-CUs7XpUO.js → index-DxunxaTw.js} +1 -1
- package/src/assets/web-panel/assets/{index-3djsY75k.js → index-F2E5RCwz.js} +1 -1
- package/src/assets/web-panel/assets/{index-D9sVcw6v.js → index-IY9bd5az.js} +1 -1
- package/src/assets/web-panel/assets/{index-DJ2OiRvh.js → index-IahILygB.js} +3 -3
- package/src/assets/web-panel/assets/{index-DjmVlpap.js → index-T3MTE6jB.js} +1 -1
- package/src/assets/web-panel/assets/{index-CSUDlsIr.js → index-Tz5dheZa.js} +1 -1
- package/src/assets/web-panel/assets/{index-B4LlAJqc.js → index-_ZtCyUdz.js} +1 -1
- package/src/assets/web-panel/assets/{index-CJoXgJ2N.js → index-o9DpkZKf.js} +1 -1
- package/src/assets/web-panel/assets/{index-7BY44UEv.js → index-t2Ch_JKn.js} +1 -1
- package/src/assets/web-panel/assets/{index-DvWWFJHJ.js → index-u9_DM3ZC.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-wrqabmui.js → initDefaultProps-BoiGJDoO.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BoyB3ilP.js → motion-5eL4E0pA.js} +1 -1
- package/src/assets/web-panel/assets/{move-Cq31cSFE.js → move-DjggDi_1.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-BkxNt-8H.js → mtc-parser-Ce8Vo2T3.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DofGni53.js → omit-D1yOBaO2.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-BnluLL16.js → pickAttrs-8NLceQe8.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-C-yegJSP.js → placementArrow-CsIdBRmQ.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-CD3ziNhu.js → responsiveObserve-GM5NE8En.js} +1 -1
- package/src/assets/web-panel/assets/{slide-ToZO4gQ1.js → slide-44yj3u49.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-DFVmDmVl.js → statusUtils-B8tqtWcX.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-De0Y8g1O.js → styleChecker-NhDPBbyB.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-wBKIYFKX.js → useFlexGapSupport-C8Qz1GtN.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-CP9nmUMJ.js → useFs-ClUv4kih.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-vFGrVDyp.js → usePersonalDataHub-BwkOVEh6.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-BcBIjvjH.js → vnode--gMF33R0.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-DnXDAQxA.js → zoom-DXg3TqOP.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +1 -1
- package/src/commands/agent-process-ownership.js +121 -0
- package/src/commands/agent.js +2 -0
- package/src/commands/hub.js +86 -9
- package/src/data/changelog.json +15 -2
- package/src/lib/audit-logger.js +46 -20
- package/src/lib/checkpoint-restore-saga.js +11 -1
- package/src/lib/eval/verify01-host-evidence.js +36 -3
- package/src/lib/process-execution-broker/index.js +91 -1
- package/src/lib/process-execution-broker/platform-sandbox.js +42 -0
- package/src/lib/process-execution-broker/windows-native-evaluator-capabilities.js +757 -0
- package/src/lib/process-execution-broker/windows-native-evaluator.js +316 -0
- package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
- package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
- package/src/lib/process-execution-broker/windows-sandbox.cs +383 -11
- package/src/assets/web-panel/assets/PdhVaultBrowser-BX7iNvle.js +0 -7
- package/src/assets/web-panel/assets/devWarning-DlIv9Mbc.js +0 -1
- package/src/assets/web-panel/assets/index-BC972Grv.js +0 -1
- package/src/assets/web-panel/assets/index-CVifyQqL.js +0 -1
package/src/commands/hub.js
CHANGED
|
@@ -3464,7 +3464,11 @@ async function cmdDerivation(operation, reference, options = {}) {
|
|
|
3464
3464
|
"Normalized entity deletion requires --confirm; raw archive is retained",
|
|
3465
3465
|
);
|
|
3466
3466
|
}
|
|
3467
|
-
if (
|
|
3467
|
+
if (
|
|
3468
|
+
operation === "prune" &&
|
|
3469
|
+
options.confirm !== true &&
|
|
3470
|
+
options.dryRun !== true
|
|
3471
|
+
) {
|
|
3468
3472
|
throw new Error("Retired derivation receipt pruning requires --confirm");
|
|
3469
3473
|
}
|
|
3470
3474
|
if (
|
|
@@ -3482,23 +3486,73 @@ async function cmdDerivation(operation, reference, options = {}) {
|
|
|
3482
3486
|
if (!Number.isSafeInteger(limit) || limit < 1 || limit > 1000) {
|
|
3483
3487
|
throw new Error("Derivation limit must be between 1 and 1000");
|
|
3484
3488
|
}
|
|
3485
|
-
const
|
|
3489
|
+
const budget = {};
|
|
3490
|
+
for (const name of ["maxVaultBytes", "minFreeBytes", "reserveBytes"]) {
|
|
3491
|
+
if (options[name] === undefined) continue;
|
|
3492
|
+
const value = Number(options[name]);
|
|
3493
|
+
if (!Number.isSafeInteger(value) || value < 0)
|
|
3494
|
+
throw new Error(`${name} must be a non-negative safe integer`);
|
|
3495
|
+
budget[name] = value;
|
|
3496
|
+
}
|
|
3497
|
+
if (options.audit && (options.state || options.kind)) {
|
|
3498
|
+
throw new Error(
|
|
3499
|
+
"Consumer audit includes all kinds and states; omit --kind and --state",
|
|
3500
|
+
);
|
|
3501
|
+
}
|
|
3502
|
+
if (
|
|
3503
|
+
operation === "status" &&
|
|
3504
|
+
Object.keys(budget).length &&
|
|
3505
|
+
!options.storage
|
|
3506
|
+
) {
|
|
3507
|
+
throw new Error(
|
|
3508
|
+
"Storage budget options require --storage for derivation-status",
|
|
3509
|
+
);
|
|
3510
|
+
}
|
|
3511
|
+
// Check before constructing a registry: full hub startup may rebuild indexes.
|
|
3512
|
+
if (operation === "retry" && Object.keys(budget).length) {
|
|
3513
|
+
const minimal = await (options._getHub || getHubMinimal)();
|
|
3514
|
+
minimal.vault.assertStorageBudget(budget);
|
|
3515
|
+
}
|
|
3516
|
+
if (operation === "status" && options.storage) {
|
|
3517
|
+
if (options.adapter !== undefined || options.scope !== undefined) {
|
|
3518
|
+
throw new Error(
|
|
3519
|
+
"Storage reports cover the whole vault; omit --adapter and --scope",
|
|
3520
|
+
);
|
|
3521
|
+
}
|
|
3522
|
+
const minimal = await (options._getHub || getHubMinimal)();
|
|
3523
|
+
const result = { storage: minimal.vault.assertStorageBudget(budget) };
|
|
3524
|
+
printJson(result);
|
|
3525
|
+
return result;
|
|
3526
|
+
}
|
|
3527
|
+
const hub = await (
|
|
3528
|
+
options._getHub ||
|
|
3529
|
+
(operation === "consumers" || (operation === "prune" && options.dryRun)
|
|
3530
|
+
? getHubMinimal
|
|
3531
|
+
: getHub)
|
|
3532
|
+
)();
|
|
3486
3533
|
const filters = { adapter: options.adapter, scope: options.scope };
|
|
3487
3534
|
let result;
|
|
3488
3535
|
if (operation === "consumers") {
|
|
3489
|
-
result =
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3536
|
+
result = options.audit
|
|
3537
|
+
? hub.vault.getDerivationStore().auditConsumers({
|
|
3538
|
+
afterConsumerId: options.after,
|
|
3539
|
+
limit,
|
|
3540
|
+
})
|
|
3541
|
+
: hub.vault.getDerivationStore().listConsumers({
|
|
3542
|
+
state: options.state,
|
|
3543
|
+
kind: options.kind,
|
|
3544
|
+
afterConsumerId: options.after,
|
|
3545
|
+
limit,
|
|
3546
|
+
});
|
|
3495
3547
|
} else if (operation === "prune") {
|
|
3496
3548
|
result = hub.vault.getDerivationStore().pruneRetiredConsumers({
|
|
3497
3549
|
consumerIds: options.consumer,
|
|
3498
|
-
activeConsumerId: hub.registry
|
|
3550
|
+
activeConsumerId: hub.registry?.consumerId,
|
|
3499
3551
|
limit,
|
|
3552
|
+
...(options.dryRun ? { dryRun: true } : {}),
|
|
3500
3553
|
});
|
|
3501
3554
|
} else if (operation === "retry") {
|
|
3555
|
+
if (Object.keys(budget).length) hub.vault.assertStorageBudget(budget);
|
|
3502
3556
|
result = await hub.registry.retryDerivations({ ...filters, limit });
|
|
3503
3557
|
} else if (operation === "state") {
|
|
3504
3558
|
result = hub.vault
|
|
@@ -3668,8 +3722,23 @@ export function registerHubCommand(program, dependencies = {}) {
|
|
|
3668
3722
|
.option("--adapter <name>", "Filter by source adapter")
|
|
3669
3723
|
.option("--scope <scope>", "Filter by source scope")
|
|
3670
3724
|
.option("--json", "Output JSON");
|
|
3725
|
+
command
|
|
3726
|
+
.option("--max-vault-bytes <n>", "Preflight maximum DB + WAL + SHM bytes")
|
|
3727
|
+
.option(
|
|
3728
|
+
"--min-free-bytes <n>",
|
|
3729
|
+
"Preflight minimum free disk bytes after reserve",
|
|
3730
|
+
)
|
|
3731
|
+
.option(
|
|
3732
|
+
"--reserve-bytes <n>",
|
|
3733
|
+
"Caller-estimated extra bytes for preflight (not a reservation)",
|
|
3734
|
+
);
|
|
3671
3735
|
if (operation === "retry")
|
|
3672
3736
|
command.option("--limit <n>", "Maximum deliveries (1-1000)", "100");
|
|
3737
|
+
else
|
|
3738
|
+
command.option(
|
|
3739
|
+
"--storage",
|
|
3740
|
+
"Inspect storage only and check the supplied byte budget",
|
|
3741
|
+
);
|
|
3673
3742
|
command.action((options) => cmdDerivation(operation, null, options));
|
|
3674
3743
|
}
|
|
3675
3744
|
|
|
@@ -3679,6 +3748,10 @@ export function registerHubCommand(program, dependencies = {}) {
|
|
|
3679
3748
|
"List registered derivation consumers without retirement tokens",
|
|
3680
3749
|
)
|
|
3681
3750
|
.option("--state <state>", "Filter by active or retired")
|
|
3751
|
+
.option(
|
|
3752
|
+
"--audit",
|
|
3753
|
+
"Inventory registered and historical consumers with retention reasons and receipt counts",
|
|
3754
|
+
)
|
|
3682
3755
|
.option("--kind <kind>", "Filter by ephemeral or persistent")
|
|
3683
3756
|
.option("--after <id>", "Continue after a consumer ID")
|
|
3684
3757
|
.option("--limit <n>", "Maximum consumers (1-1000)", "100")
|
|
@@ -3693,6 +3766,10 @@ export function registerHubCommand(program, dependencies = {}) {
|
|
|
3693
3766
|
.requiredOption("--consumer <ids...>", "Retired consumer IDs (1-100)")
|
|
3694
3767
|
.option("--limit <n>", "Maximum receipts removed (1-1000)", "100")
|
|
3695
3768
|
.option("--confirm", "Confirm removal of these retired projection receipts")
|
|
3769
|
+
.option(
|
|
3770
|
+
"--dry-run",
|
|
3771
|
+
"Validate IDs and preview bounded receipt cleanup without deletion",
|
|
3772
|
+
)
|
|
3696
3773
|
.option("--json", "Output JSON")
|
|
3697
3774
|
.action((options) => cmdDerivation("prune", null, options));
|
|
3698
3775
|
|
package/src/data/changelog.json
CHANGED
|
@@ -1,16 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"source": "CHANGELOG.md",
|
|
3
3
|
"releases": [
|
|
4
|
+
{
|
|
5
|
+
"productVersion": null,
|
|
6
|
+
"cliVersion": "0.166.91",
|
|
7
|
+
"cliVersions": ["0.166.91"],
|
|
8
|
+
"date": null,
|
|
9
|
+
"title": "",
|
|
10
|
+
"sections": [
|
|
11
|
+
{
|
|
12
|
+
"heading": "Fixed - cc CLI 0.166.91: cross-platform release validation",
|
|
13
|
+
"body": "- Accept verified directory identities through the Windows Server 2025 native\n file-information API, while retaining handle binding and reparse-point checks.\n- Preserve Windows native evaluator failure and cleanup evidence when the helper\n cannot publish a settlement. Compare journal identities within their pathname\n and descriptor domains on supported Node versions.\n- Keep literal audit search assertions independent of redacted operation text;\n verify that unsafe legacy text remains omitted from query results.\n- Give the receipt signer deadline test enough admission time on hosted runners\n and verify that the signer is actually invoked before its bounded timeout.\n- Regenerate the bundled CLI changelog from its canonical source.\n- Capture JetBrains transcript snapshots on the event dispatch thread during\n cross-platform host validation, retaining the full transcript assertions.\n- Preserve equivalent protected Windows evaluator ACLs across .NET Framework\n and PowerShell's .NET runtime through the native security API.\n- Retry cooperative lock release during nested safe owner reads without treating\n it as corruption; losing a held lock still fails closed.\n- Pin the patched `shell-quote` dependency in both workspace and standalone\n desktop installs to reject command injection after shell comment tokens.\n- Publish Session Core `0.3.16` and Personal Data Hub `0.4.64` before CLI\n `0.166.91`, with exact dependency pins and public package verification.\n- Pair VS Code `0.37.136` and JetBrains `0.4.154` with CLI `0.166.91` after\n the full exact-commit CLI and IDE validation workflows pass."
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
4
17
|
{
|
|
5
18
|
"productVersion": null,
|
|
6
19
|
"cliVersion": "0.166.90",
|
|
7
20
|
"cliVersions": ["0.166.90"],
|
|
8
|
-
"date":
|
|
21
|
+
"date": "2026-10-06",
|
|
9
22
|
"title": "",
|
|
10
23
|
"sections": [
|
|
11
24
|
{
|
|
12
25
|
"heading": "Added - cc CLI 0.166.90: recoverable projections and project risk evidence",
|
|
13
|
-
"body": "- Publish Personal Data Hub `0.4.63` and Session Core `0.3.15` before the CLI,\n with exact dependency pins and public tarball verification. Require the full\n PDH suite with its declared native SQLCipher driver on Linux, Windows and macOS.\n- Publish Agent SDK `0.2.13` with Vitest `4.1.11` test tooling to remove the\n vulnerable Tinypool dependency, and upgrade the workspace proxy-addr to\n `2.0.8`. Require SDK build and tests on the exact Linux, Windows and macOS\n release commit before OIDC publication.\n- Persist PDH projection receipts, recover incomplete derivations and support\n bounded receipt retention. Harden RAG updates, audit redaction and capability\n reporting so unavailable sources do not appear as successful live collection.\n- Add offline project risk evaluation and version-bound task description\n previews. Session Core also supplies native SQLite action/read services and\n saved rule/source reviews for the desktop project workbench; CLI previews\n carry unverified snapshot authority and do not execute those desktop actions.\n- Pair VS Code `0.37.135` and JetBrains `0.4.153` with CLI `0.166.90` after\n exact-commit release checks and public npm readback."
|
|
26
|
+
"body": "- Verified on 2026-10-06: exact release commit `28cff6adc8` passed complete\n CLI CI, Strict Sandbox, IDE host and security gates. Session Core `0.3.15`,\n Agent SDK `0.2.13`, PDH `0.4.63` and CLI `0.166.90` were published through\n GitHub Actions OIDC with independent public archive verification. Open VSX\n `0.37.135` and JetBrains `0.4.153` are public; both publication workflows\n succeeded, and JetBrains approval/listing was independently read back.\n Desktop workbench changes are outside the separate v5.0.3.138 installer.\n- Publish Personal Data Hub `0.4.63` and Session Core `0.3.15` before the CLI,\n with exact dependency pins and public tarball verification. Require the full\n PDH suite with its declared native SQLCipher driver on Linux, Windows and macOS.\n- Publish Agent SDK `0.2.13` with Vitest `4.1.11` test tooling to remove the\n vulnerable Tinypool dependency, and upgrade the workspace proxy-addr to\n `2.0.8`. Require SDK build and tests on the exact Linux, Windows and macOS\n release commit before OIDC publication.\n- Persist PDH projection receipts, recover incomplete derivations and support\n bounded receipt retention. Harden RAG updates, audit redaction and capability\n reporting so unavailable sources do not appear as successful live collection.\n- Add offline project risk evaluation and version-bound task description\n previews. Session Core also supplies native SQLite action/read services and\n saved rule/source reviews for the desktop project workbench; CLI previews\n carry unverified snapshot authority and do not execute those desktop actions.\n- Pair VS Code `0.37.135` and JetBrains `0.4.153` with CLI `0.166.90` after\n exact-commit release checks and public npm readback."
|
|
14
27
|
}
|
|
15
28
|
]
|
|
16
29
|
},
|
package/src/lib/audit-logger.js
CHANGED
|
@@ -7,6 +7,17 @@ import crypto from "crypto";
|
|
|
7
7
|
import { safeJsonParse } from "./safe-json.js";
|
|
8
8
|
import { escapeLike } from "./sql-like.js";
|
|
9
9
|
import { sanitizeAuditDetails } from "./audit-sanitizer.js";
|
|
10
|
+
import auditDataPolicy from "@chainlesschain/session-core/audit-data-policy";
|
|
11
|
+
import restrictedAudit from "@chainlesschain/session-core/restricted-audit-store";
|
|
12
|
+
|
|
13
|
+
const { projectAuditMetadata, projectAuditField, validateRetentionDays } =
|
|
14
|
+
auditDataPolicy;
|
|
15
|
+
|
|
16
|
+
// Host API: authorization must come from the invoking host, never event details.
|
|
17
|
+
// No general audit query/export includes this separate store.
|
|
18
|
+
export function createAuditDiagnostics(db, options) {
|
|
19
|
+
return new restrictedAudit.RestrictedAuditStore(db, options);
|
|
20
|
+
}
|
|
10
21
|
|
|
11
22
|
/**
|
|
12
23
|
* Event types for audit logging.
|
|
@@ -117,7 +128,7 @@ export function sanitizeDetails(details) {
|
|
|
117
128
|
}
|
|
118
129
|
|
|
119
130
|
function sanitizeErrorMessage(value) {
|
|
120
|
-
const sanitized =
|
|
131
|
+
const sanitized = projectAuditMetadata(value);
|
|
121
132
|
if (sanitized == null) return null;
|
|
122
133
|
return typeof sanitized === "object"
|
|
123
134
|
? JSON.stringify(sanitized)
|
|
@@ -131,23 +142,24 @@ export function logEvent(db, event) {
|
|
|
131
142
|
ensureAuditTables(db);
|
|
132
143
|
|
|
133
144
|
const id = crypto.randomUUID();
|
|
134
|
-
const sanitized =
|
|
135
|
-
const risk =
|
|
136
|
-
event.riskLevel
|
|
145
|
+
const sanitized = projectAuditMetadata(event.details);
|
|
146
|
+
const risk = Object.values(RISK_LEVELS).includes(event.riskLevel)
|
|
147
|
+
? event.riskLevel
|
|
148
|
+
: assessRisk(event.eventType, event.operation || "unknown", sanitized);
|
|
137
149
|
|
|
138
150
|
db.prepare(
|
|
139
151
|
`INSERT INTO audit_log (id, event_type, operation, actor, target, details, risk_level, ip_address, user_agent, success, error_message)
|
|
140
152
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
141
153
|
).run(
|
|
142
154
|
id,
|
|
143
|
-
event.eventType || EVENT_TYPES.SYSTEM,
|
|
144
|
-
event.operation || "unknown",
|
|
145
|
-
event.actor || null,
|
|
146
|
-
event.target || null,
|
|
155
|
+
projectAuditField("eventType", event.eventType || EVENT_TYPES.SYSTEM),
|
|
156
|
+
projectAuditField("operation", event.operation || "unknown"),
|
|
157
|
+
projectAuditField("actor", event.actor || null),
|
|
158
|
+
projectAuditField("target", event.target || null),
|
|
147
159
|
sanitized == null ? null : JSON.stringify(sanitized),
|
|
148
160
|
risk,
|
|
149
|
-
event.ipAddress
|
|
150
|
-
event.userAgent
|
|
161
|
+
event.ipAddress ? projectAuditField("ipAddress", event.ipAddress) : null,
|
|
162
|
+
event.userAgent ? projectAuditField("userAgent", event.userAgent) : null,
|
|
151
163
|
event.success !== false ? 1 : 0,
|
|
152
164
|
sanitizeErrorMessage(event.errorMessage),
|
|
153
165
|
);
|
|
@@ -220,8 +232,21 @@ export function queryLogs(db, filters = {}) {
|
|
|
220
232
|
const rows = db.prepare(sql).all(...params);
|
|
221
233
|
return rows.map((r) => ({
|
|
222
234
|
...r,
|
|
235
|
+
event_type: projectAuditField("eventType", r.event_type),
|
|
236
|
+
operation: projectAuditField("operation", r.operation),
|
|
223
237
|
// One corrupt details cell must not throw out of the whole query.
|
|
224
|
-
details: safeJsonParse(r.details, null),
|
|
238
|
+
details: projectAuditMetadata(safeJsonParse(r.details, null)),
|
|
239
|
+
error_message: sanitizeErrorMessage(
|
|
240
|
+
safeJsonParse(r.error_message, r.error_message),
|
|
241
|
+
),
|
|
242
|
+
actor: projectAuditField("actor", r.actor),
|
|
243
|
+
target: projectAuditField("target", r.target),
|
|
244
|
+
ip_address: r.ip_address
|
|
245
|
+
? projectAuditField("ipAddress", r.ip_address)
|
|
246
|
+
: null,
|
|
247
|
+
user_agent: r.user_agent
|
|
248
|
+
? projectAuditField("userAgent", r.user_agent)
|
|
249
|
+
: null,
|
|
225
250
|
success: r.success === 1,
|
|
226
251
|
}));
|
|
227
252
|
}
|
|
@@ -333,6 +358,7 @@ export function exportLogs(db, format = "json", filters = {}) {
|
|
|
333
358
|
* Delete old audit logs.
|
|
334
359
|
*/
|
|
335
360
|
export function purgeLogs(db, daysToKeep = 90) {
|
|
361
|
+
validateRetentionDays(daysToKeep);
|
|
336
362
|
ensureAuditTables(db);
|
|
337
363
|
|
|
338
364
|
const cutoff = new Date();
|
|
@@ -502,7 +528,7 @@ export function logEventV2(
|
|
|
502
528
|
if (_logStatesV2.has(logId)) {
|
|
503
529
|
throw new Error(`Log already registered: ${logId}`);
|
|
504
530
|
}
|
|
505
|
-
const sanitized =
|
|
531
|
+
const sanitized = projectAuditMetadata(details);
|
|
506
532
|
const risk = riskLevel || assessRisk(eventType, operation, sanitized);
|
|
507
533
|
if (!RISK_LEVELS_V2.includes(risk)) {
|
|
508
534
|
throw new Error(`Invalid riskLevel: ${risk}`);
|
|
@@ -510,14 +536,14 @@ export function logEventV2(
|
|
|
510
536
|
const now = Date.now();
|
|
511
537
|
const entry = {
|
|
512
538
|
logId,
|
|
513
|
-
eventType,
|
|
514
|
-
operation,
|
|
515
|
-
actor: actor || null,
|
|
516
|
-
target: target || null,
|
|
539
|
+
eventType: projectAuditField("eventType", eventType),
|
|
540
|
+
operation: projectAuditField("operation", operation),
|
|
541
|
+
actor: projectAuditField("actor", actor || null),
|
|
542
|
+
target: projectAuditField("target", target || null),
|
|
517
543
|
details: sanitized ?? null,
|
|
518
544
|
riskLevel: risk,
|
|
519
|
-
ipAddress: ipAddress
|
|
520
|
-
userAgent: userAgent
|
|
545
|
+
ipAddress: ipAddress ? projectAuditField("ipAddress", ipAddress) : null,
|
|
546
|
+
userAgent: userAgent ? projectAuditField("userAgent", userAgent) : null,
|
|
521
547
|
success: success !== false,
|
|
522
548
|
errorMessage: sanitizeErrorMessage(errorMessage),
|
|
523
549
|
status: LOG_STATUS_V2.ACTIVE,
|
|
@@ -539,8 +565,8 @@ export function logEventV2(
|
|
|
539
565
|
_alertStatesV2.set(alertId, {
|
|
540
566
|
alertId,
|
|
541
567
|
logId,
|
|
542
|
-
actor,
|
|
543
|
-
operation,
|
|
568
|
+
actor: entry.actor,
|
|
569
|
+
operation: entry.operation,
|
|
544
570
|
riskLevel: risk,
|
|
545
571
|
status: ALERT_STATUS_V2.OPEN,
|
|
546
572
|
reason: null,
|
|
@@ -464,6 +464,16 @@ function isMissingPathError(error) {
|
|
|
464
464
|
return error?.code === "ENOENT" || error?.cause?.code === "ENOENT";
|
|
465
465
|
}
|
|
466
466
|
|
|
467
|
+
function hasMissingLockPathCause(error) {
|
|
468
|
+
// A bounded owner read wraps secure-parent errors, which themselves wrap
|
|
469
|
+
// ENOENT when a cooperating process detaches its released lock directory.
|
|
470
|
+
// Only unlocked lock inspection uses this; losing our held owner still fails.
|
|
471
|
+
for (let depth = 0; error && depth < 8; depth++, error = error.cause) {
|
|
472
|
+
if (error.code === "ENOENT") return true;
|
|
473
|
+
}
|
|
474
|
+
return false;
|
|
475
|
+
}
|
|
476
|
+
|
|
467
477
|
function attachCommitState(error, details) {
|
|
468
478
|
if (!error || typeof error !== "object") return error;
|
|
469
479
|
for (const [key, value] of Object.entries(details)) {
|
|
@@ -1887,7 +1897,7 @@ export class CheckpointRestoreSagaStore {
|
|
|
1887
1897
|
// The same valid release can happen after readdir observed owner.json
|
|
1888
1898
|
// but before its lstat/read. Only tolerate absence during the unlocked
|
|
1889
1899
|
// pre/postflight inspection; losing our own owner still fails closed.
|
|
1890
|
-
if (
|
|
1900
|
+
if (hasMissingLockPathCause(cause) && !requireOwner) return null;
|
|
1891
1901
|
throw sagaError(
|
|
1892
1902
|
CHECKPOINT_RESTORE_SAGA_ERROR_CODES.LOCK_FAILED,
|
|
1893
1903
|
"Saga state lock owner is corrupt or unbounded",
|
|
@@ -149,13 +149,46 @@ export function inspectIdeProtocol(records, { prompt, comparison } = {}) {
|
|
|
149
149
|
resultRecords[0].event.session_id === sessionId,
|
|
150
150
|
"IDE terminal is missing or ambiguous",
|
|
151
151
|
);
|
|
152
|
+
const terminal = resultRecords[0].event;
|
|
153
|
+
// Persistent headless streams emit one lifecycle end after stdin closes.
|
|
154
|
+
// Accept only that exact, same-session one-turn trailer; task output after
|
|
155
|
+
// the result stays ambiguous. Keep the complete capture intact.
|
|
156
|
+
const trailing = outputs.slice(outputs.indexOf(resultRecords[0]) + 1);
|
|
157
|
+
const end = trailing[0]?.event;
|
|
158
|
+
const lifecycleFrames = outputs.filter(
|
|
159
|
+
(record) =>
|
|
160
|
+
record.event.type === "system" && record.event.subtype === "end",
|
|
161
|
+
);
|
|
162
|
+
const lifecycleEnded =
|
|
163
|
+
trailing.length === 1 &&
|
|
164
|
+
lifecycleFrames.length === 1 &&
|
|
165
|
+
end.type === "system" &&
|
|
166
|
+
end.subtype === "end" &&
|
|
167
|
+
end.session_id === sessionId &&
|
|
168
|
+
end.turns === 1 &&
|
|
169
|
+
terminal.turn === 1 &&
|
|
170
|
+
Object.keys(end).every((key) =>
|
|
171
|
+
["type", "subtype", "session_id", "turns", "trace_id", "seq"].includes(
|
|
172
|
+
key,
|
|
173
|
+
),
|
|
174
|
+
) &&
|
|
175
|
+
(end.trace_id === undefined ||
|
|
176
|
+
(typeof end.trace_id === "string" &&
|
|
177
|
+
end.trace_id === terminal.trace_id)) &&
|
|
178
|
+
(end.seq === undefined ||
|
|
179
|
+
(Number.isSafeInteger(end.seq) &&
|
|
180
|
+
Number.isSafeInteger(terminal.seq) &&
|
|
181
|
+
end.seq === terminal.seq + 1));
|
|
182
|
+
const taskOutputs = lifecycleEnded ? outputs.slice(0, -1) : outputs;
|
|
152
183
|
const parsed = verifyAgentTerminal(
|
|
153
|
-
|
|
184
|
+
taskOutputs.map((record) => JSON.stringify(record.event)).join("\n"),
|
|
154
185
|
);
|
|
155
|
-
|
|
186
|
+
if (lifecycleFrames.length > 0 && !lifecycleEnded)
|
|
187
|
+
parsed.terminalVerified = false;
|
|
156
188
|
// A complete explicit failure is an observation. It never becomes success.
|
|
157
189
|
const knownFailure =
|
|
158
|
-
|
|
190
|
+
taskOutputs.at(-1) === resultRecords[0] &&
|
|
191
|
+
(lifecycleFrames.length === 0 || lifecycleEnded) &&
|
|
159
192
|
terminal.is_error === true &&
|
|
160
193
|
typeof terminal.subtype === "string" &&
|
|
161
194
|
terminal.subtype.length > 0 &&
|
|
@@ -46,6 +46,7 @@ import {
|
|
|
46
46
|
SANDBOX_BOUNDARIES,
|
|
47
47
|
} from "./platform-sandbox.js";
|
|
48
48
|
import { normalizeLinuxCgroupPolicy } from "./linux-cgroup-v2.js";
|
|
49
|
+
import { consumeWindowsNativeEvaluatorPolicy } from "./windows-native-evaluator.js";
|
|
49
50
|
import { acquireLinuxSubreaperHelper } from "./linux-subreaper-helper.js";
|
|
50
51
|
import { spawnLinuxSubreaperChild } from "./linux-subreaper-process.js";
|
|
51
52
|
import {
|
|
@@ -1625,7 +1626,49 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
1625
1626
|
requiredBoundaries,
|
|
1626
1627
|
launch,
|
|
1627
1628
|
);
|
|
1628
|
-
|
|
1629
|
+
const wallTimeMs = rawPolicy?.limits?.wallTimeMs;
|
|
1630
|
+
if (wallTimeMs !== undefined) {
|
|
1631
|
+
if (
|
|
1632
|
+
!Number.isSafeInteger(wallTimeMs) ||
|
|
1633
|
+
wallTimeMs < 1 ||
|
|
1634
|
+
wallTimeMs > 3600000
|
|
1635
|
+
) {
|
|
1636
|
+
throw this._sandboxBoundaryError(
|
|
1637
|
+
"invalid_wall_time_limit",
|
|
1638
|
+
"Native wall-time limit must be an integer from 1 to 3600000 milliseconds",
|
|
1639
|
+
);
|
|
1640
|
+
}
|
|
1641
|
+
if (!requiredBoundaries.includes(SANDBOX_BOUNDARIES.RESOURCE_LIMITS)) {
|
|
1642
|
+
requiredBoundaries.push(SANDBOX_BOUNDARIES.RESOURCE_LIMITS);
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
const windowsNativeEvaluator =
|
|
1646
|
+
rawPolicy?.windowsNativeEvaluator === undefined
|
|
1647
|
+
? null
|
|
1648
|
+
: consumeWindowsNativeEvaluatorPolicy(
|
|
1649
|
+
rawPolicy.windowsNativeEvaluator,
|
|
1650
|
+
launch,
|
|
1651
|
+
options,
|
|
1652
|
+
);
|
|
1653
|
+
if (windowsNativeEvaluator) {
|
|
1654
|
+
for (const boundary of [
|
|
1655
|
+
SANDBOX_BOUNDARIES.FILESYSTEM,
|
|
1656
|
+
SANDBOX_BOUNDARIES.NETWORK,
|
|
1657
|
+
SANDBOX_BOUNDARIES.PROCESS_TREE,
|
|
1658
|
+
SANDBOX_BOUNDARIES.RESOURCE_LIMITS,
|
|
1659
|
+
]) {
|
|
1660
|
+
if (!requiredBoundaries.includes(boundary))
|
|
1661
|
+
requiredBoundaries.push(boundary);
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
return {
|
|
1665
|
+
profile,
|
|
1666
|
+
requiredBoundaries,
|
|
1667
|
+
linuxCgroup,
|
|
1668
|
+
executionContract,
|
|
1669
|
+
...(windowsNativeEvaluator ? { windowsNativeEvaluator } : {}),
|
|
1670
|
+
...(wallTimeMs !== undefined ? { wallTimeMs } : {}),
|
|
1671
|
+
};
|
|
1629
1672
|
}
|
|
1630
1673
|
|
|
1631
1674
|
_stripSandboxControlOptions(options) {
|
|
@@ -3660,6 +3703,12 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
3660
3703
|
...(sandboxPolicy.executionContract
|
|
3661
3704
|
? { executionContract: sandboxPolicy.executionContract }
|
|
3662
3705
|
: {}),
|
|
3706
|
+
...(sandboxPolicy.wallTimeMs !== undefined
|
|
3707
|
+
? { limits: Object.freeze({ wallTimeMs: sandboxPolicy.wallTimeMs }) }
|
|
3708
|
+
: {}),
|
|
3709
|
+
...(sandboxPolicy.windowsNativeEvaluator
|
|
3710
|
+
? { windowsNativeEvaluator: sandboxPolicy.windowsNativeEvaluator }
|
|
3711
|
+
: {}),
|
|
3663
3712
|
});
|
|
3664
3713
|
// Keep the legacy string profile in argument four. The built-in adapter
|
|
3665
3714
|
// reserves argument five for runtime injection, so the typed request is
|
|
@@ -3667,6 +3716,12 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
3667
3716
|
const sandboxAdapter = this._sandboxAdapter;
|
|
3668
3717
|
const applySandboxAdapter = sandboxAdapter.applySandbox;
|
|
3669
3718
|
const builtInSandboxAdapter = applySandboxAdapter === _applySandbox;
|
|
3719
|
+
if (sandboxPolicy.wallTimeMs !== undefined && !builtInSandboxAdapter) {
|
|
3720
|
+
throw this._sandboxBoundaryError(
|
|
3721
|
+
"native_wall_time_adapter_unattested",
|
|
3722
|
+
"Native wall-time enforcement requires the built-in Windows supervisor",
|
|
3723
|
+
);
|
|
3724
|
+
}
|
|
3670
3725
|
// Never dispatch the built-in through a mutable Function property or a
|
|
3671
3726
|
// global reflective helper after consulting an injected adapter getter.
|
|
3672
3727
|
// The lexical import is the identity we checked and the implementation we
|
|
@@ -3690,6 +3745,41 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
3690
3745
|
]);
|
|
3691
3746
|
let plan;
|
|
3692
3747
|
try {
|
|
3748
|
+
if (
|
|
3749
|
+
sandboxPolicy.wallTimeMs !== undefined &&
|
|
3750
|
+
(!rawPlan?.applied ||
|
|
3751
|
+
rawPlan.platform !== "win32" ||
|
|
3752
|
+
![
|
|
3753
|
+
"windows-job-restricted-token",
|
|
3754
|
+
"windows-appcontainer-job-restricted-token",
|
|
3755
|
+
].includes(rawPlan.backend) ||
|
|
3756
|
+
rawPlan.windowsWallTimeMs !== sandboxPolicy.wallTimeMs)
|
|
3757
|
+
) {
|
|
3758
|
+
throw this._sandboxBoundaryError(
|
|
3759
|
+
"native_wall_time_limit_unavailable",
|
|
3760
|
+
`The requested native wall-time limit was not enforced: ${rawPlan?.reason || "unattested_plan"}`,
|
|
3761
|
+
{
|
|
3762
|
+
requiredBoundaries,
|
|
3763
|
+
actualGuarantees: rawPlan?.guarantees || [],
|
|
3764
|
+
sandboxBackend: rawPlan?.backend,
|
|
3765
|
+
sandboxCandidateBackend: rawPlan?.candidateBackend,
|
|
3766
|
+
sandboxRuntimeProbe: rawPlan?.runtimeProbe,
|
|
3767
|
+
sandboxCandidateReason: rawPlan?.reason,
|
|
3768
|
+
},
|
|
3769
|
+
);
|
|
3770
|
+
}
|
|
3771
|
+
if (
|
|
3772
|
+
sandboxPolicy.windowsNativeEvaluator &&
|
|
3773
|
+
(rawPlan.backend !== "windows-appcontainer-job-restricted-token" ||
|
|
3774
|
+
rawPlan.policyAttested !== true ||
|
|
3775
|
+
rawPlan.windowsNativeEvaluatorDigest !==
|
|
3776
|
+
sandboxPolicy.windowsNativeEvaluator.manifestDigest)
|
|
3777
|
+
) {
|
|
3778
|
+
throw this._sandboxBoundaryError(
|
|
3779
|
+
"native_evaluator_plan_unattested",
|
|
3780
|
+
"The staged native evaluator policy was not enforced",
|
|
3781
|
+
);
|
|
3782
|
+
}
|
|
3693
3783
|
plan = this._validateSandboxPlan(rawPlan, {
|
|
3694
3784
|
command,
|
|
3695
3785
|
args: Object.freeze([...(args || [])]),
|
|
@@ -783,6 +783,8 @@ function normalizeSandboxRequest(profileOrRequest, explicitRequest) {
|
|
|
783
783
|
profile,
|
|
784
784
|
requiredBoundaries,
|
|
785
785
|
sync: request.sync === true,
|
|
786
|
+
wallTimeMs: request.limits?.wallTimeMs,
|
|
787
|
+
windowsNativeEvaluator: request.windowsNativeEvaluator || null,
|
|
786
788
|
pty: request.pty === true,
|
|
787
789
|
linuxCgroup: normalizeLinuxCgroupPolicy(request.linuxCgroup),
|
|
788
790
|
executionContract:
|
|
@@ -2106,6 +2108,12 @@ export function applyMacSandbox(
|
|
|
2106
2108
|
reason: "platform_mismatch",
|
|
2107
2109
|
});
|
|
2108
2110
|
}
|
|
2111
|
+
if (sandboxOpts.limits?.wallTimeMs !== undefined) {
|
|
2112
|
+
return createSandboxPlan({
|
|
2113
|
+
...base,
|
|
2114
|
+
reason: "native_wall_time_limit_unsupported",
|
|
2115
|
+
});
|
|
2116
|
+
}
|
|
2109
2117
|
|
|
2110
2118
|
if (
|
|
2111
2119
|
Array.isArray(sandboxOpts.requiredBoundaries) &&
|
|
@@ -4205,10 +4213,14 @@ function windowsAppContainerPolicyDigest({
|
|
|
4205
4213
|
},
|
|
4206
4214
|
job: {
|
|
4207
4215
|
killOnClose: true,
|
|
4216
|
+
wallTimeMs: launchSpec.wallTimeMs,
|
|
4208
4217
|
activeProcessLimit: launchSpec.activeProcessLimit,
|
|
4209
4218
|
cpuSeconds: launchSpec.cpuSeconds,
|
|
4210
4219
|
processMemoryBytes: launchSpec.processMemoryBytes,
|
|
4211
4220
|
},
|
|
4221
|
+
...(launchSpec.nativeEvaluator
|
|
4222
|
+
? { nativeEvaluator: launchSpec.nativeEvaluator }
|
|
4223
|
+
: {}),
|
|
4212
4224
|
execution: {
|
|
4213
4225
|
contractKind: executionContract?.kind || null,
|
|
4214
4226
|
contentSnapshot: snapshotLocks.length > 0,
|
|
@@ -4310,6 +4322,15 @@ export function applyWindowsSandbox(
|
|
|
4310
4322
|
if (runtime.platform !== "win32") {
|
|
4311
4323
|
return unavailablePlan("platform_mismatch");
|
|
4312
4324
|
}
|
|
4325
|
+
const wallTimeMs = sandboxOpts.limits?.wallTimeMs ?? 0;
|
|
4326
|
+
if (
|
|
4327
|
+
sandboxOpts.limits?.wallTimeMs !== undefined &&
|
|
4328
|
+
(!Number.isSafeInteger(wallTimeMs) ||
|
|
4329
|
+
wallTimeMs < 1 ||
|
|
4330
|
+
wallTimeMs > 3600000)
|
|
4331
|
+
) {
|
|
4332
|
+
return unavailablePlan("windows_wall_time_limit_invalid");
|
|
4333
|
+
}
|
|
4313
4334
|
let windowsDirectory;
|
|
4314
4335
|
try {
|
|
4315
4336
|
windowsDirectory = path.win32.resolve(runtime.windowsDir());
|
|
@@ -4499,6 +4520,7 @@ export function applyWindowsSandbox(
|
|
|
4499
4520
|
}
|
|
4500
4521
|
}
|
|
4501
4522
|
const launchSpec = {
|
|
4523
|
+
wallTimeMs,
|
|
4502
4524
|
cpuSeconds: Number(limits.cpu || 0),
|
|
4503
4525
|
processMemoryBytes: Number(
|
|
4504
4526
|
limits.as || (profile === "strict" ? 256 * 1024 * 1024 : 0),
|
|
@@ -4516,6 +4538,9 @@ export function applyWindowsSandbox(
|
|
|
4516
4538
|
windowsHide: invocation.options.windowsHide === true,
|
|
4517
4539
|
workingDirectory: targetWorkingDirectory,
|
|
4518
4540
|
environment: targetEnvironment,
|
|
4541
|
+
...(sandboxOpts.windowsNativeEvaluator
|
|
4542
|
+
? { nativeEvaluator: sandboxOpts.windowsNativeEvaluator }
|
|
4543
|
+
: {}),
|
|
4519
4544
|
};
|
|
4520
4545
|
if (entrySnapshot.locks) {
|
|
4521
4546
|
launchSpec.launchPathLocks = entrySnapshot.locks;
|
|
@@ -4917,6 +4942,9 @@ export function applyWindowsSandbox(
|
|
|
4917
4942
|
policyAttested: requiresAppContainer ? true : null,
|
|
4918
4943
|
policyDigest: appContainerPolicyDigest,
|
|
4919
4944
|
adapterTempRootAttestation: adapterSource.tempRootAttestation,
|
|
4945
|
+
windowsWallTimeMs: wallTimeMs || null,
|
|
4946
|
+
windowsNativeEvaluatorDigest:
|
|
4947
|
+
sandboxOpts.windowsNativeEvaluator?.manifestDigest || null,
|
|
4920
4948
|
runtimeProbe: entrySnapshotRuntimeProbe,
|
|
4921
4949
|
guarantees: [
|
|
4922
4950
|
...(requiresAppContainer
|
|
@@ -8896,6 +8924,13 @@ export function applyLinuxSandbox(
|
|
|
8896
8924
|
});
|
|
8897
8925
|
}
|
|
8898
8926
|
|
|
8927
|
+
if (sandboxOpts.limits?.wallTimeMs !== undefined) {
|
|
8928
|
+
return createSandboxPlan({
|
|
8929
|
+
...base,
|
|
8930
|
+
reason: "native_wall_time_limit_unsupported",
|
|
8931
|
+
});
|
|
8932
|
+
}
|
|
8933
|
+
|
|
8899
8934
|
const { limits = {} } = sandboxOpts;
|
|
8900
8935
|
const requiredBoundaries = Array.isArray(sandboxOpts.requiredBoundaries)
|
|
8901
8936
|
? sandboxOpts.requiredBoundaries
|
|
@@ -9984,7 +10019,14 @@ export function applySandbox(
|
|
|
9984
10019
|
pty: sandboxRequest.pty,
|
|
9985
10020
|
linuxCgroup: sandboxRequest.linuxCgroup,
|
|
9986
10021
|
executionContract: sandboxRequest.executionContract,
|
|
10022
|
+
windowsNativeEvaluator: sandboxRequest.windowsNativeEvaluator,
|
|
9987
10023
|
};
|
|
10024
|
+
if (sandboxRequest.wallTimeMs !== undefined) {
|
|
10025
|
+
profile.limits = {
|
|
10026
|
+
...profile.limits,
|
|
10027
|
+
wallTimeMs: sandboxRequest.wallTimeMs,
|
|
10028
|
+
};
|
|
10029
|
+
}
|
|
9988
10030
|
|
|
9989
10031
|
const applyRequestedLinuxCgroup = (plan) =>
|
|
9990
10032
|
applyLinuxCgroupV2ToPlan(plan, sandboxRequest.linuxCgroup, {
|