@remnic/core 9.54.5 → 9.54.6

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 (550) hide show
  1. package/dist/access-admin-ops-surface.d.ts +24 -24
  2. package/dist/access-admin-ops-surface.js +32 -29
  3. package/dist/access-authorization-probe.d.ts +25 -23
  4. package/dist/access-authorization-probe.js +35 -30
  5. package/dist/access-boundary.d.ts +26 -24
  6. package/dist/access-boundary.js +36 -31
  7. package/dist/access-cli.js +86 -80
  8. package/dist/access-cli.js.map +1 -1
  9. package/dist/access-coding-context-resolution.d.ts +1 -1
  10. package/dist/access-extraction-force-flush.d.ts +19 -19
  11. package/dist/access-extraction-force-flush.js +32 -29
  12. package/dist/access-health-types.d.ts +1 -1
  13. package/dist/access-http-lcm-compaction.d.ts +22 -22
  14. package/dist/access-http-lifecycle-flush.d.ts +22 -22
  15. package/dist/access-http-offline-stream.d.ts +18 -18
  16. package/dist/access-http-query.js +32 -29
  17. package/dist/access-http.d.ts +55 -37
  18. package/dist/access-http.js +52 -43
  19. package/dist/access-identity-continuity-surface.d.ts +9 -9
  20. package/dist/access-identity-continuity-surface.js +32 -29
  21. package/dist/access-lcm-surface.d.ts +21 -21
  22. package/dist/access-lcm-surface.js +32 -29
  23. package/dist/access-mcp.d.ts +22 -22
  24. package/dist/access-mcp.js +40 -36
  25. package/dist/access-memory-search-fanout.d.ts +2 -2
  26. package/dist/{access-namespace-preflight-BdHlGd_T.d.ts → access-namespace-preflight-CCNn_6NE.d.ts} +1 -1
  27. package/dist/access-namespace-preflight.d.ts +3 -3
  28. package/dist/access-namespace-preflight.js +32 -29
  29. package/dist/access-observe-write-surface.d.ts +22 -22
  30. package/dist/access-observe-write-surface.js +32 -29
  31. package/dist/access-offline-manifest.d.ts +9 -9
  32. package/dist/access-offline-manifest.js +2 -2
  33. package/dist/access-operations-batch.js +34 -31
  34. package/dist/access-operations.d.ts +26 -26
  35. package/dist/access-operations.js +38 -34
  36. package/dist/access-recall-concurrency.d.ts +21 -21
  37. package/dist/access-recall-concurrency.js +32 -29
  38. package/dist/access-recall-response.d.ts +19 -19
  39. package/dist/access-recall-response.js +32 -29
  40. package/dist/access-recall-surface.d.ts +19 -19
  41. package/dist/access-recall-surface.js +32 -29
  42. package/dist/access-schema.d.ts +88 -88
  43. package/dist/access-schema.js +3 -3
  44. package/dist/{access-service-DL7X9hrg.d.ts → access-service-DkSdXK4S.d.ts} +1314 -83
  45. package/dist/access-service-helpers.d.ts +22 -22
  46. package/dist/access-service.d.ts +31 -31
  47. package/dist/access-service.js +32 -29
  48. package/dist/access-surface-catalog.d.ts +22 -22
  49. package/dist/access-surface-catalog.js +209 -2
  50. package/dist/access-surface-catalog.js.map +1 -1
  51. package/dist/access-wearables-meetings-surface.d.ts +3 -3
  52. package/dist/action-confidence.d.ts +1 -1
  53. package/dist/active-memory-bridge.d.ts +6 -5
  54. package/dist/active-memory-bridge.js +2 -2
  55. package/dist/active-recall.d.ts +1 -1
  56. package/dist/active-recall.js +2 -1
  57. package/dist/active-recall.js.map +1 -1
  58. package/dist/adapters/index.js +4 -4
  59. package/dist/adapters/registry.js +2 -2
  60. package/dist/admin-console/public/what-helps-me/app.js +1594 -0
  61. package/dist/admin-console/public/what-helps-me/index.html +339 -0
  62. package/dist/admin-console/public/what-helps-me/model.js +685 -0
  63. package/dist/admin-console/public/what-helps-me/what-helps-me.css +1296 -0
  64. package/dist/ambient-provenance.d.ts +1 -1
  65. package/dist/artifact-search.d.ts +1 -1
  66. package/dist/{auto-sync-TDHLZPVP.js → auto-sync-NR3GPCOA.js} +4 -4
  67. package/dist/behavior-learner.d.ts +1 -1
  68. package/dist/behavior-signals.d.ts +1 -1
  69. package/dist/bootstrap.d.ts +9 -9
  70. package/dist/briefing.d.ts +2 -2
  71. package/dist/briefing.js +14 -14
  72. package/dist/buffer-surprise-report.d.ts +1 -1
  73. package/dist/buffer-turn-helpers.d.ts +1 -1
  74. package/dist/buffer.d.ts +2 -2
  75. package/dist/buffer.js +2 -2
  76. package/dist/bulk-import/index.d.ts +3 -3
  77. package/dist/calibration.d.ts +1 -1
  78. package/dist/calibration.js +1 -1
  79. package/dist/capabilities.d.ts +1 -1
  80. package/dist/{catalog-B90is4d8.d.ts → catalog-DGFf8mD9.d.ts} +1 -1
  81. package/dist/causal-behavior.d.ts +1 -1
  82. package/dist/causal-consolidation.d.ts +1 -1
  83. package/dist/causal-consolidation.js +15 -15
  84. package/dist/causal-trajectory-graph.d.ts +1 -1
  85. package/dist/{chunk-CSY44OKU.js → chunk-26ZXBTYN.js} +4 -4
  86. package/dist/chunk-26ZXBTYN.js.map +1 -0
  87. package/dist/{chunk-LLJMAULE.js → chunk-2FKEIPIT.js} +5 -5
  88. package/dist/{chunk-AU7Q3LSC.js → chunk-2QSZNTDO.js} +4 -4
  89. package/dist/chunk-37DZZFFM.js +502 -0
  90. package/dist/chunk-37DZZFFM.js.map +1 -0
  91. package/dist/chunk-3HSRWJTC.js +9 -0
  92. package/dist/chunk-3HSRWJTC.js.map +1 -0
  93. package/dist/{chunk-TKFGFDPJ.js → chunk-3TIZPSJC.js} +4 -4
  94. package/dist/{chunk-B4T3FQMT.js → chunk-43SEBY2M.js} +1 -1
  95. package/dist/{chunk-LVKYLMSM.js → chunk-46SZBVDS.js} +2 -2
  96. package/dist/{chunk-YKZLOPTC.js → chunk-5FD7JMTX.js} +2 -2
  97. package/dist/{chunk-2PNXOQ4P.js → chunk-5NB726GV.js} +3 -7
  98. package/dist/chunk-5NB726GV.js.map +1 -0
  99. package/dist/chunk-62OKGIJA.js +39 -0
  100. package/dist/chunk-62OKGIJA.js.map +1 -0
  101. package/dist/{chunk-WM5LD6AT.js → chunk-6CYHUWCO.js} +2 -2
  102. package/dist/{chunk-BIF4SHMD.js → chunk-76JJSXK7.js} +1 -1
  103. package/dist/chunk-76JJSXK7.js.map +1 -0
  104. package/dist/{chunk-3SXLD5T3.js → chunk-7BD6O7ZV.js} +189 -4
  105. package/dist/chunk-7BD6O7ZV.js.map +1 -0
  106. package/dist/chunk-7TBXNYLO.js +346 -0
  107. package/dist/chunk-7TBXNYLO.js.map +1 -0
  108. package/dist/{chunk-YR65W7BV.js → chunk-BRR5EUTF.js} +3 -3
  109. package/dist/{chunk-JKW663ZN.js → chunk-CIAI24TQ.js} +2 -2
  110. package/dist/{chunk-3WGI7F4V.js → chunk-D3LBIUWV.js} +9219 -5233
  111. package/dist/chunk-D3LBIUWV.js.map +1 -0
  112. package/dist/{chunk-YDWPYDML.js → chunk-EKTP7MNS.js} +4 -4
  113. package/dist/{chunk-6LEIWWAF.js → chunk-F2JRDPON.js} +2 -2
  114. package/dist/{chunk-VYQ4URQB.js → chunk-FFRTNF3L.js} +2 -2
  115. package/dist/{chunk-TY6MKIWP.js → chunk-FONWBCVY.js} +3 -3
  116. package/dist/{chunk-XSV2YDCJ.js → chunk-FPLM2TKD.js} +2 -2
  117. package/dist/{chunk-VTU5IEKY.js → chunk-FTPONF6B.js} +2 -2
  118. package/dist/{chunk-6PZGKGAO.js → chunk-FWX7W5PM.js} +2 -2
  119. package/dist/{chunk-QPW3PAIH.js → chunk-G6DFSS6A.js} +2 -2
  120. package/dist/{chunk-2DD6ZHOM.js → chunk-GJ776BC2.js} +3 -3
  121. package/dist/{chunk-XKAR4RF6.js → chunk-GN3WRFJY.js} +6 -6
  122. package/dist/{chunk-RG426DJO.js → chunk-H7NAZ3UB.js} +2 -2
  123. package/dist/{chunk-BSXGTDVJ.js → chunk-HBUFQRIM.js} +2 -2
  124. package/dist/{chunk-FFEBSFVT.js → chunk-HGJ6NJ4E.js} +2 -2
  125. package/dist/{chunk-WB7JSQCP.js → chunk-HIEWDJ2O.js} +5 -2
  126. package/dist/{chunk-WB7JSQCP.js.map → chunk-HIEWDJ2O.js.map} +1 -1
  127. package/dist/{chunk-QTO6BMQZ.js → chunk-I3MSGFGD.js} +17 -6
  128. package/dist/chunk-I3MSGFGD.js.map +1 -0
  129. package/dist/{chunk-5JKUSBMX.js → chunk-IKP5OYQQ.js} +2 -2
  130. package/dist/{chunk-KQAFEZQX.js → chunk-IPLYGWQF.js} +5 -5
  131. package/dist/{chunk-DBY26JJJ.js → chunk-IQ4NVWEF.js} +2 -2
  132. package/dist/{chunk-7Q7JWLQ4.js → chunk-JYG4OLWH.js} +2 -2
  133. package/dist/{chunk-3OTSVCPK.js → chunk-K26NWEOC.js} +4 -4
  134. package/dist/{chunk-WZWZRZ2V.js → chunk-K2UGPTYY.js} +484 -43
  135. package/dist/chunk-K2UGPTYY.js.map +1 -0
  136. package/dist/{chunk-L6CQ7WIW.js → chunk-KFBOPMF6.js} +11 -11
  137. package/dist/chunk-KFBOPMF6.js.map +1 -0
  138. package/dist/{chunk-HOIRB77A.js → chunk-L6Z5OAS4.js} +2 -2
  139. package/dist/{chunk-7RZJWZ46.js → chunk-LEPOP46W.js} +5 -5
  140. package/dist/{chunk-QQXWFDRD.js → chunk-M4YHAODQ.js} +270 -684
  141. package/dist/chunk-M4YHAODQ.js.map +1 -0
  142. package/dist/{chunk-NGT35IGQ.js → chunk-MIH3CJPN.js} +3 -3
  143. package/dist/{chunk-QPAQSG3F.js → chunk-MK5VEWCR.js} +2 -2
  144. package/dist/chunk-NISZQW72.js +140 -0
  145. package/dist/chunk-NISZQW72.js.map +1 -0
  146. package/dist/{chunk-L7RTUEDG.js → chunk-OCIP6YMD.js} +2 -2
  147. package/dist/{chunk-2INWPC6E.js → chunk-PG4QBPVG.js} +20 -10
  148. package/dist/chunk-PG4QBPVG.js.map +1 -0
  149. package/dist/{chunk-DDA55IVB.js → chunk-PT54WISF.js} +189 -55
  150. package/dist/chunk-PT54WISF.js.map +1 -0
  151. package/dist/{chunk-UWJNKGBA.js → chunk-QZLDRQ4I.js} +5 -5
  152. package/dist/{chunk-UYOXFFEY.js → chunk-RUNORG2P.js} +3 -3
  153. package/dist/{chunk-LC3FD4BV.js → chunk-RZQ6W2W4.js} +39 -39
  154. package/dist/{chunk-MRGJZ75M.js → chunk-SMNYAMJD.js} +3 -3
  155. package/dist/{chunk-MKQBXQKU.js → chunk-TB6CBZ5V.js} +22 -15
  156. package/dist/chunk-TB6CBZ5V.js.map +1 -0
  157. package/dist/{chunk-DN2IDKI5.js → chunk-TO7ZTWJW.js} +2 -2
  158. package/dist/{chunk-K2TDK7GG.js → chunk-TWTUGCTY.js} +2 -2
  159. package/dist/{chunk-CUTFSLSD.js → chunk-UCTS3DDH.js} +2 -2
  160. package/dist/{chunk-JYIJNNN3.js → chunk-UG6VXIOK.js} +2 -2
  161. package/dist/{chunk-QOQQMVR2.js → chunk-UKYS3NU5.js} +2 -2
  162. package/dist/{chunk-VZRFGJCH.js → chunk-UPLZNJKN.js} +2 -2
  163. package/dist/{chunk-C23BYTJV.js → chunk-UW5NPZJ2.js} +40 -12
  164. package/dist/chunk-UW5NPZJ2.js.map +1 -0
  165. package/dist/{chunk-DOOWFDWN.js → chunk-V6ERBR7U.js} +2 -2
  166. package/dist/{chunk-7HG7MGAP.js → chunk-W5ZKPI34.js} +462 -2673
  167. package/dist/chunk-W5ZKPI34.js.map +1 -0
  168. package/dist/{chunk-HNDIND7P.js → chunk-XX4HPFFM.js} +54 -15
  169. package/dist/chunk-XX4HPFFM.js.map +1 -0
  170. package/dist/{chunk-N7CXQ5TA.js → chunk-XZHE2DEN.js} +1 -1
  171. package/dist/chunk-YXQEKCZM.js +223 -0
  172. package/dist/chunk-YXQEKCZM.js.map +1 -0
  173. package/dist/{chunk-6NNNURLK.js → chunk-Z54EM5YZ.js} +4 -4
  174. package/dist/{chunk-F2Y6I74C.js → chunk-ZRZVLB7O.js} +2 -2
  175. package/dist/{chunk-CLKBV3Z3.js → chunk-ZUKIUXHQ.js} +9 -9
  176. package/dist/{cli-jfuZXixq.d.ts → cli-Bze8S0Qs.d.ts} +5 -5
  177. package/dist/cli.d.ts +22 -22
  178. package/dist/cli.js +66 -58
  179. package/dist/coding/pre-action-gate.d.ts +1 -1
  180. package/dist/compounding/engine.d.ts +2 -2
  181. package/dist/compounding/engine.js +14 -14
  182. package/dist/compounding/preference-consolidator.d.ts +1 -1
  183. package/dist/compression-optimizer.d.ts +1 -1
  184. package/dist/config.d.ts +1 -1
  185. package/dist/config.js +2 -1
  186. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  187. package/dist/connectors/codex-materialize-runner.js +14 -14
  188. package/dist/connectors/codex-materialize.d.ts +1 -1
  189. package/dist/connectors/index.d.ts +1 -1
  190. package/dist/connectors/index.js +14 -14
  191. package/dist/consolidation-provenance-check.d.ts +2 -2
  192. package/dist/consolidation-undo.d.ts +2 -2
  193. package/dist/contradiction/index.d.ts +2 -2
  194. package/dist/contradiction/index.js +2 -2
  195. package/dist/{contradiction-scan-KCADHXPE.js → contradiction-scan-JDTBXRGW.js} +3 -3
  196. package/dist/converge-config.d.ts +1 -1
  197. package/dist/convergence-refresh.d.ts +2 -2
  198. package/dist/convergence-refresh.js +16 -16
  199. package/dist/conversation-index/backend.d.ts +1 -1
  200. package/dist/conversation-index/backend.js +2 -2
  201. package/dist/conversation-index/chunker.d.ts +1 -1
  202. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  203. package/dist/conversation-index/indexer.d.ts +1 -1
  204. package/dist/conversation-index/search.d.ts +1 -1
  205. package/dist/corpus-watermark.d.ts +1 -1
  206. package/dist/corpus-watermark.js +16 -16
  207. package/dist/day-summary.d.ts +1 -1
  208. package/dist/delinearize.d.ts +1 -1
  209. package/dist/dependency-propagation-config.d.ts +1 -1
  210. package/dist/{dependency-propagation-delivery-CTDuAVJc.d.ts → dependency-propagation-delivery-CzEfB31P.d.ts} +1 -1
  211. package/dist/direct-answer-wiring.d.ts +1 -1
  212. package/dist/direct-answer.d.ts +1 -1
  213. package/dist/embedding-fallback.d.ts +1 -1
  214. package/dist/enrichment/index.d.ts +1 -1
  215. package/dist/entity-retrieval.d.ts +2 -2
  216. package/dist/entity-retrieval.js +14 -14
  217. package/dist/entity-schema.d.ts +1 -1
  218. package/dist/explicit-capture.d.ts +9 -9
  219. package/dist/explicit-capture.js +4 -3
  220. package/dist/external-wiki-access.d.ts +22 -22
  221. package/dist/external-wiki-access.js +33 -30
  222. package/dist/external-wiki-collection-registration.d.ts +1 -1
  223. package/dist/external-wiki-collection.d.ts +1 -1
  224. package/dist/external-wiki-mcp-tools.d.ts +22 -22
  225. package/dist/extraction-error-classification.d.ts +1 -1
  226. package/dist/extraction-faithfulness.d.ts +1 -1
  227. package/dist/extraction-faithfulness.js +2 -2
  228. package/dist/extraction-judge-telemetry.d.ts +1 -1
  229. package/dist/extraction-judge-training.d.ts +1 -1
  230. package/dist/extraction-judge.d.ts +1 -1
  231. package/dist/extraction-judge.js +2 -2
  232. package/dist/extraction-liveness.d.ts +1 -1
  233. package/dist/extraction-normalization.d.ts +1 -1
  234. package/dist/extraction-prompt.d.ts +1 -1
  235. package/dist/extraction-source-grounding-rules.d.ts +1 -1
  236. package/dist/extraction-source-grounding.d.ts +1 -1
  237. package/dist/extraction.d.ts +1 -1
  238. package/dist/extraction.js +20 -20
  239. package/dist/fallback-llm.d.ts +14 -1
  240. package/dist/fallback-llm.js +1 -1
  241. package/dist/{first-start-migration-LMMZFLKK.js → first-start-migration-CRZCZAJN.js} +5 -5
  242. package/dist/graph-dashboard-diff.d.ts +1 -1
  243. package/dist/graph-dashboard-key.d.ts +1 -1
  244. package/dist/graph-dashboard-parser.d.ts +1 -1
  245. package/dist/graph-edge-reinforcement.d.ts +1 -1
  246. package/dist/graph-path-reconstruction.d.ts +1 -1
  247. package/dist/graph-path-scoring.d.ts +1 -1
  248. package/dist/graph-snapshot.d.ts +1 -1
  249. package/dist/graph.d.ts +1 -1
  250. package/dist/harmonic-retrieval.js +1 -1
  251. package/dist/importance.d.ts +1 -1
  252. package/dist/importers/index.d.ts +1 -1
  253. package/dist/in-flight-reads.d.ts +1 -1
  254. package/dist/index.d.ts +704 -1421
  255. package/dist/index.js +203 -118
  256. package/dist/inline-script.d.ts +3 -0
  257. package/dist/inline-script.js +8 -0
  258. package/dist/inline-script.js.map +1 -0
  259. package/dist/intent.d.ts +1 -1
  260. package/dist/lcm/engine.d.ts +1 -1
  261. package/dist/lcm/engine.js +2 -2
  262. package/dist/lcm/index.d.ts +1 -1
  263. package/dist/lcm/index.js +2 -2
  264. package/dist/lcm/tools.d.ts +1 -1
  265. package/dist/lifecycle.d.ts +1 -1
  266. package/dist/live-connectors-runner.d.ts +1 -1
  267. package/dist/local-llm.d.ts +2 -1
  268. package/dist/local-llm.js +2 -2
  269. package/dist/local-model-endpoint.d.ts +1 -1
  270. package/dist/maintenance/memory-governance.d.ts +1 -1
  271. package/dist/maintenance/memory-governance.js +14 -14
  272. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  273. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +14 -14
  274. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
  275. package/dist/maintenance/rebuild-memory-projection.js +15 -15
  276. package/dist/{maintenance-heMZSq7G.d.ts → maintenance-C8aRWfhq.d.ts} +3 -3
  277. package/dist/mcp-memory-inspector-app.d.ts +22 -22
  278. package/dist/mcp-read-only-tools.js +1 -1
  279. package/dist/memory-action-policy.d.ts +1 -1
  280. package/dist/memory-cache.d.ts +1 -1
  281. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  282. package/dist/memory-projection-store.d.ts +1 -1
  283. package/dist/memory-provenance.d.ts +1 -1
  284. package/dist/memory-snapshot.d.ts +1 -1
  285. package/dist/memory-worth-outcomes.d.ts +2 -2
  286. package/dist/models-json.d.ts +1 -1
  287. package/dist/namespaces/migrate.d.ts +3 -3
  288. package/dist/namespaces/migrate.js +15 -15
  289. package/dist/namespaces/principal.d.ts +1 -1
  290. package/dist/namespaces/search.d.ts +1 -1
  291. package/dist/namespaces/search.js +6 -6
  292. package/dist/namespaces/storage.d.ts +3 -3
  293. package/dist/namespaces/storage.js +14 -14
  294. package/dist/native-knowledge.d.ts +1 -1
  295. package/dist/offline-sync-impression-drain.d.ts +1 -1
  296. package/dist/operator-doctor-corpus.d.ts +1 -1
  297. package/dist/operator-doctor-corpus.js +17 -17
  298. package/dist/operator-doctor-replica.d.ts +1 -1
  299. package/dist/operator-toolkit.d.ts +3 -3
  300. package/dist/operator-toolkit.js +23 -22
  301. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  302. package/dist/orchestration/maintenance.d.ts +4 -4
  303. package/dist/orchestration/maintenance.js +19 -19
  304. package/dist/{orchestrator-BQQPsSjs.d.ts → orchestrator-D85CzDDY.d.ts} +8 -8
  305. package/dist/orchestrator.d.ts +9 -9
  306. package/dist/orchestrator.js +86 -80
  307. package/dist/patterns-cli.d.ts +1 -1
  308. package/dist/{pipeline-DFfmsnGk.d.ts → pipeline-DPcUifCO.d.ts} +1 -1
  309. package/dist/policy-runtime.d.ts +1 -1
  310. package/dist/proactive-contention.d.ts +1 -1
  311. package/dist/provenance.d.ts +1 -1
  312. package/dist/public-http-D-SyWNj6.d.ts +25 -0
  313. package/dist/{qmd-BF5bcVRs.d.ts → qmd-dFCHp1r0.d.ts} +1 -1
  314. package/dist/qmd-preflight.d.ts +2 -2
  315. package/dist/qmd-recall-cache.d.ts +1 -1
  316. package/dist/qmd.d.ts +2 -2
  317. package/dist/recall-concurrency-config.d.ts +1 -1
  318. package/dist/recall-disclosure-escalation.d.ts +1 -1
  319. package/dist/recall-explain-renderer.d.ts +1 -1
  320. package/dist/recall-explain-renderer.js +3 -3
  321. package/dist/recall-memory-map.d.ts +1 -1
  322. package/dist/recall-planner-llm.d.ts +1 -1
  323. package/dist/recall-planner-llm.js +1 -1
  324. package/dist/recall-state.d.ts +1 -1
  325. package/dist/recall-tag-filter.d.ts +1 -1
  326. package/dist/recall-timings.d.ts +1 -1
  327. package/dist/recall-xray-cli.d.ts +1 -1
  328. package/dist/recall-xray-cli.js +4 -4
  329. package/dist/recall-xray-renderer.d.ts +1 -1
  330. package/dist/recall-xray-renderer.js +3 -3
  331. package/dist/recall-xray.d.ts +1 -1
  332. package/dist/recall-xray.js +2 -2
  333. package/dist/reconcile/cursor.d.ts +1 -1
  334. package/dist/reconcile/manifest.d.ts +1 -1
  335. package/dist/reconcile/plan.d.ts +1 -1
  336. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  337. package/dist/replay/normalizers/claude.d.ts +1 -1
  338. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  339. package/dist/replay/normalizers/shared.d.ts +1 -1
  340. package/dist/replay/runner.d.ts +1 -1
  341. package/dist/replay/types.d.ts +1 -1
  342. package/dist/replica-divergence.d.ts +1 -1
  343. package/dist/replica-peers-config.d.ts +1 -1
  344. package/dist/resolve-auth-token.d.ts +1 -1
  345. package/dist/resume-bundles.js +3 -2
  346. package/dist/retrieval-agents.d.ts +2 -2
  347. package/dist/retrieval-tiers.d.ts +1 -1
  348. package/dist/routing/engine.d.ts +1 -1
  349. package/dist/routing/store.d.ts +1 -1
  350. package/dist/salvage-envelope.d.ts +1 -1
  351. package/dist/schemas.d.ts +116 -116
  352. package/dist/{scope-profiles-CbUOsE_E.d.ts → scope-profiles-DICK7GtN.d.ts} +1 -1
  353. package/dist/search/embed-helper.d.ts +1 -1
  354. package/dist/search/factory.d.ts +1 -1
  355. package/dist/search/factory.js +5 -5
  356. package/dist/search/index.d.ts +1 -1
  357. package/dist/search/index.js +9 -9
  358. package/dist/search/lancedb-backend.d.ts +1 -1
  359. package/dist/search/meilisearch-backend.d.ts +1 -1
  360. package/dist/search/noop-backend.d.ts +1 -1
  361. package/dist/search/orama-backend.d.ts +1 -1
  362. package/dist/search/port.d.ts +1 -1
  363. package/dist/search/remote-backend.d.ts +1 -1
  364. package/dist/{semantic-consolidation-DAB3xdKM.d.ts → semantic-consolidation-BP7NAX0N.d.ts} +1 -1
  365. package/dist/semantic-consolidation.d.ts +2 -2
  366. package/dist/semantic-consolidation.js +15 -15
  367. package/dist/semantic-rule-promotion.js +14 -14
  368. package/dist/semantic-rule-verifier.d.ts +1 -1
  369. package/dist/semantic-rule-verifier.js +14 -14
  370. package/dist/{service-DGKg2O6r.d.ts → service-DT-pJyda.d.ts} +660 -660
  371. package/dist/session-observer-bands.d.ts +1 -1
  372. package/dist/session-observer-state.d.ts +1 -1
  373. package/dist/shared-context/manager.d.ts +9 -9
  374. package/dist/signal.d.ts +1 -1
  375. package/dist/source-agent-qualifier.d.ts +1 -1
  376. package/dist/source-agent-qualifier.js +16 -16
  377. package/dist/{storage-CC1jKcWg.d.ts → storage-qOnaJ1Lw.d.ts} +4 -1
  378. package/dist/storage.d.ts +2 -2
  379. package/dist/storage.js +13 -13
  380. package/dist/summarizer.d.ts +1 -1
  381. package/dist/summarizer.js +5 -5
  382. package/dist/summary-snapshot.d.ts +1 -1
  383. package/dist/support-passport/index.d.ts +518 -0
  384. package/dist/support-passport/index.js +357 -0
  385. package/dist/support-passport/index.js.map +1 -0
  386. package/dist/temporal-supersession.d.ts +2 -2
  387. package/dist/temporal-timeline-recall.d.ts +1 -1
  388. package/dist/temporal-validity.d.ts +1 -1
  389. package/dist/threading.d.ts +1 -1
  390. package/dist/tier-migration.d.ts +2 -2
  391. package/dist/tier-routing.d.ts +1 -1
  392. package/dist/tier-routing.js +2 -2
  393. package/dist/{tier-stats-JDN6HRNT.js → tier-stats-EXYSKSVN.js} +3 -3
  394. package/dist/topics.d.ts +1 -1
  395. package/dist/transcript.d.ts +1 -1
  396. package/dist/transfer/autodetect.js +1 -1
  397. package/dist/transfer/backup.js +1 -1
  398. package/dist/transfer/capsule-export.js +2 -2
  399. package/dist/transfer/types.d.ts +90 -90
  400. package/dist/trust-score-stage.d.ts +1 -1
  401. package/dist/trust-score.d.ts +1 -1
  402. package/dist/{types-BnQza1y8.d.ts → types-ed-SvS2t.d.ts} +7 -1
  403. package/dist/types.d.ts +1 -1
  404. package/dist/types.js +1 -1
  405. package/dist/utility-runtime.d.ts +1 -1
  406. package/dist/verified-recall.js +14 -14
  407. package/dist/write-envelope.d.ts +1 -1
  408. package/dist/write-rate-limiter.d.ts +11 -5
  409. package/dist/write-rate-limiter.js +1 -1
  410. package/package.json +12 -2
  411. package/scripts/build-with-heap.mjs +11 -1
  412. package/src/access-authorization-probe.ts +20 -2
  413. package/src/access-boundary.ts +32 -0
  414. package/src/access-http.test.ts +1940 -643
  415. package/src/access-http.ts +81 -74
  416. package/src/access-mcp.ts +3 -1
  417. package/src/access-operations.ts +2 -0
  418. package/src/access-service.ts +612 -845
  419. package/src/access-surface-catalog.test.ts +40 -10
  420. package/src/access-surface-catalog.ts +15 -0
  421. package/src/active-memory-bridge.ts +17 -19
  422. package/src/config.ts +18 -9
  423. package/src/fallback-llm.test.ts +54 -0
  424. package/src/fallback-llm.ts +54 -9
  425. package/src/inline-script.ts +6 -0
  426. package/src/local-llm-headers-timeout.test.ts +42 -0
  427. package/src/local-llm.ts +8 -8
  428. package/src/mcp-read-only-tools.ts +3 -0
  429. package/src/relay/mission-access.test.ts +11 -11
  430. package/src/relay/mission-ui.test.ts +3 -1
  431. package/src/storage/tombstone-blocked-capture-sync.ts +31 -0
  432. package/src/storage-contract/failure-semantics.test.ts +102 -0
  433. package/src/support-passport/access-http-base.ts +143 -0
  434. package/src/support-passport/access-http.ts +172 -0
  435. package/src/support-passport/access-operations.ts +272 -0
  436. package/src/support-passport/access-service-base.test.ts +193 -0
  437. package/src/support-passport/access-service-base.ts +176 -0
  438. package/src/support-passport/access-surface.test.ts +283 -0
  439. package/src/support-passport/access-surface.ts +286 -0
  440. package/src/support-passport/card-projection.test.ts +8 -0
  441. package/src/support-passport/card-projection.ts +77 -16
  442. package/src/support-passport/card-replacement.ts +126 -0
  443. package/src/support-passport/card-service-commit-forwarding.test.ts +160 -0
  444. package/src/support-passport/card-service.test.ts +533 -31
  445. package/src/support-passport/card-service.ts +506 -364
  446. package/src/support-passport/card-state.ts +158 -0
  447. package/src/support-passport/config-model-routing.test.ts +37 -0
  448. package/src/support-passport/config.test.ts +34 -0
  449. package/src/support-passport/config.ts +41 -0
  450. package/src/support-passport/contracts.test.ts +15 -2
  451. package/src/support-passport/contracts.ts +13 -0
  452. package/src/support-passport/errors.ts +6 -0
  453. package/src/support-passport/generated-batch.test.ts +185 -0
  454. package/src/support-passport/generated-batch.ts +338 -0
  455. package/src/support-passport/grant-contracts.ts +45 -1
  456. package/src/support-passport/grant-generated-batch-scope.test.ts +201 -0
  457. package/src/support-passport/grant-service-cache.test.ts +2 -2
  458. package/src/support-passport/grant-service-cancellation.test.ts +2 -0
  459. package/src/support-passport/grant-service-marker-cache.test.ts +62 -0
  460. package/src/support-passport/grant-service.test.ts +853 -239
  461. package/src/support-passport/grant-service.ts +206 -57
  462. package/src/support-passport/grant-store.ts +7 -3
  463. package/src/support-passport/index.ts +10 -0
  464. package/src/support-passport/mcp-tools.test.ts +222 -0
  465. package/src/support-passport/mcp-tools.ts +187 -0
  466. package/src/support-passport/model-adapter.test.ts +840 -0
  467. package/src/support-passport/model-adapter.ts +602 -0
  468. package/src/support-passport/model-audit-pinned-write.test.ts +59 -0
  469. package/src/support-passport/model-audit.ts +152 -0
  470. package/src/support-passport/model-bridge.test.ts +456 -0
  471. package/src/support-passport/model-bridge.ts +439 -0
  472. package/src/support-passport/model-contracts.ts +124 -0
  473. package/src/support-passport/model-service.test.ts +1731 -0
  474. package/src/support-passport/model-service.ts +399 -0
  475. package/src/support-passport/owner-http.test.ts +671 -0
  476. package/src/support-passport/owner-lock.ts +26 -9
  477. package/src/support-passport/private-file.test.ts +99 -0
  478. package/src/support-passport/private-file.ts +139 -12
  479. package/src/support-passport/public-http.test.ts +476 -0
  480. package/src/support-passport/public-http.ts +601 -0
  481. package/src/support-passport/ui.test.ts +181 -0
  482. package/src/types.ts +7 -0
  483. package/src/write-rate-limiter.test.ts +30 -6
  484. package/src/write-rate-limiter.ts +29 -18
  485. package/dist/chunk-2INWPC6E.js.map +0 -1
  486. package/dist/chunk-2PNXOQ4P.js.map +0 -1
  487. package/dist/chunk-3SXLD5T3.js.map +0 -1
  488. package/dist/chunk-3WGI7F4V.js.map +0 -1
  489. package/dist/chunk-7HG7MGAP.js.map +0 -1
  490. package/dist/chunk-BIF4SHMD.js.map +0 -1
  491. package/dist/chunk-C23BYTJV.js.map +0 -1
  492. package/dist/chunk-CSY44OKU.js.map +0 -1
  493. package/dist/chunk-DDA55IVB.js.map +0 -1
  494. package/dist/chunk-HNDIND7P.js.map +0 -1
  495. package/dist/chunk-L6CQ7WIW.js.map +0 -1
  496. package/dist/chunk-MKQBXQKU.js.map +0 -1
  497. package/dist/chunk-QQXWFDRD.js.map +0 -1
  498. package/dist/chunk-QTO6BMQZ.js.map +0 -1
  499. package/dist/chunk-WZWZRZ2V.js.map +0 -1
  500. /package/dist/{auto-sync-TDHLZPVP.js.map → auto-sync-NR3GPCOA.js.map} +0 -0
  501. /package/dist/{chunk-LLJMAULE.js.map → chunk-2FKEIPIT.js.map} +0 -0
  502. /package/dist/{chunk-AU7Q3LSC.js.map → chunk-2QSZNTDO.js.map} +0 -0
  503. /package/dist/{chunk-TKFGFDPJ.js.map → chunk-3TIZPSJC.js.map} +0 -0
  504. /package/dist/{chunk-B4T3FQMT.js.map → chunk-43SEBY2M.js.map} +0 -0
  505. /package/dist/{chunk-LVKYLMSM.js.map → chunk-46SZBVDS.js.map} +0 -0
  506. /package/dist/{chunk-YKZLOPTC.js.map → chunk-5FD7JMTX.js.map} +0 -0
  507. /package/dist/{chunk-WM5LD6AT.js.map → chunk-6CYHUWCO.js.map} +0 -0
  508. /package/dist/{chunk-YR65W7BV.js.map → chunk-BRR5EUTF.js.map} +0 -0
  509. /package/dist/{chunk-JKW663ZN.js.map → chunk-CIAI24TQ.js.map} +0 -0
  510. /package/dist/{chunk-YDWPYDML.js.map → chunk-EKTP7MNS.js.map} +0 -0
  511. /package/dist/{chunk-6LEIWWAF.js.map → chunk-F2JRDPON.js.map} +0 -0
  512. /package/dist/{chunk-VYQ4URQB.js.map → chunk-FFRTNF3L.js.map} +0 -0
  513. /package/dist/{chunk-TY6MKIWP.js.map → chunk-FONWBCVY.js.map} +0 -0
  514. /package/dist/{chunk-XSV2YDCJ.js.map → chunk-FPLM2TKD.js.map} +0 -0
  515. /package/dist/{chunk-VTU5IEKY.js.map → chunk-FTPONF6B.js.map} +0 -0
  516. /package/dist/{chunk-6PZGKGAO.js.map → chunk-FWX7W5PM.js.map} +0 -0
  517. /package/dist/{chunk-QPW3PAIH.js.map → chunk-G6DFSS6A.js.map} +0 -0
  518. /package/dist/{chunk-2DD6ZHOM.js.map → chunk-GJ776BC2.js.map} +0 -0
  519. /package/dist/{chunk-XKAR4RF6.js.map → chunk-GN3WRFJY.js.map} +0 -0
  520. /package/dist/{chunk-RG426DJO.js.map → chunk-H7NAZ3UB.js.map} +0 -0
  521. /package/dist/{chunk-BSXGTDVJ.js.map → chunk-HBUFQRIM.js.map} +0 -0
  522. /package/dist/{chunk-FFEBSFVT.js.map → chunk-HGJ6NJ4E.js.map} +0 -0
  523. /package/dist/{chunk-5JKUSBMX.js.map → chunk-IKP5OYQQ.js.map} +0 -0
  524. /package/dist/{chunk-KQAFEZQX.js.map → chunk-IPLYGWQF.js.map} +0 -0
  525. /package/dist/{chunk-DBY26JJJ.js.map → chunk-IQ4NVWEF.js.map} +0 -0
  526. /package/dist/{chunk-7Q7JWLQ4.js.map → chunk-JYG4OLWH.js.map} +0 -0
  527. /package/dist/{chunk-3OTSVCPK.js.map → chunk-K26NWEOC.js.map} +0 -0
  528. /package/dist/{chunk-HOIRB77A.js.map → chunk-L6Z5OAS4.js.map} +0 -0
  529. /package/dist/{chunk-7RZJWZ46.js.map → chunk-LEPOP46W.js.map} +0 -0
  530. /package/dist/{chunk-NGT35IGQ.js.map → chunk-MIH3CJPN.js.map} +0 -0
  531. /package/dist/{chunk-QPAQSG3F.js.map → chunk-MK5VEWCR.js.map} +0 -0
  532. /package/dist/{chunk-L7RTUEDG.js.map → chunk-OCIP6YMD.js.map} +0 -0
  533. /package/dist/{chunk-UWJNKGBA.js.map → chunk-QZLDRQ4I.js.map} +0 -0
  534. /package/dist/{chunk-UYOXFFEY.js.map → chunk-RUNORG2P.js.map} +0 -0
  535. /package/dist/{chunk-LC3FD4BV.js.map → chunk-RZQ6W2W4.js.map} +0 -0
  536. /package/dist/{chunk-MRGJZ75M.js.map → chunk-SMNYAMJD.js.map} +0 -0
  537. /package/dist/{chunk-DN2IDKI5.js.map → chunk-TO7ZTWJW.js.map} +0 -0
  538. /package/dist/{chunk-K2TDK7GG.js.map → chunk-TWTUGCTY.js.map} +0 -0
  539. /package/dist/{chunk-CUTFSLSD.js.map → chunk-UCTS3DDH.js.map} +0 -0
  540. /package/dist/{chunk-JYIJNNN3.js.map → chunk-UG6VXIOK.js.map} +0 -0
  541. /package/dist/{chunk-QOQQMVR2.js.map → chunk-UKYS3NU5.js.map} +0 -0
  542. /package/dist/{chunk-VZRFGJCH.js.map → chunk-UPLZNJKN.js.map} +0 -0
  543. /package/dist/{chunk-DOOWFDWN.js.map → chunk-V6ERBR7U.js.map} +0 -0
  544. /package/dist/{chunk-N7CXQ5TA.js.map → chunk-XZHE2DEN.js.map} +0 -0
  545. /package/dist/{chunk-6NNNURLK.js.map → chunk-Z54EM5YZ.js.map} +0 -0
  546. /package/dist/{chunk-F2Y6I74C.js.map → chunk-ZRZVLB7O.js.map} +0 -0
  547. /package/dist/{chunk-CLKBV3Z3.js.map → chunk-ZUKIUXHQ.js.map} +0 -0
  548. /package/dist/{contradiction-scan-KCADHXPE.js.map → contradiction-scan-JDTBXRGW.js.map} +0 -0
  549. /package/dist/{first-start-migration-LMMZFLKK.js.map → first-start-migration-CRZCZAJN.js.map} +0 -0
  550. /package/dist/{tier-stats-JDN6HRNT.js.map → tier-stats-EXYSKSVN.js.map} +0 -0
@@ -1,6 +1,16 @@
1
1
  import assert from "node:assert/strict";
2
2
  import { renameSync, symlinkSync } from "node:fs";
3
- import { lstat, mkdir, mkdtemp, open, readFile, readdir, rm, symlink, writeFile } from "node:fs/promises";
3
+ import {
4
+ lstat,
5
+ mkdir,
6
+ mkdtemp,
7
+ open,
8
+ readFile,
9
+ readdir,
10
+ rm,
11
+ symlink,
12
+ writeFile,
13
+ } from "node:fs/promises";
4
14
  import { tmpdir } from "node:os";
5
15
  import path from "node:path";
6
16
  import { test } from "node:test";
@@ -27,16 +37,24 @@ async function makeSubject() {
27
37
  const root = await mkdtemp(path.join(tmpdir(), "remnic-support-grants-"));
28
38
  const aliceStorage = new StorageManager(path.join(root, "alice"));
29
39
  const bobStorage = new StorageManager(path.join(root, "bob"));
30
- await Promise.all([aliceStorage.ensureDirectories(), bobStorage.ensureDirectories()]);
40
+ await Promise.all([
41
+ aliceStorage.ensureDirectories(),
42
+ bobStorage.ensureDirectories(),
43
+ ]);
31
44
  let currentTime = Date.parse("2026-08-11T12:00:00.000Z");
32
45
  const now = () => new Date(currentTime);
33
46
  const resolveOwner = async (principal: string) => {
34
- if (principal === "owner:alice") return { principal, namespace: "alice", storage: aliceStorage };
35
- if (principal === "owner:bob") return { principal, namespace: "bob", storage: bobStorage };
47
+ if (principal === "owner:alice")
48
+ return { principal, namespace: "alice", storage: aliceStorage };
49
+ if (principal === "owner:bob")
50
+ return { principal, namespace: "bob", storage: bobStorage };
36
51
  throw new Error("unknown test principal");
37
52
  };
38
53
  const cardService = new SupportPassportCardService({ resolveOwner, now });
39
- const grantStore = new SupportPassportGrantStore({ memoryDir: path.join(root, "shared"), now });
54
+ const grantStore = new SupportPassportGrantStore({
55
+ memoryDir: path.join(root, "shared"),
56
+ now,
57
+ });
40
58
  const grantService = new SupportPassportGrantService({
41
59
  grantStore,
42
60
  resolveOwner,
@@ -65,7 +83,10 @@ async function makeSubject() {
65
83
  };
66
84
  }
67
85
 
68
- async function createActiveCard(subject: Awaited<ReturnType<typeof makeSubject>>, title = "Quiet space") {
86
+ async function createActiveCard(
87
+ subject: Awaited<ReturnType<typeof makeSubject>>,
88
+ title = "Quiet space",
89
+ ) {
69
90
  const draft = await subject.cardService.createManualDraft({
70
91
  principal: "owner:alice",
71
92
  title,
@@ -80,7 +101,10 @@ async function createActiveCard(subject: Awaited<ReturnType<typeof makeSubject>>
80
101
  });
81
102
  }
82
103
 
83
- function expiryAfter(subject: Awaited<ReturnType<typeof makeSubject>>, milliseconds: number): string {
104
+ function expiryAfter(
105
+ subject: Awaited<ReturnType<typeof makeSubject>>,
106
+ milliseconds: number,
107
+ ): string {
84
108
  return new Date(subject.now().getTime() + milliseconds).toISOString();
85
109
  }
86
110
 
@@ -103,7 +127,7 @@ test("a grant stores only hashed credentials with private file permissions", asy
103
127
  "state",
104
128
  "support-passport",
105
129
  "grants",
106
- `${created.grant.grantId}.json`
130
+ `${created.grant.grantId}.json`,
107
131
  );
108
132
  const body = await readFile(filePath, "utf8");
109
133
  const state = JSON.parse(body);
@@ -122,14 +146,52 @@ test("a grant stores only hashed credentials with private file permissions", asy
122
146
  }
123
147
  });
124
148
 
149
+ test("grant creation stops the new link when its owner request is cancelled after persistence", async () => {
150
+ const subject = await makeSubject();
151
+ const controller = new AbortController();
152
+ const create = subject.grantStore.create.bind(subject.grantStore);
153
+ subject.grantStore.create = async (...args) => {
154
+ const created = await create(...args);
155
+ controller.abort(new Error("simulated owner request timeout"));
156
+ return created;
157
+ };
158
+ try {
159
+ const card = await createActiveCard(subject);
160
+ await assert.rejects(
161
+ subject.grantService.createGrant(
162
+ {
163
+ principal: "owner:alice",
164
+ cards: [{ cardId: card.cardId, revision: card.revision }],
165
+ expiresAt: expiryAfter(subject, 3_600_000),
166
+ },
167
+ { signal: controller.signal },
168
+ ),
169
+ /simulated owner request timeout/,
170
+ );
171
+ const grants = await subject.grantService.listGrants({
172
+ principal: "owner:alice",
173
+ });
174
+ assert.equal(grants.length, 1);
175
+ assert.equal(grants[0]?.status, "revoked");
176
+ } finally {
177
+ await subject.cleanup();
178
+ }
179
+ });
180
+
125
181
  test("owner grant listings read only the indexed owner grants", async () => {
126
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-grant-index-"));
182
+ const root = await mkdtemp(
183
+ path.join(tmpdir(), "remnic-support-grant-index-"),
184
+ );
127
185
  try {
128
- const grantIds = ["00000000-0000-4000-8000-000000000001", "00000000-0000-4000-8000-000000000002"];
186
+ const grantIds = [
187
+ "00000000-0000-4000-8000-000000000001",
188
+ "00000000-0000-4000-8000-000000000002",
189
+ ];
129
190
  const now = new Date("2026-08-11T12:00:00.000Z");
130
191
  const store = new SupportPassportGrantStore({
131
192
  memoryDir: root,
132
- makeGrantId: () => grantIds.shift() ?? "00000000-0000-4000-8000-000000000003",
193
+ makeGrantId: () =>
194
+ grantIds.shift() ?? "00000000-0000-4000-8000-000000000003",
133
195
  now: () => now,
134
196
  });
135
197
  const common = {
@@ -153,7 +215,7 @@ test("owner grant listings read only the indexed owner grants", async () => {
153
215
 
154
216
  assert.deepEqual(
155
217
  listed.map((state) => state.grantId),
156
- [alice.state.grantId]
218
+ [alice.state.grantId],
157
219
  );
158
220
  assert.deepEqual(readGrantIds, [alice.state.grantId]);
159
221
  assert.notEqual(alice.state.grantId, bob.state.grantId);
@@ -163,25 +225,34 @@ test("owner grant listings read only the indexed owner grants", async () => {
163
225
  });
164
226
 
165
227
  test("owner grant listings propagate indexed grant read failures", async () => {
166
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-grant-list-error-"));
228
+ const root = await mkdtemp(
229
+ path.join(tmpdir(), "remnic-support-grant-list-error-"),
230
+ );
167
231
  try {
168
232
  const now = new Date("2026-08-11T12:00:00.000Z");
169
- const store = new SupportPassportGrantStore({ memoryDir: root, now: () => now });
233
+ const store = new SupportPassportGrantStore({
234
+ memoryDir: root,
235
+ now: () => now,
236
+ });
170
237
  const created = await store.create({
171
238
  namespace: "alice",
172
239
  principal: "owner:alice",
173
240
  cards: [{ cardId: "card-1", revision: "a".repeat(64) }],
174
241
  expiresAt: new Date(now.getTime() + 3_600_000).toISOString(),
175
242
  });
176
- const inspected = store as unknown as { readState(grantId: string): Promise<unknown> };
243
+ const inspected = store as unknown as {
244
+ readState(grantId: string): Promise<unknown>;
245
+ };
177
246
  inspected.readState = async (grantId) => {
178
247
  assert.equal(grantId, created.state.grantId);
179
- throw Object.assign(new Error("simulated grant read failure"), { code: "EIO" });
248
+ throw Object.assign(new Error("simulated grant read failure"), {
249
+ code: "EIO",
250
+ });
180
251
  };
181
252
 
182
253
  await assert.rejects(
183
254
  store.listForOwner("alice", "owner:alice"),
184
- (error: unknown) => (error as NodeJS.ErrnoException).code === "EIO"
255
+ (error: unknown) => (error as NodeJS.ErrnoException).code === "EIO",
185
256
  );
186
257
  } finally {
187
258
  await rm(root, { recursive: true, force: true });
@@ -189,13 +260,16 @@ test("owner grant listings propagate indexed grant read failures", async () => {
189
260
  });
190
261
 
191
262
  test("owner grant listings put active links before inactive history", async () => {
192
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-grant-list-order-"));
263
+ const root = await mkdtemp(
264
+ path.join(tmpdir(), "remnic-support-grant-list-order-"),
265
+ );
193
266
  try {
194
267
  let currentTime = Date.parse("2026-08-11T12:00:00.000Z");
195
268
  let nextGrantId = 1;
196
269
  const store = new SupportPassportGrantStore({
197
270
  memoryDir: root,
198
- makeGrantId: () => `00000000-0000-4000-8000-${String(nextGrantId++).padStart(12, "0")}`,
271
+ makeGrantId: () =>
272
+ `00000000-0000-4000-8000-${String(nextGrantId++).padStart(12, "0")}`,
199
273
  now: () => new Date(currentTime),
200
274
  });
201
275
  const input = {
@@ -206,7 +280,10 @@ test("owner grant listings put active links before inactive history", async () =
206
280
  };
207
281
  const inactive = await store.create(input);
208
282
  currentTime += 1_000;
209
- const active = await store.create({ ...input, expiresAt: new Date(currentTime + 3_600_000).toISOString() });
283
+ const active = await store.create({
284
+ ...input,
285
+ expiresAt: new Date(currentTime + 3_600_000).toISOString(),
286
+ });
210
287
  await store.revoke({
211
288
  grantId: inactive.state.grantId,
212
289
  namespace: input.namespace,
@@ -217,7 +294,7 @@ test("owner grant listings put active links before inactive history", async () =
217
294
 
218
295
  assert.deepEqual(
219
296
  listed.map((state) => state.grantId),
220
- [active.state.grantId, inactive.state.grantId]
297
+ [active.state.grantId, inactive.state.grantId],
221
298
  );
222
299
  } finally {
223
300
  await rm(root, { recursive: true, force: true });
@@ -225,10 +302,15 @@ test("owner grant listings put active links before inactive history", async () =
225
302
  });
226
303
 
227
304
  test("owner grant operations reject a noncanonical namespace and trim the principal", async () => {
228
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-grant-namespace-"));
305
+ const root = await mkdtemp(
306
+ path.join(tmpdir(), "remnic-support-grant-namespace-"),
307
+ );
229
308
  try {
230
309
  const now = new Date("2026-08-11T12:00:00.000Z");
231
- const store = new SupportPassportGrantStore({ memoryDir: root, now: () => now });
310
+ const store = new SupportPassportGrantStore({
311
+ memoryDir: root,
312
+ now: () => now,
313
+ });
232
314
  await assert.rejects(
233
315
  store.create({
234
316
  namespace: " alice ",
@@ -236,7 +318,8 @@ test("owner grant operations reject a noncanonical namespace and trim the princi
236
318
  cards: [{ cardId: "card-1", revision: "a".repeat(64) }],
237
319
  expiresAt: new Date(now.getTime() + 3_600_000).toISOString(),
238
320
  }),
239
- (error: unknown) => error instanceof SupportPassportError && error.code === "invalid_input"
321
+ (error: unknown) =>
322
+ error instanceof SupportPassportError && error.code === "invalid_input",
240
323
  );
241
324
  const created = await store.create({
242
325
  namespace: "alice",
@@ -246,8 +329,10 @@ test("owner grant operations reject a noncanonical namespace and trim the princi
246
329
  });
247
330
 
248
331
  assert.deepEqual(
249
- (await store.listForOwner("alice", "owner:alice")).map((state) => state.grantId),
250
- [created.state.grantId]
332
+ (await store.listForOwner("alice", "owner:alice")).map(
333
+ (state) => state.grantId,
334
+ ),
335
+ [created.state.grantId],
251
336
  );
252
337
  const revoked = await store.revoke({
253
338
  grantId: created.state.grantId,
@@ -262,13 +347,16 @@ test("owner grant operations reject a noncanonical namespace and trim the princi
262
347
  });
263
348
 
264
349
  test("owner grant history stays bounded while an inactive link frees capacity", async () => {
265
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-grant-history-"));
350
+ const root = await mkdtemp(
351
+ path.join(tmpdir(), "remnic-support-grant-history-"),
352
+ );
266
353
  try {
267
354
  const now = new Date("2026-08-11T12:00:00.000Z");
268
355
  let nextGrantId = 1;
269
356
  const store = new SupportPassportGrantStore({
270
357
  memoryDir: root,
271
- makeGrantId: () => `00000000-0000-4000-8000-${String(nextGrantId++).padStart(12, "0")}`,
358
+ makeGrantId: () =>
359
+ `00000000-0000-4000-8000-${String(nextGrantId++).padStart(12, "0")}`,
272
360
  now: () => now,
273
361
  });
274
362
  const input = {
@@ -282,7 +370,8 @@ test("owner grant history stays bounded while an inactive link frees capacity",
282
370
 
283
371
  await assert.rejects(
284
372
  store.create(input),
285
- (error: unknown) => error instanceof SupportPassportError && error.code === "invalid_input"
373
+ (error: unknown) =>
374
+ error instanceof SupportPassportError && error.code === "invalid_input",
286
375
  );
287
376
  await store.revoke({
288
377
  grantId: first.state.grantId,
@@ -290,7 +379,13 @@ test("owner grant history stays bounded while an inactive link frees capacity",
290
379
  principal: input.principal,
291
380
  expectedStateVersion: first.state.stateVersion,
292
381
  });
293
- const firstGrantPath = path.join(root, "state", "support-passport", "grants", `${first.state.grantId}.json`);
382
+ const firstGrantPath = path.join(
383
+ root,
384
+ "state",
385
+ "support-passport",
386
+ "grants",
387
+ `${first.state.grantId}.json`,
388
+ );
294
389
  const inspected = store as unknown as {
295
390
  readState(grantId: string): Promise<unknown>;
296
391
  writeOwnerIndex(ownerHash: string, grantIds: string[]): Promise<void>;
@@ -298,25 +393,44 @@ test("owner grant history stays bounded while an inactive link frees capacity",
298
393
  const readState = inspected.readState.bind(store);
299
394
  const writeOwnerIndex = inspected.writeOwnerIndex.bind(store);
300
395
  inspected.writeOwnerIndex = async () => {
301
- throw Object.assign(new Error("simulated owner index write failure"), { code: "EIO" });
396
+ throw Object.assign(new Error("simulated owner index write failure"), {
397
+ code: "EIO",
398
+ });
302
399
  };
303
- await assert.rejects(store.create(input), (error: unknown) => (error as NodeJS.ErrnoException).code === "EIO");
400
+ await assert.rejects(
401
+ store.create(input),
402
+ (error: unknown) => (error as NodeJS.ErrnoException).code === "EIO",
403
+ );
304
404
  inspected.writeOwnerIndex = writeOwnerIndex;
305
405
  assert.equal((await lstat(firstGrantPath)).isFile(), true);
306
- assert.equal((await store.listForOwner(input.namespace, input.principal)).length, 100);
406
+ assert.equal(
407
+ (await store.listForOwner(input.namespace, input.principal)).length,
408
+ 100,
409
+ );
307
410
 
308
411
  inspected.readState = async (grantId) => {
309
412
  if (grantId === first.state.grantId) {
310
- throw Object.assign(new Error("simulated indexed grant read failure"), { code: "EIO" });
413
+ throw Object.assign(new Error("simulated indexed grant read failure"), {
414
+ code: "EIO",
415
+ });
311
416
  }
312
417
  return await readState(grantId);
313
418
  };
314
- await assert.rejects(store.create(input), (error: unknown) => (error as NodeJS.ErrnoException).code === "EIO");
419
+ await assert.rejects(
420
+ store.create(input),
421
+ (error: unknown) => (error as NodeJS.ErrnoException).code === "EIO",
422
+ );
315
423
  inspected.readState = readState;
316
- assert.equal((await store.listForOwner(input.namespace, input.principal)).length, 100);
424
+ assert.equal(
425
+ (await store.listForOwner(input.namespace, input.principal)).length,
426
+ 100,
427
+ );
317
428
  const evictedGrantLocks: string[] = [];
318
429
  const lockAwareStore = store as unknown as {
319
- withGrantLock<T>(grantId: string, task: (lock: { refresh(): Promise<boolean> }) => Promise<T>): Promise<T>;
430
+ withGrantLock<T>(
431
+ grantId: string,
432
+ task: (lock: { refresh(): Promise<boolean> }) => Promise<T>,
433
+ ): Promise<T>;
320
434
  };
321
435
  const withGrantLock = lockAwareStore.withGrantLock.bind(store);
322
436
  lockAwareStore.withGrantLock = async (grantId, task) => {
@@ -328,21 +442,26 @@ test("owner grant history stays bounded while an inactive link frees capacity",
328
442
  assert.equal(listed.length, 100);
329
443
  assert.equal(
330
444
  listed.some((state) => state.grantId === first.state.grantId),
331
- false
445
+ false,
332
446
  );
333
447
  assert.equal(
334
448
  listed.some((state) => state.grantId === replacement.state.grantId),
335
- true
449
+ true,
336
450
  );
337
451
  assert.deepEqual(evictedGrantLocks, [first.state.grantId]);
338
- await assert.rejects(lstat(firstGrantPath), (error: unknown) => (error as NodeJS.ErrnoException).code === "ENOENT");
452
+ await assert.rejects(
453
+ lstat(firstGrantPath),
454
+ (error: unknown) => (error as NodeJS.ErrnoException).code === "ENOENT",
455
+ );
339
456
  } finally {
340
457
  await rm(root, { recursive: true, force: true });
341
458
  }
342
459
  });
343
460
 
344
461
  test("grant creation accepts a state write that committed before its durability error", async () => {
345
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-grant-state-commit-"));
462
+ const root = await mkdtemp(
463
+ path.join(tmpdir(), "remnic-support-grant-state-commit-"),
464
+ );
346
465
  try {
347
466
  const grantId = "00000000-0000-4000-8000-000000000001";
348
467
  const now = new Date("2026-08-11T12:00:00.000Z");
@@ -362,7 +481,9 @@ test("grant creation accepts a state write that committed before its durability
362
481
  const writeState = inspected.writeState.bind(store);
363
482
  inspected.writeState = async (state, requireAbsent) => {
364
483
  await writeState(state, requireAbsent);
365
- throw Object.assign(new Error("simulated post-commit state error"), { code: "EIO" });
484
+ throw Object.assign(new Error("simulated post-commit state error"), {
485
+ code: "EIO",
486
+ });
366
487
  };
367
488
 
368
489
  const created = await store.create({
@@ -374,8 +495,10 @@ test("grant creation accepts a state write that committed before its durability
374
495
 
375
496
  assert.equal(created.state.grantId, grantId);
376
497
  assert.deepEqual(
377
- (await store.listForOwner("alice", "owner:alice")).map((state) => state.grantId),
378
- [grantId]
498
+ (await store.listForOwner("alice", "owner:alice")).map(
499
+ (state) => state.grantId,
500
+ ),
501
+ [grantId],
379
502
  );
380
503
  assert.deepEqual(
381
504
  directorySyncs.map((directory) => path.basename(directory)),
@@ -427,18 +550,26 @@ test("grant creation fails closed when a committed state cannot be re-synced", a
427
550
  });
428
551
 
429
552
  test("grant creation re-syncs an owner index write that committed before its durability error", async () => {
430
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-grant-index-commit-"));
553
+ const root = await mkdtemp(
554
+ path.join(tmpdir(), "remnic-support-grant-index-commit-"),
555
+ );
431
556
  try {
432
557
  const grantId = "00000000-0000-4000-8000-000000000001";
433
558
  const now = new Date("2026-08-11T12:00:00.000Z");
434
- const store = new SupportPassportGrantStore({ memoryDir: root, makeGrantId: () => grantId, now: () => now });
559
+ const store = new SupportPassportGrantStore({
560
+ memoryDir: root,
561
+ makeGrantId: () => grantId,
562
+ now: () => now,
563
+ });
435
564
  const inspected = store as unknown as {
436
565
  writeOwnerIndex(ownerHash: string, grantIds: string[]): Promise<void>;
437
566
  };
438
567
  const writeOwnerIndex = inspected.writeOwnerIndex.bind(store);
439
568
  inspected.writeOwnerIndex = async (ownerHash, grantIds) => {
440
569
  await writeOwnerIndex(ownerHash, grantIds);
441
- throw Object.assign(new Error("simulated post-commit index error"), { code: "EIO" });
570
+ throw Object.assign(new Error("simulated post-commit index error"), {
571
+ code: "EIO",
572
+ });
442
573
  };
443
574
 
444
575
  const created = await store.create({
@@ -450,8 +581,10 @@ test("grant creation re-syncs an owner index write that committed before its dur
450
581
 
451
582
  assert.equal(created.state.grantId, grantId);
452
583
  assert.deepEqual(
453
- (await store.listForOwner("alice", "owner:alice")).map((state) => state.grantId),
454
- [grantId]
584
+ (await store.listForOwner("alice", "owner:alice")).map(
585
+ (state) => state.grantId,
586
+ ),
587
+ [grantId],
455
588
  );
456
589
  } finally {
457
590
  await rm(root, { recursive: true, force: true });
@@ -514,7 +647,8 @@ test("owner grant rollover ignores a foreign derived-index entry", async () => {
514
647
  let nextGrantId = 1;
515
648
  const store = new SupportPassportGrantStore({
516
649
  memoryDir: root,
517
- makeGrantId: () => `00000000-0000-4000-8000-${String(nextGrantId++).padStart(12, "0")}`,
650
+ makeGrantId: () =>
651
+ `00000000-0000-4000-8000-${String(nextGrantId++).padStart(12, "0")}`,
518
652
  now: () => now,
519
653
  });
520
654
  const common = {
@@ -524,7 +658,9 @@ test("owner grant rollover ignores a foreign derived-index entry", async () => {
524
658
  };
525
659
  const aliceGrants = [];
526
660
  for (let index = 0; index < 99; index += 1) {
527
- aliceGrants.push(await store.create({ ...common, principal: "owner:alice" }));
661
+ aliceGrants.push(
662
+ await store.create({ ...common, principal: "owner:alice" }),
663
+ );
528
664
  }
529
665
  const bob = await store.create({ ...common, principal: "owner:bob" });
530
666
  await store.revoke({
@@ -538,12 +674,21 @@ test("owner grant rollover ignores a foreign derived-index entry", async () => {
538
674
  };
539
675
  const firstAliceGrant = aliceGrants[0];
540
676
  assert.ok(firstAliceGrant);
541
- const aliceOwnerHash = inspected.ownerHash(common.namespace, firstAliceGrant.state.principalHash);
677
+ const aliceOwnerHash = inspected.ownerHash(
678
+ common.namespace,
679
+ firstAliceGrant.state.principalHash,
680
+ );
542
681
  await inspected.writeOwnerIndex(aliceOwnerHash, [
543
682
  ...aliceGrants.map((grant) => grant.state.grantId),
544
683
  bob.state.grantId,
545
684
  ]);
546
- const bobGrantPath = path.join(root, "state", "support-passport", "grants", `${bob.state.grantId}.json`);
685
+ const bobGrantPath = path.join(
686
+ root,
687
+ "state",
688
+ "support-passport",
689
+ "grants",
690
+ `${bob.state.grantId}.json`,
691
+ );
547
692
 
548
693
  const replacement = await store.create({ ...common, principal: "owner:alice" });
549
694
 
@@ -556,7 +701,9 @@ test("owner grant rollover ignores a foreign derived-index entry", async () => {
556
701
  });
557
702
 
558
703
  test("owner grant history uses one expiry cutoff while it prunes old links", async () => {
559
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-grant-cutoff-"));
704
+ const root = await mkdtemp(
705
+ path.join(tmpdir(), "remnic-support-grant-cutoff-"),
706
+ );
560
707
  try {
561
708
  const initialTime = Date.parse("2026-08-11T12:00:00.000Z");
562
709
  let currentTime = initialTime;
@@ -565,10 +712,13 @@ test("owner grant history uses one expiry cutoff while it prunes old links", asy
565
712
  let nextGrantId = 1;
566
713
  const store = new SupportPassportGrantStore({
567
714
  memoryDir: root,
568
- makeGrantId: () => `00000000-0000-4000-8000-${String(nextGrantId++).padStart(12, "0")}`,
715
+ makeGrantId: () =>
716
+ `00000000-0000-4000-8000-${String(nextGrantId++).padStart(12, "0")}`,
569
717
  now: () => {
570
718
  partitionCalls += 1;
571
- return new Date(currentTime + (crossExpiry && partitionCalls > 101 ? 1 : 0));
719
+ return new Date(
720
+ currentTime + (crossExpiry && partitionCalls > 101 ? 1 : 0),
721
+ );
572
722
  },
573
723
  });
574
724
  const common = {
@@ -610,11 +760,11 @@ test("owner grant history uses one expiry cutoff while it prunes old links", asy
610
760
  assert.equal(new Set(listed.map((state) => state.grantId)).size, 100);
611
761
  assert.equal(
612
762
  listed.some((state) => state.grantId === crossing.state.grantId),
613
- true
763
+ true,
614
764
  );
615
765
  assert.equal(
616
766
  listed.some((state) => state.grantId === created.state.grantId),
617
- true
767
+ true,
618
768
  );
619
769
  } finally {
620
770
  await rm(root, { recursive: true, force: true });
@@ -626,7 +776,10 @@ test("grant mutations report a storage conflict when the file lock is busy", asy
626
776
  try {
627
777
  const now = new Date("2026-08-11T12:00:00.000Z");
628
778
  const rejectLock = (async (_lockPath, _options, task) =>
629
- await task(false, { refresh: async () => false, failure: "timeout" })) as typeof withHeldFileLock;
779
+ await task(false, {
780
+ refresh: async () => false,
781
+ failure: "timeout",
782
+ })) as typeof withHeldFileLock;
630
783
  const store = new SupportPassportGrantStore({
631
784
  memoryDir: root,
632
785
  now: () => now,
@@ -641,7 +794,9 @@ test("grant mutations report a storage conflict when the file lock is busy", asy
641
794
  expiresAt: new Date(now.getTime() + 300_000).toISOString(),
642
795
  }),
643
796
  (error: unknown) =>
644
- error instanceof SupportPassportError && error.code === "storage_conflict" && error.status === 409
797
+ error instanceof SupportPassportError &&
798
+ error.code === "storage_conflict" &&
799
+ error.status === 409,
645
800
  );
646
801
  } finally {
647
802
  await rm(root, { recursive: true, force: true });
@@ -652,7 +807,9 @@ test("grant creation rechecks the owner lock immediately before commit", async (
652
807
  const subject = await makeSubject();
653
808
  try {
654
809
  const card = await createActiveCard(subject);
655
- const originalRead = subject.aliceStorage.readAllMemories.bind(subject.aliceStorage);
810
+ const originalRead = subject.aliceStorage.readAllMemories.bind(
811
+ subject.aliceStorage,
812
+ );
656
813
  let replacedLock = false;
657
814
  subject.aliceStorage.readAllMemories = async (...args) => {
658
815
  const memories = await originalRead(...args);
@@ -662,7 +819,10 @@ test("grant creation rechecks the owner lock immediately before commit", async (
662
819
  namespace: "alice",
663
820
  principal: "owner:alice",
664
821
  });
665
- await writeFile(lockPath, `${process.pid} 00000000-0000-4000-8000-000000000000 peer\n`);
822
+ await writeFile(
823
+ lockPath,
824
+ `${process.pid} 00000000-0000-4000-8000-000000000000 peer\n`,
825
+ );
666
826
  }
667
827
  return memories;
668
828
  };
@@ -674,9 +834,53 @@ test("grant creation rechecks the owner lock immediately before commit", async (
674
834
  expiresAt: expiryAfter(subject, 300_000),
675
835
  }),
676
836
  (error: unknown) =>
677
- error instanceof SupportPassportError && error.code === "storage_conflict" && error.status === 409
837
+ error instanceof SupportPassportError &&
838
+ error.code === "storage_conflict" &&
839
+ error.status === 409,
840
+ );
841
+ assert.deepEqual(
842
+ await subject.grantService.listGrants({ principal: "owner:alice" }),
843
+ [],
844
+ );
845
+ } finally {
846
+ await subject.cleanup();
847
+ }
848
+ });
849
+
850
+ test("grant creation does not report a commit before owner indexing completes", async () => {
851
+ const subject = await makeSubject();
852
+ try {
853
+ const active = await createActiveCard(subject);
854
+ const inspected = subject.grantStore as unknown as {
855
+ addToOwnerIndex(): Promise<void>;
856
+ };
857
+ inspected.addToOwnerIndex = async () => {
858
+ throw new Error("simulated owner index failure");
859
+ };
860
+ let committed = 0;
861
+
862
+ await assert.rejects(
863
+ subject.grantService.createGrant(
864
+ {
865
+ principal: "owner:alice",
866
+ cards: [{ cardId: active.cardId, revision: active.revision }],
867
+ expiresAt: new Date(
868
+ subject.now().getTime() + 3_600_000,
869
+ ).toISOString(),
870
+ },
871
+ {
872
+ onCommitted: () => {
873
+ committed += 1;
874
+ },
875
+ },
876
+ ),
877
+ /simulated owner index failure/,
878
+ );
879
+ assert.equal(committed, 0);
880
+ assert.deepEqual(
881
+ await subject.grantService.listGrants({ principal: "owner:alice" }),
882
+ [],
678
883
  );
679
- assert.deepEqual(await subject.grantService.listGrants({ principal: "owner:alice" }), []);
680
884
  } finally {
681
885
  await subject.cleanup();
682
886
  }
@@ -798,7 +1002,9 @@ test("grant creation measures its minimum lifetime from request receipt", async
798
1002
  try {
799
1003
  const card = await createActiveCard(subject);
800
1004
  const expiresAt = expiryAfter(subject, 300_000);
801
- const readAllMemories = subject.aliceStorage.readAllMemories.bind(subject.aliceStorage);
1005
+ const readAllMemories = subject.aliceStorage.readAllMemories.bind(
1006
+ subject.aliceStorage,
1007
+ );
802
1008
  let delayed = false;
803
1009
  subject.aliceStorage.readAllMemories = async (...args) => {
804
1010
  const memories = await readAllMemories(...args);
@@ -883,19 +1089,25 @@ test("directory sync ignores only explicit unsupported errors", async () => {
883
1089
 
884
1090
  await assert.rejects(
885
1091
  syncDirectoryForDurability("/unused", failingOpen("EIO")),
886
- (error: unknown) => (error as NodeJS.ErrnoException).code === "EIO"
1092
+ (error: unknown) => (error as NodeJS.ErrnoException).code === "EIO",
887
1093
  );
888
1094
  await syncDirectoryForDurability("/unused", failingOpen("EINVAL"));
889
1095
  });
890
1096
 
891
1097
  test("grant creation aborts before replacing an owner index after lock ownership is lost", async () => {
892
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-grant-lock-loss-"));
1098
+ const root = await mkdtemp(
1099
+ path.join(tmpdir(), "remnic-support-grant-lock-loss-"),
1100
+ );
893
1101
  try {
894
- const grantIds = ["00000000-0000-4000-8000-000000000001", "00000000-0000-4000-8000-000000000002"];
1102
+ const grantIds = [
1103
+ "00000000-0000-4000-8000-000000000001",
1104
+ "00000000-0000-4000-8000-000000000002",
1105
+ ];
895
1106
  const now = new Date("2026-08-11T12:00:00.000Z");
896
1107
  const store = new SupportPassportGrantStore({
897
1108
  memoryDir: root,
898
- makeGrantId: () => grantIds.shift() ?? "00000000-0000-4000-8000-000000000003",
1109
+ makeGrantId: () =>
1110
+ grantIds.shift() ?? "00000000-0000-4000-8000-000000000003",
899
1111
  now: () => now,
900
1112
  });
901
1113
  const input = {
@@ -907,7 +1119,9 @@ test("grant creation aborts before replacing an owner index after lock ownership
907
1119
  const first = await store.create(input);
908
1120
  let refreshes = 0;
909
1121
  const inspected = store as unknown as {
910
- withMutationLock<T>(task: (lock: { refresh(): Promise<boolean> }) => Promise<T>): Promise<T>;
1122
+ withMutationLock<T>(
1123
+ task: (lock: { refresh(): Promise<boolean> }) => Promise<T>,
1124
+ ): Promise<T>;
911
1125
  };
912
1126
  inspected.withMutationLock = async (task) =>
913
1127
  await task({
@@ -919,12 +1133,16 @@ test("grant creation aborts before replacing an owner index after lock ownership
919
1133
 
920
1134
  await assert.rejects(
921
1135
  store.create(input),
922
- (error: unknown) => error instanceof SupportPassportError && error.code === "storage_conflict"
1136
+ (error: unknown) =>
1137
+ error instanceof SupportPassportError &&
1138
+ error.code === "storage_conflict",
923
1139
  );
924
1140
  assert.equal(refreshes, 2);
925
1141
  assert.deepEqual(
926
- (await store.listForOwner("alice", "owner:alice")).map((state) => state.grantId),
927
- [first.state.grantId]
1142
+ (await store.listForOwner("alice", "owner:alice")).map(
1143
+ (state) => state.grantId,
1144
+ ),
1145
+ [first.state.grantId],
928
1146
  );
929
1147
  } finally {
930
1148
  await rm(root, { recursive: true, force: true });
@@ -1332,13 +1550,20 @@ test("one owner's index transaction does not block another owner", async () => {
1332
1550
  });
1333
1551
 
1334
1552
  test("grant creation rechecks its mutation lock after the commit callback", async () => {
1335
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-grant-callback-lock-"));
1553
+ const root = await mkdtemp(
1554
+ path.join(tmpdir(), "remnic-support-grant-callback-lock-"),
1555
+ );
1336
1556
  try {
1337
1557
  const now = new Date("2026-08-11T12:00:00.000Z");
1338
- const store = new SupportPassportGrantStore({ memoryDir: root, now: () => now });
1558
+ const store = new SupportPassportGrantStore({
1559
+ memoryDir: root,
1560
+ now: () => now,
1561
+ });
1339
1562
  let refreshes = 0;
1340
1563
  const inspected = store as unknown as {
1341
- withMutationLock<T>(task: (lock: { refresh(): Promise<boolean> }) => Promise<T>): Promise<T>;
1564
+ withMutationLock<T>(
1565
+ task: (lock: { refresh(): Promise<boolean> }) => Promise<T>,
1566
+ ): Promise<T>;
1342
1567
  };
1343
1568
  inspected.withMutationLock = async (task) =>
1344
1569
  await task({
@@ -1356,9 +1581,11 @@ test("grant creation rechecks its mutation lock after the commit callback", asyn
1356
1581
  cards: [{ cardId: "card-1", revision: "a".repeat(64) }],
1357
1582
  expiresAt: new Date(now.getTime() + 300_000).toISOString(),
1358
1583
  },
1359
- async () => undefined
1584
+ async () => undefined,
1360
1585
  ),
1361
- (error: unknown) => error instanceof SupportPassportError && error.code === "storage_conflict"
1586
+ (error: unknown) =>
1587
+ error instanceof SupportPassportError &&
1588
+ error.code === "storage_conflict",
1362
1589
  );
1363
1590
  assert.equal(refreshes, 2);
1364
1591
  assert.deepEqual(await readdir(path.join(root, "state", "support-passport", "grants")), ["owners"]);
@@ -1368,10 +1595,15 @@ test("grant creation rechecks its mutation lock after the commit callback", asyn
1368
1595
  });
1369
1596
 
1370
1597
  test("grant revocation rechecks its mutation lock after the commit callback", async () => {
1371
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-revoke-callback-lock-"));
1598
+ const root = await mkdtemp(
1599
+ path.join(tmpdir(), "remnic-support-revoke-callback-lock-"),
1600
+ );
1372
1601
  try {
1373
1602
  const now = new Date("2026-08-11T12:00:00.000Z");
1374
- const store = new SupportPassportGrantStore({ memoryDir: root, now: () => now });
1603
+ const store = new SupportPassportGrantStore({
1604
+ memoryDir: root,
1605
+ now: () => now,
1606
+ });
1375
1607
  const created = await store.create({
1376
1608
  namespace: "alice",
1377
1609
  principal: "owner:alice",
@@ -1380,7 +1612,10 @@ test("grant revocation rechecks its mutation lock after the commit callback", as
1380
1612
  });
1381
1613
  let refreshes = 0;
1382
1614
  const inspected = store as unknown as {
1383
- withGrantLock<T>(grantId: string, task: (lock: { refresh(): Promise<boolean> }) => Promise<T>): Promise<T>;
1615
+ withGrantLock<T>(
1616
+ grantId: string,
1617
+ task: (lock: { refresh(): Promise<boolean> }) => Promise<T>,
1618
+ ): Promise<T>;
1384
1619
  };
1385
1620
  inspected.withGrantLock = async (_grantId, task) =>
1386
1621
  await task({
@@ -1392,13 +1627,23 @@ test("grant revocation rechecks its mutation lock after the commit callback", as
1392
1627
 
1393
1628
  await assert.rejects(
1394
1629
  store.revoke(
1395
- { grantId: created.state.grantId, namespace: "alice", principal: "owner:alice" },
1396
- async () => undefined
1630
+ {
1631
+ grantId: created.state.grantId,
1632
+ namespace: "alice",
1633
+ principal: "owner:alice",
1634
+ },
1635
+ { beforeCommit: async () => undefined },
1397
1636
  ),
1398
- (error: unknown) => error instanceof SupportPassportError && error.code === "storage_conflict"
1637
+ (error: unknown) =>
1638
+ error instanceof SupportPassportError &&
1639
+ error.code === "storage_conflict",
1399
1640
  );
1400
1641
  assert.equal(refreshes, 2);
1401
- assert.equal((await store.authenticate(created.state.grantId, created.secret)).revokedAt, undefined);
1642
+ assert.equal(
1643
+ (await store.authenticate(created.state.grantId, created.secret))
1644
+ .revokedAt,
1645
+ undefined,
1646
+ );
1402
1647
  } finally {
1403
1648
  await rm(root, { recursive: true, force: true });
1404
1649
  }
@@ -1439,7 +1684,9 @@ test("a helper sees only the selected active card through a valid secret", async
1439
1684
 
1440
1685
  test("grants reject cards owned by another namespace in shared storage", async () => {
1441
1686
  StorageManager.clearAllStaticCaches();
1442
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-grant-card-scope-"));
1687
+ const root = await mkdtemp(
1688
+ path.join(tmpdir(), "remnic-support-grant-card-scope-"),
1689
+ );
1443
1690
  try {
1444
1691
  const storage = new StorageManager(path.join(root, "shared-storage"));
1445
1692
  await storage.ensureDirectories();
@@ -1450,7 +1697,10 @@ test("grants reject cards owned by another namespace in shared storage", async (
1450
1697
  storage,
1451
1698
  });
1452
1699
  const cardService = new SupportPassportCardService({ resolveOwner, now });
1453
- const grantStore = new SupportPassportGrantStore({ memoryDir: path.join(root, "grants"), now });
1700
+ const grantStore = new SupportPassportGrantStore({
1701
+ memoryDir: path.join(root, "grants"),
1702
+ now,
1703
+ });
1454
1704
  const grantService = new SupportPassportGrantService({
1455
1705
  grantStore,
1456
1706
  resolveOwner,
@@ -1476,7 +1726,9 @@ test("grants reject cards owned by another namespace in shared storage", async (
1476
1726
  cards: [{ cardId: aliceCard.cardId, revision: aliceCard.revision }],
1477
1727
  expiresAt: "2026-08-11T13:00:00.000Z",
1478
1728
  }),
1479
- (error: unknown) => error instanceof SupportPassportError && error.code === "invalid_card_status"
1729
+ (error: unknown) =>
1730
+ error instanceof SupportPassportError &&
1731
+ error.code === "invalid_card_status",
1480
1732
  );
1481
1733
  const forged = await grantStore.create({
1482
1734
  namespace: "bob",
@@ -1485,8 +1737,12 @@ test("grants reject cards owned by another namespace in shared storage", async (
1485
1737
  expiresAt: "2026-08-11T13:00:00.000Z",
1486
1738
  });
1487
1739
  await assert.rejects(
1488
- grantService.readGrant({ grantId: forged.state.grantId, secret: forged.secret }),
1489
- (error: unknown) => error instanceof SupportPassportError && error.code === "grant_stale"
1740
+ grantService.readGrant({
1741
+ grantId: forged.state.grantId,
1742
+ secret: forged.secret,
1743
+ }),
1744
+ (error: unknown) =>
1745
+ error instanceof SupportPassportError && error.code === "grant_stale",
1490
1746
  );
1491
1747
  } finally {
1492
1748
  StorageManager.clearAllStaticCaches();
@@ -1496,14 +1752,23 @@ test("grants reject cards owned by another namespace in shared storage", async (
1496
1752
 
1497
1753
  test("grants reject cards owned by another principal inside a shared namespace", async () => {
1498
1754
  StorageManager.clearAllStaticCaches();
1499
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-grant-owner-scope-"));
1755
+ const root = await mkdtemp(
1756
+ path.join(tmpdir(), "remnic-support-grant-owner-scope-"),
1757
+ );
1500
1758
  try {
1501
1759
  const storage = new StorageManager(path.join(root, "shared-storage"));
1502
1760
  await storage.ensureDirectories();
1503
1761
  const now = () => new Date("2026-08-11T12:00:00.000Z");
1504
- const resolveOwner = async (principal: string) => ({ principal, namespace: "team", storage });
1762
+ const resolveOwner = async (principal: string) => ({
1763
+ principal,
1764
+ namespace: "team",
1765
+ storage,
1766
+ });
1505
1767
  const cardService = new SupportPassportCardService({ resolveOwner, now });
1506
- const grantStore = new SupportPassportGrantStore({ memoryDir: path.join(root, "grants"), now });
1768
+ const grantStore = new SupportPassportGrantStore({
1769
+ memoryDir: path.join(root, "grants"),
1770
+ now,
1771
+ });
1507
1772
  const grantService = new SupportPassportGrantService({
1508
1773
  grantStore,
1509
1774
  resolveOwner,
@@ -1529,7 +1794,9 @@ test("grants reject cards owned by another principal inside a shared namespace",
1529
1794
  cards: [{ cardId: aliceCard.cardId, revision: aliceCard.revision }],
1530
1795
  expiresAt: "2026-08-11T13:00:00.000Z",
1531
1796
  }),
1532
- (error: unknown) => error instanceof SupportPassportError && error.code === "invalid_card_status"
1797
+ (error: unknown) =>
1798
+ error instanceof SupportPassportError &&
1799
+ error.code === "invalid_card_status",
1533
1800
  );
1534
1801
  const forged = await grantStore.create({
1535
1802
  namespace: "team",
@@ -1538,8 +1805,12 @@ test("grants reject cards owned by another principal inside a shared namespace",
1538
1805
  expiresAt: "2026-08-11T13:00:00.000Z",
1539
1806
  });
1540
1807
  await assert.rejects(
1541
- grantService.readGrant({ grantId: forged.state.grantId, secret: forged.secret }),
1542
- (error: unknown) => error instanceof SupportPassportError && error.code === "grant_stale"
1808
+ grantService.readGrant({
1809
+ grantId: forged.state.grantId,
1810
+ secret: forged.secret,
1811
+ }),
1812
+ (error: unknown) =>
1813
+ error instanceof SupportPassportError && error.code === "grant_stale",
1543
1814
  );
1544
1815
  } finally {
1545
1816
  StorageManager.clearAllStaticCaches();
@@ -1581,6 +1852,10 @@ test("helper snapshots ignore colliding card IDs from other owners and reject ow
1581
1852
  expiresAt: "2026-08-11T13:00:00.000Z",
1582
1853
  });
1583
1854
  const originalMemories = await storage.readAllMemories();
1855
+ const getCorpusScanVersion = storage.getCorpusScanVersion.bind(storage);
1856
+ let testCorpusVersion = 0;
1857
+ storage.getCorpusScanVersion = () =>
1858
+ `${getCorpusScanVersion()}:test-${testCorpusVersion}`;
1584
1859
  const aliceMemory = originalMemories.find((memory) => memory.frontmatter.id === card.cardId);
1585
1860
  assert.ok(aliceMemory);
1586
1861
  const foreignCollision = {
@@ -1607,6 +1882,7 @@ test("helper snapshots ignore colliding card IDs from other owners and reject ow
1607
1882
  path: path.join(storage.dir, "preferences", "owned-duplicate.md"),
1608
1883
  };
1609
1884
  storage.readAllMemories = async () => [...originalMemories, foreignCollision, ownedDuplicate];
1885
+ testCorpusVersion += 1;
1610
1886
  await assert.rejects(
1611
1887
  grantService.readGrant({ grantId: created.grant.grantId, secret: created.secret }),
1612
1888
  (error: unknown) => error instanceof SupportPassportError && error.code === "card_data_invalid",
@@ -1621,7 +1897,9 @@ test("grant creation and card withdrawal cannot interleave", async () => {
1621
1897
  const subject = await makeSubject();
1622
1898
  try {
1623
1899
  const card = await createActiveCard(subject);
1624
- const readAllMemories = subject.aliceStorage.readAllMemories.bind(subject.aliceStorage);
1900
+ const readAllMemories = subject.aliceStorage.readAllMemories.bind(
1901
+ subject.aliceStorage,
1902
+ );
1625
1903
  let releaseRead!: () => void;
1626
1904
  let markReadStarted!: () => void;
1627
1905
  const readStarted = new Promise<void>((resolve) => {
@@ -1681,9 +1959,14 @@ test("bad secrets return not found, while valid revoked and expired grants revea
1681
1959
  });
1682
1960
 
1683
1961
  await assert.rejects(
1684
- subject.grantService.readGrant({ grantId: created.grant.grantId, secret: "x".repeat(43) }),
1962
+ subject.grantService.readGrant({
1963
+ grantId: created.grant.grantId,
1964
+ secret: "x".repeat(43),
1965
+ }),
1685
1966
  (error: unknown) =>
1686
- error instanceof SupportPassportError && error.code === "grant_not_found" && error.status === 404
1967
+ error instanceof SupportPassportError &&
1968
+ error.code === "grant_not_found" &&
1969
+ error.status === 404,
1687
1970
  );
1688
1971
 
1689
1972
  await assert.rejects(
@@ -1694,10 +1977,15 @@ test("bad secrets return not found, while valid revoked and expired grants revea
1694
1977
  expectedStateVersion: created.grant.stateVersion + 1,
1695
1978
  }),
1696
1979
  (error: unknown) =>
1697
- error instanceof SupportPassportError && error.code === "state_conflict" && error.status === 409
1980
+ error instanceof SupportPassportError &&
1981
+ error.code === "state_conflict" &&
1982
+ error.status === 409,
1698
1983
  );
1699
1984
 
1700
- const peerStore = new SupportPassportGrantStore({ memoryDir: path.join(subject.root, "shared"), now: subject.now });
1985
+ const peerStore = new SupportPassportGrantStore({
1986
+ memoryDir: path.join(subject.root, "shared"),
1987
+ now: subject.now,
1988
+ });
1701
1989
  const peerRevoked = await peerStore.revoke({
1702
1990
  namespace: "alice",
1703
1991
  principal: "owner:alice",
@@ -1713,8 +2001,14 @@ test("bad secrets return not found, while valid revoked and expired grants revea
1713
2001
  assert.equal(repeated.stateVersion, peerRevoked.stateVersion);
1714
2002
  assert.equal(repeated.revokedAt, peerRevoked.revokedAt);
1715
2003
  await assert.rejects(
1716
- subject.grantService.readGrant({ grantId: created.grant.grantId, secret: created.secret }),
1717
- (error: unknown) => error instanceof SupportPassportError && error.code === "grant_gone" && error.status === 410
2004
+ subject.grantService.readGrant({
2005
+ grantId: created.grant.grantId,
2006
+ secret: created.secret,
2007
+ }),
2008
+ (error: unknown) =>
2009
+ error instanceof SupportPassportError &&
2010
+ error.code === "grant_gone" &&
2011
+ error.status === 410,
1718
2012
  );
1719
2013
 
1720
2014
  const second = await subject.grantService.createGrant({
@@ -1724,9 +2018,14 @@ test("bad secrets return not found, while valid revoked and expired grants revea
1724
2018
  });
1725
2019
  subject.advance(300_000);
1726
2020
  await assert.rejects(
1727
- subject.grantService.readGrant({ grantId: second.grant.grantId, secret: second.secret }),
2021
+ subject.grantService.readGrant({
2022
+ grantId: second.grant.grantId,
2023
+ secret: second.secret,
2024
+ }),
1728
2025
  (error: unknown) =>
1729
- error instanceof SupportPassportError && error.code === "grant_expired" && error.status === 410
2026
+ error instanceof SupportPassportError &&
2027
+ error.code === "grant_expired" &&
2028
+ error.status === 410,
1730
2029
  );
1731
2030
  } finally {
1732
2031
  await subject.cleanup();
@@ -1742,20 +2041,26 @@ test("a grant that expires during guide assembly does not return a guide", async
1742
2041
  cards: [{ cardId: card.cardId, revision: card.revision }],
1743
2042
  expiresAt: expiryAfter(subject, 300_000),
1744
2043
  });
1745
- const readAllMemories = subject.aliceStorage.readAllMemories.bind(subject.aliceStorage);
2044
+ const authenticate = subject.grantStore.authenticate.bind(
2045
+ subject.grantStore,
2046
+ );
1746
2047
  let advanced = false;
1747
- subject.aliceStorage.readAllMemories = async (...args) => {
1748
- const memories = await readAllMemories(...args);
2048
+ subject.grantStore.authenticate = async (grantId, secret) => {
2049
+ const state = await authenticate(grantId, secret);
1749
2050
  if (!advanced) {
1750
2051
  advanced = true;
1751
2052
  subject.advance(300_000);
1752
2053
  }
1753
- return memories;
2054
+ return state;
1754
2055
  };
1755
2056
 
1756
2057
  await assert.rejects(
1757
- subject.grantService.readGrant({ grantId: created.grant.grantId, secret: created.secret }),
1758
- (error: unknown) => error instanceof SupportPassportError && error.code === "grant_expired"
2058
+ subject.grantService.readGrant({
2059
+ grantId: created.grant.grantId,
2060
+ secret: created.secret,
2061
+ }),
2062
+ (error: unknown) =>
2063
+ error instanceof SupportPassportError && error.code === "grant_expired",
1759
2064
  );
1760
2065
  } finally {
1761
2066
  await subject.cleanup();
@@ -1773,17 +2078,22 @@ test("revocation wins while an optimistic helper card read is still pending", as
1773
2078
  cards: [{ cardId: card.cardId, revision: card.revision }],
1774
2079
  expiresAt: expiryAfter(subject, 3_600_000),
1775
2080
  });
1776
- const peerStore = new SupportPassportGrantStore({ memoryDir: path.join(subject.root, "shared"), now: subject.now });
1777
- const readAllMemories = subject.aliceStorage.readAllMemories.bind(subject.aliceStorage);
1778
- let paused = false;
1779
- subject.aliceStorage.readAllMemories = async (...args) => {
1780
- const memories = await readAllMemories(...args);
1781
- if (!paused) {
1782
- paused = true;
2081
+ const peerStore = new SupportPassportGrantStore({
2082
+ memoryDir: path.join(subject.root, "shared"),
2083
+ now: subject.now,
2084
+ });
2085
+ const authenticate = subject.grantStore.authenticate.bind(
2086
+ subject.grantStore,
2087
+ );
2088
+ let authentications = 0;
2089
+ subject.grantStore.authenticate = async (grantId, secret) => {
2090
+ const state = await authenticate(grantId, secret);
2091
+ authentications += 1;
2092
+ if (authentications === 1) {
1783
2093
  cardReadStarted.resolve();
1784
2094
  await releaseCardRead.promise;
1785
2095
  }
1786
- return memories;
2096
+ return state;
1787
2097
  };
1788
2098
 
1789
2099
  const readPromise = subject.grantService.readGrant({
@@ -1802,7 +2112,8 @@ test("revocation wins while an optimistic helper card read is still pending", as
1802
2112
  releaseCardRead.resolve();
1803
2113
  await assert.rejects(
1804
2114
  readPromise,
1805
- (error: unknown) => error instanceof SupportPassportError && error.code === "grant_gone"
2115
+ (error: unknown) =>
2116
+ error instanceof SupportPassportError && error.code === "grant_gone",
1806
2117
  );
1807
2118
  } finally {
1808
2119
  releaseCardRead.resolve();
@@ -1827,7 +2138,9 @@ test("helper reads for different grants do not block each other", async () => {
1827
2138
  expiresAt: expiryAfter(subject, 3_600_000),
1828
2139
  });
1829
2140
  const firstStarted = Promise.withResolvers<void>();
1830
- const authenticate = subject.grantStore.authenticate.bind(subject.grantStore);
2141
+ const authenticate = subject.grantStore.authenticate.bind(
2142
+ subject.grantStore,
2143
+ );
1831
2144
  subject.grantStore.authenticate = async (grantId, secret) => {
1832
2145
  const state = await authenticate(grantId, secret);
1833
2146
  if (grantId === first.grant.grantId) {
@@ -1836,7 +2149,10 @@ test("helper reads for different grants do not block each other", async () => {
1836
2149
  }
1837
2150
  return state;
1838
2151
  };
1839
- const firstRead = subject.grantService.readGrant({ grantId: first.grant.grantId, secret: first.secret });
2152
+ const firstRead = subject.grantService.readGrant({
2153
+ grantId: first.grant.grantId,
2154
+ secret: first.secret,
2155
+ });
1840
2156
  await firstStarted.promise;
1841
2157
  const secondGuide = await subject.grantService.readGrant({
1842
2158
  grantId: second.grant.grantId,
@@ -1877,7 +2193,7 @@ test("helper guide snapshots reuse selected cards from the corpus snapshot", asy
1877
2193
 
1878
2194
  assert.deepEqual(
1879
2195
  guide.cards.map((card) => card.cardId),
1880
- [firstCard.cardId, secondCard.cardId]
2196
+ [firstCard.cardId, secondCard.cardId],
1881
2197
  );
1882
2198
  } finally {
1883
2199
  await subject.cleanup();
@@ -1895,7 +2211,9 @@ test("final helper guide assembly blocks card withdrawal", async () => {
1895
2211
  cards: [{ cardId: card.cardId, revision: card.revision }],
1896
2212
  expiresAt: expiryAfter(subject, 3_600_000),
1897
2213
  });
1898
- const authenticate = subject.grantStore.authenticate.bind(subject.grantStore);
2214
+ const authenticate = subject.grantStore.authenticate.bind(
2215
+ subject.grantStore,
2216
+ );
1899
2217
  let authentications = 0;
1900
2218
  subject.grantStore.authenticate = async (grantId, secret) => {
1901
2219
  const state = await authenticate(grantId, secret);
@@ -1947,7 +2265,9 @@ test("final helper guide assembly blocks owner revocation", async () => {
1947
2265
  cards: [{ cardId: card.cardId, revision: card.revision }],
1948
2266
  expiresAt: expiryAfter(subject, 3_600_000),
1949
2267
  });
1950
- const authenticate = subject.grantStore.authenticate.bind(subject.grantStore);
2268
+ const authenticate = subject.grantStore.authenticate.bind(
2269
+ subject.grantStore,
2270
+ );
1951
2271
  let authentications = 0;
1952
2272
  subject.grantStore.authenticate = async (grantId, secret) => {
1953
2273
  const state = await authenticate(grantId, secret);
@@ -1997,7 +2317,9 @@ test("helper guide assembly fails when owner-lock ownership is lost", async () =
1997
2317
  cards: [{ cardId: card.cardId, revision: card.revision }],
1998
2318
  expiresAt: expiryAfter(subject, 3_600_000),
1999
2319
  });
2000
- const authenticate = subject.grantStore.authenticate.bind(subject.grantStore);
2320
+ const authenticate = subject.grantStore.authenticate.bind(
2321
+ subject.grantStore,
2322
+ );
2001
2323
  let authentications = 0;
2002
2324
  subject.grantStore.authenticate = async (grantId, secret) => {
2003
2325
  const state = await authenticate(grantId, secret);
@@ -2007,14 +2329,22 @@ test("helper guide assembly fails when owner-lock ownership is lost", async () =
2007
2329
  namespace: "alice",
2008
2330
  principal: "owner:alice",
2009
2331
  });
2010
- await writeFile(lockPath, `${process.pid} 00000000-0000-4000-8000-000000000000 peer\n`);
2332
+ await writeFile(
2333
+ lockPath,
2334
+ `${process.pid} 00000000-0000-4000-8000-000000000000 peer\n`,
2335
+ );
2011
2336
  }
2012
2337
  return state;
2013
2338
  };
2014
2339
 
2015
2340
  await assert.rejects(
2016
- subject.grantService.readGrant({ grantId: created.grant.grantId, secret: created.secret }),
2017
- (error: unknown) => error instanceof SupportPassportError && error.code === "storage_conflict"
2341
+ subject.grantService.readGrant({
2342
+ grantId: created.grant.grantId,
2343
+ secret: created.secret,
2344
+ }),
2345
+ (error: unknown) =>
2346
+ error instanceof SupportPassportError &&
2347
+ error.code === "storage_conflict",
2018
2348
  );
2019
2349
  } finally {
2020
2350
  await subject.cleanup();
@@ -2030,7 +2360,9 @@ test("helper guide assembly rechecks the owner lock after grant reauthentication
2030
2360
  cards: [{ cardId: card.cardId, revision: card.revision }],
2031
2361
  expiresAt: expiryAfter(subject, 3_600_000),
2032
2362
  });
2033
- const authenticate = subject.grantStore.authenticate.bind(subject.grantStore);
2363
+ const authenticate = subject.grantStore.authenticate.bind(
2364
+ subject.grantStore,
2365
+ );
2034
2366
  let authentications = 0;
2035
2367
  subject.grantStore.authenticate = async (grantId, secret) => {
2036
2368
  const state = await authenticate(grantId, secret);
@@ -2040,14 +2372,22 @@ test("helper guide assembly rechecks the owner lock after grant reauthentication
2040
2372
  namespace: "alice",
2041
2373
  principal: "owner:alice",
2042
2374
  });
2043
- await writeFile(lockPath, `${process.pid} 00000000-0000-4000-8000-000000000000 peer\n`);
2375
+ await writeFile(
2376
+ lockPath,
2377
+ `${process.pid} 00000000-0000-4000-8000-000000000000 peer\n`,
2378
+ );
2044
2379
  }
2045
2380
  return state;
2046
2381
  };
2047
2382
 
2048
2383
  await assert.rejects(
2049
- subject.grantService.readGrant({ grantId: created.grant.grantId, secret: created.secret }),
2050
- (error: unknown) => error instanceof SupportPassportError && error.code === "storage_conflict"
2384
+ subject.grantService.readGrant({
2385
+ grantId: created.grant.grantId,
2386
+ secret: created.secret,
2387
+ }),
2388
+ (error: unknown) =>
2389
+ error instanceof SupportPassportError &&
2390
+ error.code === "storage_conflict",
2051
2391
  );
2052
2392
  assert.equal(authentications, 3);
2053
2393
  } finally {
@@ -2064,7 +2404,14 @@ test("helper guide assembly refreshes the owner lock after its final snapshot re
2064
2404
  cards: [{ cardId: card.cardId, revision: card.revision }],
2065
2405
  expiresAt: expiryAfter(subject, 3_600_000),
2066
2406
  });
2067
- const readAllMemories = subject.aliceStorage.readAllMemories.bind(subject.aliceStorage);
2407
+ await subject.aliceStorage.writeMemory(
2408
+ "fact",
2409
+ "An unrelated memory invalidates the cached card snapshot.",
2410
+ { source: "support-passport-test" },
2411
+ );
2412
+ const readAllMemories = subject.aliceStorage.readAllMemories.bind(
2413
+ subject.aliceStorage,
2414
+ );
2068
2415
  let reads = 0;
2069
2416
  subject.aliceStorage.readAllMemories = async (...args) => {
2070
2417
  const memories = await readAllMemories(...args);
@@ -2074,14 +2421,22 @@ test("helper guide assembly refreshes the owner lock after its final snapshot re
2074
2421
  namespace: "alice",
2075
2422
  principal: "owner:alice",
2076
2423
  });
2077
- await writeFile(lockPath, `${process.pid} 00000000-0000-4000-8000-000000000000 peer\n`);
2424
+ await writeFile(
2425
+ lockPath,
2426
+ `${process.pid} 00000000-0000-4000-8000-000000000000 peer\n`,
2427
+ );
2078
2428
  }
2079
2429
  return memories;
2080
2430
  };
2081
2431
 
2082
2432
  await assert.rejects(
2083
- subject.grantService.readGrant({ grantId: created.grant.grantId, secret: created.secret }),
2084
- (error: unknown) => error instanceof SupportPassportError && error.code === "storage_conflict"
2433
+ subject.grantService.readGrant({
2434
+ grantId: created.grant.grantId,
2435
+ secret: created.secret,
2436
+ }),
2437
+ (error: unknown) =>
2438
+ error instanceof SupportPassportError &&
2439
+ error.code === "storage_conflict",
2085
2440
  );
2086
2441
  assert.equal(reads, 1);
2087
2442
  } finally {
@@ -2098,16 +2453,26 @@ test("helper guide assembly rechecks expiry after its final owner-lock refresh",
2098
2453
  cards: [{ cardId: card.cardId, revision: card.revision }],
2099
2454
  expiresAt: expiryAfter(subject, 300_000),
2100
2455
  });
2101
- const withAuthenticatedGrant = subject.grantStore.withAuthenticatedGrant.bind(subject.grantStore);
2102
- subject.grantStore.withAuthenticatedGrant = async (grantId, secret, task, beforeReturn) =>
2456
+ const withAuthenticatedGrant =
2457
+ subject.grantStore.withAuthenticatedGrant.bind(subject.grantStore);
2458
+ subject.grantStore.withAuthenticatedGrant = async (
2459
+ grantId,
2460
+ secret,
2461
+ task,
2462
+ beforeReturn,
2463
+ ) =>
2103
2464
  await withAuthenticatedGrant(grantId, secret, task, async (state) => {
2104
2465
  subject.advance(300_000);
2105
2466
  await beforeReturn?.(state);
2106
2467
  });
2107
2468
 
2108
2469
  await assert.rejects(
2109
- subject.grantService.readGrant({ grantId: created.grant.grantId, secret: created.secret }),
2110
- (error: unknown) => error instanceof SupportPassportError && error.code === "grant_expired"
2470
+ subject.grantService.readGrant({
2471
+ grantId: created.grant.grantId,
2472
+ secret: created.secret,
2473
+ }),
2474
+ (error: unknown) =>
2475
+ error instanceof SupportPassportError && error.code === "grant_expired",
2111
2476
  );
2112
2477
  } finally {
2113
2478
  await subject.cleanup();
@@ -2134,8 +2499,89 @@ test("a changed card makes the whole grant stale without a partial guide", async
2134
2499
  });
2135
2500
 
2136
2501
  await assert.rejects(
2137
- subject.grantService.readGrant({ grantId: created.grant.grantId, secret: created.secret }),
2138
- (error: unknown) => error instanceof SupportPassportError && error.code === "grant_stale" && error.status === 410
2502
+ subject.grantService.readGrant({
2503
+ grantId: created.grant.grantId,
2504
+ secret: created.secret,
2505
+ }),
2506
+ (error: unknown) =>
2507
+ error instanceof SupportPassportError &&
2508
+ error.code === "grant_stale" &&
2509
+ error.status === 410,
2510
+ );
2511
+ } finally {
2512
+ await subject.cleanup();
2513
+ }
2514
+ });
2515
+
2516
+ test("an active replacement makes predecessor shares stale before retirement finishes", async () => {
2517
+ const subject = await makeSubject();
2518
+ try {
2519
+ const active = await createActiveCard(subject, "Plan changes");
2520
+ const created = await subject.grantService.createGrant({
2521
+ principal: "owner:alice",
2522
+ cards: [{ cardId: active.cardId, revision: active.revision }],
2523
+ expiresAt: expiryAfter(subject, 3_600_000),
2524
+ });
2525
+ const replacement = await subject.cardService.replaceCard({
2526
+ principal: "owner:alice",
2527
+ cardId: active.cardId,
2528
+ expectedRevision: active.revision,
2529
+ title: "Plan changes",
2530
+ statement: "Tell me early when plans change.",
2531
+ category: "transitions",
2532
+ reviewBy: "2026-09-01T12:00:00.000Z",
2533
+ });
2534
+ const writeFrontmatter =
2535
+ subject.aliceStorage.writeMemoryFrontmatterIfUnchanged.bind(
2536
+ subject.aliceStorage,
2537
+ );
2538
+ subject.aliceStorage.writeMemoryFrontmatterIfUnchanged = async (
2539
+ memory,
2540
+ patch,
2541
+ lifecycle,
2542
+ ) => {
2543
+ if (lifecycle?.reasonCode === "support-passport-replacement-pending") {
2544
+ throw new Error("simulated interruption before predecessor retirement");
2545
+ }
2546
+ return await writeFrontmatter(memory, patch, lifecycle);
2547
+ };
2548
+ const approved = await subject.cardService.approveCard({
2549
+ principal: "owner:alice",
2550
+ cardId: replacement.cardId,
2551
+ expectedRevision: replacement.revision,
2552
+ });
2553
+
2554
+ await assert.rejects(
2555
+ subject.grantService.readGrant({
2556
+ grantId: created.grant.grantId,
2557
+ secret: created.secret,
2558
+ }),
2559
+ (error: unknown) =>
2560
+ error instanceof SupportPassportError && error.code === "grant_stale",
2561
+ );
2562
+ await assert.rejects(
2563
+ subject.grantService.createGrant({
2564
+ principal: "owner:alice",
2565
+ cards: [{ cardId: active.cardId, revision: active.revision }],
2566
+ expiresAt: expiryAfter(subject, 3_600_000),
2567
+ }),
2568
+ (error: unknown) =>
2569
+ error instanceof SupportPassportError &&
2570
+ error.code === "invalid_card_status",
2571
+ );
2572
+ const replacementGrant = await subject.grantService.createGrant({
2573
+ principal: "owner:alice",
2574
+ cards: [{ cardId: approved.cardId, revision: approved.revision }],
2575
+ expiresAt: expiryAfter(subject, 3_600_000),
2576
+ });
2577
+ assert.equal(
2578
+ (
2579
+ await subject.grantService.readGrant({
2580
+ grantId: replacementGrant.grant.grantId,
2581
+ secret: replacementGrant.secret,
2582
+ })
2583
+ ).cards[0]?.cardId,
2584
+ approved.cardId,
2139
2585
  );
2140
2586
  } finally {
2141
2587
  await subject.cleanup();
@@ -2183,15 +2629,21 @@ test("unrelated memory writes do not invalidate an unchanged shared guide", asyn
2183
2629
  cards: [{ cardId: card.cardId, revision: card.revision }],
2184
2630
  expiresAt: expiryAfter(subject, 3_600_000),
2185
2631
  });
2186
- const readAllMemories = subject.aliceStorage.readAllMemories.bind(subject.aliceStorage);
2632
+ const readAllMemories = subject.aliceStorage.readAllMemories.bind(
2633
+ subject.aliceStorage,
2634
+ );
2187
2635
  let wroteUnrelated = false;
2188
2636
  subject.aliceStorage.readAllMemories = async (...args) => {
2189
2637
  const memories = await readAllMemories(...args);
2190
2638
  if (!wroteUnrelated) {
2191
2639
  wroteUnrelated = true;
2192
- await subject.aliceStorage.writeMemory("fact", "An unrelated memory write.", {
2193
- source: "support-passport-test",
2194
- });
2640
+ await subject.aliceStorage.writeMemory(
2641
+ "fact",
2642
+ "An unrelated memory write.",
2643
+ {
2644
+ source: "support-passport-test",
2645
+ },
2646
+ );
2195
2647
  }
2196
2648
  return memories;
2197
2649
  };
@@ -2207,7 +2659,7 @@ test("unrelated memory writes do not invalidate an unchanged shared guide", asyn
2207
2659
  }
2208
2660
  });
2209
2661
 
2210
- test("one unchanged guide read validates a fresh final corpus snapshot", async () => {
2662
+ test("one unchanged guide read reuses one fresh corpus snapshot", async () => {
2211
2663
  const subject = await makeSubject();
2212
2664
  try {
2213
2665
  const card = await createActiveCard(subject);
@@ -2216,7 +2668,14 @@ test("one unchanged guide read validates a fresh final corpus snapshot", async (
2216
2668
  cards: [{ cardId: card.cardId, revision: card.revision }],
2217
2669
  expiresAt: expiryAfter(subject, 3_600_000),
2218
2670
  });
2219
- const readAllMemories = subject.aliceStorage.readAllMemories.bind(subject.aliceStorage);
2671
+ await subject.aliceStorage.writeMemory(
2672
+ "fact",
2673
+ "An unrelated memory invalidates the cached card snapshot.",
2674
+ { source: "support-passport-test" },
2675
+ );
2676
+ const readAllMemories = subject.aliceStorage.readAllMemories.bind(
2677
+ subject.aliceStorage,
2678
+ );
2220
2679
  let corpusReads = 0;
2221
2680
  subject.aliceStorage.readAllMemories = async (...args) => {
2222
2681
  corpusReads += 1;
@@ -2232,7 +2691,7 @@ test("one unchanged guide read validates a fresh final corpus snapshot", async (
2232
2691
  });
2233
2692
 
2234
2693
  assert.equal(guide.cards[0]?.cardId, card.cardId);
2235
- assert.equal(corpusReads, 2);
2694
+ assert.equal(corpusReads, 1);
2236
2695
  } finally {
2237
2696
  await subject.cleanup();
2238
2697
  }
@@ -2248,9 +2707,12 @@ test("grant creation rejects an approved card with an invalid update timestamp",
2248
2707
  await subject.aliceStorage.writeMemoryFrontmatterIfUnchanged(memory, {
2249
2708
  updated: "2026-08-11T12:00:00+99:99",
2250
2709
  }),
2251
- true
2710
+ true,
2711
+ );
2712
+ assert.deepEqual(
2713
+ await subject.cardService.listCards({ principal: "owner:alice" }),
2714
+ [],
2252
2715
  );
2253
- assert.deepEqual(await subject.cardService.listCards({ principal: "owner:alice" }), []);
2254
2716
 
2255
2717
  await assert.rejects(
2256
2718
  subject.grantService.createGrant({
@@ -2258,9 +2720,14 @@ test("grant creation rejects an approved card with an invalid update timestamp",
2258
2720
  cards: [{ cardId: card.cardId, revision: card.revision }],
2259
2721
  expiresAt: expiryAfter(subject, 3_600_000),
2260
2722
  }),
2261
- (error: unknown) => error instanceof SupportPassportError && error.code === "invalid_card_status"
2723
+ (error: unknown) =>
2724
+ error instanceof SupportPassportError &&
2725
+ error.code === "invalid_card_status",
2726
+ );
2727
+ assert.deepEqual(
2728
+ await subject.grantService.listGrants({ principal: "owner:alice" }),
2729
+ [],
2262
2730
  );
2263
- assert.deepEqual(await subject.grantService.listGrants({ principal: "owner:alice" }), []);
2264
2731
  } finally {
2265
2732
  await subject.cleanup();
2266
2733
  }
@@ -2272,25 +2739,38 @@ test("public guides compare card update timestamps as instants", async () => {
2272
2739
  const first = await createActiveCard(subject, "Earlier card");
2273
2740
  const second = await createActiveCard(subject, "Later card");
2274
2741
  const firstMemory = await subject.aliceStorage.getMemoryById(first.cardId);
2275
- const secondMemory = await subject.aliceStorage.getMemoryById(second.cardId);
2742
+ const secondMemory = await subject.aliceStorage.getMemoryById(
2743
+ second.cardId,
2744
+ );
2276
2745
  assert.ok(firstMemory);
2277
2746
  assert.ok(secondMemory);
2278
2747
  assert.equal(
2279
- await subject.aliceStorage.writeMemoryFrontmatterIfUnchanged(firstMemory, {
2280
- updated: "2026-08-11T12:00:00+05:00",
2281
- }),
2282
- true
2748
+ await subject.aliceStorage.writeMemoryFrontmatterIfUnchanged(
2749
+ firstMemory,
2750
+ {
2751
+ updated: "2026-08-11T12:00:00+05:00",
2752
+ },
2753
+ ),
2754
+ true,
2283
2755
  );
2284
2756
  assert.equal(
2285
- await subject.aliceStorage.writeMemoryFrontmatterIfUnchanged(secondMemory, {
2286
- updated: "2026-08-11T10:00:00Z",
2287
- }),
2288
- true
2757
+ await subject.aliceStorage.writeMemoryFrontmatterIfUnchanged(
2758
+ secondMemory,
2759
+ {
2760
+ updated: "2026-08-11T10:00:00Z",
2761
+ },
2762
+ ),
2763
+ true,
2289
2764
  );
2290
- const cards = await subject.cardService.listCards({ principal: "owner:alice" });
2765
+ const cards = await subject.cardService.listCards({
2766
+ principal: "owner:alice",
2767
+ });
2291
2768
  const created = await subject.grantService.createGrant({
2292
2769
  principal: "owner:alice",
2293
- cards: cards.map((card) => ({ cardId: card.cardId, revision: card.revision })),
2770
+ cards: cards.map((card) => ({
2771
+ cardId: card.cardId,
2772
+ revision: card.revision,
2773
+ })),
2294
2774
  expiresAt: expiryAfter(subject, 3_600_000),
2295
2775
  });
2296
2776
 
@@ -2318,7 +2798,10 @@ test("grant creation rejects drafts, duplicate cards, and unsafe durations", asy
2318
2798
  const active = await createActiveCard(subject);
2319
2799
 
2320
2800
  for (const input of [
2321
- { cards: [{ cardId: draft.cardId, revision: draft.revision }], expiresAt: expiryAfter(subject, 3_600_000) },
2801
+ {
2802
+ cards: [{ cardId: draft.cardId, revision: draft.revision }],
2803
+ expiresAt: expiryAfter(subject, 3_600_000),
2804
+ },
2322
2805
  {
2323
2806
  cards: [
2324
2807
  { cardId: active.cardId, revision: active.revision },
@@ -2326,7 +2809,10 @@ test("grant creation rejects drafts, duplicate cards, and unsafe durations", asy
2326
2809
  ],
2327
2810
  expiresAt: expiryAfter(subject, 3_600_000),
2328
2811
  },
2329
- { cards: [{ cardId: active.cardId, revision: active.revision }], expiresAt: expiryAfter(subject, 299_999) },
2812
+ {
2813
+ cards: [{ cardId: active.cardId, revision: active.revision }],
2814
+ expiresAt: expiryAfter(subject, 299_999),
2815
+ },
2330
2816
  {
2331
2817
  cards: [{ cardId: active.cardId, revision: active.revision }],
2332
2818
  expiresAt: expiryAfter(subject, 604_800_001),
@@ -2337,8 +2823,11 @@ test("grant creation rejects drafts, duplicate cards, and unsafe durations", asy
2337
2823
  },
2338
2824
  ]) {
2339
2825
  await assert.rejects(
2340
- subject.grantService.createGrant({ principal: "owner:alice", ...input }),
2341
- (error: unknown) => error instanceof SupportPassportError
2826
+ subject.grantService.createGrant({
2827
+ principal: "owner:alice",
2828
+ ...input,
2829
+ }),
2830
+ (error: unknown) => error instanceof SupportPassportError,
2342
2831
  );
2343
2832
  }
2344
2833
  } finally {
@@ -2351,9 +2840,14 @@ test("the grant store rejects a symlinked grant directory", async () => {
2351
2840
  try {
2352
2841
  const memoryDir = path.join(root, "memory");
2353
2842
  const outside = path.join(root, "outside");
2354
- await mkdir(path.join(memoryDir, "state", "support-passport"), { recursive: true });
2843
+ await mkdir(path.join(memoryDir, "state", "support-passport"), {
2844
+ recursive: true,
2845
+ });
2355
2846
  await mkdir(outside);
2356
- await symlink(outside, path.join(memoryDir, "state", "support-passport", "grants"));
2847
+ await symlink(
2848
+ outside,
2849
+ path.join(memoryDir, "state", "support-passport", "grants"),
2850
+ );
2357
2851
  const now = new Date("2026-08-11T12:00:00.000Z");
2358
2852
  const store = new SupportPassportGrantStore({ memoryDir, now: () => now });
2359
2853
 
@@ -2364,7 +2858,7 @@ test("the grant store rejects a symlinked grant directory", async () => {
2364
2858
  cards: [{ cardId: "card-1", revision: "a".repeat(64) }],
2365
2859
  expiresAt: new Date(now.getTime() + 300_000).toISOString(),
2366
2860
  }),
2367
- /must remain inside the memory directory/
2861
+ /must remain inside the memory directory/,
2368
2862
  );
2369
2863
  } finally {
2370
2864
  await rm(root, { recursive: true, force: true });
@@ -2373,15 +2867,27 @@ test("the grant store rejects a symlinked grant directory", async () => {
2373
2867
 
2374
2868
  test("private file operations select supported directory access strategies", () => {
2375
2869
  assert.throws(
2376
- () => requirePrivateFileDescriptorRoot("win32", "private file directory cannot be pinned"),
2377
- /private file directory cannot be pinned/
2870
+ () =>
2871
+ requirePrivateFileDescriptorRoot(
2872
+ "win32",
2873
+ "private file directory cannot be pinned",
2874
+ ),
2875
+ /private file directory cannot be pinned/,
2876
+ );
2877
+ assert.equal(
2878
+ requirePrivateFileDescriptorRoot("linux", "unreachable"),
2879
+ "/proc/self/fd",
2880
+ );
2881
+ assert.equal(
2882
+ requirePrivateFileDescriptorRoot("darwin", "unreachable"),
2883
+ "/dev/fd",
2378
2884
  );
2379
- assert.equal(requirePrivateFileDescriptorRoot("linux", "unreachable"), "/proc/self/fd");
2380
- assert.equal(requirePrivateFileDescriptorRoot("darwin", "unreachable"), "/dev/fd");
2381
2885
  });
2382
2886
 
2383
2887
  test("private directory creation syncs every verified parent entry", async () => {
2384
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-private-directory-sync-"));
2888
+ const root = await mkdtemp(
2889
+ path.join(tmpdir(), "remnic-support-private-directory-sync-"),
2890
+ );
2385
2891
  try {
2386
2892
  const target = path.join(root, "state", "support-passport", "grants");
2387
2893
  let syncs = 0;
@@ -2389,9 +2895,19 @@ test("private directory creation syncs every verified parent entry", async () =>
2389
2895
  syncs += 1;
2390
2896
  };
2391
2897
 
2392
- await ensurePrivateDirectoryNoFollow(root, target, "private directory creation failed", syncVerifiedParent);
2898
+ await ensurePrivateDirectoryNoFollow(
2899
+ root,
2900
+ target,
2901
+ "private directory creation failed",
2902
+ syncVerifiedParent,
2903
+ );
2393
2904
  assert.equal(syncs, 3);
2394
- await ensurePrivateDirectoryNoFollow(root, target, "private directory creation failed", syncVerifiedParent);
2905
+ await ensurePrivateDirectoryNoFollow(
2906
+ root,
2907
+ target,
2908
+ "private directory creation failed",
2909
+ syncVerifiedParent,
2910
+ );
2395
2911
  assert.equal(syncs, 6);
2396
2912
  } finally {
2397
2913
  await rm(root, { recursive: true, force: true });
@@ -2399,21 +2915,35 @@ test("private directory creation syncs every verified parent entry", async () =>
2399
2915
  });
2400
2916
 
2401
2917
  test("private directory creation retries a failed parent sync", async () => {
2402
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-private-directory-sync-retry-"));
2918
+ const root = await mkdtemp(
2919
+ path.join(tmpdir(), "remnic-support-private-directory-sync-retry-"),
2920
+ );
2403
2921
  try {
2404
2922
  const target = path.join(root, "state", "support-passport", "grants");
2405
2923
  await assert.rejects(
2406
- ensurePrivateDirectoryNoFollow(root, target, "private directory creation failed", async () => {
2407
- throw Object.assign(new Error("simulated directory sync failure"), { code: "EIO" });
2408
- }),
2409
- (error: unknown) => (error as NodeJS.ErrnoException).code === "EIO"
2924
+ ensurePrivateDirectoryNoFollow(
2925
+ root,
2926
+ target,
2927
+ "private directory creation failed",
2928
+ async () => {
2929
+ throw Object.assign(new Error("simulated directory sync failure"), {
2930
+ code: "EIO",
2931
+ });
2932
+ },
2933
+ ),
2934
+ (error: unknown) => (error as NodeJS.ErrnoException).code === "EIO",
2410
2935
  );
2411
2936
  assert.equal((await lstat(path.join(root, "state"))).isDirectory(), true);
2412
2937
 
2413
2938
  let retrySyncs = 0;
2414
- await ensurePrivateDirectoryNoFollow(root, target, "private directory creation failed", async () => {
2415
- retrySyncs += 1;
2416
- });
2939
+ await ensurePrivateDirectoryNoFollow(
2940
+ root,
2941
+ target,
2942
+ "private directory creation failed",
2943
+ async () => {
2944
+ retrySyncs += 1;
2945
+ },
2946
+ );
2417
2947
  assert.equal(retrySyncs, 3);
2418
2948
  } finally {
2419
2949
  await rm(root, { recursive: true, force: true });
@@ -2421,24 +2951,38 @@ test("private directory creation retries a failed parent sync", async () => {
2421
2951
  });
2422
2952
 
2423
2953
  test("private directory creation retries parent sync when rollback cannot remove the child", async () => {
2424
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-private-directory-sync-populated-"));
2954
+ const root = await mkdtemp(
2955
+ path.join(tmpdir(), "remnic-support-private-directory-sync-populated-"),
2956
+ );
2425
2957
  try {
2426
2958
  const target = path.join(root, "state");
2427
2959
  let failed = false;
2428
2960
  await assert.rejects(
2429
- ensurePrivateDirectoryNoFollow(root, target, "private directory creation failed", async () => {
2430
- if (failed) return;
2431
- failed = true;
2432
- await writeFile(path.join(target, "peer-entry"), "peer");
2433
- throw Object.assign(new Error("simulated directory sync failure"), { code: "EIO" });
2434
- }),
2435
- (error: unknown) => (error as NodeJS.ErrnoException).code === "EIO"
2961
+ ensurePrivateDirectoryNoFollow(
2962
+ root,
2963
+ target,
2964
+ "private directory creation failed",
2965
+ async () => {
2966
+ if (failed) return;
2967
+ failed = true;
2968
+ await writeFile(path.join(target, "peer-entry"), "peer");
2969
+ throw Object.assign(new Error("simulated directory sync failure"), {
2970
+ code: "EIO",
2971
+ });
2972
+ },
2973
+ ),
2974
+ (error: unknown) => (error as NodeJS.ErrnoException).code === "EIO",
2436
2975
  );
2437
2976
 
2438
2977
  let retrySyncs = 0;
2439
- await ensurePrivateDirectoryNoFollow(root, target, "private directory creation failed", async () => {
2440
- retrySyncs += 1;
2441
- });
2978
+ await ensurePrivateDirectoryNoFollow(
2979
+ root,
2980
+ target,
2981
+ "private directory creation failed",
2982
+ async () => {
2983
+ retrySyncs += 1;
2984
+ },
2985
+ );
2442
2986
  assert.equal(retrySyncs, 1);
2443
2987
  } finally {
2444
2988
  await rm(root, { recursive: true, force: true });
@@ -2469,14 +3013,20 @@ test("a failed parent sync never unlinks a directory opened by a concurrent setu
2469
3013
  });
2470
3014
 
2471
3015
  test("private directory tree creation syncs missing memory-root ancestors", async () => {
2472
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-private-root-sync-"));
3016
+ const root = await mkdtemp(
3017
+ path.join(tmpdir(), "remnic-support-private-root-sync-"),
3018
+ );
2473
3019
  try {
2474
3020
  const target = path.join(root, "new-parent", "memory");
2475
3021
  let syncs = 0;
2476
3022
 
2477
- await ensurePrivateDirectoryTreeNoFollow(target, "private directory creation failed", async () => {
2478
- syncs += 1;
2479
- });
3023
+ await ensurePrivateDirectoryTreeNoFollow(
3024
+ target,
3025
+ "private directory creation failed",
3026
+ async () => {
3027
+ syncs += 1;
3028
+ },
3029
+ );
2480
3030
 
2481
3031
  const expectedSyncs = path.relative(path.parse(target).root, target).split(path.sep).filter(Boolean).length;
2482
3032
  assert.equal(syncs, expectedSyncs);
@@ -2504,7 +3054,9 @@ test("private directory tree ignores a read-only filesystem-root sync", async ()
2504
3054
  });
2505
3055
 
2506
3056
  test("private directory tree creation rejects a symlink in the ancestor chain", async () => {
2507
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-private-root-link-"));
3057
+ const root = await mkdtemp(
3058
+ path.join(tmpdir(), "remnic-support-private-root-link-"),
3059
+ );
2508
3060
  try {
2509
3061
  const outside = path.join(root, "outside");
2510
3062
  const linked = path.join(root, "linked");
@@ -2513,8 +3065,11 @@ test("private directory tree creation rejects a symlink in the ancestor chain",
2513
3065
  await symlink(outside, linked);
2514
3066
 
2515
3067
  await assert.rejects(
2516
- ensurePrivateDirectoryTreeNoFollow(target, "private directory creation failed"),
2517
- /private directory creation failed/
3068
+ ensurePrivateDirectoryTreeNoFollow(
3069
+ target,
3070
+ "private directory creation failed",
3071
+ ),
3072
+ /private directory creation failed/,
2518
3073
  );
2519
3074
  assert.deepEqual(await readdir(outside), []);
2520
3075
  } finally {
@@ -2580,7 +3135,9 @@ test("Windows private-file operations fail before mutation", async () => {
2580
3135
  });
2581
3136
 
2582
3137
  test("grant cleanup never follows a swapped grant directory", async () => {
2583
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-grant-cleanup-swap-"));
3138
+ const root = await mkdtemp(
3139
+ path.join(tmpdir(), "remnic-support-grant-cleanup-swap-"),
3140
+ );
2584
3141
  try {
2585
3142
  const grantId = "00000000-0000-4000-8000-000000000001";
2586
3143
  const now = new Date("2026-08-11T12:00:00.000Z");
@@ -2600,15 +3157,23 @@ test("grant cleanup never follows a swapped grant directory", async () => {
2600
3157
  const outsideDir = path.join(root, "outside");
2601
3158
  const fileName = `${grantId}.json`;
2602
3159
  await mkdir(outsideDir);
2603
- await writeFile(path.join(outsideDir, fileName), "outside must remain", { mode: 0o600 });
3160
+ await writeFile(path.join(outsideDir, fileName), "outside must remain", {
3161
+ mode: 0o600,
3162
+ });
2604
3163
  renameSync(grantsDir, parkedDir);
2605
3164
  symlinkSync(outsideDir, grantsDir, "dir");
2606
3165
  const inspected = store as unknown as {
2607
3166
  removeGrantStates(grantIds: string[]): Promise<void>;
2608
3167
  };
2609
3168
 
2610
- await assert.rejects(inspected.removeGrantStates([grantId]), /regular files in a stable directory/);
2611
- assert.equal(await readFile(path.join(outsideDir, fileName), "utf8"), "outside must remain");
3169
+ await assert.rejects(
3170
+ inspected.removeGrantStates([grantId]),
3171
+ /regular files in a stable directory/,
3172
+ );
3173
+ assert.equal(
3174
+ await readFile(path.join(outsideDir, fileName), "utf8"),
3175
+ "outside must remain",
3176
+ );
2612
3177
  assert.equal((await lstat(path.join(parkedDir, fileName))).isFile(), true);
2613
3178
  } finally {
2614
3179
  await rm(root, { recursive: true, force: true });
@@ -2620,7 +3185,12 @@ test("grant writes reject a directory swapped after the initial safety check", a
2620
3185
  try {
2621
3186
  const memoryDir = path.join(root, "memory");
2622
3187
  const outside = path.join(root, "outside");
2623
- const grantsDir = path.join(memoryDir, "state", "support-passport", "grants");
3188
+ const grantsDir = path.join(
3189
+ memoryDir,
3190
+ "state",
3191
+ "support-passport",
3192
+ "grants",
3193
+ );
2624
3194
  const parkedDir = path.join(root, "parked-grants");
2625
3195
  await mkdir(outside, { recursive: true });
2626
3196
  const now = new Date("2026-08-11T12:00:00.000Z");
@@ -2637,12 +3207,14 @@ test("grant writes reject a directory swapped after the initial safety check", a
2637
3207
  cards: [{ cardId: "card-1", revision: "a".repeat(64) }],
2638
3208
  expiresAt: new Date(now.getTime() + 300_000).toISOString(),
2639
3209
  },
2640
- async () => {
2641
- renameSync(grantsDir, parkedDir);
2642
- symlinkSync(outside, grantsDir, "dir");
2643
- }
3210
+ {
3211
+ beforeCommit: async () => {
3212
+ renameSync(grantsDir, parkedDir);
3213
+ symlinkSync(outside, grantsDir, "dir");
3214
+ },
3215
+ },
2644
3216
  ),
2645
- /regular files in a stable directory/
3217
+ /regular files in a stable directory/,
2646
3218
  );
2647
3219
  assert.deepEqual(await readdir(outside), []);
2648
3220
  } finally {
@@ -2651,7 +3223,9 @@ test("grant writes reject a directory swapped after the initial safety check", a
2651
3223
  });
2652
3224
 
2653
3225
  test("grant writes reject an ancestor swapped after the initial safety check", async () => {
2654
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-grant-ancestor-swap-"));
3226
+ const root = await mkdtemp(
3227
+ path.join(tmpdir(), "remnic-support-grant-ancestor-swap-"),
3228
+ );
2655
3229
  try {
2656
3230
  const memoryDir = path.join(root, "memory");
2657
3231
  const passportDir = path.join(memoryDir, "state", "support-passport");
@@ -2659,7 +3233,9 @@ test("grant writes reject an ancestor swapped after the initial safety check", a
2659
3233
  const outside = path.join(root, "outside-support-passport");
2660
3234
  await mkdir(path.join(outside, "grants", "owners"), { recursive: true });
2661
3235
  const acceptLock = (async (_lockPath, _options, task) =>
2662
- await task(true, { refresh: async () => true })) as typeof withHeldFileLock;
3236
+ await task(true, {
3237
+ refresh: async () => true,
3238
+ })) as typeof withHeldFileLock;
2663
3239
  const now = new Date("2026-08-11T12:00:00.000Z");
2664
3240
  const store = new SupportPassportGrantStore({
2665
3241
  memoryDir,
@@ -2677,12 +3253,14 @@ test("grant writes reject an ancestor swapped after the initial safety check", a
2677
3253
  cards: [{ cardId: "card-1", revision: "a".repeat(64) }],
2678
3254
  expiresAt: new Date(now.getTime() + 300_000).toISOString(),
2679
3255
  },
2680
- async () => {
2681
- renameSync(passportDir, parkedDir);
2682
- symlinkSync(outside, passportDir, "dir");
2683
- }
3256
+ {
3257
+ beforeCommit: async () => {
3258
+ renameSync(passportDir, parkedDir);
3259
+ symlinkSync(outside, passportDir, "dir");
3260
+ },
3261
+ },
2684
3262
  ),
2685
- /regular files in a stable directory/
3263
+ /regular files in a stable directory/,
2686
3264
  );
2687
3265
  assert.deepEqual(await readdir(path.join(outside, "grants")), ["owners"]);
2688
3266
  } finally {
@@ -2724,7 +3302,9 @@ test("grant reads reject a memory-root ancestor swapped after a completed operat
2724
3302
  });
2725
3303
 
2726
3304
  test("the grant store fails closed for corrupt and symlinked grant files", async () => {
2727
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-grant-state-"));
3305
+ const root = await mkdtemp(
3306
+ path.join(tmpdir(), "remnic-support-grant-state-"),
3307
+ );
2728
3308
  try {
2729
3309
  const firstGrantId = "00000000-0000-4000-8000-000000000001";
2730
3310
  const secondGrantId = "00000000-0000-4000-8000-000000000002";
@@ -2753,15 +3333,20 @@ test("the grant store fails closed for corrupt and symlinked grant files", async
2753
3333
  await writeFile(outsidePath, await readFile(linkedPath), { mode: 0o600 });
2754
3334
  await rm(linkedPath);
2755
3335
  await symlink(outsidePath, linkedPath);
2756
- await assert.rejects(store.authenticate(secondGrantId, linked.secret), /must be regular files/);
3336
+ await assert.rejects(
3337
+ store.authenticate(secondGrantId, linked.secret),
3338
+ /must be regular files/,
3339
+ );
2757
3340
  await assert.rejects(store.listForOwner("alice", "owner:alice"));
2758
3341
  } finally {
2759
3342
  await rm(root, { recursive: true, force: true });
2760
3343
  }
2761
3344
  });
2762
3345
 
2763
- test("the grant store rejects a state file whose grant ID does not match its file name", async () => {
2764
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-grant-identity-"));
3346
+ test("the grant store omits a state file whose grant ID does not match its file name", async () => {
3347
+ const root = await mkdtemp(
3348
+ path.join(tmpdir(), "remnic-support-grant-identity-"),
3349
+ );
2765
3350
  try {
2766
3351
  const firstGrantId = "00000000-0000-4000-8000-000000000001";
2767
3352
  const secondGrantId = "00000000-0000-4000-8000-000000000002";
@@ -2784,7 +3369,7 @@ test("the grant store rejects a state file whose grant ID does not match its fil
2784
3369
  await writeFile(
2785
3370
  path.join(grantDir, `${secondGrantId}.json`),
2786
3371
  await readFile(path.join(grantDir, `${firstGrantId}.json`)),
2787
- { mode: 0o600 }
3372
+ { mode: 0o600 },
2788
3373
  );
2789
3374
 
2790
3375
  await assert.rejects(store.authenticate(secondGrantId, second.secret), /grant ID must match its file name/);
@@ -2799,11 +3384,17 @@ test("the grant store rejects a state file whose grant ID does not match its fil
2799
3384
  });
2800
3385
 
2801
3386
  test("the grant store rejects unsafe durations and grant ID collisions", async () => {
2802
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-grant-collision-"));
3387
+ const root = await mkdtemp(
3388
+ path.join(tmpdir(), "remnic-support-grant-collision-"),
3389
+ );
2803
3390
  try {
2804
3391
  const grantId = "00000000-0000-4000-8000-000000000001";
2805
3392
  const now = new Date("2026-08-11T12:00:00.000Z");
2806
- const store = new SupportPassportGrantStore({ memoryDir: root, makeGrantId: () => grantId, now: () => now });
3393
+ const store = new SupportPassportGrantStore({
3394
+ memoryDir: root,
3395
+ makeGrantId: () => grantId,
3396
+ now: () => now,
3397
+ });
2807
3398
  const input = {
2808
3399
  namespace: "alice",
2809
3400
  principal: "owner:alice",
@@ -2813,11 +3404,17 @@ test("the grant store rejects unsafe durations and grant ID collisions", async (
2813
3404
  await store.create(input);
2814
3405
  await assert.rejects(
2815
3406
  store.create(input),
2816
- (error: unknown) => error instanceof SupportPassportError && error.code === "storage_conflict"
3407
+ (error: unknown) =>
3408
+ error instanceof SupportPassportError &&
3409
+ error.code === "storage_conflict",
2817
3410
  );
2818
3411
  await assert.rejects(
2819
- store.create({ ...input, expiresAt: new Date(now.getTime() + 299_999).toISOString() }),
2820
- (error: unknown) => error instanceof SupportPassportError && error.code === "invalid_input"
3412
+ store.create({
3413
+ ...input,
3414
+ expiresAt: new Date(now.getTime() + 299_999).toISOString(),
3415
+ }),
3416
+ (error: unknown) =>
3417
+ error instanceof SupportPassportError && error.code === "invalid_input",
2821
3418
  );
2822
3419
  } finally {
2823
3420
  await rm(root, { recursive: true, force: true });
@@ -2825,7 +3422,9 @@ test("the grant store rejects unsafe durations and grant ID collisions", async (
2825
3422
  });
2826
3423
 
2827
3424
  test("the grant store canonicalizes UUID letter case", async () => {
2828
- const root = await mkdtemp(path.join(tmpdir(), "remnic-support-grant-id-case-"));
3425
+ const root = await mkdtemp(
3426
+ path.join(tmpdir(), "remnic-support-grant-id-case-"),
3427
+ );
2829
3428
  try {
2830
3429
  const uppercaseGrantId = "AAAAAAAA-AAAA-4AAA-8AAA-AAAAAAAAAAAA";
2831
3430
  const lowercaseGrantId = uppercaseGrantId.toLowerCase();
@@ -2843,10 +3442,19 @@ test("the grant store canonicalizes UUID letter case", async () => {
2843
3442
  });
2844
3443
 
2845
3444
  assert.equal(created.state.grantId, lowercaseGrantId);
2846
- assert.equal((await store.authenticate(uppercaseGrantId, created.secret)).grantId, lowercaseGrantId);
2847
3445
  assert.equal(
2848
- (await store.revoke({ grantId: uppercaseGrantId, namespace: "alice", principal: "owner:alice" })).grantId,
2849
- lowercaseGrantId
3446
+ (await store.authenticate(uppercaseGrantId, created.secret)).grantId,
3447
+ lowercaseGrantId,
3448
+ );
3449
+ assert.equal(
3450
+ (
3451
+ await store.revoke({
3452
+ grantId: uppercaseGrantId,
3453
+ namespace: "alice",
3454
+ principal: "owner:alice",
3455
+ })
3456
+ ).grantId,
3457
+ lowercaseGrantId,
2850
3458
  );
2851
3459
  } finally {
2852
3460
  await rm(root, { recursive: true, force: true });
@@ -2857,7 +3465,10 @@ test("the grant store rejects invalid calendar dates", async () => {
2857
3465
  const root = await mkdtemp(path.join(tmpdir(), "remnic-support-grant-date-"));
2858
3466
  try {
2859
3467
  const now = new Date("2026-02-28T12:00:00.000Z");
2860
- const store = new SupportPassportGrantStore({ memoryDir: root, now: () => now });
3468
+ const store = new SupportPassportGrantStore({
3469
+ memoryDir: root,
3470
+ now: () => now,
3471
+ });
2861
3472
 
2862
3473
  await assert.rejects(
2863
3474
  store.create({
@@ -2866,7 +3477,8 @@ test("the grant store rejects invalid calendar dates", async () => {
2866
3477
  cards: [{ cardId: "card-1", revision: "a".repeat(64) }],
2867
3478
  expiresAt: "2026-02-31T12:00:00.000Z",
2868
3479
  }),
2869
- (error: unknown) => error instanceof SupportPassportError && error.code === "invalid_input"
3480
+ (error: unknown) =>
3481
+ error instanceof SupportPassportError && error.code === "invalid_input",
2870
3482
  );
2871
3483
  } finally {
2872
3484
  await rm(root, { recursive: true, force: true });
@@ -2874,7 +3486,9 @@ test("the grant store rejects invalid calendar dates", async () => {
2874
3486
  });
2875
3487
 
2876
3488
  test("the grant store expands a leading tilde in its memory directory", () => {
2877
- const store = new SupportPassportGrantStore({ memoryDir: "~/support-passport-path-test" });
3489
+ const store = new SupportPassportGrantStore({
3490
+ memoryDir: "~/support-passport-path-test",
3491
+ });
2878
3492
  const memoryDir = (store as unknown as { memoryDir: string }).memoryDir;
2879
3493
  assert.equal(memoryDir.includes(`${path.sep}~${path.sep}`), false);
2880
3494
  assert.equal(path.basename(memoryDir), "support-passport-path-test");