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.
Files changed (172) hide show
  1. package/README.md +9 -7
  2. package/package.json +3 -3
  3. package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
  4. package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
  5. package/src/assets/web-panel/assets/{AIOps-CZzXRe1-.js → AIOps-DgV7xb8F.js} +1 -1
  6. package/src/assets/web-panel/assets/{ActionButton-_AZfbW1Q.js → ActionButton-CgANpkKu.js} +1 -1
  7. package/src/assets/web-panel/assets/{Analytics-CzaUx_wv.js → Analytics-DnvpX7RB.js} +3 -3
  8. package/src/assets/web-panel/assets/{AppLayout-xHEeeD-m.js → AppLayout-C2bHccBM.js} +4 -4
  9. package/src/assets/web-panel/assets/{Artifacts-DmTbtudE.js → Artifacts-BIhijC9g.js} +1 -1
  10. package/src/assets/web-panel/assets/{Audit-Cn4ng4fo.js → Audit-CKRjWGdp.js} +1 -1
  11. package/src/assets/web-panel/assets/{BackgroundAgents-DLUY1VD2.js → BackgroundAgents-CblYtgBE.js} +1 -1
  12. package/src/assets/web-panel/assets/{Backup-B2v--wB6.js → Backup-Cq35b78a.js} +1 -1
  13. package/src/assets/web-panel/assets/{BaseInput-Bgih7yAv.js → BaseInput-DcB7NoRz.js} +1 -1
  14. package/src/assets/web-panel/assets/{Chat-1MiiA3yA.js → Chat-tc3b-s7i.js} +5 -5
  15. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CPLynmbb.js → ChatBubbleRenderer-fcc_Tvqu.js} +1 -1
  16. package/src/assets/web-panel/assets/{Checkbox-DsyBa_NO.js → Checkbox-BLD5bH5u.js} +1 -1
  17. package/src/assets/web-panel/assets/{Codegen-B7WCFx9H.js → Codegen-BLOsoazN.js} +1 -1
  18. package/src/assets/web-panel/assets/{Col-D2x4GBGm.js → Col-Bdr7JwIx.js} +1 -1
  19. package/src/assets/web-panel/assets/{Community-Rnwg9nea.js → Community-C84BsWE0.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compact-BPczlrRh.js → Compact-Dzdwd04z.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compliance-Br1L_wGU.js → Compliance-CCG-R0EV.js} +1 -1
  22. package/src/assets/web-panel/assets/{Cowork-DlsWB_oS.js → Cowork-BYj72SK0.js} +3 -3
  23. package/src/assets/web-panel/assets/{Cron-BWo_KGpG.js → Cron-B6iKAwOf.js} +2 -2
  24. package/src/assets/web-panel/assets/{Crosschain-Cug7N8ge.js → Crosschain-BJ-oDC6u.js} +1 -1
  25. package/src/assets/web-panel/assets/{DID-CMbyOZJN.js → DID-BnMckGLr.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dashboard-C4dl_UaE.js → Dashboard-Cyje-gCO.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dropdown-CBrC7M-9.js → Dropdown-BpNlenjK.js} +1 -1
  28. package/src/assets/web-panel/assets/{EmailListRenderer-DTq7tU4b.js → EmailListRenderer-BhonO7Nv.js} +1 -1
  29. package/src/assets/web-panel/assets/{EvolutionSettings-DWP3csxS.js → EvolutionSettings-DVoNU-Id.js} +1 -1
  30. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DZl7zuv_.js → FamilyGuardDashboard-tdn-KC67.js} +1 -1
  31. package/src/assets/web-panel/assets/{Federation-W-GSlVK5.js → Federation--EEVrHhz.js} +1 -1
  32. package/src/assets/web-panel/assets/{FormItemContext-DMB7xYFV.js → FormItemContext-Cy8zr0-4.js} +1 -1
  33. package/src/assets/web-panel/assets/{GenericCardRenderer-DNv8GEoq.js → GenericCardRenderer-BuUhpgFi.js} +1 -1
  34. package/src/assets/web-panel/assets/{Git-BZ0Bbzw6.js → Git-Ctd3E5Pe.js} +2 -2
  35. package/src/assets/web-panel/assets/{Governance-BNEdcOM5.js → Governance-Ce7dV6aU.js} +1 -1
  36. package/src/assets/web-panel/assets/{Inference-C8249gIz.js → Inference-CD1vExIH.js} +1 -1
  37. package/src/assets/web-panel/assets/{KnowledgeGraph-ngzebU3e.js → KnowledgeGraph-Dn64OdQ7.js} +1 -1
  38. package/src/assets/web-panel/assets/{Logs-CP15th-f.js → Logs-PmElVRrT.js} +2 -2
  39. package/src/assets/web-panel/assets/{MarkdownRenderer-CW3B3JDq.js → MarkdownRenderer-BFiVKf5t.js} +1 -1
  40. package/src/assets/web-panel/assets/{Marketplace-CaH59OsY.js → Marketplace-OW4jTXwx.js} +1 -1
  41. package/src/assets/web-panel/assets/{McpTools-C07vnJev.js → McpTools-BEq2Ib4x.js} +3 -3
  42. package/src/assets/web-panel/assets/{Memory-CqAOkVAS.js → Memory-Can_P2oK.js} +2 -2
  43. package/src/assets/web-panel/assets/{MobileBridge-qp7mZimq.js → MobileBridge-DJ8R-dn3.js} +1 -1
  44. package/src/assets/web-panel/assets/{MobileProjects-DKhbqvTw.js → MobileProjects-B7kV9GOt.js} +1 -1
  45. package/src/assets/web-panel/assets/{Mtc-CRYCnWXv.js → Mtc-BfxamolS.js} +4 -4
  46. package/src/assets/web-panel/assets/{MtcAudit-Z08IrKws.js → MtcAudit-DHtuv7av.js} +4 -4
  47. package/src/assets/web-panel/assets/{Multisig-BWdatUnH.js → Multisig-DLkLpvxc.js} +3 -3
  48. package/src/assets/web-panel/assets/{NLProgramming-BKWiCZ_m.js → NLProgramming-u4XtJTIt.js} +1 -1
  49. package/src/assets/web-panel/assets/{Notes-Bgpzk3sm.js → Notes-BwuuPJLS.js} +3 -3
  50. package/src/assets/web-panel/assets/{NotificationSettings-DvtZEktR.js → NotificationSettings-HEeu-E9v.js} +1 -1
  51. package/src/assets/web-panel/assets/{OrderTableRenderer-CBcy0szc.js → OrderTableRenderer-BtvN-Qwh.js} +1 -1
  52. package/src/assets/web-panel/assets/{Organization-DRRL6vW1.js → Organization-Yh-czs3b.js} +4 -4
  53. package/src/assets/web-panel/assets/{Overflow-COmfB8Ns.js → Overflow-DmE8mYVM.js} +1 -1
  54. package/src/assets/web-panel/assets/{P2P-BqMq_DSa.js → P2P-CWVck8WN.js} +2 -2
  55. package/src/assets/web-panel/assets/PdhVaultBrowser-DgFqekod.js +7 -0
  56. package/src/assets/web-panel/assets/{Permissions-DzYkjmV_.js → Permissions-BtJBVOHV.js} +4 -4
  57. package/src/assets/web-panel/assets/{PersonalDataHub-BBTcxBbN.js → PersonalDataHub-6VBObXzd.js} +4 -4
  58. package/src/assets/web-panel/assets/{Pipeline-eRkYFSbO.js → Pipeline-D222FmqY.js} +1 -1
  59. package/src/assets/web-panel/assets/{Privacy-Ch7IFKBh.js → Privacy-Bi9FMikp.js} +1 -1
  60. package/src/assets/web-panel/assets/{ProjectInit-Ci8EcBYg.js → ProjectInit-Bo52H47H.js} +2 -2
  61. package/src/assets/web-panel/assets/{ProjectSettings-B4lYHFbI.js → ProjectSettings-BPkesfOc.js} +2 -2
  62. package/src/assets/web-panel/assets/{Projects-zkE5cCo_.js → Projects-GynohSFX.js} +1 -1
  63. package/src/assets/web-panel/assets/{Providers-BKDVD3_e.js → Providers-DVdMg04n.js} +1 -1
  64. package/src/assets/web-panel/assets/{QrScannerModal-BromrHlf.js → QrScannerModal-DqJCb595.js} +1 -1
  65. package/src/assets/web-panel/assets/{QuickAsk-CCgoY1gR.js → QuickAsk-J7loQbXi.js} +1 -1
  66. package/src/assets/web-panel/assets/{Recommend-DCPZvpq7.js → Recommend-BI5aURVc.js} +1 -1
  67. package/src/assets/web-panel/assets/{RemoteSession-DPnFP8HU.js → RemoteSession-BN2sqGvz.js} +3 -3
  68. package/src/assets/web-panel/assets/{Reputation-l6r8ytAs.js → Reputation-BGOND-Fi.js} +1 -1
  69. package/src/assets/web-panel/assets/{Row-ke9Mk1cx.js → Row-77dfwaUk.js} +1 -1
  70. package/src/assets/web-panel/assets/{RssFeed-DQOEzUEn.js → RssFeed-FtBAxS3g.js} +2 -2
  71. package/src/assets/web-panel/assets/{Search-BqgA0aUz.js → Search-BaYVLFb7.js} +1 -1
  72. package/src/assets/web-panel/assets/{Security-FeGD_jqV.js → Security-LE3Vv6ab.js} +3 -3
  73. package/src/assets/web-panel/assets/{Services-4kiYYAjZ.js → Services-C5pP-Whz.js} +2 -2
  74. package/src/assets/web-panel/assets/{Skeleton-BbU8Xegs.js → Skeleton-CLqKUVsF.js} +1 -1
  75. package/src/assets/web-panel/assets/{Skills-Dl2bUMUL.js → Skills-BPjN0SX5.js} +1 -1
  76. package/src/assets/web-panel/assets/{Sla-xRGALeaZ.js → Sla-14jD70kg.js} +1 -1
  77. package/src/assets/web-panel/assets/{SpeechSettings-DZfd4RDm.js → SpeechSettings-Dr9ij42W.js} +1 -1
  78. package/src/assets/web-panel/assets/{SyncSettings-BRtCV9Ga.js → SyncSettings-BzLHP7B8.js} +2 -2
  79. package/src/assets/web-panel/assets/{Tasks-DVRQklfG.js → Tasks-YqV9b0rV.js} +1 -1
  80. package/src/assets/web-panel/assets/{Templates-BbhE5jt5.js → Templates-CxxAE4PK.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tenant-qXPDNKbK.js → Tenant-CRb3PcKJ.js} +1 -1
  82. package/src/assets/web-panel/assets/{Terminal-CV48Ks7E.js → Terminal-CTzPpBaP.js} +2 -2
  83. package/src/assets/web-panel/assets/{TimelineRenderer-BLGfJIDr.js → TimelineRenderer-DjFUj_hy.js} +1 -1
  84. package/src/assets/web-panel/assets/{Tokens-7G9H6Hrt.js → Tokens-Bbb8tPvx.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trigger--F64N11F.js → Trigger-CSeWGM0W.js} +1 -1
  86. package/src/assets/web-panel/assets/{Trust-Cq1r-D_y.js → Trust-JgESMBo3.js} +1 -1
  87. package/src/assets/web-panel/assets/{UkeySign-Dqyu4RVh.js → UkeySign-CiObLk0T.js} +1 -1
  88. package/src/assets/web-panel/assets/{VideoEditing-DuFmWH_B.js → VideoEditing-CFEZaQ2x.js} +1 -1
  89. package/src/assets/web-panel/assets/{Wallet-C3mg7EWP.js → Wallet-DR8ZGDNn.js} +4 -4
  90. package/src/assets/web-panel/assets/{WebAuthn-CDK-Aj_X.js → WebAuthn-DxZukvu7.js} +5 -5
  91. package/src/assets/web-panel/assets/{WorkflowEditor--K7K-T1F.js → WorkflowEditor-CKgSZQwn.js} +1 -1
  92. package/src/assets/web-panel/assets/{chat-BQDcS6VP.js → chat-CTxEQE66.js} +1 -1
  93. package/src/assets/web-panel/assets/{colors-BKxJL2-T.js → colors-CAjKMUu3.js} +1 -1
  94. package/src/assets/web-panel/assets/{compact-item-CFjQAMbY.js → compact-item-BXuz49at.js} +1 -1
  95. package/src/assets/web-panel/assets/{createContext-DbgCsdQd.js → createContext-CFN_Hwr9.js} +1 -1
  96. package/src/assets/web-panel/assets/devWarning-CfB8DxT2.js +1 -0
  97. package/src/assets/web-panel/assets/{hasIn-BhkaOBNv.js → hasIn-BwoSBSfP.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-D-Yh3-1z.js → index-B0QbLlWn.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-BfGGsAU7.js → index-B2o_BBjg.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-CoOu7sdP.js → index-B2tEnBPx.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-BRqlCTrz.js → index-B7kp-zRE.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-CB4oHynY.js → index-B9yR7zqr.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DEwHywz9.js → index-BK4ftQ4d.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-Du_SxxBY.js → index-Bj4hIiLW.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-DFt48Z-x.js → index-BmQITjMU.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-DdcrixaQ.js → index-BmXpdcHI.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-BuWPqSGT.js → index-Bqv_Cray.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DmYK9Tqt.js → index-Bu2P6u8m.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-T9ka3Xj3.js → index-Bw9s2d3c.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-COGy6wXn.js → index-C8er4W9u.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-sKfUUldY.js → index-CB3kVd9c.js} +1 -1
  112. package/src/assets/web-panel/assets/index-CCsRfd0k.js +1 -0
  113. package/src/assets/web-panel/assets/{index-Dhfa_BIl.js → index-CF9lWi1o.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-CRtUDiXx.js → index-CN53dE_u.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-D2Zb-Kd1.js → index-CSmFby3Q.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-DP1NrM9J.js → index-CehdwJ_Q.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-aPdVzagA.js → index-Cgk0YEiq.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-3YutaXnp.js → index-Cp5y7lX_.js} +1 -1
  119. package/src/assets/web-panel/assets/index-CsmiZIQ4.js +1 -0
  120. package/src/assets/web-panel/assets/{index-C0DzhUOX.js → index-DTX9CJPx.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-bMX8BBLE.js → index-DViK2bkv.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-Dn2QSsuI.js → index-DY-gBSm8.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-BNjYPJNU.js → index-DjF5BOZx.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-CE506mgj.js → index-DmkbAADP.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-De7daEnc.js → index-DpdDnZX_.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-3uR0ThJO.js → index-Dv7V2kg6.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-CUs7XpUO.js → index-DxunxaTw.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-3djsY75k.js → index-F2E5RCwz.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-D9sVcw6v.js → index-IY9bd5az.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-DJ2OiRvh.js → index-IahILygB.js} +3 -3
  131. package/src/assets/web-panel/assets/{index-DjmVlpap.js → index-T3MTE6jB.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-CSUDlsIr.js → index-Tz5dheZa.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-B4LlAJqc.js → index-_ZtCyUdz.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-CJoXgJ2N.js → index-o9DpkZKf.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-7BY44UEv.js → index-t2Ch_JKn.js} +1 -1
  136. package/src/assets/web-panel/assets/{index-DvWWFJHJ.js → index-u9_DM3ZC.js} +1 -1
  137. package/src/assets/web-panel/assets/{initDefaultProps-wrqabmui.js → initDefaultProps-BoiGJDoO.js} +1 -1
  138. package/src/assets/web-panel/assets/{motion-BoyB3ilP.js → motion-5eL4E0pA.js} +1 -1
  139. package/src/assets/web-panel/assets/{move-Cq31cSFE.js → move-DjggDi_1.js} +1 -1
  140. package/src/assets/web-panel/assets/{mtc-parser-BkxNt-8H.js → mtc-parser-Ce8Vo2T3.js} +1 -1
  141. package/src/assets/web-panel/assets/{omit-DofGni53.js → omit-D1yOBaO2.js} +1 -1
  142. package/src/assets/web-panel/assets/{pickAttrs-BnluLL16.js → pickAttrs-8NLceQe8.js} +1 -1
  143. package/src/assets/web-panel/assets/{placementArrow-C-yegJSP.js → placementArrow-CsIdBRmQ.js} +1 -1
  144. package/src/assets/web-panel/assets/{responsiveObserve-CD3ziNhu.js → responsiveObserve-GM5NE8En.js} +1 -1
  145. package/src/assets/web-panel/assets/{slide-ToZO4gQ1.js → slide-44yj3u49.js} +1 -1
  146. package/src/assets/web-panel/assets/{statusUtils-DFVmDmVl.js → statusUtils-B8tqtWcX.js} +1 -1
  147. package/src/assets/web-panel/assets/{styleChecker-De0Y8g1O.js → styleChecker-NhDPBbyB.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFlexGapSupport-wBKIYFKX.js → useFlexGapSupport-C8Qz1GtN.js} +1 -1
  149. package/src/assets/web-panel/assets/{useFs-CP9nmUMJ.js → useFs-ClUv4kih.js} +1 -1
  150. package/src/assets/web-panel/assets/{usePersonalDataHub-vFGrVDyp.js → usePersonalDataHub-BwkOVEh6.js} +1 -1
  151. package/src/assets/web-panel/assets/{vnode-BcBIjvjH.js → vnode--gMF33R0.js} +1 -1
  152. package/src/assets/web-panel/assets/{zoom-DnXDAQxA.js → zoom-DXg3TqOP.js} +1 -1
  153. package/src/assets/web-panel/index.html +1 -1
  154. package/src/command-help-index.json +1 -1
  155. package/src/commands/agent-process-ownership.js +121 -0
  156. package/src/commands/agent.js +2 -0
  157. package/src/commands/hub.js +86 -9
  158. package/src/data/changelog.json +15 -2
  159. package/src/lib/audit-logger.js +46 -20
  160. package/src/lib/checkpoint-restore-saga.js +11 -1
  161. package/src/lib/eval/verify01-host-evidence.js +36 -3
  162. package/src/lib/process-execution-broker/index.js +91 -1
  163. package/src/lib/process-execution-broker/platform-sandbox.js +42 -0
  164. package/src/lib/process-execution-broker/windows-native-evaluator-capabilities.js +757 -0
  165. package/src/lib/process-execution-broker/windows-native-evaluator.js +316 -0
  166. package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
  167. package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
  168. package/src/lib/process-execution-broker/windows-sandbox.cs +383 -11
  169. package/src/assets/web-panel/assets/PdhVaultBrowser-BX7iNvle.js +0 -7
  170. package/src/assets/web-panel/assets/devWarning-DlIv9Mbc.js +0 -1
  171. package/src/assets/web-panel/assets/index-BC972Grv.js +0 -1
  172. package/src/assets/web-panel/assets/index-CVifyQqL.js +0 -1
@@ -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 (operation === "prune" && options.confirm !== true) {
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 hub = await (options._getHub || getHub)();
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 = hub.vault.getDerivationStore().listConsumers({
3490
- state: options.state,
3491
- kind: options.kind,
3492
- afterConsumerId: options.after,
3493
- limit,
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.consumerId,
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
 
@@ -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": null,
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
  },
@@ -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 = sanitizeDetails(value);
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 = sanitizeDetails(event.details);
135
- const risk =
136
- event.riskLevel || assessRisk(event.eventType, event.operation, sanitized);
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 || null,
150
- event.userAgent || null,
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 = sanitizeDetails(details);
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 || null,
520
- userAgent: userAgent || null,
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 (isMissingPathError(cause) && !requireOwner) return null;
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
- outputs.map((record) => JSON.stringify(record.event)).join("\n"),
184
+ taskOutputs.map((record) => JSON.stringify(record.event)).join("\n"),
154
185
  );
155
- const terminal = resultRecords[0].event;
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
- outputs.at(-1) === resultRecords[0] &&
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
- return { profile, requiredBoundaries, linuxCgroup, executionContract };
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, {