chainlesschain 0.166.85 → 0.166.86

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 (178) hide show
  1. package/README.md +8 -0
  2. package/package.json +3 -2
  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-Cgo7OFpi.js → AIOps-DZwiXAIh.js} +1 -1
  6. package/src/assets/web-panel/assets/{ActionButton-lUMnE2Ln.js → ActionButton-aNzXoIJP.js} +1 -1
  7. package/src/assets/web-panel/assets/{Analytics-CsvKzTot.js → Analytics-ETQk4ZXt.js} +3 -3
  8. package/src/assets/web-panel/assets/{AppLayout-C2z1h1Pv.js → AppLayout-D5oEbeEC.js} +3 -3
  9. package/src/assets/web-panel/assets/{Artifacts-C5Q0ZhNb.js → Artifacts-ja48FAne.js} +1 -1
  10. package/src/assets/web-panel/assets/{Audit-DXnfPKsI.js → Audit-DlN0YnDt.js} +1 -1
  11. package/src/assets/web-panel/assets/{BackgroundAgents-DjbGcLm3.js → BackgroundAgents-CzvyNsRg.js} +1 -1
  12. package/src/assets/web-panel/assets/{Backup-9bVrKvXE.js → Backup-DXgEC2MQ.js} +1 -1
  13. package/src/assets/web-panel/assets/{BaseInput-bx5ri7BD.js → BaseInput-D9XqejLx.js} +1 -1
  14. package/src/assets/web-panel/assets/{Chat-CCFmeUMY.js → Chat-BTwuYUlN.js} +4 -4
  15. package/src/assets/web-panel/assets/ChatBubbleRenderer-0anIC2Wn.js +1 -0
  16. package/src/assets/web-panel/assets/{Checkbox-ei7MQXe9.js → Checkbox-CLuaQbDt.js} +1 -1
  17. package/src/assets/web-panel/assets/{Codegen-CXgBJ9iu.js → Codegen-KwQUZs8A.js} +1 -1
  18. package/src/assets/web-panel/assets/{Col-DMkMsizS.js → Col-BCmROkzc.js} +1 -1
  19. package/src/assets/web-panel/assets/{Community-CvpB_UFR.js → Community-CXlUEHR4.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compact-gay5hbFX.js → Compact-Dzx-lWI2.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compliance-dG8JQyRL.js → Compliance-CfXW82FF.js} +1 -1
  22. package/src/assets/web-panel/assets/{Cowork-BA3xfaTW.js → Cowork-DIISTRm2.js} +4 -4
  23. package/src/assets/web-panel/assets/{Cron-D1_HsxyY.js → Cron-nyJ-KcFE.js} +2 -2
  24. package/src/assets/web-panel/assets/{Crosschain-DZqoqoy5.js → Crosschain-Dtv1E4cV.js} +1 -1
  25. package/src/assets/web-panel/assets/{DID-Cwnr8hCO.js → DID-BCTpektS.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dashboard-CxevypiI.js → Dashboard-C1Q_m0So.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dropdown-Bs7-yWgr.js → Dropdown-BrQ5_PPL.js} +1 -1
  28. package/src/assets/web-panel/assets/{EmailListRenderer-CcEs2Puo.js → EmailListRenderer-DjoNlONP.js} +1 -1
  29. package/src/assets/web-panel/assets/{EvolutionSettings-C9ipBzAQ.js → EvolutionSettings-DaGaE6bX.js} +1 -1
  30. package/src/assets/web-panel/assets/{FamilyGuardDashboard-Dt6--mGn.js → FamilyGuardDashboard-nJDWBECt.js} +1 -1
  31. package/src/assets/web-panel/assets/{Federation-CD0JN5FF.js → Federation-DhMUY_wG.js} +1 -1
  32. package/src/assets/web-panel/assets/{FormItemContext-POypz3Xv.js → FormItemContext-CbONJPuc.js} +1 -1
  33. package/src/assets/web-panel/assets/{GenericCardRenderer-Dv9f-0F5.js → GenericCardRenderer-CDdX4dX-.js} +1 -1
  34. package/src/assets/web-panel/assets/{Git-BbTh5Atv.js → Git-DXbDVJdR.js} +2 -2
  35. package/src/assets/web-panel/assets/{Governance-C71dgoir.js → Governance-DbAfAvs1.js} +1 -1
  36. package/src/assets/web-panel/assets/{Inference-DwSHxbJB.js → Inference-Dy-fGea2.js} +1 -1
  37. package/src/assets/web-panel/assets/{KnowledgeGraph-Cx1oQYQZ.js → KnowledgeGraph-DAxRpGUF.js} +1 -1
  38. package/src/assets/web-panel/assets/{Logs-BAJWe00o.js → Logs-5L1UCR8X.js} +2 -2
  39. package/src/assets/web-panel/assets/{MarkdownRenderer-CD8a7lHT.js → MarkdownRenderer-u0FPafvT.js} +1 -1
  40. package/src/assets/web-panel/assets/{Marketplace-fwuY7P7Y.js → Marketplace-DUk_McDG.js} +1 -1
  41. package/src/assets/web-panel/assets/{McpTools-Di4693uc.js → McpTools-B6PNsZ_p.js} +2 -2
  42. package/src/assets/web-panel/assets/{Memory-Cz3L-GUB.js → Memory-BUUs8j5F.js} +2 -2
  43. package/src/assets/web-panel/assets/{MobileBridge-BuXKIkSb.js → MobileBridge-pXRsgyuO.js} +1 -1
  44. package/src/assets/web-panel/assets/MobileProjects-D7v-2Hwm.js +1 -0
  45. package/src/assets/web-panel/assets/{Mtc-LnACMFd0.js → Mtc-Deaj4faB.js} +6 -6
  46. package/src/assets/web-panel/assets/{MtcAudit-BZy7yE0t.js → MtcAudit-wUV0VUH1.js} +2 -2
  47. package/src/assets/web-panel/assets/{Multisig-BFG5iVrE.js → Multisig-C67IIkts.js} +3 -3
  48. package/src/assets/web-panel/assets/{NLProgramming-DgXi04vJ.js → NLProgramming-BCA_CWrW.js} +1 -1
  49. package/src/assets/web-panel/assets/{Notes-BAj0Kgg4.js → Notes-D9eu14hQ.js} +4 -4
  50. package/src/assets/web-panel/assets/{NotificationSettings-AixrsHw5.js → NotificationSettings-Cnd-J4LM.js} +1 -1
  51. package/src/assets/web-panel/assets/{OrderTableRenderer-Dwqk3FlG.js → OrderTableRenderer-C4pHUuyZ.js} +1 -1
  52. package/src/assets/web-panel/assets/{Organization-UNCBC3ux.js → Organization-4YExAbnp.js} +4 -4
  53. package/src/assets/web-panel/assets/{Overflow-Drh8oAFT.js → Overflow-BF-wFuZz.js} +1 -1
  54. package/src/assets/web-panel/assets/{P2P-bc2q0xEB.js → P2P-CdiajqCT.js} +2 -2
  55. package/src/assets/web-panel/assets/{PdhVaultBrowser-BGwKxcDM.js → PdhVaultBrowser-BkjfS6Th.js} +3 -3
  56. package/src/assets/web-panel/assets/{Permissions-DOnUxUzu.js → Permissions-DrZ4D78_.js} +4 -4
  57. package/src/assets/web-panel/assets/{PersonalDataHub-B3qPZkrr.js → PersonalDataHub-lDc6OXjz.js} +6 -6
  58. package/src/assets/web-panel/assets/{Pipeline-B6hfa4-i.js → Pipeline-DqDS9ON1.js} +1 -1
  59. package/src/assets/web-panel/assets/{Privacy-Bun3c35F.js → Privacy-BMekZRZu.js} +1 -1
  60. package/src/assets/web-panel/assets/{ProjectInit-CCObdzk9.js → ProjectInit-LYS7NFvJ.js} +2 -2
  61. package/src/assets/web-panel/assets/{ProjectSettings-C6lKrSXY.js → ProjectSettings-CcJNHk9A.js} +2 -2
  62. package/src/assets/web-panel/assets/{Projects-DYcta7MZ.js → Projects-DrfAHgdF.js} +1 -1
  63. package/src/assets/web-panel/assets/{Providers-BtykxKCe.js → Providers-aqsly9SR.js} +1 -1
  64. package/src/assets/web-panel/assets/{QrScannerModal-D9CDyroY.js → QrScannerModal-ZWvR3zqg.js} +1 -1
  65. package/src/assets/web-panel/assets/{QuickAsk-CJauCxXx.js → QuickAsk-BT5CgsvW.js} +1 -1
  66. package/src/assets/web-panel/assets/{Recommend-BbiYZofR.js → Recommend-Cz8Dz2RN.js} +1 -1
  67. package/src/assets/web-panel/assets/{RemoteSession-BymCrgFW.js → RemoteSession-BlxPVbtQ.js} +2 -2
  68. package/src/assets/web-panel/assets/{Reputation-BWrGpMpF.js → Reputation-B3VGBE-1.js} +1 -1
  69. package/src/assets/web-panel/assets/{Row-9pOYIhiW.js → Row-Bwv7vSEA.js} +1 -1
  70. package/src/assets/web-panel/assets/{RssFeed-D3bQJ4qB.js → RssFeed-DHI085r_.js} +2 -2
  71. package/src/assets/web-panel/assets/{Search-BpKOOFE0.js → Search-DBler5T0.js} +1 -1
  72. package/src/assets/web-panel/assets/{Security-DC6C0NSz.js → Security-BZdw43NW.js} +4 -4
  73. package/src/assets/web-panel/assets/{Services-Lkf1046J.js → Services-Cslk5lUj.js} +2 -2
  74. package/src/assets/web-panel/assets/{Skeleton-eCQ_SsDb.js → Skeleton-Bur-C-25.js} +1 -1
  75. package/src/assets/web-panel/assets/Skills-v0zgLy0X.js +1 -0
  76. package/src/assets/web-panel/assets/{Sla-BQbKy8XJ.js → Sla-B1OWgQ51.js} +1 -1
  77. package/src/assets/web-panel/assets/{SpeechSettings-DHsRx-XA.js → SpeechSettings-CaBcEaV4.js} +1 -1
  78. package/src/assets/web-panel/assets/{SyncSettings-CC281X_J.js → SyncSettings-CBbG8L6J.js} +2 -2
  79. package/src/assets/web-panel/assets/Tasks-C7EjXrnN.js +1 -0
  80. package/src/assets/web-panel/assets/{Templates-Cr2vC0tg.js → Templates-VBBOZ1H5.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tenant-DeYO5pIG.js → Tenant-CtQTj7IF.js} +1 -1
  82. package/src/assets/web-panel/assets/{Terminal-DBNgbfPr.js → Terminal-DXVTQjnl.js} +2 -2
  83. package/src/assets/web-panel/assets/{TimelineRenderer-MoxgaF3x.js → TimelineRenderer-BRIno0aN.js} +1 -1
  84. package/src/assets/web-panel/assets/{Tokens-CT2QfAN7.js → Tokens-uiiAfkYN.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trigger-DPUnomxs.js → Trigger-CPApN8o6.js} +1 -1
  86. package/src/assets/web-panel/assets/{Trust-DnufuaTx.js → Trust-T2jKVwCE.js} +1 -1
  87. package/src/assets/web-panel/assets/{UkeySign-CJ6iOdPs.js → UkeySign-C2U_gbzP.js} +1 -1
  88. package/src/assets/web-panel/assets/{VideoEditing-xBWkH8bL.js → VideoEditing-BCdlr3Kj.js} +1 -1
  89. package/src/assets/web-panel/assets/{Wallet-WYV-4hMR.js → Wallet-CWnjoSc1.js} +4 -4
  90. package/src/assets/web-panel/assets/{WebAuthn-DJ5Mhd9L.js → WebAuthn-CqSbYqHq.js} +4 -4
  91. package/src/assets/web-panel/assets/{WorkflowEditor-B__UdOjN.js → WorkflowEditor-Dr_I3jcr.js} +1 -1
  92. package/src/assets/web-panel/assets/{chat-CLlmBVhp.js → chat-Cg21FKdE.js} +1 -1
  93. package/src/assets/web-panel/assets/{colors-B8zoPQYm.js → colors-CK85tY9e.js} +1 -1
  94. package/src/assets/web-panel/assets/{compact-item-CvJ-dUsH.js → compact-item-m-XYPC7W.js} +1 -1
  95. package/src/assets/web-panel/assets/{createContext-LAtMm8SC.js → createContext-BmiEeNvs.js} +1 -1
  96. package/src/assets/web-panel/assets/devWarning-CkMEODFC.js +1 -0
  97. package/src/assets/web-panel/assets/{hasIn-CLYvg42H.js → hasIn-CCw4KAoc.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-B02qgCao.js → index-6jXf-Lln.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-B6zlMzZz.js → index-8KzhlvJ9.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BCzyJ1xS.js → index-B7xJkhtJ.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-Di9vKira.js → index-B8IC9ZeZ.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-DfOOACfd.js → index-BGUYgc96.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DDm9m4vC.js → index-BGb1j2z9.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-DX0aHEHL.js → index-BHsiSoGY.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-BUVrYDNV.js → index-BIOTRzaF.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-CUcE6rIa.js → index-BStyjmLG.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-DNQUdPam.js → index-BUYyhYP6.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-CxJ4NPVq.js → index-BcfVHmFK.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-4rr5jFOL.js → index-BiVPFsat.js} +1 -1
  110. package/src/assets/web-panel/assets/index-BjE5qaKn.js +1 -0
  111. package/src/assets/web-panel/assets/{index-C3uD5H7u.js → index-Br0ZNdu1.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-C5v7cEtm.js → index-Br9t_I1X.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-DX99e8Xy.js → index-BtvVupUL.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BGrQ2uEl.js → index-Bv90WEWa.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-Cpda0SAz.js → index-BvjC3t35.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-Cv7vwX3z.js → index-ByVvAXdl.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-D0Z13xcZ.js → index-CBcgIWOe.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-DYW4Z3y-.js → index-CN2xbLGz.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-f1ptYBMr.js → index-CYEzWoyZ.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-C_dq-6_3.js → index-Cf5arJie.js} +1 -1
  121. package/src/assets/web-panel/assets/index-CsFH-2Zk.js +1 -0
  122. package/src/assets/web-panel/assets/{index-C2KFnUsv.js → index-D1sU5-XA.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-B_RPWP_5.js → index-D7gS_TJl.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-iJ6s24bA.js → index-DAlGVix-.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-Bu7-I2L4.js → index-DI9GJFcn.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-C6PETyel.js → index-DIlGxS2W.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-CVDcRQuX.js → index-DMbrl43d.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-BkcQJvsz.js → index-DmSgfXuz.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-DHq2Of6z.js → index-DpIy2HzE.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-BM2HqHdT.js → index-DxRhnsEC.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-GR3omApz.js → index-IskAKXhx.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-B1hHp9_M.js → index-J81uvUMN.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-DpeV-6y4.js → index-OIbfsi-o.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-oX216HRH.js → index-lhoexBDH.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-CnLXLaEF.js → index-sWUmvT8H.js} +1 -1
  136. package/src/assets/web-panel/assets/{index-09YzRb6Z.js → index-yYmjkf38.js} +3 -3
  137. package/src/assets/web-panel/assets/{initDefaultProps-QD-koeaw.js → initDefaultProps-Cc1XOmNe.js} +1 -1
  138. package/src/assets/web-panel/assets/{motion-CTItLW4-.js → motion-BehsX88u.js} +1 -1
  139. package/src/assets/web-panel/assets/{move-CGsdTOdN.js → move-BPx2YsqY.js} +1 -1
  140. package/src/assets/web-panel/assets/{mtc-parser-C1kW_CNU.js → mtc-parser-BSFJgFQA.js} +1 -1
  141. package/src/assets/web-panel/assets/{omit-B4PilaYy.js → omit-DBN5KUeo.js} +1 -1
  142. package/src/assets/web-panel/assets/{pickAttrs-DBGUE12e.js → pickAttrs-BDK1yZ-9.js} +1 -1
  143. package/src/assets/web-panel/assets/{placementArrow-DZxCLjuo.js → placementArrow-C4rMmKNJ.js} +1 -1
  144. package/src/assets/web-panel/assets/{responsiveObserve-CZjQiocN.js → responsiveObserve-BoeoOnxX.js} +1 -1
  145. package/src/assets/web-panel/assets/{slide-Btz5hh2_.js → slide-BKlr1bl9.js} +1 -1
  146. package/src/assets/web-panel/assets/{statusUtils-CfuxuLIt.js → statusUtils-Ky1apWPI.js} +1 -1
  147. package/src/assets/web-panel/assets/{styleChecker-DdO0Obo_.js → styleChecker-DxxR7uXk.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFlexGapSupport-CxftJ-Zs.js → useFlexGapSupport-DmsUqVe9.js} +1 -1
  149. package/src/assets/web-panel/assets/{useFs-pVJChh6K.js → useFs-CwkG7sOg.js} +1 -1
  150. package/src/assets/web-panel/assets/{usePersonalDataHub-wv7Q0uNE.js → usePersonalDataHub-CddgeEfF.js} +1 -1
  151. package/src/assets/web-panel/assets/{vnode-DVOVfAqC.js → vnode-C_-H8i4Y.js} +1 -1
  152. package/src/assets/web-panel/assets/{zoom-B5tebZuT.js → zoom-aAsHUMNE.js} +1 -1
  153. package/src/assets/web-panel/index.html +1 -1
  154. package/src/data/changelog.json +13 -0
  155. package/src/lib/context-memory-kernel/durable-memory-port.js +5 -2
  156. package/src/lib/context-memory-kernel/index.js +1 -0
  157. package/src/lib/context-memory-kernel/memory-service.js +43 -16
  158. package/src/lib/context-memory-kernel/runtime.js +5 -3
  159. package/src/lib/context-memory-kernel/segmented-memory-port.js +687 -0
  160. package/src/lib/packer/pack-update-applier.js +13 -8
  161. package/src/lib/permission-authority.js +146 -10
  162. package/src/lib/sandbox-egress-authority-monitor.js +62 -5
  163. package/src/lib/scoped-permission-store.js +104 -1
  164. package/src/lib/settings-authority-domain.cjs +37 -2
  165. package/src/lib/settings-loader.cjs +67 -34
  166. package/src/lib/settings-permission-authority.cjs +373 -0
  167. package/src/runtime/agent-core.js +79 -383
  168. package/src/runtime/headless-runner.js +8 -3
  169. package/src/runtime/headless-stream.js +10 -3
  170. package/src/runtime/permission-authority-host.js +137 -0
  171. package/src/runtime/provider-stream-state.js +379 -0
  172. package/src/assets/web-panel/assets/ChatBubbleRenderer-ClqsIfTT.js +0 -1
  173. package/src/assets/web-panel/assets/MobileProjects-Bk-lK4Um.js +0 -1
  174. package/src/assets/web-panel/assets/Skills-BvDSQ3-d.js +0 -1
  175. package/src/assets/web-panel/assets/Tasks-CHHSWHom.js +0 -1
  176. package/src/assets/web-panel/assets/devWarning-DgZ4fdGI.js +0 -1
  177. package/src/assets/web-panel/assets/index-jLEdASOV.js +0 -1
  178. package/src/assets/web-panel/assets/index-jesGo4rl.js +0 -1
@@ -853,6 +853,11 @@ async function scheduleWindowsTransaction(ctx) {
853
853
  function windowsGenerationJournalHelperSource() {
854
854
  return String.raw`param()
855
855
  $ErrorActionPreference = 'Stop'
856
+ # The journal contains only JSON primitives. Use the inbox .NET serializer and
857
+ # file/path APIs so each phase does not repeat PowerShell module discovery.
858
+ # Keep the same synchronous atomic replacement and durable flush protocol.
859
+ [void][Reflection.Assembly]::Load('System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35')
860
+ $Serializer = [Web.Script.Serialization.JavaScriptSerializer]::new()
856
861
  $Action = [string]$env:JOURNAL_ACTION
857
862
  $JournalPath = [string]$env:JOURNAL_FILE
858
863
  $RetiredPath = [string]$env:JOURNAL_RETIRED
@@ -872,7 +877,7 @@ if (($Phase -eq 'committed') -ne ($Decision -eq 'commit')) { throw 'Invalid phas
872
877
  if ($Action -eq 'write' -and $Phase -eq 'prepared') {
873
878
  if ([IO.File]::Exists($JournalPath)) { throw 'A generation journal already exists' }
874
879
  $Bytes = [Convert]::FromBase64String([string]$env:JOURNAL_INITIAL_BASE64)
875
- $Journal = [Text.Encoding]::UTF8.GetString($Bytes) | ConvertFrom-Json
880
+ $Journal = $Serializer.DeserializeObject([Text.Encoding]::UTF8.GetString($Bytes))
876
881
  $ParentSource = @'
877
882
  using System;
878
883
  using System.Runtime.InteropServices;
@@ -900,10 +905,10 @@ public static class CcParentProcess {
900
905
  }
901
906
  '@
902
907
  Add-Type -TypeDefinition $ParentSource -Language CSharp
903
- $Journal | Add-Member -NotePropertyName ownerPid -NotePropertyValue ([CcParentProcess]::Get())
908
+ $Journal.Add('ownerPid', [CcParentProcess]::Get())
904
909
  } else {
905
910
  if (-not [IO.File]::Exists($JournalPath)) { throw 'Generation journal is missing' }
906
- $Journal = Get-Content -Raw -LiteralPath $JournalPath | ConvertFrom-Json
911
+ $Journal = $Serializer.DeserializeObject([IO.File]::ReadAllText($JournalPath, [Text.Encoding]::UTF8))
907
912
  }
908
913
 
909
914
  $ValidBefore = {
@@ -931,7 +936,7 @@ if ($Action -eq 'retire') {
931
936
  if ([string]$Journal.phase -ne $Phase -or [string]$Journal.decision -ne $Decision) {
932
937
  throw 'Generation journal decision changed before retirement'
933
938
  }
934
- $ReplacedPath = Join-Path (Split-Path -Parent $JournalPath) ('.chainlesschain.journal-retired-previous-' + [guid]::NewGuid().ToString('N'))
939
+ $ReplacedPath = [IO.Path]::Combine([IO.Path]::GetDirectoryName($JournalPath), ('.chainlesschain.journal-retired-previous-' + [guid]::NewGuid().ToString('N')))
935
940
  try {
936
941
  if ([IO.File]::Exists($RetiredPath)) {
937
942
  [IO.File]::Replace($JournalPath, $RetiredPath, $ReplacedPath, $true)
@@ -985,11 +990,11 @@ if ($Phase -ne 'prepared') {
985
990
  $Journal.phase = $Phase
986
991
  $Journal.decision = $Decision
987
992
  $Journal.updatedAt = [DateTimeOffset]::UtcNow.ToString('o')
988
- $Directory = Split-Path -Parent $JournalPath
989
- $StagingPath = Join-Path $Directory ('.chainlesschain.journal-' + [guid]::NewGuid().ToString('N'))
990
- $ReplacedPath = Join-Path $Directory ('.chainlesschain.journal-previous-' + [guid]::NewGuid().ToString('N'))
993
+ $Directory = [IO.Path]::GetDirectoryName($JournalPath)
994
+ $StagingPath = [IO.Path]::Combine($Directory, ('.chainlesschain.journal-' + [guid]::NewGuid().ToString('N')))
995
+ $ReplacedPath = [IO.Path]::Combine($Directory, ('.chainlesschain.journal-previous-' + [guid]::NewGuid().ToString('N')))
991
996
  try {
992
- $Payload = $Journal | ConvertTo-Json -Compress -Depth 8
997
+ $Payload = $Serializer.Serialize($Journal)
993
998
  $PayloadBytes = [Text.UTF8Encoding]::new($false).GetBytes($Payload + [Environment]::NewLine)
994
999
  $Stream = [IO.File]::Open($StagingPath, [IO.FileMode]::CreateNew, [IO.FileAccess]::Write, [IO.FileShare]::None)
995
1000
  try {
@@ -1,11 +1,13 @@
1
1
  /** Resolve static settings plus CLI-owned workspace-scoped permission rules. */
2
2
 
3
3
  import settingsLoader from "./settings-loader.cjs";
4
+ import persistentSettings from "./settings-permission-authority.cjs";
4
5
  import path from "node:path";
5
6
  import {
6
7
  ScopedPermissionStore,
7
8
  getScopedPermissionRevision,
8
9
  subscribeScopedPermissionRevision,
10
+ projectScopedPermissionObservation,
9
11
  } from "./scoped-permission-store.js";
10
12
 
11
13
  const {
@@ -86,16 +88,41 @@ export function loadPermissionAuthority({
86
88
  env = process.env,
87
89
  baseRules = null,
88
90
  scopedStore = null,
91
+ settingsAuthority: persistentAuthority = null,
89
92
  } = {}) {
90
93
  const settingsRevision = getSettingsPermissionRevision();
91
94
  const scopedRevision = baseRules ? null : getScopedPermissionRevision();
92
- const settingsObservation = inspectSettingsSources({
93
- cwd,
94
- settingsFile,
95
- managedSettingsFile,
96
- env,
97
- });
98
- const loaded = projectSettingsObservation(settingsObservation, { env });
95
+ const persistent = persistentAuthority
96
+ ? persistentSettings.readSettingsPermissionAuthority(persistentAuthority)
97
+ : null;
98
+ if (persistentAuthority) {
99
+ const bound =
100
+ persistentSettings.settingsPermissionAuthorityOptions(
101
+ persistentAuthority,
102
+ );
103
+ if (
104
+ path.resolve(cwd) !== bound.cwd ||
105
+ (settingsFile &&
106
+ path.resolve(cwd, settingsFile) !== bound.settingsFile) ||
107
+ (managedSettingsFile &&
108
+ path.resolve(managedSettingsFile) !== bound.managedSettingsFile)
109
+ )
110
+ throw new TypeError("persistent settings authority options mismatch");
111
+ }
112
+ const settingsObservation =
113
+ persistent?.observation ||
114
+ inspectSettingsSources({
115
+ cwd,
116
+ settingsFile,
117
+ managedSettingsFile,
118
+ env,
119
+ });
120
+ const loaded = persistent
121
+ ? persistentSettings.projectSettingsPermissionObservation(
122
+ settingsObservation,
123
+ { env },
124
+ )
125
+ : projectSettingsObservation(settingsObservation, { env });
99
126
  const sources = baseRules ? {} : { ...loaded.sources };
100
127
  let rules = baseRules
101
128
  ? applyManagedPermissionPolicy(baseRules, loaded.managed, sources)
@@ -105,7 +132,29 @@ export function loadPermissionAuthority({
105
132
  // Explicit caller rules retain their historical replacement semantics.
106
133
  // Managed-only policy also suppresses every user-owned scoped grant.
107
134
  if (!baseRules) {
108
- scoped = (scopedStore || new ScopedPermissionStore({ cwd })).list();
135
+ const bound = persistentAuthority
136
+ ? persistentSettings.settingsPermissionAuthorityOptions(
137
+ persistentAuthority,
138
+ )
139
+ : null;
140
+ const store =
141
+ scopedStore ||
142
+ new ScopedPermissionStore({
143
+ cwd,
144
+ ...(bound
145
+ ? {
146
+ filePath: bound.scopedFile,
147
+ settingsAuthority: persistentAuthority,
148
+ }
149
+ : {}),
150
+ });
151
+ scoped = persistent
152
+ ? projectScopedPermissionObservation(
153
+ store,
154
+ persistentAuthority,
155
+ persistent.scopedObservation,
156
+ )
157
+ : store.list();
109
158
  const managedOnly =
110
159
  loaded.managed?.allowManagedPermissionRulesOnly === true;
111
160
  scoped = {
@@ -143,6 +192,17 @@ export function loadPermissionAuthority({
143
192
  error.code = "CC_SCOPED_PERMISSION_AUTHORITY_CHANGED";
144
193
  throw error;
145
194
  }
195
+ if (
196
+ persistent &&
197
+ persistentSettings.readSettingsPermissionAuthority(persistentAuthority)
198
+ .snapshot !== persistent.snapshot
199
+ ) {
200
+ const error = new Error(
201
+ "persistent settings changed while permission authority was loading",
202
+ );
203
+ error.code = "CC_SETTINGS_PERMISSION_AUTHORITY_CHANGED";
204
+ throw error;
205
+ }
146
206
  return freezeSnapshot({
147
207
  ...loaded,
148
208
  rules,
@@ -151,12 +211,17 @@ export function loadPermissionAuthority({
151
211
  hasRules: hasRules(rules),
152
212
  settingsRevision,
153
213
  settingsObservation,
214
+ ...(persistent ? { persistentSettingsRevision: persistent.snapshot } : {}),
154
215
  ...(scopedRevision ? { scopedRevision } : {}),
155
216
  });
156
217
  }
157
218
 
158
219
  export function createPermissionRulesProvider(options = {}) {
159
- const cwd = path.resolve(options.cwd || process.cwd());
220
+ const persistentAuthority = options.settingsAuthority ?? null;
221
+ const bound = persistentAuthority
222
+ ? persistentSettings.settingsPermissionAuthorityOptions(persistentAuthority)
223
+ : null;
224
+ const cwd = path.resolve(options.cwd || bound?.cwd || process.cwd());
160
225
  const captured = Object.freeze({
161
226
  cwd,
162
227
  settingsFile: options.settingsFile
@@ -172,15 +237,86 @@ export function createPermissionRulesProvider(options = {}) {
172
237
  ? freezeSnapshot(cloneRules(options.baseRules))
173
238
  : null,
174
239
  scopedStore: options.scopedStore || null,
240
+ settingsAuthority: persistentAuthority,
175
241
  });
242
+ if (
243
+ bound &&
244
+ (cwd !== bound.cwd ||
245
+ (captured.settingsFile && captured.settingsFile !== bound.settingsFile) ||
246
+ (captured.managedSettingsFile &&
247
+ captured.managedSettingsFile !== bound.managedSettingsFile))
248
+ )
249
+ throw new TypeError("persistent settings authority options mismatch");
176
250
  const provider = () => loadPermissionAuthority(captured);
251
+ const localAuthority = captured.baseRules
252
+ ? settingsAuthority
253
+ : combinedAuthority;
177
254
  providers.set(
178
255
  provider,
179
- captured.baseRules ? settingsAuthority : combinedAuthority,
256
+ persistentAuthority
257
+ ? persistentProviderAuthority(persistentAuthority, localAuthority)
258
+ : localAuthority,
180
259
  );
181
260
  return Object.freeze(provider);
182
261
  }
183
262
 
263
+ function persistentProviderAuthority(binding, localAuthority) {
264
+ let last = null;
265
+ function getSnapshot() {
266
+ const local = localAuthority.getSnapshot();
267
+ const durable =
268
+ persistentSettings.readSettingsPermissionAuthority(binding).snapshot;
269
+ if (last?.local !== local || last?.durable !== durable)
270
+ last = Object.freeze({ local, durable });
271
+ return last;
272
+ }
273
+ return Object.freeze({
274
+ getSnapshot,
275
+ assertWorkspace(cwd) {
276
+ if (
277
+ path.resolve(cwd) !==
278
+ persistentSettings.settingsPermissionAuthorityOptions(binding).cwd
279
+ )
280
+ throw Object.assign(
281
+ new Error("persistent permission authority workspace mismatch"),
282
+ { code: "CC_SETTINGS_AUTHORITY_BINDING_CHANGED" },
283
+ );
284
+ },
285
+ assertWritableRoots(roots) {
286
+ persistentSettings.assertSettingsPermissionWritableRoots(binding, roots);
287
+ },
288
+ subscribePolicyRevision(listener) {
289
+ if (typeof listener !== "function")
290
+ throw new TypeError("permission revision listener must be a function");
291
+ let known = getSnapshot();
292
+ const remove = localAuthority.subscribePolicyRevision(listener);
293
+ // Persistence prevents official ABA loss between polls. Timers provide
294
+ // bounded observation, not a promise that another process has stopped
295
+ // before synchronous addRule returns.
296
+ const timer = setInterval(() => {
297
+ let next;
298
+ try {
299
+ next = getSnapshot();
300
+ } catch {
301
+ next = null;
302
+ }
303
+ if (next === known) return;
304
+ known = next;
305
+ try {
306
+ listener(next);
307
+ } catch {
308
+ /* isolate observers */
309
+ }
310
+ }, 100);
311
+ timer.unref?.();
312
+ return () => {
313
+ clearInterval(timer);
314
+ remove();
315
+ };
316
+ },
317
+ });
318
+ }
319
+
184
320
  // A legacy callback cannot advertise a trusted revision subscription simply
185
321
  // by copying properties onto itself. It still receives sampled revalidation.
186
322
  export function permissionRulesProviderAuthority(provider) {
@@ -1,3 +1,5 @@
1
+ import { randomUUID } from "node:crypto";
2
+
1
3
  /**
2
4
  * Recheck the live shell authority while a Docker egress session exists. This
3
5
  * uses bounded polling as a fallback. Trusted policy owners also call revoke()
@@ -9,19 +11,35 @@ export function createDockerEgressAuthorityMonitor({
9
11
  abortProxy,
10
12
  intervalMs = 500,
11
13
  checkTimeoutMs = 5_000,
14
+ sessionId = null,
15
+ policyVersion = null,
12
16
  }) {
13
17
  if (typeof revalidate !== "function" || typeof abortProxy !== "function")
14
18
  throw new TypeError("Docker egress authority callbacks are required");
19
+ if (
20
+ (sessionId !== null && typeof sessionId !== "string") ||
21
+ (policyVersion !== null && typeof policyVersion !== "string")
22
+ )
23
+ throw new TypeError(
24
+ "Docker egress acknowledgement identities must be strings",
25
+ );
26
+ const stopIdentity = Object.freeze({
27
+ receiverId: randomUUID(),
28
+ sessionId,
29
+ policyVersion,
30
+ });
15
31
  let revoked = null;
16
32
  let session = null;
17
33
  let timer = null;
18
34
  let checking = null;
19
35
  let stopped = false;
20
36
  const cleanupTasks = new Set();
37
+ let proxyStopped = false;
38
+ let sessionStopped = false;
21
39
 
22
- function trackCleanup(operation) {
40
+ function trackCleanup(operation, onStopped) {
23
41
  try {
24
- const task = Promise.resolve(operation());
42
+ const task = Promise.resolve(operation()).then(onStopped);
25
43
  cleanupTasks.add(task);
26
44
  void task.catch((error) => {
27
45
  if (revoked && !revoked.cleanupError) revoked.cleanupError = error;
@@ -41,8 +59,18 @@ export function createDockerEgressAuthorityMonitor({
41
59
  if (!revoked.code) revoked.code = "CC_DOCKER_EGRESS_AUTHORITY_CHANGED";
42
60
  clearTimeout(timer);
43
61
  // Latch first, then cut the broker before closing the target containers.
44
- trackCleanup(abortProxy);
45
- if (session) trackCleanup(() => session.close());
62
+ trackCleanup(abortProxy, () => {
63
+ proxyStopped = true;
64
+ });
65
+ if (session) {
66
+ const closing = session;
67
+ trackCleanup(
68
+ () => closing.close(),
69
+ () => {
70
+ if (session === closing) sessionStopped = true;
71
+ },
72
+ );
73
+ }
46
74
  return revoked;
47
75
  }
48
76
 
@@ -51,9 +79,17 @@ export function createDockerEgressAuthorityMonitor({
51
79
  }
52
80
 
53
81
  function attachSession(value) {
82
+ if (session)
83
+ throw new TypeError("Docker egress monitor session is already attached");
54
84
  session = value;
85
+ sessionStopped = false;
55
86
  if (revoked) {
56
- trackCleanup(() => value.close());
87
+ trackCleanup(
88
+ () => value.close(),
89
+ () => {
90
+ if (session === value) sessionStopped = true;
91
+ },
92
+ );
57
93
  throw revoked;
58
94
  }
59
95
  }
@@ -112,6 +148,7 @@ export function createDockerEgressAuthorityMonitor({
112
148
  }
113
149
 
114
150
  return {
151
+ stopIdentity,
115
152
  get revocationError() {
116
153
  return revoked;
117
154
  },
@@ -134,5 +171,25 @@ export function createDockerEgressAuthorityMonitor({
134
171
  async awaitCleanup() {
135
172
  await Promise.allSettled([...cleanupTasks]);
136
173
  },
174
+ getStopAcknowledgement() {
175
+ // A synchronous writer commit is never a stop ACK. Only the receiving
176
+ // runtime, after stopping checks and awaiting both teardown operations,
177
+ // can report this acknowledgement. Cleanup failures never mint one.
178
+ if (
179
+ !stopped ||
180
+ !revoked ||
181
+ revoked.cleanupError ||
182
+ cleanupTasks.size ||
183
+ !proxyStopped ||
184
+ !sessionStopped
185
+ )
186
+ return null;
187
+ return Object.freeze({
188
+ schema: "chainlesschain.egress-stop-ack/v1",
189
+ ...stopIdentity,
190
+ proxyStopped: true,
191
+ sessionStopped: true,
192
+ });
193
+ },
137
194
  };
138
195
  }
@@ -11,6 +11,7 @@ import path from "node:path";
11
11
  import { createHash, randomUUID } from "node:crypto";
12
12
  import projectRoot from "./project-root.cjs";
13
13
  import permissionRules from "./permission-rules.cjs";
14
+ import persistentSettings from "./settings-permission-authority.cjs";
14
15
  import { getMachineSecurityAnchorDir } from "./paths.js";
15
16
  import {
16
17
  readSecurityStore,
@@ -27,6 +28,7 @@ const STORE_LABEL = "scoped permission";
27
28
  const RULE_ID_PATTERN = /^spr_[0-9a-f]{32}$/;
28
29
  const DECISIONS = new Set(["allow", "ask", "deny"]);
29
30
  const DEFAULT_MAX_RECORDS = 1000;
31
+ const persistentBindings = new WeakMap();
30
32
 
31
33
  // Official mutations revoke every provider in this module instance. Path
32
34
  // matching alone misses aliases and files that did not exist at admission.
@@ -216,6 +218,7 @@ export class ScopedPermissionStore {
216
218
  maxRecords = DEFAULT_MAX_RECORDS,
217
219
  lock = undefined,
218
220
  randomId = () => `spr_${randomUUID().replaceAll("-", "")}`,
221
+ settingsAuthority = null,
219
222
  } = {}) {
220
223
  this.workspace = workspaceBinding(cwd);
221
224
  this.filePath = path.resolve(
@@ -242,6 +245,17 @@ export class ScopedPermissionStore {
242
245
  );
243
246
  this._lock = lock;
244
247
  this._randomId = randomId;
248
+ if (settingsAuthority) {
249
+ const bound =
250
+ persistentSettings.settingsPermissionAuthorityOptions(
251
+ settingsAuthority,
252
+ );
253
+ if (path.resolve(cwd) !== bound.cwd || this.filePath !== bound.scopedFile)
254
+ throw new TypeError(
255
+ "persistent scoped permission authority options mismatch",
256
+ );
257
+ persistentBindings.set(this, settingsAuthority);
258
+ }
245
259
  }
246
260
 
247
261
  _capture() {
@@ -253,7 +267,22 @@ export class ScopedPermissionStore {
253
267
  randomId: this._randomId.bind(this),
254
268
  maxRecords: this.maxRecords,
255
269
  lock: this._lock || withFileLock,
270
+ settingsAuthority: persistentBindings.get(this) || null,
256
271
  });
272
+ if (captured.settingsAuthority) {
273
+ const bound = persistentSettings.settingsPermissionAuthorityOptions(
274
+ captured.settingsAuthority,
275
+ );
276
+ const workspace = workspaceBinding(bound.cwd);
277
+ if (
278
+ captured.filePath !== bound.scopedFile ||
279
+ captured.workspace.id !== workspace.id ||
280
+ captured.workspace.root !== workspace.root
281
+ )
282
+ throw new TypeError(
283
+ "persistent scoped permission authority options mismatch",
284
+ );
285
+ }
257
286
  if (getScopedPermissionRevision() !== revision)
258
287
  throw scopedPermissionError(
259
288
  "CC_SCOPED_PERMISSION_AUTHORITY_CHANGED",
@@ -264,13 +293,54 @@ export class ScopedPermissionStore {
264
293
 
265
294
  _read(captured = this._capture()) {
266
295
  getScopedPermissionRevision();
267
- const stored = readSecurityStore(captured.filePath, STORE_LABEL);
296
+ const stored = captured.settingsAuthority
297
+ ? persistentSettings.readSettingsPermissionAuthority(
298
+ captured.settingsAuthority,
299
+ ).scopedObservation.settings || {}
300
+ : readSecurityStore(captured.filePath, STORE_LABEL);
268
301
  if (Object.keys(stored).length === 0) return emptyState(captured.workspace);
269
302
  return validateState(stored, captured.workspace);
270
303
  }
271
304
 
272
305
  _mutate(captured, update) {
273
306
  getScopedPermissionRevision(); // Reject observer reentry before the lock.
307
+ if (captured.settingsAuthority) {
308
+ let started = false;
309
+ try {
310
+ persistentSettings.mutateSettingsPermissionSource(
311
+ captured.settingsAuthority,
312
+ {
313
+ logicalPath: captured.filePath,
314
+ prepare(draft) {
315
+ if (Object.keys(draft).length === 0)
316
+ Object.assign(draft, emptyState(captured.workspace));
317
+ validateState(draft, captured.workspace);
318
+ if (update(draft) === false) return false;
319
+ validateState(draft, captured.workspace);
320
+ },
321
+ revokeLocal() {
322
+ started = true;
323
+ beginMutation();
324
+ },
325
+ replace(file, draft) {
326
+ validateState(draft, captured.workspace);
327
+ writeSecurityStore(file, STORE_LABEL, draft);
328
+ },
329
+ },
330
+ );
331
+ if (started) finishMutation("ready");
332
+ } catch (error) {
333
+ if (started)
334
+ finishMutation(
335
+ error.commitState === "unknown" ||
336
+ permissionRevision.state === "invalid"
337
+ ? "invalid"
338
+ : "ready",
339
+ );
340
+ throw error;
341
+ }
342
+ return;
343
+ }
274
344
  fs.mkdirSync(path.dirname(captured.filePath), {
275
345
  recursive: true,
276
346
  mode: 0o700,
@@ -487,3 +557,36 @@ export class ScopedPermissionStore {
487
557
  return projectRecord(revoked, now, captured.filePath);
488
558
  }
489
559
  }
560
+
561
+ // Only the production provider uses a scoped observation already validated in
562
+ // the same durable read as settings. A store cannot substitute another source.
563
+ export function projectScopedPermissionObservation(
564
+ store,
565
+ binding,
566
+ observation,
567
+ ) {
568
+ if (persistentBindings.get(store) !== binding)
569
+ throw new TypeError(
570
+ "scoped store must use the provider's persistent authority",
571
+ );
572
+ const captured = ScopedPermissionStore.prototype._capture.call(store);
573
+ if (observation.logicalPath !== captured.filePath)
574
+ throw new TypeError("persistent scoped permission source mismatch");
575
+ const stored = observation.settings || {};
576
+ const state =
577
+ Object.keys(stored).length === 0
578
+ ? emptyState(captured.workspace)
579
+ : validateState(stored, captured.workspace);
580
+ const now = captured.now();
581
+ return Object.freeze({
582
+ schema: state.schema,
583
+ schemaVersion: state.schemaVersion,
584
+ generation: state.generation,
585
+ updatedAt: state.updatedAt,
586
+ workspace: structuredClone(state.workspace),
587
+ file: captured.filePath,
588
+ rules: state.rules.map((record) =>
589
+ projectRecord(record, now, captured.filePath),
590
+ ),
591
+ });
592
+ }
@@ -727,12 +727,24 @@ function transitionSettingsAuthority(
727
727
  replace,
728
728
  revokeLocal,
729
729
  transactionId = randomUUID(),
730
+ expectedSnapshot = null,
731
+ localRevision = null,
730
732
  } = {},
731
733
  ) {
732
734
  const state = stateFor(handle);
733
735
  // Snapshot caller data before any callback. These are trusted host APIs, but
734
736
  // mutable intents must not turn an already-validated no-op into a mutation.
735
737
  intent = plainCopy(intent);
738
+ if (expectedSnapshot !== null) {
739
+ expectedSnapshot = plainCopy(expectedSnapshot);
740
+ shape(expectedSnapshot, [
741
+ "domainId",
742
+ "epoch",
743
+ "generation",
744
+ "digest",
745
+ "state",
746
+ ]);
747
+ }
736
748
  requireSynchronous(observeContexts);
737
749
  requireSynchronous(revokeLocal);
738
750
  if (intent.kind === "write") requireSynchronous(replace);
@@ -743,7 +755,15 @@ function transitionSettingsAuthority(
743
755
  try {
744
756
  return locked(state, () => {
745
757
  const perform = () => {
746
- const current = readSettingsAuthority(handle, { observeContexts });
758
+ const current = readSettingsAuthority(handle, {
759
+ observeContexts,
760
+ localRevision,
761
+ });
762
+ if (
763
+ expectedSnapshot !== null &&
764
+ !sameData(current.snapshot, expectedSnapshot)
765
+ )
766
+ refuse("CC_SETTINGS_AUTHORITY_CONFLICT");
747
767
  if (
748
768
  intent.kind === "register" &&
749
769
  current.ledger.contexts.some(
@@ -841,7 +861,15 @@ function transitionSettingsAuthority(
841
861
  };
842
862
  };
843
863
  if (intent.kind !== "write") return perform();
844
- const admission = readSettingsAuthority(handle, { observeContexts });
864
+ const admission = readSettingsAuthority(handle, {
865
+ observeContexts,
866
+ localRevision,
867
+ });
868
+ if (
869
+ expectedSnapshot !== null &&
870
+ !sameData(admission.snapshot, expectedSnapshot)
871
+ )
872
+ refuse("CC_SETTINGS_AUTHORITY_CONFLICT");
845
873
  records.prepareTransition({
846
874
  ledger: admission.ledger,
847
875
  transactionId,
@@ -878,6 +906,12 @@ function transitionSettingsAuthority(
878
906
  }
879
907
  }
880
908
 
909
+ // Official read/modify/write adapters take an initial snapshot under the same
910
+ // authority lock. The later transition MUST still compare expectedSnapshot.
911
+ function readSettingsAuthorityForUpdate(handle, options) {
912
+ return locked(stateFor(handle), () => readSettingsAuthority(handle, options));
913
+ }
914
+
881
915
  function recoverSettingsAuthority(
882
916
  handle,
883
917
  { transactionId, observeContexts, outcome } = {},
@@ -954,6 +988,7 @@ function recoverSettingsAuthority(
954
988
  }
955
989
 
956
990
  module.exports = {
991
+ readSettingsAuthorityForUpdate,
957
992
  DOMAIN_SCHEMA,
958
993
  initializeSettingsAuthorityDomain,
959
994
  pinSettingsAuthorityDomain,