chainlesschain 0.166.83 → 0.166.85

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 (179) hide show
  1. package/README.md +9 -4
  2. package/package.json +1 -1
  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-D5a4i3N7.js → AIOps-Cgo7OFpi.js} +1 -1
  6. package/src/assets/web-panel/assets/{ActionButton-DxsRk5n1.js → ActionButton-lUMnE2Ln.js} +1 -1
  7. package/src/assets/web-panel/assets/{Analytics-D-7EvH4S.js → Analytics-CsvKzTot.js} +3 -3
  8. package/src/assets/web-panel/assets/{AppLayout-DDEWVr-d.js → AppLayout-C2z1h1Pv.js} +3 -3
  9. package/src/assets/web-panel/assets/{Artifacts-CAlJAjRB.js → Artifacts-C5Q0ZhNb.js} +1 -1
  10. package/src/assets/web-panel/assets/{Audit-tuaWDOAM.js → Audit-DXnfPKsI.js} +1 -1
  11. package/src/assets/web-panel/assets/{BackgroundAgents-CIwRFJ50.js → BackgroundAgents-DjbGcLm3.js} +1 -1
  12. package/src/assets/web-panel/assets/{Backup-CpBepJlH.js → Backup-9bVrKvXE.js} +1 -1
  13. package/src/assets/web-panel/assets/{BaseInput-eKguCzQc.js → BaseInput-bx5ri7BD.js} +1 -1
  14. package/src/assets/web-panel/assets/{Chat-CFrUfXDV.js → Chat-CCFmeUMY.js} +4 -4
  15. package/src/assets/web-panel/assets/ChatBubbleRenderer-ClqsIfTT.js +1 -0
  16. package/src/assets/web-panel/assets/{Checkbox-o5FEn6a1.js → Checkbox-ei7MQXe9.js} +1 -1
  17. package/src/assets/web-panel/assets/{Codegen-Dih8HogC.js → Codegen-CXgBJ9iu.js} +1 -1
  18. package/src/assets/web-panel/assets/{Col-D5r-6WZe.js → Col-DMkMsizS.js} +1 -1
  19. package/src/assets/web-panel/assets/{Community-jeQ6bGey.js → Community-CvpB_UFR.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compact-CEP7QsWp.js → Compact-gay5hbFX.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compliance-B8NydOHd.js → Compliance-dG8JQyRL.js} +1 -1
  22. package/src/assets/web-panel/assets/{Cowork-Bmi1zuPy.js → Cowork-BA3xfaTW.js} +4 -4
  23. package/src/assets/web-panel/assets/{Cron-BAL9bwSp.js → Cron-D1_HsxyY.js} +2 -2
  24. package/src/assets/web-panel/assets/{Crosschain-D8WUi2dS.js → Crosschain-DZqoqoy5.js} +1 -1
  25. package/src/assets/web-panel/assets/{DID-CQCkYcLY.js → DID-Cwnr8hCO.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dashboard-DogXg6kh.js → Dashboard-CxevypiI.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dropdown-BJBJyQJn.js → Dropdown-Bs7-yWgr.js} +1 -1
  28. package/src/assets/web-panel/assets/{EmailListRenderer-CxPWquJx.js → EmailListRenderer-CcEs2Puo.js} +1 -1
  29. package/src/assets/web-panel/assets/{EvolutionSettings-BijH1x8G.js → EvolutionSettings-C9ipBzAQ.js} +1 -1
  30. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DStwf-00.js → FamilyGuardDashboard-Dt6--mGn.js} +1 -1
  31. package/src/assets/web-panel/assets/{Federation-LU9_sNxC.js → Federation-CD0JN5FF.js} +1 -1
  32. package/src/assets/web-panel/assets/{FormItemContext-DNfWhj7P.js → FormItemContext-POypz3Xv.js} +1 -1
  33. package/src/assets/web-panel/assets/{GenericCardRenderer-DWYsPjzk.js → GenericCardRenderer-Dv9f-0F5.js} +1 -1
  34. package/src/assets/web-panel/assets/{Git-CA0O9ulB.js → Git-BbTh5Atv.js} +2 -2
  35. package/src/assets/web-panel/assets/{Governance-ECShL7BJ.js → Governance-C71dgoir.js} +1 -1
  36. package/src/assets/web-panel/assets/{Inference-9GA2542e.js → Inference-DwSHxbJB.js} +1 -1
  37. package/src/assets/web-panel/assets/{KnowledgeGraph-nC5mTbEH.js → KnowledgeGraph-Cx1oQYQZ.js} +1 -1
  38. package/src/assets/web-panel/assets/{Logs-B7IqgnDy.js → Logs-BAJWe00o.js} +2 -2
  39. package/src/assets/web-panel/assets/MarkdownRenderer-CD8a7lHT.js +1 -0
  40. package/src/assets/web-panel/assets/{Marketplace-CEr0suM8.js → Marketplace-fwuY7P7Y.js} +1 -1
  41. package/src/assets/web-panel/assets/{McpTools-DhTPQKOE.js → McpTools-Di4693uc.js} +3 -3
  42. package/src/assets/web-panel/assets/{Memory-mHRZP1w4.js → Memory-Cz3L-GUB.js} +2 -2
  43. package/src/assets/web-panel/assets/{MobileBridge-BNfX6Rdo.js → MobileBridge-BuXKIkSb.js} +1 -1
  44. package/src/assets/web-panel/assets/MobileProjects-Bk-lK4Um.js +1 -0
  45. package/src/assets/web-panel/assets/{Mtc-CzkV3wsn.js → Mtc-LnACMFd0.js} +5 -5
  46. package/src/assets/web-panel/assets/{MtcAudit-DWYljJik.js → MtcAudit-BZy7yE0t.js} +2 -2
  47. package/src/assets/web-panel/assets/{Multisig-kHgtvZY_.js → Multisig-BFG5iVrE.js} +3 -3
  48. package/src/assets/web-panel/assets/{NLProgramming-56uQiPiY.js → NLProgramming-DgXi04vJ.js} +1 -1
  49. package/src/assets/web-panel/assets/{Notes-DxGOZqRf.js → Notes-BAj0Kgg4.js} +4 -4
  50. package/src/assets/web-panel/assets/{NotificationSettings-DabaCpmo.js → NotificationSettings-AixrsHw5.js} +1 -1
  51. package/src/assets/web-panel/assets/{OrderTableRenderer-SzeQNlGT.js → OrderTableRenderer-Dwqk3FlG.js} +1 -1
  52. package/src/assets/web-panel/assets/{Organization-D9gnPpK2.js → Organization-UNCBC3ux.js} +4 -4
  53. package/src/assets/web-panel/assets/{Overflow-Cqp_bXm4.js → Overflow-Drh8oAFT.js} +1 -1
  54. package/src/assets/web-panel/assets/{P2P-DTeK-r0G.js → P2P-bc2q0xEB.js} +2 -2
  55. package/src/assets/web-panel/assets/{PdhVaultBrowser-CsjG85GT.js → PdhVaultBrowser-BGwKxcDM.js} +3 -3
  56. package/src/assets/web-panel/assets/{Permissions-B4ofZq3j.js → Permissions-DOnUxUzu.js} +3 -3
  57. package/src/assets/web-panel/assets/{PersonalDataHub-Cvas5cYd.js → PersonalDataHub-B3qPZkrr.js} +4 -4
  58. package/src/assets/web-panel/assets/{Pipeline-Er3wmAew.js → Pipeline-B6hfa4-i.js} +1 -1
  59. package/src/assets/web-panel/assets/{Privacy-DMFYeZox.js → Privacy-Bun3c35F.js} +1 -1
  60. package/src/assets/web-panel/assets/{ProjectInit-DaVaYPy0.js → ProjectInit-CCObdzk9.js} +2 -2
  61. package/src/assets/web-panel/assets/{ProjectSettings-dPx5q2Ac.js → ProjectSettings-C6lKrSXY.js} +2 -2
  62. package/src/assets/web-panel/assets/{Projects-N0JNeCui.js → Projects-DYcta7MZ.js} +1 -1
  63. package/src/assets/web-panel/assets/{Providers-BPQo_gQa.js → Providers-BtykxKCe.js} +1 -1
  64. package/src/assets/web-panel/assets/{QrScannerModal-CD-sEsWh.js → QrScannerModal-D9CDyroY.js} +1 -1
  65. package/src/assets/web-panel/assets/{QuickAsk-LOKRJiN_.js → QuickAsk-CJauCxXx.js} +1 -1
  66. package/src/assets/web-panel/assets/{Recommend-BwPXqcWy.js → Recommend-BbiYZofR.js} +1 -1
  67. package/src/assets/web-panel/assets/{RemoteSession-BjotndxF.js → RemoteSession-BymCrgFW.js} +3 -3
  68. package/src/assets/web-panel/assets/{Reputation-BlZ2gcbU.js → Reputation-BWrGpMpF.js} +1 -1
  69. package/src/assets/web-panel/assets/{Row-D399HM-d.js → Row-9pOYIhiW.js} +1 -1
  70. package/src/assets/web-panel/assets/{RssFeed-C7H-ibnY.js → RssFeed-D3bQJ4qB.js} +2 -2
  71. package/src/assets/web-panel/assets/{Search-CNHCVmM1.js → Search-BpKOOFE0.js} +1 -1
  72. package/src/assets/web-panel/assets/{Security-C70eDGYY.js → Security-DC6C0NSz.js} +4 -4
  73. package/src/assets/web-panel/assets/{Services-6xfq9G-H.js → Services-Lkf1046J.js} +2 -2
  74. package/src/assets/web-panel/assets/{Skeleton-BbY2zeZV.js → Skeleton-eCQ_SsDb.js} +1 -1
  75. package/src/assets/web-panel/assets/{Skills-DYtyZ7_6.js → Skills-BvDSQ3-d.js} +1 -1
  76. package/src/assets/web-panel/assets/{Sla-CkWcl5OH.js → Sla-BQbKy8XJ.js} +1 -1
  77. package/src/assets/web-panel/assets/{SpeechSettings-CiknYk2P.js → SpeechSettings-DHsRx-XA.js} +1 -1
  78. package/src/assets/web-panel/assets/{SyncSettings-D-8JVip4.js → SyncSettings-CC281X_J.js} +2 -2
  79. package/src/assets/web-panel/assets/{Tasks-B2KnR9XC.js → Tasks-CHHSWHom.js} +1 -1
  80. package/src/assets/web-panel/assets/{Templates-CipXkOE-.js → Templates-Cr2vC0tg.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tenant-DbwgIMmx.js → Tenant-DeYO5pIG.js} +1 -1
  82. package/src/assets/web-panel/assets/{Terminal-OtCriHEE.js → Terminal-DBNgbfPr.js} +2 -2
  83. package/src/assets/web-panel/assets/TimelineRenderer-MoxgaF3x.js +1 -0
  84. package/src/assets/web-panel/assets/{Tokens-B4iFVxvH.js → Tokens-CT2QfAN7.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trigger-BegM2v8q.js → Trigger-DPUnomxs.js} +1 -1
  86. package/src/assets/web-panel/assets/{Trust-COkqnnFj.js → Trust-DnufuaTx.js} +1 -1
  87. package/src/assets/web-panel/assets/{UkeySign-BzqKPChj.js → UkeySign-CJ6iOdPs.js} +1 -1
  88. package/src/assets/web-panel/assets/{VideoEditing-D-F2XL3C.js → VideoEditing-xBWkH8bL.js} +1 -1
  89. package/src/assets/web-panel/assets/{Wallet-22PzRY9T.js → Wallet-WYV-4hMR.js} +3 -3
  90. package/src/assets/web-panel/assets/{WebAuthn-eSMq_qtz.js → WebAuthn-DJ5Mhd9L.js} +4 -4
  91. package/src/assets/web-panel/assets/{WorkflowEditor-BvdAakpq.js → WorkflowEditor-B__UdOjN.js} +1 -1
  92. package/src/assets/web-panel/assets/{chat-C6jhpF7E.js → chat-CLlmBVhp.js} +1 -1
  93. package/src/assets/web-panel/assets/{colors-BbbW2Pfv.js → colors-B8zoPQYm.js} +1 -1
  94. package/src/assets/web-panel/assets/{compact-item-CVFeLTqt.js → compact-item-CvJ-dUsH.js} +1 -1
  95. package/src/assets/web-panel/assets/{createContext-DS0m7NZc.js → createContext-LAtMm8SC.js} +1 -1
  96. package/src/assets/web-panel/assets/devWarning-DgZ4fdGI.js +1 -0
  97. package/src/assets/web-panel/assets/{hasIn-DVouP0t6.js → hasIn-CLYvg42H.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-Be12HoCS.js → index-09YzRb6Z.js} +3 -3
  99. package/src/assets/web-panel/assets/{index-CPS8E-J6.js → index-4rr5jFOL.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BXw6ivB8.js → index-B02qgCao.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-BaUah6TO.js → index-B1hHp9_M.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-Ds4wbrgk.js → index-B6zlMzZz.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-JeJqXbUU.js → index-BCzyJ1xS.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-54aHB4FL.js → index-BGrQ2uEl.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-eaXEQFuP.js → index-BM2HqHdT.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-C74emdKD.js → index-BUVrYDNV.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-BrIv7C9a.js → index-B_RPWP_5.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DGYX17YW.js → index-BkcQJvsz.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-DotRL126.js → index-Bu7-I2L4.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-BvCgzl0X.js → index-C2KFnUsv.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-C4xmLgLa.js → index-C3uD5H7u.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-BwozzG6k.js → index-C5v7cEtm.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-C6q2MkIG.js → index-C6PETyel.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-DUBkae39.js → index-CUcE6rIa.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-BwZnPiFd.js → index-CVDcRQuX.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-CIk7mg6G.js → index-C_dq-6_3.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-B8a_c_qZ.js → index-CnLXLaEF.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CIg4nqyp.js → index-Cpda0SAz.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-BhvnNFfd.js → index-Cv7vwX3z.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CpTbnbUI.js → index-CxJ4NPVq.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-BzL3LWFX.js → index-D0Z13xcZ.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-BE_u-rXr.js → index-DDm9m4vC.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-ByLsH9CL.js → index-DHq2Of6z.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-BOOsA080.js → index-DNQUdPam.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-SdFkCtiC.js → index-DX0aHEHL.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-Bw-ZGQCH.js → index-DX99e8Xy.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-CkdYB0_g.js → index-DYW4Z3y-.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-DuVjTDcW.js → index-DfOOACfd.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-DpReoAGb.js → index-Di9vKira.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-CwYFDMn_.js → index-DpeV-6y4.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-DR6TDz5H.js → index-GR3omApz.js} +1 -1
  132. package/src/assets/web-panel/assets/{index--AdzSlH7.js → index-f1ptYBMr.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-8QbwhE3i.js → index-iJ6s24bA.js} +1 -1
  134. package/src/assets/web-panel/assets/index-jLEdASOV.js +1 -0
  135. package/src/assets/web-panel/assets/index-jesGo4rl.js +1 -0
  136. package/src/assets/web-panel/assets/{index-B5JRIZXi.js → index-oX216HRH.js} +1 -1
  137. package/src/assets/web-panel/assets/{initDefaultProps-CB5cUnQ5.js → initDefaultProps-QD-koeaw.js} +1 -1
  138. package/src/assets/web-panel/assets/{motion-bn_fWhQV.js → motion-CTItLW4-.js} +1 -1
  139. package/src/assets/web-panel/assets/{move-DY4-Odtu.js → move-CGsdTOdN.js} +1 -1
  140. package/src/assets/web-panel/assets/{mtc-parser-B5l5mjoh.js → mtc-parser-C1kW_CNU.js} +1 -1
  141. package/src/assets/web-panel/assets/{omit-rJ-Ci8CW.js → omit-B4PilaYy.js} +1 -1
  142. package/src/assets/web-panel/assets/{pickAttrs-BMwGJd6C.js → pickAttrs-DBGUE12e.js} +1 -1
  143. package/src/assets/web-panel/assets/{placementArrow-CaiQyGXG.js → placementArrow-DZxCLjuo.js} +1 -1
  144. package/src/assets/web-panel/assets/{responsiveObserve-DQTO5wDH.js → responsiveObserve-CZjQiocN.js} +1 -1
  145. package/src/assets/web-panel/assets/{slide-Dg6ZDtbz.js → slide-Btz5hh2_.js} +1 -1
  146. package/src/assets/web-panel/assets/{statusUtils-bvjrktKc.js → statusUtils-CfuxuLIt.js} +1 -1
  147. package/src/assets/web-panel/assets/{styleChecker-C1geIU_x.js → styleChecker-DdO0Obo_.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFlexGapSupport-BzU3RJRi.js → useFlexGapSupport-CxftJ-Zs.js} +1 -1
  149. package/src/assets/web-panel/assets/{useFs-B7l6OwLe.js → useFs-pVJChh6K.js} +1 -1
  150. package/src/assets/web-panel/assets/{usePersonalDataHub-BYF1L_8x.js → usePersonalDataHub-wv7Q0uNE.js} +1 -1
  151. package/src/assets/web-panel/assets/{vnode-6c2GVkT-.js → vnode-DVOVfAqC.js} +1 -1
  152. package/src/assets/web-panel/assets/{zoom-BYAY6QeD.js → zoom-B5tebZuT.js} +1 -1
  153. package/src/assets/web-panel/index.html +1 -1
  154. package/src/commands/permissions.js +27 -2
  155. package/src/data/changelog.json +26 -0
  156. package/src/lib/background-interaction-resolver.js +4 -0
  157. package/src/lib/context-memory-kernel/durable-memory-port.js +68 -15
  158. package/src/lib/packer/pack-update-applier.js +28 -9
  159. package/src/lib/packer/pkg-config-generator.js +119 -2
  160. package/src/lib/packer/pkg-runner.js +7 -0
  161. package/src/lib/packer/pkg-targets.js +83 -0
  162. package/src/lib/packer/web-panel-builder.js +7 -0
  163. package/src/lib/permission-authority.js +56 -7
  164. package/src/lib/process-execution-broker/index.js +11 -0
  165. package/src/lib/process-execution-broker/linux-subreaper-helper.js +87 -13
  166. package/src/lib/process-execution-broker/packer-build-policy.js +31 -0
  167. package/src/lib/process-execution-broker/platform-sandbox.js +11 -3
  168. package/src/lib/scoped-permission-store.js +241 -121
  169. package/src/lib/settings-authority-domain.cjs +966 -0
  170. package/src/lib/settings-authority-record.cjs +701 -0
  171. package/src/lib/settings-loader.cjs +45 -8
  172. package/src/lib/settings-source-observation.cjs +8 -0
  173. package/src/assets/web-panel/assets/ChatBubbleRenderer-DaRtY87l.js +0 -1
  174. package/src/assets/web-panel/assets/MarkdownRenderer-BqlqrJkY.js +0 -1
  175. package/src/assets/web-panel/assets/MobileProjects-8zG8f5li.js +0 -1
  176. package/src/assets/web-panel/assets/TimelineRenderer-B9LU5qrl.js +0 -1
  177. package/src/assets/web-panel/assets/devWarning-D50gzPS9.js +0 -1
  178. package/src/assets/web-panel/assets/index-CgensV-n.js +0 -1
  179. package/src/assets/web-panel/assets/index-Ctkf06Z_.js +0 -1
@@ -0,0 +1,701 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Pure records for the cooperative settings-authority protocol. This module
5
+ * performs no I/O, enrollment, locking, recovery, or permission admission.
6
+ * Callers must publish guard -> prepared -> settings -> ready durably, then
7
+ * remove the guard. Construction of a record is not evidence of persistence.
8
+ *
9
+ * A write changes one physical source, including every registered alias.
10
+ * Parent materialization is deliberately unsupported: a changed parent binding
11
+ * cannot be accepted merely because the resulting content has the right hash.
12
+ */
13
+ const path = require("node:path");
14
+ const { createHash } = require("node:crypto");
15
+ const { types } = require("node:util");
16
+
17
+ const LEDGER_SCHEMA = "chainlesschain.settings-authority/v1";
18
+ const GUARD_SCHEMA = "chainlesschain.settings-authority-guard/v1";
19
+ const LIMITS = Object.freeze({
20
+ contexts: 64,
21
+ sourcesPerContext: 64,
22
+ sources: 1024,
23
+ discoveryPaths: 64,
24
+ pathBytes: 4096,
25
+ recordBytes: 4 * 1024 * 1024,
26
+ sourceBytes: 1024 * 1024,
27
+ });
28
+ const SOURCE_KEYS = [
29
+ "logicalPath",
30
+ "physicalPath",
31
+ "nearestExistingParent",
32
+ "remainingPath",
33
+ "parentIdentity",
34
+ "exists",
35
+ "byteLength",
36
+ "digest",
37
+ "fileIdentity",
38
+ ];
39
+ const FILE_FIELDS = [
40
+ "dev",
41
+ "ino",
42
+ "mode",
43
+ "nlink",
44
+ "size",
45
+ "mtimeNs",
46
+ "ctimeNs",
47
+ ];
48
+
49
+ function fail(code = "CC_SETTINGS_AUTHORITY_RECORD_INVALID") {
50
+ const error = new Error(
51
+ "Settings authority record is invalid or inconsistent",
52
+ );
53
+ error.name = "SettingsAuthorityRecordError";
54
+ error.code = code;
55
+ throw error;
56
+ }
57
+
58
+ // Reject accessors/Proxy/toJSON before any property read. Never invoke caller
59
+ // code during validation; limits apply before recursive copying/stringifying.
60
+ function copyData(value) {
61
+ let nodes = 0;
62
+ let stringBytes = 0;
63
+ const ancestors = new Set();
64
+ function visit(input, depth) {
65
+ if (++nodes > 100000 || depth > 24) fail();
66
+ if (input === null || typeof input === "boolean") return input;
67
+ if (typeof input === "string") {
68
+ stringBytes += Buffer.byteLength(input);
69
+ if (stringBytes > LIMITS.recordBytes) fail();
70
+ return input;
71
+ }
72
+ if (typeof input === "number") {
73
+ if (!Number.isSafeInteger(input)) fail();
74
+ return input;
75
+ }
76
+ if (!input || typeof input !== "object" || types.isProxy(input)) fail();
77
+ if (ancestors.has(input)) fail();
78
+ const array = Array.isArray(input);
79
+ const prototype = Object.getPrototypeOf(input);
80
+ if (
81
+ array
82
+ ? prototype !== Array.prototype
83
+ : prototype !== Object.prototype && prototype !== null
84
+ )
85
+ fail();
86
+ const descriptors = Object.getOwnPropertyDescriptors(input);
87
+ const keys = Reflect.ownKeys(descriptors);
88
+ if (keys.some((key) => typeof key !== "string")) fail();
89
+ if (array && input.length > 4096) fail();
90
+ const output = array ? [] : {};
91
+ ancestors.add(input);
92
+ for (const key of keys) {
93
+ if (array && key === "length") continue;
94
+ const descriptor = descriptors[key];
95
+ if (
96
+ !Object.hasOwn(descriptor, "value") ||
97
+ !descriptor.enumerable ||
98
+ key === "__proto__"
99
+ )
100
+ fail();
101
+ if (
102
+ array &&
103
+ (!/^(0|[1-9][0-9]*)$/.test(key) || Number(key) >= input.length)
104
+ )
105
+ fail();
106
+ Object.defineProperty(output, key, {
107
+ value: visit(descriptor.value, depth + 1),
108
+ enumerable: true,
109
+ configurable: true,
110
+ writable: true,
111
+ });
112
+ }
113
+ ancestors.delete(input);
114
+ if (
115
+ array &&
116
+ (output.length !== input.length || keys.length !== input.length + 1)
117
+ )
118
+ fail();
119
+ return output;
120
+ }
121
+ const result = visit(value, 0);
122
+ if (Buffer.byteLength(JSON.stringify(result)) > LIMITS.recordBytes) fail();
123
+ return result;
124
+ }
125
+
126
+ function freeze(value) {
127
+ if (value && typeof value === "object") {
128
+ for (const child of Object.values(value)) freeze(child);
129
+ Object.freeze(value);
130
+ }
131
+ return value;
132
+ }
133
+
134
+ function shape(value, keys) {
135
+ if (!value || typeof value !== "object" || Array.isArray(value)) fail();
136
+ const actual = Object.keys(value);
137
+ if (
138
+ actual.length !== keys.length ||
139
+ keys.some((key) => !Object.hasOwn(value, key))
140
+ )
141
+ fail();
142
+ }
143
+
144
+ function list(value, max, min = 0) {
145
+ if (!Array.isArray(value) || value.length < min || value.length > max) fail();
146
+ }
147
+
148
+ function identifier(value) {
149
+ if (
150
+ typeof value !== "string" ||
151
+ !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(value)
152
+ )
153
+ fail();
154
+ }
155
+
156
+ function generation(value) {
157
+ if (!Number.isSafeInteger(value) || value < 0) fail();
158
+ }
159
+
160
+ function hash(value) {
161
+ if (typeof value !== "string" || !/^[a-f0-9]{64}$/.test(value)) fail();
162
+ }
163
+
164
+ function platformName(value) {
165
+ if (value === "win32") return value;
166
+ if (
167
+ ["posix", "linux", "darwin", "freebsd", "openbsd", "aix", "sunos"].includes(
168
+ value,
169
+ )
170
+ )
171
+ return "posix";
172
+ fail();
173
+ }
174
+
175
+ function normalizedPath(value, platform, absolute = true) {
176
+ if (
177
+ typeof value !== "string" ||
178
+ !value ||
179
+ value.includes("\0") ||
180
+ Buffer.byteLength(value) > LIMITS.pathBytes
181
+ )
182
+ fail();
183
+ const api = platform === "win32" ? path.win32 : path.posix;
184
+ if (absolute) {
185
+ if (!api.isAbsolute(value)) fail();
186
+ if (
187
+ platform === "win32" &&
188
+ !/^(?:[a-z]:[\\/]|[\\/]{2}[^\\/]+[\\/][^\\/]+[\\/])/i.test(value)
189
+ )
190
+ fail();
191
+ } else if (
192
+ api.isAbsolute(value) ||
193
+ (platform === "win32" && /^[a-z]:/i.test(value))
194
+ )
195
+ fail();
196
+ let result = api.normalize(value);
197
+ if (platform === "win32") {
198
+ if (result.startsWith("\\\\?\\") || result.startsWith("\\\\.\\")) fail();
199
+ const segments = result
200
+ .replace(/^[a-z]:/i, "")
201
+ .split("\\")
202
+ .filter(Boolean);
203
+ if (
204
+ segments.some(
205
+ (segment) => /[.: ]$/.test(segment) || segment.includes(":"),
206
+ )
207
+ )
208
+ fail();
209
+ result = result.toLowerCase();
210
+ }
211
+ if (
212
+ !absolute &&
213
+ (result === "." || result === ".." || result.startsWith(`..${api.sep}`))
214
+ )
215
+ fail();
216
+ return result;
217
+ }
218
+
219
+ function identity(value, fields) {
220
+ shape(value, fields);
221
+ for (const field of fields) {
222
+ const signed = field === "mtimeNs" || field === "ctimeNs";
223
+ if (
224
+ typeof value[field] !== "string" ||
225
+ value[field].length > 40 ||
226
+ !(signed ? /^(?:0|-?[1-9][0-9]*)$/ : /^(?:0|[1-9][0-9]*)$/).test(
227
+ value[field],
228
+ )
229
+ )
230
+ fail();
231
+ }
232
+ }
233
+
234
+ function content(value) {
235
+ if (
236
+ typeof value.exists !== "boolean" ||
237
+ !Number.isSafeInteger(value.byteLength) ||
238
+ value.byteLength < 0 ||
239
+ value.byteLength > LIMITS.sourceBytes
240
+ )
241
+ fail();
242
+ if (value.exists) hash(value.digest);
243
+ else if (value.byteLength !== 0 || value.digest !== null) fail();
244
+ }
245
+
246
+ function validateSource(value, platform) {
247
+ shape(value, SOURCE_KEYS);
248
+ for (const key of ["logicalPath", "physicalPath", "nearestExistingParent"])
249
+ if (normalizedPath(value[key], platform) !== value[key]) fail();
250
+ if (
251
+ normalizedPath(value.remainingPath, platform, false) !== value.remainingPath
252
+ )
253
+ fail();
254
+ const api = platform === "win32" ? path.win32 : path.posix;
255
+ if (
256
+ api.join(value.nearestExistingParent, value.remainingPath) !==
257
+ value.physicalPath
258
+ )
259
+ fail();
260
+ identity(value.parentIdentity, ["dev", "ino"]);
261
+ content(value);
262
+ if (value.exists) {
263
+ identity(value.fileIdentity, FILE_FIELDS);
264
+ if (
265
+ value.fileIdentity.nlink !== "1" ||
266
+ BigInt(value.fileIdentity.size) !== BigInt(value.byteLength) ||
267
+ (BigInt(value.fileIdentity.mode) & 0o170000n) !== 0o100000n ||
268
+ api.dirname(value.physicalPath) !== value.nearestExistingParent
269
+ )
270
+ fail();
271
+ } else if (value.fileIdentity !== null) fail();
272
+ }
273
+
274
+ function validateManifest(manifest, platform) {
275
+ shape(manifest, ["contextId", "discovery", "sources"]);
276
+ identifier(manifest.contextId);
277
+ list(manifest.discovery, LIMITS.discoveryPaths, 1);
278
+ for (const item of manifest.discovery)
279
+ if (normalizedPath(item, platform) !== item) fail();
280
+ list(manifest.sources, LIMITS.sourcesPerContext, 1);
281
+ for (const source of manifest.sources) validateSource(source, platform);
282
+ }
283
+
284
+ function canonical(value) {
285
+ if (Array.isArray(value)) return value.map(canonical);
286
+ if (!value || typeof value !== "object") return value;
287
+ return Object.fromEntries(
288
+ Object.keys(value)
289
+ .sort()
290
+ .map((key) => [key, canonical(value[key])]),
291
+ );
292
+ }
293
+
294
+ function equal(a, b) {
295
+ return JSON.stringify(canonical(a)) === JSON.stringify(canonical(b));
296
+ }
297
+
298
+ function digest(value) {
299
+ return createHash("sha256")
300
+ .update(JSON.stringify(canonical(value)))
301
+ .digest("hex");
302
+ }
303
+
304
+ function headOf(source) {
305
+ const head = { ...source };
306
+ delete head.logicalPath;
307
+ return head;
308
+ }
309
+
310
+ function inverseHeads(contexts, platform) {
311
+ list(contexts, LIMITS.contexts);
312
+ const ids = new Set();
313
+ const logical = new Map();
314
+ const heads = new Map();
315
+ const inodes = new Map();
316
+ let sourceCount = 0;
317
+ for (const manifest of contexts) {
318
+ validateManifest(manifest, platform);
319
+ if (ids.has(manifest.contextId)) fail();
320
+ ids.add(manifest.contextId);
321
+ sourceCount += manifest.sources.length;
322
+ if (sourceCount > LIMITS.sources) fail();
323
+ for (const source of manifest.sources) {
324
+ const previous = logical.get(source.logicalPath);
325
+ if (previous && !equal(previous, source))
326
+ fail("CC_SETTINGS_AUTHORITY_BINDING_CHANGED");
327
+ logical.set(source.logicalPath, source);
328
+ const head = headOf(source);
329
+ const known = heads.get(source.physicalPath);
330
+ if (known && !equal(known, head))
331
+ fail("CC_SETTINGS_AUTHORITY_BINDING_CHANGED");
332
+ heads.set(source.physicalPath, head);
333
+ if (source.exists) {
334
+ const inode = `${source.fileIdentity.dev}:${source.fileIdentity.ino}`;
335
+ const previousPath = inodes.get(inode);
336
+ // A final-component alias that canonical parent resolution missed must
337
+ // not create a second head. Reject it instead of inventing equivalence.
338
+ if (previousPath && previousPath !== source.physicalPath)
339
+ fail("CC_SETTINGS_AUTHORITY_BINDING_CHANGED");
340
+ inodes.set(inode, source.physicalPath);
341
+ }
342
+ }
343
+ }
344
+ return [...heads.values()].sort((a, b) =>
345
+ a.physicalPath < b.physicalPath
346
+ ? -1
347
+ : a.physicalPath > b.physicalPath
348
+ ? 1
349
+ : 0,
350
+ );
351
+ }
352
+
353
+ function readyRecord({ platform, epoch, generation: revision, contexts }) {
354
+ return {
355
+ schema: LEDGER_SCHEMA,
356
+ platform,
357
+ epoch,
358
+ generation: revision,
359
+ phase: "ready",
360
+ transactionId: null,
361
+ transition: null,
362
+ contexts,
363
+ physicalHeads: inverseHeads(contexts, platform),
364
+ };
365
+ }
366
+
367
+ function validateIntent(intent, platform) {
368
+ if (intent?.kind === "register") {
369
+ shape(intent, ["kind", "manifest"]);
370
+ validateManifest(intent.manifest, platform);
371
+ } else if (intent?.kind === "write") {
372
+ shape(intent, ["kind", "physicalPath", "after"]);
373
+ if (normalizedPath(intent.physicalPath, platform) !== intent.physicalPath)
374
+ fail();
375
+ shape(intent.after, ["exists", "byteLength", "digest"]);
376
+ content(intent.after);
377
+ } else fail();
378
+ }
379
+
380
+ function checkIntentAgainstBefore(before, intent) {
381
+ if (intent.kind === "write") {
382
+ const target = before.physicalHeads.find(
383
+ (head) => head.physicalPath === intent.physicalPath,
384
+ );
385
+ if (!target) fail("CC_SETTINGS_AUTHORITY_SOURCE_UNREGISTERED");
386
+ const api = before.platform === "win32" ? path.win32 : path.posix;
387
+ if (api.dirname(target.physicalPath) !== target.nearestExistingParent)
388
+ fail("CC_SETTINGS_AUTHORITY_PARENT_MATERIALIZATION_UNSUPPORTED");
389
+ } else {
390
+ if (
391
+ before.contexts.some(
392
+ (context) => context.contextId === intent.manifest.contextId,
393
+ )
394
+ )
395
+ fail("CC_SETTINGS_AUTHORITY_CONTEXT_EXISTS");
396
+ // Combining with all existing contexts verifies every logical and inverse
397
+ // physical binding before an alias or a new project may be enrolled.
398
+ inverseHeads([...before.contexts, intent.manifest], before.platform);
399
+ }
400
+ }
401
+
402
+ function beforeOf(prepared) {
403
+ return readyRecord({
404
+ platform: prepared.platform,
405
+ epoch: prepared.epoch,
406
+ generation: prepared.transition.fromGeneration,
407
+ contexts: prepared.contexts,
408
+ });
409
+ }
410
+
411
+ function validateLedgerData(record) {
412
+ shape(record, [
413
+ "schema",
414
+ "platform",
415
+ "epoch",
416
+ "generation",
417
+ "phase",
418
+ "transactionId",
419
+ "transition",
420
+ "contexts",
421
+ "physicalHeads",
422
+ ]);
423
+ if (
424
+ record.schema !== LEDGER_SCHEMA ||
425
+ !["posix", "win32"].includes(record.platform)
426
+ )
427
+ fail();
428
+ identifier(record.epoch);
429
+ generation(record.generation);
430
+ if (
431
+ !equal(inverseHeads(record.contexts, record.platform), record.physicalHeads)
432
+ )
433
+ fail("CC_SETTINGS_AUTHORITY_BINDING_CHANGED");
434
+ if (record.phase === "ready") {
435
+ if (record.transactionId !== null || record.transition !== null) fail();
436
+ } else if (record.phase === "prepared") {
437
+ identifier(record.transactionId);
438
+ shape(record.transition, ["fromGeneration", "beforeDigest", "intent"]);
439
+ generation(record.transition.fromGeneration);
440
+ if (
441
+ record.generation <= 0 ||
442
+ record.transition.fromGeneration !== record.generation - 1
443
+ )
444
+ fail();
445
+ hash(record.transition.beforeDigest);
446
+ validateIntent(record.transition.intent, record.platform);
447
+ const before = beforeOf(record);
448
+ if (digest(before) !== record.transition.beforeDigest)
449
+ fail("CC_SETTINGS_AUTHORITY_TRANSACTION_MISMATCH");
450
+ checkIntentAgainstBefore(before, record.transition.intent);
451
+ } else fail();
452
+ return record;
453
+ }
454
+
455
+ function validateLedger({ record }) {
456
+ return freeze(validateLedgerData(copyData(record)));
457
+ }
458
+
459
+ function requireReady(record) {
460
+ if (record.phase !== "ready") fail("CC_SETTINGS_AUTHORITY_NOT_READY");
461
+ }
462
+
463
+ function createManifest({
464
+ contextId,
465
+ discovery,
466
+ sources,
467
+ platform = process.platform,
468
+ }) {
469
+ const normalizedPlatform = platformName(platform);
470
+ // Observer settings may be a large nested object. Deliberately select only
471
+ // data descriptors of the binding fields, without reading/invoking settings.
472
+ if (!Array.isArray(sources) || types.isProxy(sources)) fail();
473
+ const selected = [];
474
+ if (sources.length > LIMITS.sourcesPerContext) fail();
475
+ for (let index = 0; index < sources.length; index++) {
476
+ const itemDescriptor = Object.getOwnPropertyDescriptor(
477
+ sources,
478
+ String(index),
479
+ );
480
+ if (!itemDescriptor || !Object.hasOwn(itemDescriptor, "value")) fail();
481
+ const source = itemDescriptor.value;
482
+ if (!source || typeof source !== "object" || types.isProxy(source)) fail();
483
+ const data = {};
484
+ for (const key of SOURCE_KEYS) {
485
+ const descriptor = Object.getOwnPropertyDescriptor(source, key);
486
+ if (!descriptor || !Object.hasOwn(descriptor, "value")) fail();
487
+ data[key] = descriptor.value;
488
+ }
489
+ selected.push(data);
490
+ }
491
+ const manifest = copyData({ contextId, discovery, sources: selected });
492
+ list(manifest.discovery, LIMITS.discoveryPaths, 1);
493
+ manifest.discovery = manifest.discovery.map((item) =>
494
+ normalizedPath(item, normalizedPlatform),
495
+ );
496
+ for (const source of manifest.sources) {
497
+ for (const key of ["logicalPath", "physicalPath", "nearestExistingParent"])
498
+ source[key] = normalizedPath(source[key], normalizedPlatform);
499
+ source.remainingPath = normalizedPath(
500
+ source.remainingPath,
501
+ normalizedPlatform,
502
+ false,
503
+ );
504
+ }
505
+ validateManifest(manifest, normalizedPlatform);
506
+ inverseHeads([manifest], normalizedPlatform);
507
+ return freeze(manifest);
508
+ }
509
+
510
+ function createInitialLedger({
511
+ epoch,
512
+ platform = process.platform,
513
+ contexts = [],
514
+ }) {
515
+ const data = copyData({ epoch, contexts });
516
+ return validateLedger({
517
+ record: readyRecord({
518
+ platform: platformName(platform),
519
+ epoch: data.epoch,
520
+ generation: 0,
521
+ contexts: data.contexts,
522
+ }),
523
+ });
524
+ }
525
+
526
+ function recordDigest({ record }) {
527
+ return digest(validateLedger({ record }));
528
+ }
529
+
530
+ function assertContextMatches({ ledger, manifest }) {
531
+ const current = validateLedger({ record: ledger });
532
+ requireReady(current);
533
+ const observed = copyData(manifest);
534
+ validateManifest(observed, current.platform);
535
+ const known = current.contexts.find(
536
+ (context) => context.contextId === observed.contextId,
537
+ );
538
+ if (!known) fail("CC_SETTINGS_AUTHORITY_CONTEXT_UNREGISTERED");
539
+ if (!equal(known, observed)) fail("CC_SETTINGS_AUTHORITY_BINDING_CHANGED");
540
+ return true;
541
+ }
542
+
543
+ function guardOf(prepared) {
544
+ return {
545
+ schema: GUARD_SCHEMA,
546
+ platform: prepared.platform,
547
+ epoch: prepared.epoch,
548
+ generation: prepared.generation,
549
+ transactionId: prepared.transactionId,
550
+ beforeDigest: prepared.transition.beforeDigest,
551
+ intent: prepared.transition.intent,
552
+ };
553
+ }
554
+
555
+ function validateGuard({ guard, prepared = null }) {
556
+ const data = copyData(guard);
557
+ shape(data, [
558
+ "schema",
559
+ "platform",
560
+ "epoch",
561
+ "generation",
562
+ "transactionId",
563
+ "beforeDigest",
564
+ "intent",
565
+ ]);
566
+ if (
567
+ data.schema !== GUARD_SCHEMA ||
568
+ !["posix", "win32"].includes(data.platform)
569
+ )
570
+ fail();
571
+ identifier(data.epoch);
572
+ identifier(data.transactionId);
573
+ generation(data.generation);
574
+ if (!data.generation) fail();
575
+ hash(data.beforeDigest);
576
+ validateIntent(data.intent, data.platform);
577
+ if (prepared !== null) {
578
+ const record = validateLedger({ record: prepared });
579
+ if (record.phase !== "prepared" || !equal(data, guardOf(record)))
580
+ fail("CC_SETTINGS_AUTHORITY_TRANSACTION_MISMATCH");
581
+ }
582
+ return freeze(data);
583
+ }
584
+
585
+ function prepareTransition({ ledger, transactionId, intent }) {
586
+ const before = validateLedger({ record: ledger });
587
+ requireReady(before);
588
+ identifier(transactionId);
589
+ if (before.generation === Number.MAX_SAFE_INTEGER)
590
+ fail("CC_SETTINGS_AUTHORITY_GENERATION_EXHAUSTED");
591
+ const plan = copyData(intent);
592
+ validateIntent(plan, before.platform);
593
+ checkIntentAgainstBefore(before, plan);
594
+ const prepared = validateLedger({
595
+ record: {
596
+ ...before,
597
+ phase: "prepared",
598
+ generation: before.generation + 1,
599
+ transactionId,
600
+ transition: {
601
+ fromGeneration: before.generation,
602
+ beforeDigest: digest(before),
603
+ intent: plan,
604
+ },
605
+ },
606
+ });
607
+ return freeze({
608
+ prepared,
609
+ guard: validateGuard({ guard: guardOf(prepared), prepared }),
610
+ });
611
+ }
612
+
613
+ function registerContext({ ledger, manifest, transactionId }) {
614
+ return prepareTransition({
615
+ ledger,
616
+ transactionId,
617
+ intent: { kind: "register", manifest },
618
+ });
619
+ }
620
+
621
+ function sameBinding(left, right) {
622
+ return [
623
+ "logicalPath",
624
+ "physicalPath",
625
+ "nearestExistingParent",
626
+ "remainingPath",
627
+ "parentIdentity",
628
+ ].every((key) => equal(left[key], right[key]));
629
+ }
630
+
631
+ function settleTransition({ prepared, guard, contexts, outcome }) {
632
+ const pending = validateLedger({ record: prepared });
633
+ if (pending.phase !== "prepared") fail("CC_SETTINGS_AUTHORITY_NOT_PREPARED");
634
+ validateGuard({ guard, prepared: pending });
635
+ if (!["before", "after"].includes(outcome)) fail();
636
+ const observed = copyData(contexts);
637
+ inverseHeads(observed, pending.platform);
638
+ const intent = pending.transition.intent;
639
+ const expectedContexts =
640
+ intent.kind === "register" && outcome === "after"
641
+ ? [...pending.contexts, intent.manifest]
642
+ : pending.contexts;
643
+ if (observed.length !== expectedContexts.length)
644
+ fail("CC_SETTINGS_AUTHORITY_BINDING_CHANGED");
645
+ for (let i = 0; i < expectedContexts.length; i++) {
646
+ const old = expectedContexts[i];
647
+ const next = observed[i];
648
+ if (
649
+ old.contextId !== next.contextId ||
650
+ !equal(old.discovery, next.discovery) ||
651
+ old.sources.length !== next.sources.length
652
+ )
653
+ fail("CC_SETTINGS_AUTHORITY_BINDING_CHANGED");
654
+ for (let j = 0; j < old.sources.length; j++) {
655
+ const prior = old.sources[j];
656
+ const source = next.sources[j];
657
+ if (
658
+ intent.kind !== "write" ||
659
+ prior.physicalPath !== intent.physicalPath
660
+ ) {
661
+ if (!equal(prior, source))
662
+ fail("CC_SETTINGS_AUTHORITY_BINDING_CHANGED");
663
+ continue;
664
+ }
665
+ if (!sameBinding(prior, source))
666
+ fail("CC_SETTINGS_AUTHORITY_BINDING_CHANGED");
667
+ const wanted = outcome === "after" ? intent.after : prior;
668
+ if (
669
+ !["exists", "byteLength", "digest"].every(
670
+ (key) => source[key] === wanted[key],
671
+ )
672
+ )
673
+ fail("CC_SETTINGS_AUTHORITY_CONTENT_MISMATCH");
674
+ }
675
+ }
676
+ // Both completion and verified-old recovery consume the prepared generation.
677
+ // Never retain a pending transaction in a ready record or decrement revision.
678
+ return validateLedger({
679
+ record: readyRecord({
680
+ platform: pending.platform,
681
+ epoch: pending.epoch,
682
+ generation: pending.generation,
683
+ contexts: observed,
684
+ }),
685
+ });
686
+ }
687
+
688
+ module.exports = {
689
+ LEDGER_SCHEMA,
690
+ GUARD_SCHEMA,
691
+ LIMITS,
692
+ createManifest,
693
+ createInitialLedger,
694
+ validateLedger,
695
+ validateGuard,
696
+ recordDigest,
697
+ assertContextMatches,
698
+ prepareTransition,
699
+ registerContext,
700
+ settleTransition,
701
+ };