chainlesschain 0.166.92 → 0.166.93

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 (174) hide show
  1. package/package.json +3 -3
  2. package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
  3. package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
  4. package/src/assets/web-panel/assets/{AIOps-C74YzqwJ.js → AIOps-oo9rE0gh.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-TFef1hOE.js → ActionButton-CVJVVv4i.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-CYsWpkkU.js → Analytics-CUXuwmia.js} +3 -3
  7. package/src/assets/web-panel/assets/{AppLayout-CFf9kjwu.js → AppLayout-iM4PvCuY.js} +5 -5
  8. package/src/assets/web-panel/assets/{Artifacts-TQqa94YO.js → Artifacts-DKUIJbf9.js} +1 -1
  9. package/src/assets/web-panel/assets/{Audit-B79ayqfS.js → Audit-C4_SzFN2.js} +1 -1
  10. package/src/assets/web-panel/assets/{BackgroundAgents-pjkHfLP9.js → BackgroundAgents-C3427uy-.js} +1 -1
  11. package/src/assets/web-panel/assets/{Backup-CE6A-t_r.js → Backup-BpEQQiog.js} +1 -1
  12. package/src/assets/web-panel/assets/{BaseInput-CwcgWMBY.js → BaseInput-C_exQomZ.js} +1 -1
  13. package/src/assets/web-panel/assets/{Chat-BIkDNesY.js → Chat-DzpkLtWa.js} +6 -6
  14. package/src/assets/web-panel/assets/{ChatBubbleRenderer-DgaokYts.js → ChatBubbleRenderer-DX4XmTWm.js} +1 -1
  15. package/src/assets/web-panel/assets/{Checkbox-MbypIy5V.js → Checkbox-CxAC1CU8.js} +1 -1
  16. package/src/assets/web-panel/assets/{Codegen-DiFHWDnt.js → Codegen-wDFAGCLp.js} +1 -1
  17. package/src/assets/web-panel/assets/{Col-BNMlYMso.js → Col-BvwirhMf.js} +1 -1
  18. package/src/assets/web-panel/assets/{Community-B3HVyHOX.js → Community-BJuA7paY.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compact-C7hlAubb.js → Compact-DzV35_u2.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compliance-PaXZu6sE.js → Compliance-CIDPPvr9.js} +1 -1
  21. package/src/assets/web-panel/assets/{Cowork-BGiojbm-.js → Cowork-DyTMxP3N.js} +3 -3
  22. package/src/assets/web-panel/assets/{Cron-Bmr-1QAx.js → Cron-PcNLjMFx.js} +2 -2
  23. package/src/assets/web-panel/assets/{Crosschain-BwUvWCVd.js → Crosschain-B_O7ck6Z.js} +1 -1
  24. package/src/assets/web-panel/assets/{DID-k_4QZocW.js → DID-CII35Me1.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dashboard-_ieRo2C5.js → Dashboard-DU56fkNz.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dropdown-DYHh6T27.js → Dropdown-DHC8HVeJ.js} +1 -1
  27. package/src/assets/web-panel/assets/{EmailListRenderer-BNlQcWQX.js → EmailListRenderer-oUOHFNsD.js} +1 -1
  28. package/src/assets/web-panel/assets/{EvolutionSettings-DIkZ6U2D.js → EvolutionSettings-D7RCAWNl.js} +1 -1
  29. package/src/assets/web-panel/assets/{FamilyGuardDashboard-Dq7qSr0P.js → FamilyGuardDashboard-CGONPZxC.js} +1 -1
  30. package/src/assets/web-panel/assets/{Federation-C64e3Cbx.js → Federation-BbDlPWcl.js} +1 -1
  31. package/src/assets/web-panel/assets/{FormItemContext-D-GE2vUa.js → FormItemContext-BBJbFQQT.js} +1 -1
  32. package/src/assets/web-panel/assets/{GenericCardRenderer-DO3B2gis.js → GenericCardRenderer-iuxAero4.js} +1 -1
  33. package/src/assets/web-panel/assets/{Git-0ETirIQH.js → Git-Dw0prdY5.js} +2 -2
  34. package/src/assets/web-panel/assets/{Governance-C9fnRygX.js → Governance-DOGqi_uV.js} +1 -1
  35. package/src/assets/web-panel/assets/{Inference-CLJ9RTsK.js → Inference-BY5oUGGj.js} +1 -1
  36. package/src/assets/web-panel/assets/{KnowledgeGraph-D3C_GxrN.js → KnowledgeGraph-CcE2EVYX.js} +1 -1
  37. package/src/assets/web-panel/assets/{Logs-C5ctGbkN.js → Logs-DyfN4R5w.js} +2 -2
  38. package/src/assets/web-panel/assets/MarkdownRenderer-Bj62Aq0M.js +1 -0
  39. package/src/assets/web-panel/assets/{Marketplace-GF_t6hJ_.js → Marketplace-CuuuAXUh.js} +1 -1
  40. package/src/assets/web-panel/assets/{McpTools-BGsGzgQs.js → McpTools-948Fithv.js} +2 -2
  41. package/src/assets/web-panel/assets/{Memory-CcrY2A0j.js → Memory-D4PINvyy.js} +2 -2
  42. package/src/assets/web-panel/assets/{MobileBridge-Bi4T0RlS.js → MobileBridge-ECKMaLzX.js} +1 -1
  43. package/src/assets/web-panel/assets/{MobileProjects-DvjEGyvf.js → MobileProjects-CB5MAcvD.js} +1 -1
  44. package/src/assets/web-panel/assets/{Mtc-DL77Vf-k.js → Mtc-BRzIM3HJ.js} +4 -4
  45. package/src/assets/web-panel/assets/{MtcAudit-CDy_Uswb.js → MtcAudit-CGeAXJGn.js} +2 -2
  46. package/src/assets/web-panel/assets/{Multisig-DL0BAO_c.js → Multisig-C_qJ-8K-.js} +3 -3
  47. package/src/assets/web-panel/assets/{NLProgramming-B-woh5IR.js → NLProgramming-DAEyCn7T.js} +1 -1
  48. package/src/assets/web-panel/assets/{Notes-CEFVCxk7.js → Notes-DmD3MEec.js} +3 -3
  49. package/src/assets/web-panel/assets/{NotificationSettings-BqPPMuAP.js → NotificationSettings-Cv4Q3VC9.js} +1 -1
  50. package/src/assets/web-panel/assets/OrderTableRenderer-BNlpaFjH.js +1 -0
  51. package/src/assets/web-panel/assets/{Organization-B1gX8jlr.js → Organization-DqAFdz6p.js} +2 -2
  52. package/src/assets/web-panel/assets/{Overflow-CeMxuUZy.js → Overflow-8Ye9cIcE.js} +1 -1
  53. package/src/assets/web-panel/assets/{P2P-B5aIRWwJ.js → P2P-755SfHoJ.js} +2 -2
  54. package/src/assets/web-panel/assets/{PdhVaultBrowser-6rYgejd4.js → PdhVaultBrowser-CgZLiucX.js} +4 -4
  55. package/src/assets/web-panel/assets/{Permissions-CqCp2SIl.js → Permissions-C-vFF_rL.js} +3 -3
  56. package/src/assets/web-panel/assets/{PersonalDataHub-BsA7DJWW.js → PersonalDataHub-Diz1oXM3.js} +5 -5
  57. package/src/assets/web-panel/assets/{Pipeline-CiW6HeZh.js → Pipeline-D4kIzsZG.js} +1 -1
  58. package/src/assets/web-panel/assets/{Privacy-DckUOLYq.js → Privacy-QKLkSAUH.js} +1 -1
  59. package/src/assets/web-panel/assets/{ProjectInit-CZppOOYR.js → ProjectInit-I0S9o_RT.js} +2 -2
  60. package/src/assets/web-panel/assets/{ProjectSettings-B9QPzhDU.js → ProjectSettings-DdgV3-Ho.js} +2 -2
  61. package/src/assets/web-panel/assets/{Projects-BErjjGha.js → Projects-BJHHegtj.js} +1 -1
  62. package/src/assets/web-panel/assets/{Providers-DehU6Qiz.js → Providers-uVa1zfbS.js} +1 -1
  63. package/src/assets/web-panel/assets/{QrScannerModal-E1SUvv1m.js → QrScannerModal-YLVpOChR.js} +1 -1
  64. package/src/assets/web-panel/assets/{QuickAsk-COWFxyH3.js → QuickAsk-535AYH61.js} +1 -1
  65. package/src/assets/web-panel/assets/{Recommend-D26pWKxX.js → Recommend-C_P6eNSw.js} +1 -1
  66. package/src/assets/web-panel/assets/{RemoteSession-DCOIaId3.js → RemoteSession-EXH1SbNj.js} +2 -2
  67. package/src/assets/web-panel/assets/{Reputation-DT_AHGAR.js → Reputation-Cxc7d3eU.js} +1 -1
  68. package/src/assets/web-panel/assets/{Row-B50S-1nl.js → Row-EDqJy-wS.js} +1 -1
  69. package/src/assets/web-panel/assets/{RssFeed-BaBnHg3Q.js → RssFeed-C03Xeg9_.js} +2 -2
  70. package/src/assets/web-panel/assets/{Search-BVdnLuuS.js → Search-DsIga9DK.js} +1 -1
  71. package/src/assets/web-panel/assets/{Security-BnacH74J.js → Security-DgArMFc-.js} +3 -3
  72. package/src/assets/web-panel/assets/{Services-CxM08Zch.js → Services-MooDpHBP.js} +2 -2
  73. package/src/assets/web-panel/assets/{Skeleton-DE7CIc1N.js → Skeleton-B10P1Dr6.js} +1 -1
  74. package/src/assets/web-panel/assets/{Skills-CGI0SJmf.js → Skills-DHLHEkLl.js} +1 -1
  75. package/src/assets/web-panel/assets/{Sla-DpEzPcqc.js → Sla-D4RT7d4g.js} +1 -1
  76. package/src/assets/web-panel/assets/{SpeechSettings-CTmnmMHn.js → SpeechSettings-D8u6F-LV.js} +1 -1
  77. package/src/assets/web-panel/assets/{SyncSettings-Dxgrd9hd.js → SyncSettings-4nvNzRq8.js} +2 -2
  78. package/src/assets/web-panel/assets/{Tasks-CW4slS0A.js → Tasks-CmCb8zNO.js} +1 -1
  79. package/src/assets/web-panel/assets/{Templates-DxvGWDgB.js → Templates-CzESIa21.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tenant-_Q0o2tNK.js → Tenant-Ch_N3p4d.js} +1 -1
  81. package/src/assets/web-panel/assets/{Terminal-BTZn8pow.js → Terminal-BZccUf_X.js} +2 -2
  82. package/src/assets/web-panel/assets/{TimelineRenderer-CauL0KFe.js → TimelineRenderer-FrKcNy_3.js} +1 -1
  83. package/src/assets/web-panel/assets/{Tokens-CDoM2qeT.js → Tokens-4xvLpXfD.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trigger-B-QYGEU7.js → Trigger-84UjyxXd.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trust-BD6XJHT-.js → Trust-M6UtHnji.js} +1 -1
  86. package/src/assets/web-panel/assets/{UkeySign-x4TFwCy0.js → UkeySign-L_xEgtCg.js} +1 -1
  87. package/src/assets/web-panel/assets/{VideoEditing-t3imBK_0.js → VideoEditing-BLJCX9ru.js} +1 -1
  88. package/src/assets/web-panel/assets/{Wallet-BCfkWwNC.js → Wallet-DwL6uJCj.js} +4 -4
  89. package/src/assets/web-panel/assets/{WebAuthn-WH314Mdm.js → WebAuthn-Bmn9pdzz.js} +5 -5
  90. package/src/assets/web-panel/assets/{WorkflowEditor-jUlcjrUg.js → WorkflowEditor-DSsZ5xG1.js} +1 -1
  91. package/src/assets/web-panel/assets/{chat-Dg3VASTL.js → chat--FGNUaa8.js} +1 -1
  92. package/src/assets/web-panel/assets/{colors-BNvmBRKE.js → colors-DeuwNdqX.js} +1 -1
  93. package/src/assets/web-panel/assets/{compact-item-BGOfoqf4.js → compact-item-I4XKxRFU.js} +1 -1
  94. package/src/assets/web-panel/assets/{createContext-BNQeqKAs.js → createContext-RoD2p5Ba.js} +1 -1
  95. package/src/assets/web-panel/assets/devWarning-ctnml4IW.js +1 -0
  96. package/src/assets/web-panel/assets/{hasIn-Bg3AjCrq.js → hasIn-BsvyddUM.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-D6UqK83L.js → index-0tRU1Sv-.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-uH2LnAs_.js → index-4xHc2WjT.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-xzaUx19r.js → index-B8-eGLN9.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DYn5DnDk.js → index-BS_uqSTa.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-DO0VlNtc.js → index-BYEVBlCl.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-DF_FKSVH.js → index-BcBM065G.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-CY8cRKHR.js → index-BnrL4s-3.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-COol3xfA.js → index-BrZPb0On.js} +1 -1
  105. package/src/assets/web-panel/assets/index-C7PN8mh1.js +1 -0
  106. package/src/assets/web-panel/assets/{index-BBCMulQ-.js → index-CBazK4-7.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-OUFoxUgH.js → index-CPS3zv1c.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-60AnjUTX.js → index-CSrZiiAs.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-D072oLjp.js → index-CVwZMt9Z.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-D_O2ZjPk.js → index-CdgKZYgm.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-DcCnO0RU.js → index-CesTu01s.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-7QJUWemf.js → index-CiHlSuMl.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-DS04wRll.js → index-CsLVac9n.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-Dkp-okWa.js → index-D1ONyBTW.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-BmTacaQV.js → index-D4IZsKbF.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-BaPvEvB4.js → index-D4P4vpmv.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-Co_LnCWD.js → index-D6J8dz7X.js} +1 -1
  118. package/src/assets/web-panel/assets/{index--I3UF5t1.js → index-DChy2sHE.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-B0mgngoB.js → index-DKUCl_Lk.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-Cx2EXRfr.js → index-DRluW3_r.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-B_JmInC0.js → index-DWUmhNO-.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-DLwEXRrb.js → index-DXnpVGG3.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-fOwii3LP.js → index-DYOpAS6-.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-ZD5Kd8tx.js → index-DiH-3cR2.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-D-mSvCQK.js → index-DlEfwgzr.js} +1 -1
  126. package/src/assets/web-panel/assets/index-KnbBJAO-.js +1 -0
  127. package/src/assets/web-panel/assets/{index-B--0QM0S.js → index-R4St_zjR.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-CCFZN66A.js → index-ScgoDU9V.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-BSNhW95G.js → index-UWdT_lty.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-Cbp-wp-U.js → index-VAlor744.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-Bkz1tgFR.js → index-Wco_uvRo.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-pVdQieac.js → index-ZgFED_Zd.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-2D04Zltx.js → index-jaHeti4i.js} +3 -3
  134. package/src/assets/web-panel/assets/{index-hG7jXGEW.js → index-rJDabtw4.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-Wo0f2iqb.js → index-vRiGKIP0.js} +1 -1
  136. package/src/assets/web-panel/assets/{initDefaultProps-B8PN9AxJ.js → initDefaultProps-BHT0PacY.js} +1 -1
  137. package/src/assets/web-panel/assets/{motion-BHivfw5Q.js → motion-CBYsMtsC.js} +1 -1
  138. package/src/assets/web-panel/assets/{move-B0QU5nDd.js → move-DnHfFV4K.js} +1 -1
  139. package/src/assets/web-panel/assets/{mtc-parser-DRwRM3PE.js → mtc-parser-DfGkRYrx.js} +1 -1
  140. package/src/assets/web-panel/assets/{omit-SHt2rV2p.js → omit-SjLcPQA9.js} +1 -1
  141. package/src/assets/web-panel/assets/{pickAttrs-CcmDlEb2.js → pickAttrs-CCZHF4ep.js} +1 -1
  142. package/src/assets/web-panel/assets/{placementArrow-DYatmXDS.js → placementArrow-DjCGn2sJ.js} +1 -1
  143. package/src/assets/web-panel/assets/{responsiveObserve-B7qrsXq5.js → responsiveObserve-BCFCl2on.js} +1 -1
  144. package/src/assets/web-panel/assets/{slide-BRGhlOWd.js → slide-DsfmuIZu.js} +1 -1
  145. package/src/assets/web-panel/assets/{statusUtils-CT-7NXsQ.js → statusUtils-hPKuJUia.js} +1 -1
  146. package/src/assets/web-panel/assets/{styleChecker-rZdw_Yyp.js → styleChecker-DOXKH7Kf.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFlexGapSupport-D8YNIP4P.js → useFlexGapSupport-B_G7yqio.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFs-B8pt0Gu-.js → useFs-BXOTOm2l.js} +1 -1
  149. package/src/assets/web-panel/assets/{usePersonalDataHub-VMmYM1tt.js → usePersonalDataHub-CRvie3g7.js} +1 -1
  150. package/src/assets/web-panel/assets/{vnode-UNDuoPoq.js → vnode-D9_zMmww.js} +1 -1
  151. package/src/assets/web-panel/assets/{zoom-dN-u667S.js → zoom-C4tW03qI.js} +1 -1
  152. package/src/assets/web-panel/index.html +1 -1
  153. package/src/data/changelog.json +13 -0
  154. package/src/lib/artifact-store.js +51 -3
  155. package/src/lib/bounded-artifact-file-read.js +131 -0
  156. package/src/lib/evolution/evolution-artifact-ports.js +209 -129
  157. package/src/lib/evolution/rrsi-history-ledger-adapter.js +25 -0
  158. package/src/lib/evolution/rrsi-installation-route-contracts.js +275 -0
  159. package/src/lib/evolution/rrsi-installation-route-reader.js +282 -0
  160. package/src/lib/evolution/rrsi-observed-text-index.js +978 -0
  161. package/src/lib/evolution/rrsi-registry-runtime-policy.js +648 -0
  162. package/src/lib/evolution/rrsi-registry-store-policy.js +95 -15
  163. package/src/lib/evolution/rrsi-tenant-index-anchor-contracts.js +223 -0
  164. package/src/lib/evolution/rrsi-tenant-index-anchor-history.js +157 -0
  165. package/src/lib/evolution/skill-release-registry.js +20 -5
  166. package/src/lib/process-execution-broker/windows-native-evaluator-capabilities.js +291 -30
  167. package/src/lib/remote-read-loop-guard.js +227 -24
  168. package/src/lib/task-progress-tracker.js +6 -1
  169. package/src/runtime/agent-core.js +71 -23
  170. package/src/assets/web-panel/assets/MarkdownRenderer-Ce-eWK3j.js +0 -1
  171. package/src/assets/web-panel/assets/OrderTableRenderer-GUKQ1xwp.js +0 -1
  172. package/src/assets/web-panel/assets/devWarning-B7_ypN1G.js +0 -1
  173. package/src/assets/web-panel/assets/index-B-jSKJK6.js +0 -1
  174. package/src/assets/web-panel/assets/index-P4FXZJqI.js +0 -1
@@ -24,7 +24,9 @@ import fs from "fs";
24
24
  import os from "os";
25
25
  import path from "path";
26
26
  import crypto from "crypto";
27
+ import { types as utilTypes } from "node:util";
27
28
  import { withFileLock } from "./with-file-lock.js";
29
+ import { readBoundedArtifactFile } from "./bounded-artifact-file-read.js";
28
30
 
29
31
  export const ARTIFACT_KINDS = Object.freeze([
30
32
  "report",
@@ -144,6 +146,39 @@ function normalizeLineage(lineage) {
144
146
  return normalized;
145
147
  }
146
148
 
149
+ function integrityReadBounds(value) {
150
+ if (
151
+ !value ||
152
+ typeof value !== "object" ||
153
+ utilTypes.isProxy(value) ||
154
+ Object.getPrototypeOf(value) !== Object.prototype ||
155
+ Reflect.ownKeys(value).length !== 2
156
+ )
157
+ throw new TypeError(
158
+ "artifact integrity bounds require exact own data fields",
159
+ );
160
+ const values = Object.fromEntries(
161
+ ["expectedSize", "maximumBytes"].map((name) => {
162
+ const field = Object.getOwnPropertyDescriptor(value, name);
163
+ if (!field?.enumerable || !("value" in field))
164
+ throw new TypeError("artifact integrity bounds cannot use accessors");
165
+ return [name, field.value];
166
+ }),
167
+ );
168
+ if (
169
+ !Number.isSafeInteger(values.expectedSize) ||
170
+ !Number.isSafeInteger(values.maximumBytes) ||
171
+ values.expectedSize < 0 ||
172
+ values.maximumBytes < 1 ||
173
+ values.expectedSize > values.maximumBytes ||
174
+ values.maximumBytes > MAX_ARTIFACT_BYTES
175
+ )
176
+ throw new TypeError(
177
+ "artifact integrity bounds exceed finite deliverable limits",
178
+ );
179
+ return Object.freeze(values);
180
+ }
181
+
147
182
  export class ArtifactStore {
148
183
  constructor({
149
184
  dir = null,
@@ -449,8 +484,14 @@ export class ArtifactStore {
449
484
  return path.join(this._filesDir(), entry.file);
450
485
  }
451
486
 
452
- /** Recompute the stored copy's digest; unknown/missing bytes fail closed. */
453
- verifyIntegrity(idOrEntry) {
487
+ /** Explicit bounds constrain artifact bytes only; id lookup may still read the index. */
488
+ verifyIntegrity(idOrEntry, bounds) {
489
+ if (arguments.length > 2)
490
+ throw new TypeError(
491
+ "artifact integrity accepts at most one bounds object",
492
+ );
493
+ // An explicitly supplied invalid value must never select the legacy raw read.
494
+ const bounded = arguments.length > 1 ? integrityReadBounds(bounds) : null;
454
495
  const entry =
455
496
  typeof idOrEntry === "object" && idOrEntry
456
497
  ? idOrEntry
@@ -465,7 +506,14 @@ export class ArtifactStore {
465
506
  }
466
507
  let body;
467
508
  try {
468
- body = fs.readFileSync(this.storedPath(entry));
509
+ const target = this.storedPath(entry);
510
+ body = bounded
511
+ ? readBoundedArtifactFile(
512
+ path.resolve(target),
513
+ bounded.expectedSize,
514
+ bounded.maximumBytes,
515
+ )
516
+ : fs.readFileSync(target);
469
517
  } catch {
470
518
  return {
471
519
  ok: false,
@@ -0,0 +1,131 @@
1
+ /** A bounded canonical-path read, not a persistent identity or authority grant. */
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { readBoundedDescriptor } from "./evolution/bounded-descriptor-read.js";
5
+ import { withEvolutionFileIdentity } from "./evolution/evolution-file-identity.js";
6
+ import { artifactPhysicalIdentity } from "./evolution/evolution-artifact-identity.js";
7
+
8
+ export const ARTIFACT_BOUNDED_READ_FAILED_CODE =
9
+ "CC_ARTIFACT_BOUNDED_READ_FAILED";
10
+ const FIELDS = Object.freeze([
11
+ "dev",
12
+ "ino",
13
+ "mode",
14
+ "uid",
15
+ "gid",
16
+ "nlink",
17
+ "size",
18
+ "mtimeNs",
19
+ "ctimeNs",
20
+ ]);
21
+ const MUTATION_FIELDS = Object.freeze(
22
+ FIELDS.filter((name) => name !== "dev" && name !== "ino"),
23
+ );
24
+ const DIRECTORY_FS = Object.freeze({
25
+ constants: fs.constants,
26
+ realpathSync: fs.realpathSync,
27
+ lstatSync: (...args) => fs.lstatSync(...args),
28
+ fstatSync: (...args) => fs.fstatSync(...args),
29
+ closeSync: (...args) => fs.closeSync(...args),
30
+ openSync: (target, flags) =>
31
+ fs.openSync(
32
+ target,
33
+ flags | (fs.constants.O_NONBLOCK || 0) | (fs.constants.O_DIRECTORY || 0),
34
+ ),
35
+ });
36
+ const canonical = (value) =>
37
+ process.platform === "win32" ? value.toLowerCase() : value;
38
+ function fail(message, cause) {
39
+ const error = new Error(message, cause ? { cause } : undefined);
40
+ error.code = ARTIFACT_BOUNDED_READ_FAILED_CODE;
41
+ throw error;
42
+ }
43
+ function safeStat(stat, expectedSize, maximumBytes, label) {
44
+ if (FIELDS.some((name) => typeof stat?.[name] !== "bigint"))
45
+ fail(`${label} requires full-precision stat fields`);
46
+ if (!stat.isFile() || stat.isSymbolicLink() || stat.nlink !== 1n)
47
+ fail(`${label} must be a regular, non-symlink, single-link file`);
48
+ if (
49
+ stat.size < 0n ||
50
+ stat.size > BigInt(maximumBytes) ||
51
+ stat.size !== BigInt(expectedSize)
52
+ )
53
+ fail(`${label} differs from its bounded expected size`);
54
+ }
55
+ function sameMetadata(left, right) {
56
+ return (
57
+ MUTATION_FIELDS.every((name) => left[name] === right[name]) &&
58
+ artifactPhysicalIdentity(left).birthtimeMs ===
59
+ artifactPhysicalIdentity(right).birthtimeMs
60
+ );
61
+ }
62
+ function sameStat(left, right) {
63
+ return (
64
+ left.dev === right.dev &&
65
+ left.ino === right.ino &&
66
+ sameMetadata(left, right)
67
+ );
68
+ }
69
+
70
+ /** Read one stable window only. Callers retain hash/signature and root checks. */
71
+ export function readBoundedArtifactFile(target, expectedSize, maximumBytes) {
72
+ if (
73
+ arguments.length !== 3 ||
74
+ typeof target !== "string" ||
75
+ !path.isAbsolute(target) ||
76
+ path.resolve(target) !== target ||
77
+ !Number.isSafeInteger(expectedSize) ||
78
+ !Number.isSafeInteger(maximumBytes) ||
79
+ expectedSize < 0 ||
80
+ maximumBytes < 1 ||
81
+ expectedSize > maximumBytes
82
+ )
83
+ throw new TypeError(
84
+ "bounded artifact read requires a canonical path and finite size bounds",
85
+ );
86
+ try {
87
+ return withEvolutionFileIdentity(DIRECTORY_FS, target, (samePathHandle) => {
88
+ const before = fs.lstatSync(target, { bigint: true });
89
+ safeStat(before, expectedSize, maximumBytes, "artifact path");
90
+ if (canonical(fs.realpathSync.native(target)) !== canonical(target))
91
+ fail("artifact path is not physically canonical");
92
+ const fd = fs.openSync(
93
+ target,
94
+ fs.constants.O_RDONLY |
95
+ (fs.constants.O_NOFOLLOW || 0) |
96
+ (fs.constants.O_NONBLOCK || 0),
97
+ );
98
+ try {
99
+ const opened = fs.fstatSync(fd, { bigint: true });
100
+ safeStat(opened, expectedSize, maximumBytes, "artifact descriptor");
101
+ if (!samePathHandle(before, opened) || !sameMetadata(before, opened))
102
+ fail("artifact path and descriptor identities differ");
103
+ const bytes = readBoundedDescriptor(
104
+ fs,
105
+ fd,
106
+ Number(opened.size),
107
+ maximumBytes,
108
+ );
109
+ const closed = fs.fstatSync(fd, { bigint: true });
110
+ const after = fs.lstatSync(target, { bigint: true });
111
+ safeStat(closed, expectedSize, maximumBytes, "artifact descriptor");
112
+ safeStat(after, expectedSize, maximumBytes, "artifact path");
113
+ if (!sameStat(opened, closed))
114
+ fail("artifact descriptor changed during bounded read");
115
+ if (
116
+ !sameStat(before, after) ||
117
+ !samePathHandle(after, closed) ||
118
+ !sameMetadata(after, closed) ||
119
+ canonical(fs.realpathSync.native(target)) !== canonical(target)
120
+ )
121
+ fail("artifact pathname changed during bounded read");
122
+ return bytes;
123
+ } finally {
124
+ fs.closeSync(fd);
125
+ }
126
+ });
127
+ } catch (cause) {
128
+ if (cause?.code === ARTIFACT_BOUNDED_READ_FAILED_CODE) throw cause;
129
+ fail("artifact bounded descriptor read failed", cause);
130
+ }
131
+ }