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
@@ -0,0 +1,316 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { createHash } from "node:crypto";
5
+
6
+ const issued = new WeakMap();
7
+ const hash = (bytes) => createHash("sha256").update(bytes).digest("hex");
8
+ const MAX_FILE_BYTES = 1024 * 1024;
9
+ const MAX_TOTAL_BYTES = 8 * MAX_FILE_BYTES;
10
+ const MAX_FILES = 64;
11
+ function requireCondition(condition, message) {
12
+ if (!condition) throw new Error(`Windows native evaluator: ${message}`);
13
+ }
14
+ function identity(file, directory = false, maxBytes = MAX_FILE_BYTES) {
15
+ const stat = fs.lstatSync(file, { bigint: true });
16
+ requireCondition(
17
+ !stat.isSymbolicLink() && (directory ? stat.isDirectory() : stat.isFile()),
18
+ "plain paths required",
19
+ );
20
+ if (!directory)
21
+ requireCondition(stat.nlink === 1n, "hard-linked files are forbidden");
22
+ if (!directory)
23
+ requireCondition(stat.size <= BigInt(maxBytes), "file exceeds byte limit");
24
+ requireCondition(
25
+ fs.realpathSync.native(file).toLowerCase() ===
26
+ path.resolve(file).toLowerCase(),
27
+ "path alias forbidden",
28
+ );
29
+ return {
30
+ path: file,
31
+ dev: String(stat.dev),
32
+ ino: String(stat.ino),
33
+ ...(directory
34
+ ? {}
35
+ : { bytes: Number(stat.size), sha256: hash(fs.readFileSync(file)) }),
36
+ };
37
+ }
38
+ function relativeFile(value) {
39
+ requireCondition(
40
+ typeof value === "string" && value.length <= 180,
41
+ "invalid relative file",
42
+ );
43
+ const parts = value.split("/");
44
+ requireCondition(
45
+ parts.length <= 8 &&
46
+ parts.every(
47
+ (part) =>
48
+ /^[A-Za-z0-9_-][A-Za-z0-9_.-]*$/u.test(part) &&
49
+ !part.endsWith(".") &&
50
+ !/^(?:con|prn|aux|nul|com[0-9]|lpt[0-9])(?:\.|$)/iu.test(part),
51
+ ),
52
+ "invalid relative file",
53
+ );
54
+ return parts;
55
+ }
56
+ function snapshotFile(root, relative) {
57
+ const parts = relativeFile(relative);
58
+ let current = root;
59
+ for (const [index, part] of parts.entries()) {
60
+ current = path.join(current, part);
61
+ identity(current, index < parts.length - 1);
62
+ }
63
+ const before = identity(current);
64
+ requireCondition(before.bytes <= MAX_FILE_BYTES, "source file exceeds 1 MiB");
65
+ const bytes = fs.readFileSync(current);
66
+ const after = identity(current);
67
+ requireCondition(
68
+ JSON.stringify(before) === JSON.stringify(after) &&
69
+ hash(bytes) === before.sha256,
70
+ "source changed during capture",
71
+ );
72
+ return bytes;
73
+ }
74
+
75
+ /** Narrow first-stage native evaluator, not a general workspace sandbox.
76
+ * No existing directory can be nominated as its staging or ACL target.
77
+ * Source bytes and the trusted evaluator are copied before any policy exists.
78
+ */
79
+ export function createWindowsNativeEvaluator(options) {
80
+ requireCondition(process.platform === "win32", "Windows host required");
81
+ requireCondition(
82
+ options &&
83
+ Object.keys(options).every((key) =>
84
+ ["sourceRoot", "files", "checkSource", "wallTimeMs"].includes(key),
85
+ ),
86
+ "unknown factory option",
87
+ );
88
+ const { sourceRoot, files, checkSource, wallTimeMs = 10000 } = options;
89
+ requireCondition(
90
+ Number.isSafeInteger(wallTimeMs) &&
91
+ wallTimeMs >= 1 &&
92
+ wallTimeMs <= 3600000,
93
+ "invalid wall-time limit",
94
+ );
95
+ requireCondition(
96
+ Array.isArray(files) && files.length > 0 && files.length <= MAX_FILES,
97
+ "expected 1..64 source files",
98
+ );
99
+ requireCondition(
100
+ new Set(files.map((file) => String(file).toLowerCase())).size ===
101
+ files.length,
102
+ "duplicate source file",
103
+ );
104
+ requireCondition(
105
+ typeof checkSource === "string" &&
106
+ Buffer.byteLength(checkSource) > 0 &&
107
+ Buffer.byteLength(checkSource) <= MAX_FILE_BYTES,
108
+ "check must be bounded source bytes",
109
+ );
110
+ const source = path.resolve(sourceRoot);
111
+ identity(source, true);
112
+ const captures = files.map((relative) => ({
113
+ relative,
114
+ bytes: snapshotFile(source, relative),
115
+ }));
116
+ const directoryNames = new Set(["", "workspace", "control", "scratch"]);
117
+ for (const file of files) {
118
+ const parts = relativeFile(file);
119
+ for (let depth = 1; depth < parts.length; depth++)
120
+ directoryNames.add(`workspace/${parts.slice(0, depth).join("/")}`);
121
+ }
122
+ requireCondition(directoryNames.size <= 128, "too many stage directories");
123
+ requireCondition(
124
+ captures.reduce(
125
+ (total, file) => total + file.bytes.length,
126
+ Buffer.byteLength(checkSource),
127
+ ) <= MAX_TOTAL_BYTES,
128
+ "stage exceeds 8 MiB",
129
+ );
130
+ const sourceRuntime = identity(
131
+ fs.realpathSync.native(process.execPath),
132
+ false,
133
+ 128 * MAX_FILE_BYTES,
134
+ );
135
+ const root = fs.mkdtempSync(
136
+ path.join(fs.realpathSync.native(os.tmpdir()), "cc-native-evaluator-"),
137
+ );
138
+ const directories = new Set([root]);
139
+ const ensure = (directory) => {
140
+ if (directories.has(directory)) return;
141
+ ensure(path.dirname(directory));
142
+ fs.mkdirSync(directory, { mode: 0o700 });
143
+ directories.add(directory);
144
+ };
145
+ const workspace = path.join(root, "workspace");
146
+ const control = path.join(root, "control");
147
+ const scratch = path.join(root, "scratch");
148
+ for (const directory of [workspace, control, scratch]) ensure(directory);
149
+ // Copy the runtime too: granting access to a caller-owned installation would
150
+ // widen the ACL change beyond this factory's private stage.
151
+ const runtimePath = path.join(control, "node.exe");
152
+ fs.copyFileSync(sourceRuntime.path, runtimePath, fs.constants.COPYFILE_EXCL);
153
+ const runtime = identity(runtimePath, false, 128 * MAX_FILE_BYTES);
154
+ requireCondition(
155
+ runtime.bytes === sourceRuntime.bytes &&
156
+ runtime.sha256 === sourceRuntime.sha256,
157
+ "runtime changed during capture",
158
+ );
159
+ const stagedFiles = [];
160
+ for (const capture of captures) {
161
+ const target = path.join(workspace, ...relativeFile(capture.relative));
162
+ ensure(path.dirname(target));
163
+ fs.writeFileSync(target, capture.bytes, { flag: "wx", mode: 0o600 });
164
+ stagedFiles.push(identity(target));
165
+ }
166
+ const check = path.join(control, "check.cjs");
167
+ fs.writeFileSync(check, checkSource, { flag: "wx", mode: 0o600 });
168
+ stagedFiles.push(identity(check));
169
+ requireCondition(directories.size <= 128, "too many stage directories");
170
+ const manifest = Object.freeze({
171
+ version: 1,
172
+ root,
173
+ workspace,
174
+ control,
175
+ scratch,
176
+ check,
177
+ wallTimeMs,
178
+ runtime: Object.freeze(runtime),
179
+ directories: Object.freeze(
180
+ [...directories]
181
+ .sort((a, b) => a.length - b.length || a.localeCompare(b))
182
+ .map((directory) => Object.freeze(identity(directory, true))),
183
+ ),
184
+ files: Object.freeze(stagedFiles.map(Object.freeze)),
185
+ });
186
+ const manifestDigest = hash(JSON.stringify(manifest));
187
+ const token = Object.freeze({
188
+ kind: "windows-native-evaluator-v1",
189
+ manifestDigest,
190
+ });
191
+ issued.set(token, { manifest, manifestDigest });
192
+ let attempted = false;
193
+ let settled = false;
194
+ const rootIdentity = identity(root, true);
195
+ return Object.freeze({
196
+ root,
197
+ manifest,
198
+ policy: token,
199
+ manifestDigest,
200
+ async execute() {
201
+ requireCondition(!attempted, "evaluator policy already consumed");
202
+ attempted = true;
203
+ const receiptPath = path.join(root, "settlement.json");
204
+ requireCondition(
205
+ !fs.existsSync(receiptPath),
206
+ "pre-existing settlement forbidden",
207
+ );
208
+ const { executionBroker } = await import("./index.js");
209
+ const result = executionBroker.spawnSync(
210
+ runtime.path,
211
+ [
212
+ "--preserve-symlinks",
213
+ "--preserve-symlinks-main",
214
+ check,
215
+ workspace,
216
+ scratch,
217
+ ],
218
+ {
219
+ cwd: scratch,
220
+ shell: false,
221
+ windowsHide: true,
222
+ encoding: "utf8",
223
+ timeout: wallTimeMs + 180000,
224
+ maxBuffer: 8 * 1024 * 1024,
225
+ env: {
226
+ SystemRoot: process.env.SystemRoot,
227
+ WINDIR: process.env.WINDIR,
228
+ PATH: path.dirname(runtime.path),
229
+ },
230
+ origin: "native-evaluator:check",
231
+ scope: "private-staged-evaluator",
232
+ policy: "allow",
233
+ sandboxPolicy: {
234
+ profile: "default",
235
+ requiredBoundaries: [
236
+ "filesystem",
237
+ "network",
238
+ "process-tree",
239
+ "resource-limits",
240
+ ],
241
+ limits: { wallTimeMs },
242
+ windowsNativeEvaluator: token,
243
+ },
244
+ },
245
+ );
246
+ let receiptIdentity;
247
+ try {
248
+ receiptIdentity = identity(receiptPath);
249
+ } catch (cause) {
250
+ const error = new Error(
251
+ `Windows native evaluator: native settlement unavailable; stage retained (${cause.message}); supervisor status=${result.status}, signal=${result.signal}, error=${result.error?.message || "none"}, stderr=${String(result.stderr || "").trim()}`,
252
+ { cause },
253
+ );
254
+ error.nativeEvaluator = { result, manifestDigest, stage: root };
255
+ throw error;
256
+ }
257
+ requireCondition(
258
+ receiptIdentity.bytes <= 16384,
259
+ "invalid settlement size",
260
+ );
261
+ const receipt = JSON.parse(fs.readFileSync(receiptPath, "utf8"));
262
+ requireCondition(
263
+ receipt.manifestDigest === manifestDigest &&
264
+ receipt.cleanupConfirmed === true &&
265
+ receipt.capabilityCount === 0 &&
266
+ receipt.loopbackExemptionAbsent === true &&
267
+ /^[a-f0-9]{64}$/u.test(receipt.supervisorUserSidSha256),
268
+ "native settlement unconfirmed; stage retained",
269
+ );
270
+ settled = true;
271
+ return { result, receipt, manifestDigest };
272
+ },
273
+ dispose() {
274
+ requireCondition(
275
+ !attempted || settled,
276
+ "unconfirmed native cleanup; stage retained",
277
+ );
278
+ issued.delete(token);
279
+ requireCondition(
280
+ JSON.stringify(identity(root, true)) === JSON.stringify(rootIdentity),
281
+ "stage root identity changed",
282
+ );
283
+ // The only recursive target is this factory-created, identity-checked root.
284
+ // After execution it is removed only after the native empty-Job fence.
285
+ fs.rmSync(root, { recursive: true });
286
+ },
287
+ });
288
+ }
289
+
290
+ export function consumeWindowsNativeEvaluatorPolicy(token, launch, options) {
291
+ const issuedPolicy = issued.get(token);
292
+ requireCondition(issuedPolicy, "unissued or consumed evaluator policy");
293
+ issued.delete(token);
294
+ const { manifest } = issuedPolicy;
295
+ requireCondition(
296
+ launch.sync === true &&
297
+ launch.command === manifest.runtime.path &&
298
+ JSON.stringify(launch.args) ===
299
+ JSON.stringify([
300
+ "--preserve-symlinks",
301
+ "--preserve-symlinks-main",
302
+ manifest.check,
303
+ manifest.workspace,
304
+ manifest.scratch,
305
+ ]) &&
306
+ path.resolve(options.cwd) === manifest.scratch &&
307
+ options.shell === false &&
308
+ options.detached !== true &&
309
+ options.sandboxPolicy.limits.wallTimeMs === manifest.wallTimeMs,
310
+ "evaluator launch binding mismatch",
311
+ );
312
+ return Object.freeze({
313
+ ...manifest,
314
+ manifestDigest: issuedPolicy.manifestDigest,
315
+ });
316
+ }