@remnic/core 9.54.4 → 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 (648) hide show
  1. package/dist/access-admin-ops-surface.d.ts +24 -23
  2. package/dist/access-admin-ops-surface.js +55 -50
  3. package/dist/access-authorization-probe.d.ts +25 -22
  4. package/dist/access-authorization-probe.js +58 -51
  5. package/dist/access-boundary.d.ts +26 -23
  6. package/dist/access-boundary.js +59 -52
  7. package/dist/access-cli.js +115 -107
  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 -18
  11. package/dist/access-extraction-force-flush.js +55 -50
  12. package/dist/access-health-types.d.ts +1 -1
  13. package/dist/access-http-lcm-compaction.d.ts +22 -21
  14. package/dist/access-http-lifecycle-flush.d.ts +22 -21
  15. package/dist/access-http-offline-stream.d.ts +19 -18
  16. package/dist/access-http-query.js +55 -50
  17. package/dist/access-http.d.ts +55 -36
  18. package/dist/access-http.js +76 -65
  19. package/dist/access-identity-continuity-surface.d.ts +9 -9
  20. package/dist/access-identity-continuity-surface.js +55 -50
  21. package/dist/access-lcm-surface.d.ts +21 -20
  22. package/dist/access-lcm-surface.js +55 -50
  23. package/dist/access-mcp.d.ts +22 -21
  24. package/dist/access-mcp.js +63 -57
  25. package/dist/access-memory-search-fanout.d.ts +22 -2
  26. package/dist/access-memory-search-fanout.js +1 -1
  27. package/dist/{access-namespace-preflight-C7n4tgWC.d.ts → access-namespace-preflight-CCNn_6NE.d.ts} +1 -1
  28. package/dist/access-namespace-preflight.d.ts +3 -3
  29. package/dist/access-namespace-preflight.js +55 -50
  30. package/dist/access-observe-write-surface.d.ts +22 -21
  31. package/dist/access-observe-write-surface.js +55 -50
  32. package/dist/access-offline-manifest.d.ts +10 -9
  33. package/dist/access-offline-manifest.js +12 -10
  34. package/dist/access-operations-batch.js +57 -52
  35. package/dist/access-operations.d.ts +23 -22
  36. package/dist/access-operations.js +61 -55
  37. package/dist/access-recall-concurrency.d.ts +21 -20
  38. package/dist/access-recall-concurrency.js +55 -50
  39. package/dist/access-recall-response.d.ts +19 -18
  40. package/dist/access-recall-response.js +55 -50
  41. package/dist/access-recall-surface.d.ts +19 -18
  42. package/dist/access-recall-surface.js +55 -50
  43. package/dist/access-schema.d.ts +2 -2
  44. package/dist/access-schema.js +5 -4
  45. package/dist/{access-service-CXvbxLK-.d.ts → access-service-DkSdXK4S.d.ts} +1314 -83
  46. package/dist/access-service-helpers.d.ts +22 -21
  47. package/dist/access-service.d.ts +31 -30
  48. package/dist/access-service.js +55 -50
  49. package/dist/access-surface-catalog.d.ts +22 -21
  50. package/dist/access-surface-catalog.js +209 -2
  51. package/dist/access-surface-catalog.js.map +1 -1
  52. package/dist/access-wearables-meetings-surface.d.ts +3 -3
  53. package/dist/action-confidence.d.ts +1 -1
  54. package/dist/active-memory-bridge.d.ts +14 -1
  55. package/dist/active-memory-bridge.js +6 -1
  56. package/dist/active-recall.d.ts +1 -1
  57. package/dist/active-recall.js +4 -2
  58. package/dist/active-recall.js.map +1 -1
  59. package/dist/adapters/index.js +7 -7
  60. package/dist/adapters/registry.js +3 -3
  61. package/dist/admin-console/public/what-helps-me/app.js +1594 -0
  62. package/dist/admin-console/public/what-helps-me/index.html +339 -0
  63. package/dist/admin-console/public/what-helps-me/model.js +685 -0
  64. package/dist/admin-console/public/what-helps-me/what-helps-me.css +1296 -0
  65. package/dist/ambient-provenance.d.ts +1 -1
  66. package/dist/artifact-search.d.ts +1 -1
  67. package/dist/{auto-sync-TDHLZPVP.js → auto-sync-NR3GPCOA.js} +4 -4
  68. package/dist/behavior-learner.d.ts +1 -1
  69. package/dist/behavior-signals.d.ts +1 -1
  70. package/dist/bootstrap.d.ts +9 -9
  71. package/dist/briefing.d.ts +2 -2
  72. package/dist/briefing.js +33 -12
  73. package/dist/buffer-surprise-report.d.ts +1 -1
  74. package/dist/buffer-turn-helpers.d.ts +1 -1
  75. package/dist/buffer.d.ts +2 -2
  76. package/dist/buffer.js +3 -3
  77. package/dist/bulk-import/index.d.ts +3 -3
  78. package/dist/calibration.d.ts +1 -1
  79. package/dist/calibration.js +1 -1
  80. package/dist/capabilities.d.ts +1 -1
  81. package/dist/{catalog-BOOxl-I2.d.ts → catalog-DGFf8mD9.d.ts} +1 -1
  82. package/dist/causal-behavior.d.ts +1 -1
  83. package/dist/causal-consolidation.d.ts +1 -1
  84. package/dist/causal-consolidation.js +34 -13
  85. package/dist/causal-consolidation.js.map +1 -1
  86. package/dist/causal-trajectory-graph.d.ts +1 -1
  87. package/dist/{chunk-ZYLC7NFO.js → chunk-26ZXBTYN.js} +4 -4
  88. package/dist/chunk-26ZXBTYN.js.map +1 -0
  89. package/dist/{chunk-LLJMAULE.js → chunk-2FKEIPIT.js} +5 -5
  90. package/dist/{chunk-3CSX3ETE.js → chunk-2LWQSV6A.js} +23 -11
  91. package/dist/chunk-2LWQSV6A.js.map +1 -0
  92. package/dist/{chunk-JBPKEARU.js → chunk-2QSZNTDO.js} +7 -7
  93. package/dist/chunk-37DZZFFM.js +502 -0
  94. package/dist/chunk-37DZZFFM.js.map +1 -0
  95. package/dist/chunk-3HSRWJTC.js +9 -0
  96. package/dist/chunk-3HSRWJTC.js.map +1 -0
  97. package/dist/{chunk-XUAMCLY4.js → chunk-3TIZPSJC.js} +17 -13
  98. package/dist/chunk-3TIZPSJC.js.map +1 -0
  99. package/dist/{chunk-PDDTI7IC.js → chunk-43SEBY2M.js} +1 -1
  100. package/dist/{chunk-HWRD23DW.js → chunk-46SZBVDS.js} +3 -3
  101. package/dist/{chunk-6HPHEFXT.js → chunk-5FD7JMTX.js} +2 -2
  102. package/dist/{chunk-7BZOBA5J.js → chunk-5NB726GV.js} +70 -16
  103. package/dist/chunk-5NB726GV.js.map +1 -0
  104. package/dist/chunk-62OKGIJA.js +39 -0
  105. package/dist/chunk-62OKGIJA.js.map +1 -0
  106. package/dist/{chunk-IBKR2TFR.js → chunk-6CYHUWCO.js} +2 -2
  107. package/dist/{chunk-YN6ASZUG.js → chunk-6QPI2ITJ.js} +5 -5
  108. package/dist/{chunk-UU3G6GUP.js → chunk-76JJSXK7.js} +1 -1
  109. package/dist/chunk-76JJSXK7.js.map +1 -0
  110. package/dist/{chunk-PX2LSHYM.js → chunk-7BD6O7ZV.js} +189 -4
  111. package/dist/chunk-7BD6O7ZV.js.map +1 -0
  112. package/dist/chunk-7TBXNYLO.js +346 -0
  113. package/dist/chunk-7TBXNYLO.js.map +1 -0
  114. package/dist/{chunk-NH5IR2WM.js → chunk-BRR5EUTF.js} +6 -2
  115. package/dist/chunk-BRR5EUTF.js.map +1 -0
  116. package/dist/{chunk-NIS256NW.js → chunk-CIAI24TQ.js} +3 -3
  117. package/dist/{chunk-T2JHZWH6.js → chunk-D3LBIUWV.js} +11703 -7573
  118. package/dist/chunk-D3LBIUWV.js.map +1 -0
  119. package/dist/{chunk-7FGL6CGA.js → chunk-DVYRD4HY.js} +2 -2
  120. package/dist/{chunk-G7Z6EENO.js → chunk-EKTP7MNS.js} +4 -4
  121. package/dist/{chunk-S75M5ZRK.js → chunk-F2JRDPON.js} +16 -1
  122. package/dist/chunk-F2JRDPON.js.map +1 -0
  123. package/dist/{chunk-RZ4XGKOJ.js → chunk-FFRTNF3L.js} +8 -8
  124. package/dist/{chunk-VKXWK44Q.js → chunk-FONWBCVY.js} +3 -3
  125. package/dist/{chunk-DZD576ZU.js → chunk-FPLM2TKD.js} +2 -2
  126. package/dist/{chunk-ZPJ4QSGP.js → chunk-FTPONF6B.js} +2 -2
  127. package/dist/{chunk-LJS7KUPV.js → chunk-FWX7W5PM.js} +2 -2
  128. package/dist/{chunk-UTRO5UJU.js → chunk-G6DFSS6A.js} +5 -1
  129. package/dist/chunk-G6DFSS6A.js.map +1 -0
  130. package/dist/{chunk-6LAPLZOS.js → chunk-GJ776BC2.js} +8 -3
  131. package/dist/chunk-GJ776BC2.js.map +1 -0
  132. package/dist/{chunk-G4T7L557.js → chunk-GN3WRFJY.js} +6 -6
  133. package/dist/{chunk-QT2FRYI4.js → chunk-H7NAZ3UB.js} +2 -2
  134. package/dist/{chunk-APPFNGX6.js → chunk-HBUFQRIM.js} +2 -2
  135. package/dist/{chunk-UU7TRFNE.js → chunk-HGJ6NJ4E.js} +2 -2
  136. package/dist/{chunk-WB7JSQCP.js → chunk-HIEWDJ2O.js} +5 -2
  137. package/dist/{chunk-WB7JSQCP.js.map → chunk-HIEWDJ2O.js.map} +1 -1
  138. package/dist/{chunk-UES4BHA2.js → chunk-I3MSGFGD.js} +17 -6
  139. package/dist/chunk-I3MSGFGD.js.map +1 -0
  140. package/dist/{chunk-C4ZNGVK3.js → chunk-IKP5OYQQ.js} +2 -2
  141. package/dist/{chunk-KQAFEZQX.js → chunk-IPLYGWQF.js} +5 -5
  142. package/dist/{chunk-RDJRFDJY.js → chunk-IQ4NVWEF.js} +2 -2
  143. package/dist/{chunk-CGVHPCP2.js → chunk-JYG4OLWH.js} +2 -2
  144. package/dist/{chunk-WOPA3SGI.js → chunk-K26NWEOC.js} +8 -8
  145. package/dist/{chunk-K4QS7LXU.js → chunk-K2UGPTYY.js} +485 -44
  146. package/dist/chunk-K2UGPTYY.js.map +1 -0
  147. package/dist/{chunk-L6CQ7WIW.js → chunk-KFBOPMF6.js} +11 -11
  148. package/dist/chunk-KFBOPMF6.js.map +1 -0
  149. package/dist/{chunk-G7A5HLUS.js → chunk-KJH6W2I7.js} +2 -2
  150. package/dist/{chunk-IXEBUYO4.js → chunk-KM55SMLG.js} +11 -2
  151. package/dist/{chunk-IXEBUYO4.js.map → chunk-KM55SMLG.js.map} +1 -1
  152. package/dist/{chunk-HOIRB77A.js → chunk-L6Z5OAS4.js} +2 -2
  153. package/dist/chunk-LC2BDILZ.js +57 -0
  154. package/dist/chunk-LC2BDILZ.js.map +1 -0
  155. package/dist/{chunk-227UFSEQ.js → chunk-LEPOP46W.js} +4 -4
  156. package/dist/{chunk-6R4G7N4S.js → chunk-M4YHAODQ.js} +388 -748
  157. package/dist/chunk-M4YHAODQ.js.map +1 -0
  158. package/dist/{chunk-3JLPGJ43.js → chunk-MIH3CJPN.js} +5 -5
  159. package/dist/{chunk-QHFV6VNU.js → chunk-MK5VEWCR.js} +2 -2
  160. package/dist/chunk-NISZQW72.js +140 -0
  161. package/dist/chunk-NISZQW72.js.map +1 -0
  162. package/dist/{chunk-GUKBW4HL.js → chunk-NQMSEB5D.js} +6 -6
  163. package/dist/{chunk-G2LUMAUF.js → chunk-OCIP6YMD.js} +12 -5
  164. package/dist/chunk-OCIP6YMD.js.map +1 -0
  165. package/dist/{chunk-47P3RYZP.js → chunk-PG4QBPVG.js} +21 -11
  166. package/dist/chunk-PG4QBPVG.js.map +1 -0
  167. package/dist/{chunk-WRJVB3C2.js → chunk-PO7NXBG2.js} +2 -2
  168. package/dist/{chunk-QWGE2PUH.js → chunk-PT54WISF.js} +190 -56
  169. package/dist/chunk-PT54WISF.js.map +1 -0
  170. package/dist/{chunk-AZM4CCAC.js → chunk-QZLDRQ4I.js} +8 -8
  171. package/dist/{chunk-THPPCISA.js → chunk-RBII7637.js} +5 -5
  172. package/dist/{chunk-JDZPNCMA.js → chunk-RUNORG2P.js} +6 -3
  173. package/dist/chunk-RUNORG2P.js.map +1 -0
  174. package/dist/{chunk-JV5YUBIZ.js → chunk-RZQ6W2W4.js} +50 -44
  175. package/dist/chunk-RZQ6W2W4.js.map +1 -0
  176. package/dist/{chunk-RUMNY5DT.js → chunk-SMNYAMJD.js} +6 -2
  177. package/dist/chunk-SMNYAMJD.js.map +1 -0
  178. package/dist/{chunk-MKQBXQKU.js → chunk-TB6CBZ5V.js} +22 -15
  179. package/dist/chunk-TB6CBZ5V.js.map +1 -0
  180. package/dist/{chunk-VMMQDEN5.js → chunk-TO7ZTWJW.js} +2 -2
  181. package/dist/{chunk-K2TDK7GG.js → chunk-TWTUGCTY.js} +2 -2
  182. package/dist/{chunk-HLYR2TQL.js → chunk-UCTS3DDH.js} +2 -2
  183. package/dist/{chunk-JYIJNNN3.js → chunk-UG6VXIOK.js} +2 -2
  184. package/dist/{chunk-WM65LU67.js → chunk-UKYS3NU5.js} +2 -2
  185. package/dist/{chunk-WDBX6VER.js → chunk-UPLZNJKN.js} +5 -5
  186. package/dist/{chunk-C23BYTJV.js → chunk-UW5NPZJ2.js} +40 -12
  187. package/dist/chunk-UW5NPZJ2.js.map +1 -0
  188. package/dist/{chunk-2GFK22OZ.js → chunk-V6ERBR7U.js} +2 -2
  189. package/dist/{chunk-CYF6WVE7.js → chunk-W5ZKPI34.js} +139 -158
  190. package/dist/chunk-W5ZKPI34.js.map +1 -0
  191. package/dist/chunk-XX4HPFFM.js +370 -0
  192. package/dist/chunk-XX4HPFFM.js.map +1 -0
  193. package/dist/{chunk-ZMYDYNI4.js → chunk-XZHE2DEN.js} +4 -4
  194. package/dist/chunk-YXQEKCZM.js +223 -0
  195. package/dist/chunk-YXQEKCZM.js.map +1 -0
  196. package/dist/{chunk-GYPQL6XN.js → chunk-Z4N7SVVF.js} +35 -47
  197. package/dist/chunk-Z4N7SVVF.js.map +1 -0
  198. package/dist/{chunk-MAXVH44E.js → chunk-Z54EM5YZ.js} +7 -7
  199. package/dist/{chunk-YGLY6QFV.js → chunk-ZRZVLB7O.js} +2 -2
  200. package/dist/{chunk-4IIFL7GC.js → chunk-ZUKIUXHQ.js} +10 -10
  201. package/dist/{cli-DVUFIa5E.d.ts → cli-Bze8S0Qs.d.ts} +5 -5
  202. package/dist/cli.d.ts +22 -21
  203. package/dist/cli.js +90 -80
  204. package/dist/coding/pre-action-gate.d.ts +1 -1
  205. package/dist/compounding/engine.d.ts +2 -2
  206. package/dist/compounding/engine.js +33 -12
  207. package/dist/compounding/preference-consolidator.d.ts +1 -1
  208. package/dist/compression-optimizer.d.ts +1 -1
  209. package/dist/config.d.ts +1 -1
  210. package/dist/config.js +4 -2
  211. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  212. package/dist/connectors/codex-materialize-runner.js +33 -12
  213. package/dist/connectors/codex-materialize.d.ts +1 -1
  214. package/dist/connectors/index.d.ts +1 -1
  215. package/dist/connectors/index.js +32 -12
  216. package/dist/consolidation-provenance-check.d.ts +2 -2
  217. package/dist/consolidation-undo.d.ts +2 -2
  218. package/dist/contradiction/index.d.ts +2 -2
  219. package/dist/contradiction/index.js +3 -1
  220. package/dist/contradiction-scan-JDTBXRGW.js +20 -0
  221. package/dist/converge-config.d.ts +1 -1
  222. package/dist/convergence-refresh.d.ts +2 -2
  223. package/dist/convergence-refresh.js +35 -14
  224. package/dist/conversation-index/backend.d.ts +1 -1
  225. package/dist/conversation-index/backend.js +2 -2
  226. package/dist/conversation-index/chunker.d.ts +1 -1
  227. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  228. package/dist/conversation-index/indexer.d.ts +1 -1
  229. package/dist/conversation-index/search.d.ts +1 -1
  230. package/dist/corpus-watermark.d.ts +1 -1
  231. package/dist/corpus-watermark.js +25 -24
  232. package/dist/day-summary.d.ts +1 -1
  233. package/dist/delinearize.d.ts +1 -1
  234. package/dist/dependency-propagation-config.d.ts +1 -1
  235. package/dist/{dependency-propagation-delivery-XzF76C9n.d.ts → dependency-propagation-delivery-CzEfB31P.d.ts} +1 -1
  236. package/dist/direct-answer-wiring.d.ts +1 -1
  237. package/dist/direct-answer.d.ts +1 -1
  238. package/dist/embedding-fallback.d.ts +1 -1
  239. package/dist/enrichment/index.d.ts +1 -1
  240. package/dist/entity-retrieval.d.ts +2 -2
  241. package/dist/entity-retrieval.js +33 -12
  242. package/dist/entity-schema.d.ts +1 -1
  243. package/dist/explicit-capture.d.ts +9 -9
  244. package/dist/explicit-capture.js +7 -4
  245. package/dist/external-wiki-access.d.ts +22 -21
  246. package/dist/external-wiki-access.js +56 -51
  247. package/dist/external-wiki-collection-registration.d.ts +1 -1
  248. package/dist/external-wiki-collection.d.ts +1 -1
  249. package/dist/external-wiki-mcp-tools.d.ts +22 -21
  250. package/dist/extraction-error-classification.d.ts +1 -1
  251. package/dist/extraction-faithfulness.d.ts +1 -1
  252. package/dist/extraction-faithfulness.js +2 -2
  253. package/dist/extraction-judge-telemetry.d.ts +1 -1
  254. package/dist/extraction-judge-training.d.ts +1 -1
  255. package/dist/extraction-judge.d.ts +1 -1
  256. package/dist/extraction-judge.js +2 -2
  257. package/dist/extraction-liveness.d.ts +1 -1
  258. package/dist/extraction-normalization.d.ts +1 -1
  259. package/dist/extraction-prompt.d.ts +1 -1
  260. package/dist/extraction-source-grounding-rules.d.ts +1 -1
  261. package/dist/extraction-source-grounding.d.ts +1 -1
  262. package/dist/extraction.d.ts +1 -1
  263. package/dist/extraction.js +35 -19
  264. package/dist/fallback-llm.d.ts +14 -1
  265. package/dist/fallback-llm.js +1 -1
  266. package/dist/{first-start-migration-626C5554.js → first-start-migration-CRZCZAJN.js} +11 -3
  267. package/dist/first-start-migration-CRZCZAJN.js.map +1 -0
  268. package/dist/graph-dashboard-diff.d.ts +1 -1
  269. package/dist/graph-dashboard-key.d.ts +1 -1
  270. package/dist/graph-dashboard-parser.d.ts +1 -1
  271. package/dist/graph-edge-reinforcement.d.ts +1 -1
  272. package/dist/graph-path-reconstruction.d.ts +1 -1
  273. package/dist/graph-path-scoring.d.ts +1 -1
  274. package/dist/graph-snapshot.d.ts +1 -1
  275. package/dist/graph.d.ts +1 -1
  276. package/dist/harmonic-retrieval.js +1 -1
  277. package/dist/importance.d.ts +1 -1
  278. package/dist/importers/index.d.ts +1 -1
  279. package/dist/in-flight-reads.d.ts +1 -1
  280. package/dist/index.d.ts +314 -308
  281. package/dist/index.js +304 -133
  282. package/dist/inline-script.d.ts +3 -0
  283. package/dist/inline-script.js +8 -0
  284. package/dist/inline-script.js.map +1 -0
  285. package/dist/intent.d.ts +1 -1
  286. package/dist/lcm/engine.d.ts +1 -1
  287. package/dist/lcm/engine.js +3 -3
  288. package/dist/lcm/index.d.ts +1 -1
  289. package/dist/lcm/index.js +6 -6
  290. package/dist/lcm/tools.d.ts +1 -1
  291. package/dist/lifecycle.d.ts +1 -1
  292. package/dist/live-connectors-runner.d.ts +1 -1
  293. package/dist/local-llm.d.ts +2 -1
  294. package/dist/local-llm.js +2 -2
  295. package/dist/local-model-endpoint.d.ts +1 -1
  296. package/dist/maintenance/memory-governance.d.ts +1 -1
  297. package/dist/maintenance/memory-governance.js +33 -12
  298. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  299. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +33 -12
  300. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
  301. package/dist/maintenance/rebuild-memory-projection.js +34 -13
  302. package/dist/{maintenance-BJzNIKBE.d.ts → maintenance-C8aRWfhq.d.ts} +3 -3
  303. package/dist/mcp-memory-inspector-app.d.ts +22 -21
  304. package/dist/mcp-read-only-tools.js +1 -1
  305. package/dist/memory-action-policy.d.ts +1 -1
  306. package/dist/memory-cache.d.ts +1 -1
  307. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  308. package/dist/memory-projection-mutations.js +2 -2
  309. package/dist/memory-projection-store.d.ts +6 -2
  310. package/dist/memory-projection-store.js +1 -1
  311. package/dist/memory-provenance.d.ts +1 -1
  312. package/dist/memory-snapshot.d.ts +1 -1
  313. package/dist/memory-worth-outcomes.d.ts +2 -2
  314. package/dist/models-json.d.ts +1 -1
  315. package/dist/namespaces/migrate.d.ts +3 -3
  316. package/dist/namespaces/migrate.js +24 -23
  317. package/dist/namespaces/principal.d.ts +1 -1
  318. package/dist/namespaces/search.d.ts +1 -1
  319. package/dist/namespaces/search.js +8 -8
  320. package/dist/namespaces/storage.d.ts +3 -3
  321. package/dist/namespaces/storage.js +33 -12
  322. package/dist/native-knowledge.d.ts +1 -1
  323. package/dist/offline-sync-file-io.d.ts +20 -0
  324. package/dist/offline-sync-file-io.js +18 -0
  325. package/dist/offline-sync-file-io.js.map +1 -0
  326. package/dist/offline-sync-impression-drain.d.ts +1 -1
  327. package/dist/offline-sync-impression-drain.js +5 -5
  328. package/dist/offline-sync.d.ts +8 -6
  329. package/dist/offline-sync.js +2 -1
  330. package/dist/operator-doctor-corpus.d.ts +1 -1
  331. package/dist/operator-doctor-corpus.js +26 -25
  332. package/dist/operator-doctor-replica.d.ts +1 -1
  333. package/dist/operator-toolkit.d.ts +3 -3
  334. package/dist/operator-toolkit.js +39 -36
  335. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  336. package/dist/orchestration/maintenance.d.ts +4 -4
  337. package/dist/orchestration/maintenance.js +38 -18
  338. package/dist/{orchestrator-BiXgBJBQ.d.ts → orchestrator-D85CzDDY.d.ts} +11 -8
  339. package/dist/orchestrator.d.ts +9 -9
  340. package/dist/orchestrator.js +117 -109
  341. package/dist/patterns-cli.d.ts +1 -1
  342. package/dist/{pipeline-sz_dcuLg.d.ts → pipeline-DPcUifCO.d.ts} +1 -1
  343. package/dist/policy-runtime.d.ts +1 -1
  344. package/dist/proactive-contention.d.ts +1 -1
  345. package/dist/provenance.d.ts +1 -1
  346. package/dist/public-http-D-SyWNj6.d.ts +25 -0
  347. package/dist/{purge-533FZLS4.js → purge-GB7PZHT2.js} +2 -2
  348. package/dist/{qmd-eAWObK4M.d.ts → qmd-dFCHp1r0.d.ts} +1 -1
  349. package/dist/qmd-preflight.d.ts +2 -2
  350. package/dist/qmd-recall-cache.d.ts +1 -1
  351. package/dist/qmd.d.ts +2 -2
  352. package/dist/recall-concurrency-config.d.ts +1 -1
  353. package/dist/recall-disclosure-escalation.d.ts +1 -1
  354. package/dist/recall-explain-renderer.d.ts +1 -1
  355. package/dist/recall-explain-renderer.js +3 -3
  356. package/dist/recall-memory-map.d.ts +1 -1
  357. package/dist/recall-planner-llm.d.ts +1 -1
  358. package/dist/recall-planner-llm.js +1 -1
  359. package/dist/recall-state.d.ts +1 -1
  360. package/dist/recall-tag-filter.d.ts +1 -1
  361. package/dist/recall-timings.d.ts +1 -1
  362. package/dist/recall-xray-cli.d.ts +1 -1
  363. package/dist/recall-xray-cli.js +4 -4
  364. package/dist/recall-xray-renderer.d.ts +1 -1
  365. package/dist/recall-xray-renderer.js +3 -3
  366. package/dist/recall-xray.d.ts +1 -1
  367. package/dist/recall-xray.js +2 -2
  368. package/dist/reconcile/cursor.d.ts +2 -1
  369. package/dist/reconcile/manifest.d.ts +2 -1
  370. package/dist/reconcile/manifest.js +6 -5
  371. package/dist/reconcile/plan.d.ts +2 -1
  372. package/dist/reconcile/plan.js +3 -2
  373. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  374. package/dist/replay/normalizers/claude.d.ts +1 -1
  375. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  376. package/dist/replay/normalizers/shared.d.ts +1 -1
  377. package/dist/replay/runner.d.ts +1 -1
  378. package/dist/replay/types.d.ts +1 -1
  379. package/dist/replica-divergence.d.ts +1 -1
  380. package/dist/replica-peers-config.d.ts +1 -1
  381. package/dist/resolve-auth-token.d.ts +1 -1
  382. package/dist/resume-bundles.js +5 -3
  383. package/dist/retrieval-agents.d.ts +2 -2
  384. package/dist/retrieval-tiers.d.ts +1 -1
  385. package/dist/routing/engine.d.ts +1 -1
  386. package/dist/routing/store.d.ts +1 -1
  387. package/dist/salvage-envelope.d.ts +1 -1
  388. package/dist/schemas.d.ts +38 -38
  389. package/dist/{scope-profiles-BBQsXuyj.d.ts → scope-profiles-DICK7GtN.d.ts} +1 -1
  390. package/dist/search/embed-helper.d.ts +1 -1
  391. package/dist/search/factory.d.ts +1 -1
  392. package/dist/search/factory.js +6 -6
  393. package/dist/search/index.d.ts +1 -1
  394. package/dist/search/index.js +12 -12
  395. package/dist/search/lancedb-backend.d.ts +1 -1
  396. package/dist/search/meilisearch-backend.d.ts +1 -1
  397. package/dist/search/noop-backend.d.ts +1 -1
  398. package/dist/search/orama-backend.d.ts +1 -1
  399. package/dist/search/port.d.ts +1 -1
  400. package/dist/search/remote-backend.d.ts +1 -1
  401. package/dist/{semantic-consolidation-HD8RkzVA.d.ts → semantic-consolidation-BP7NAX0N.d.ts} +1 -1
  402. package/dist/semantic-consolidation.d.ts +2 -2
  403. package/dist/semantic-consolidation.js +34 -13
  404. package/dist/semantic-rule-promotion.js +33 -12
  405. package/dist/semantic-rule-verifier.d.ts +1 -1
  406. package/dist/semantic-rule-verifier.js +33 -12
  407. package/dist/{service-DIrtHHEg.d.ts → service-DT-pJyda.d.ts} +660 -660
  408. package/dist/session-observer-bands.d.ts +1 -1
  409. package/dist/session-observer-state.d.ts +1 -1
  410. package/dist/shared-context/manager.d.ts +1 -1
  411. package/dist/signal.d.ts +1 -1
  412. package/dist/source-agent-qualifier.d.ts +1 -1
  413. package/dist/source-agent-qualifier.js +31 -15
  414. package/dist/{storage-DqCzXi56.d.ts → storage-qOnaJ1Lw.d.ts} +49 -13
  415. package/dist/storage.d.ts +2 -2
  416. package/dist/storage.js +33 -12
  417. package/dist/summarizer.d.ts +1 -1
  418. package/dist/summarizer.js +5 -5
  419. package/dist/summary-snapshot.d.ts +1 -1
  420. package/dist/support-passport/index.d.ts +518 -0
  421. package/dist/support-passport/index.js +357 -0
  422. package/dist/support-passport/index.js.map +1 -0
  423. package/dist/temporal-supersession.d.ts +2 -2
  424. package/dist/temporal-timeline-recall.d.ts +1 -1
  425. package/dist/temporal-validity.d.ts +1 -1
  426. package/dist/threading.d.ts +1 -1
  427. package/dist/tier-migration.d.ts +2 -2
  428. package/dist/tier-routing.d.ts +2 -2
  429. package/dist/tier-routing.js +7 -1
  430. package/dist/{tier-stats-2JCZYEF7.js → tier-stats-EXYSKSVN.js} +8 -2
  431. package/dist/{tier-stats-2JCZYEF7.js.map → tier-stats-EXYSKSVN.js.map} +1 -1
  432. package/dist/topics.d.ts +1 -1
  433. package/dist/transcript.d.ts +1 -1
  434. package/dist/transfer/autodetect.js +1 -1
  435. package/dist/transfer/backup.js +1 -1
  436. package/dist/transfer/capsule-export.js +2 -2
  437. package/dist/transfer/types.d.ts +36 -36
  438. package/dist/trust-score-stage.d.ts +1 -1
  439. package/dist/trust-score.d.ts +1 -1
  440. package/dist/{types-d_j4vC6N.d.ts → types-ed-SvS2t.d.ts} +8 -1
  441. package/dist/types.d.ts +1 -1
  442. package/dist/types.js +1 -1
  443. package/dist/utility-runtime.d.ts +2 -2
  444. package/dist/verified-recall.js +33 -12
  445. package/dist/write-envelope.d.ts +1 -1
  446. package/dist/write-rate-limiter.d.ts +11 -5
  447. package/dist/write-rate-limiter.js +1 -1
  448. package/package.json +12 -2
  449. package/scripts/build-with-heap.mjs +11 -1
  450. package/src/access-authorization-probe.ts +20 -2
  451. package/src/access-boundary.ts +32 -0
  452. package/src/access-http.test.ts +1971 -643
  453. package/src/access-http.ts +81 -74
  454. package/src/access-mcp.ts +3 -1
  455. package/src/access-memory-search-fanout.ts +24 -1
  456. package/src/access-offline-manifest.ts +5 -0
  457. package/src/access-operations.ts +2 -0
  458. package/src/access-service-namespace.test.ts +14 -0
  459. package/src/access-service-observe-scope.test.ts +2 -0
  460. package/src/access-service-offline-file-content.test.ts +211 -0
  461. package/src/access-service.ts +628 -884
  462. package/src/access-surface-catalog.test.ts +40 -10
  463. package/src/access-surface-catalog.ts +15 -0
  464. package/src/active-memory-bridge.test.ts +151 -0
  465. package/src/active-memory-bridge.ts +95 -21
  466. package/src/briefing.test.ts +38 -0
  467. package/src/briefing.ts +3 -3
  468. package/src/cli.ts +6 -1
  469. package/src/config.ts +18 -9
  470. package/src/connectors/codex-materialize-runner.ts +2 -0
  471. package/src/contradiction/contradiction-scan.ts +2 -0
  472. package/src/contradiction/contradiction.test.ts +42 -0
  473. package/src/correction/correction-access-wiring.ts +8 -2
  474. package/src/correction/correction-storage-integration.test.ts +7 -0
  475. package/src/explicit-capture.test.ts +24 -0
  476. package/src/explicit-capture.ts +2 -0
  477. package/src/fallback-llm.test.ts +54 -0
  478. package/src/fallback-llm.ts +54 -9
  479. package/src/index.ts +3 -0
  480. package/src/inline-script.ts +6 -0
  481. package/src/local-llm-headers-timeout.test.ts +42 -0
  482. package/src/local-llm.ts +8 -8
  483. package/src/maintenance/first-start-migration.ts +2 -1
  484. package/src/maintenance/memory-governance.test.ts +25 -0
  485. package/src/maintenance/memory-governance.ts +4 -1
  486. package/src/maintenance/pattern-reinforcement.test.ts +20 -0
  487. package/src/maintenance/pattern-reinforcement.ts +2 -1
  488. package/src/maintenance/rebuild-memory-projection.ts +8 -8
  489. package/src/mcp-read-only-tools.ts +3 -0
  490. package/src/memory-projection-store.ts +25 -27
  491. package/src/offline-sync-file-io.ts +68 -0
  492. package/src/offline-sync.ts +43 -57
  493. package/src/orchestration/consolidation-run.ts +5 -4
  494. package/src/orchestration/contradiction-linking-coordinator.ts +7 -0
  495. package/src/orchestration/contradiction-localization.integration.test.ts +115 -0
  496. package/src/orchestration/lifecycle-policy-coordinator.ts +2 -1
  497. package/src/orchestration/qmd-result-resolver.test.ts +215 -14
  498. package/src/orchestration/qmd-result-resolver.ts +142 -82
  499. package/src/orchestration/recall-search-pipeline.test.ts +41 -0
  500. package/src/orchestration/recall-search-pipeline.ts +12 -0
  501. package/src/orchestration/semantic-consolidation-coordinator.ts +2 -1
  502. package/src/orchestration/tier-migration-coordinator.ts +23 -56
  503. package/src/orchestration/workspace-ops.test.ts +37 -0
  504. package/src/orchestration/workspace-ops.ts +5 -29
  505. package/src/orchestrator.ts +7 -8
  506. package/src/relay/mission-access.test.ts +11 -11
  507. package/src/relay/mission-ui.test.ts +3 -1
  508. package/src/storage/supersession-audit.ts +7 -1
  509. package/src/storage/supersession-side-effects.ts +17 -5
  510. package/src/storage/tombstone-blocked-capture-sync.ts +31 -0
  511. package/src/storage-contract/failure-semantics.test.ts +102 -0
  512. package/src/storage.ts +18 -19
  513. package/src/support-passport/access-http-base.ts +143 -0
  514. package/src/support-passport/access-http.ts +172 -0
  515. package/src/support-passport/access-operations.ts +272 -0
  516. package/src/support-passport/access-service-base.test.ts +193 -0
  517. package/src/support-passport/access-service-base.ts +176 -0
  518. package/src/support-passport/access-surface.test.ts +283 -0
  519. package/src/support-passport/access-surface.ts +286 -0
  520. package/src/support-passport/card-projection.test.ts +137 -0
  521. package/src/support-passport/card-projection.ts +348 -0
  522. package/src/support-passport/card-replacement.ts +126 -0
  523. package/src/support-passport/card-service-commit-forwarding.test.ts +160 -0
  524. package/src/support-passport/card-service.test.ts +2964 -0
  525. package/src/support-passport/card-service.ts +1184 -0
  526. package/src/support-passport/card-state.ts +158 -0
  527. package/src/support-passport/config-model-routing.test.ts +37 -0
  528. package/src/support-passport/config.test.ts +34 -0
  529. package/src/support-passport/config.ts +41 -0
  530. package/src/support-passport/contracts.test.ts +156 -0
  531. package/src/support-passport/contracts.ts +149 -0
  532. package/src/support-passport/errors.ts +30 -0
  533. package/src/support-passport/generated-batch.test.ts +185 -0
  534. package/src/support-passport/generated-batch.ts +338 -0
  535. package/src/support-passport/grant-contracts.ts +183 -0
  536. package/src/support-passport/grant-generated-batch-scope.test.ts +201 -0
  537. package/src/support-passport/grant-service-cache.test.ts +148 -0
  538. package/src/support-passport/grant-service-cancellation.test.ts +83 -0
  539. package/src/support-passport/grant-service-marker-cache.test.ts +62 -0
  540. package/src/support-passport/grant-service.test.ts +3496 -0
  541. package/src/support-passport/grant-service.ts +513 -0
  542. package/src/support-passport/grant-store-commit-hook.test.ts +123 -0
  543. package/src/support-passport/grant-store-order.test.ts +60 -0
  544. package/src/support-passport/grant-store-path-safety.test.ts +30 -0
  545. package/src/support-passport/grant-store-recovery.test.ts +448 -0
  546. package/src/support-passport/grant-store.ts +906 -0
  547. package/src/support-passport/index.ts +17 -0
  548. package/src/support-passport/mcp-tools.test.ts +222 -0
  549. package/src/support-passport/mcp-tools.ts +187 -0
  550. package/src/support-passport/model-adapter.test.ts +840 -0
  551. package/src/support-passport/model-adapter.ts +602 -0
  552. package/src/support-passport/model-audit-pinned-write.test.ts +59 -0
  553. package/src/support-passport/model-audit.ts +152 -0
  554. package/src/support-passport/model-bridge.test.ts +456 -0
  555. package/src/support-passport/model-bridge.ts +439 -0
  556. package/src/support-passport/model-contracts.ts +124 -0
  557. package/src/support-passport/model-service.test.ts +1731 -0
  558. package/src/support-passport/model-service.ts +399 -0
  559. package/src/support-passport/offline-sync-guard.ts +230 -0
  560. package/src/support-passport/owner-http.test.ts +671 -0
  561. package/src/support-passport/owner-lock.ts +70 -0
  562. package/src/support-passport/private-file.test.ts +99 -0
  563. package/src/support-passport/private-file.ts +498 -0
  564. package/src/support-passport/public-http.test.ts +476 -0
  565. package/src/support-passport/public-http.ts +601 -0
  566. package/src/support-passport/ui.test.ts +181 -0
  567. package/src/tier-routing.ts +28 -17
  568. package/src/training-export/converter.test.ts +24 -0
  569. package/src/training-export/converter.ts +2 -0
  570. package/src/types.ts +8 -1
  571. package/src/wearables/service.test.ts +13 -0
  572. package/src/wearables/service.ts +2 -0
  573. package/src/write-rate-limiter.test.ts +30 -6
  574. package/src/write-rate-limiter.ts +29 -18
  575. package/dist/chunk-3CSX3ETE.js.map +0 -1
  576. package/dist/chunk-47P3RYZP.js.map +0 -1
  577. package/dist/chunk-6LAPLZOS.js.map +0 -1
  578. package/dist/chunk-6R4G7N4S.js.map +0 -1
  579. package/dist/chunk-7BZOBA5J.js.map +0 -1
  580. package/dist/chunk-C23BYTJV.js.map +0 -1
  581. package/dist/chunk-CYF6WVE7.js.map +0 -1
  582. package/dist/chunk-G2LUMAUF.js.map +0 -1
  583. package/dist/chunk-GYPQL6XN.js.map +0 -1
  584. package/dist/chunk-JDZPNCMA.js.map +0 -1
  585. package/dist/chunk-JV5YUBIZ.js.map +0 -1
  586. package/dist/chunk-K4QS7LXU.js.map +0 -1
  587. package/dist/chunk-L6CQ7WIW.js.map +0 -1
  588. package/dist/chunk-MKQBXQKU.js.map +0 -1
  589. package/dist/chunk-NH5IR2WM.js.map +0 -1
  590. package/dist/chunk-PX2LSHYM.js.map +0 -1
  591. package/dist/chunk-QWGE2PUH.js.map +0 -1
  592. package/dist/chunk-RUMNY5DT.js.map +0 -1
  593. package/dist/chunk-S75M5ZRK.js.map +0 -1
  594. package/dist/chunk-T2JHZWH6.js.map +0 -1
  595. package/dist/chunk-UES4BHA2.js.map +0 -1
  596. package/dist/chunk-UTRO5UJU.js.map +0 -1
  597. package/dist/chunk-UU3G6GUP.js.map +0 -1
  598. package/dist/chunk-XUAMCLY4.js.map +0 -1
  599. package/dist/chunk-ZYLC7NFO.js.map +0 -1
  600. package/dist/contradiction-scan-HYLIRMJ2.js +0 -14
  601. package/dist/first-start-migration-626C5554.js.map +0 -1
  602. /package/dist/{auto-sync-TDHLZPVP.js.map → auto-sync-NR3GPCOA.js.map} +0 -0
  603. /package/dist/{chunk-LLJMAULE.js.map → chunk-2FKEIPIT.js.map} +0 -0
  604. /package/dist/{chunk-JBPKEARU.js.map → chunk-2QSZNTDO.js.map} +0 -0
  605. /package/dist/{chunk-PDDTI7IC.js.map → chunk-43SEBY2M.js.map} +0 -0
  606. /package/dist/{chunk-HWRD23DW.js.map → chunk-46SZBVDS.js.map} +0 -0
  607. /package/dist/{chunk-6HPHEFXT.js.map → chunk-5FD7JMTX.js.map} +0 -0
  608. /package/dist/{chunk-IBKR2TFR.js.map → chunk-6CYHUWCO.js.map} +0 -0
  609. /package/dist/{chunk-YN6ASZUG.js.map → chunk-6QPI2ITJ.js.map} +0 -0
  610. /package/dist/{chunk-NIS256NW.js.map → chunk-CIAI24TQ.js.map} +0 -0
  611. /package/dist/{chunk-7FGL6CGA.js.map → chunk-DVYRD4HY.js.map} +0 -0
  612. /package/dist/{chunk-G7Z6EENO.js.map → chunk-EKTP7MNS.js.map} +0 -0
  613. /package/dist/{chunk-RZ4XGKOJ.js.map → chunk-FFRTNF3L.js.map} +0 -0
  614. /package/dist/{chunk-VKXWK44Q.js.map → chunk-FONWBCVY.js.map} +0 -0
  615. /package/dist/{chunk-DZD576ZU.js.map → chunk-FPLM2TKD.js.map} +0 -0
  616. /package/dist/{chunk-ZPJ4QSGP.js.map → chunk-FTPONF6B.js.map} +0 -0
  617. /package/dist/{chunk-LJS7KUPV.js.map → chunk-FWX7W5PM.js.map} +0 -0
  618. /package/dist/{chunk-G4T7L557.js.map → chunk-GN3WRFJY.js.map} +0 -0
  619. /package/dist/{chunk-QT2FRYI4.js.map → chunk-H7NAZ3UB.js.map} +0 -0
  620. /package/dist/{chunk-APPFNGX6.js.map → chunk-HBUFQRIM.js.map} +0 -0
  621. /package/dist/{chunk-UU7TRFNE.js.map → chunk-HGJ6NJ4E.js.map} +0 -0
  622. /package/dist/{chunk-C4ZNGVK3.js.map → chunk-IKP5OYQQ.js.map} +0 -0
  623. /package/dist/{chunk-KQAFEZQX.js.map → chunk-IPLYGWQF.js.map} +0 -0
  624. /package/dist/{chunk-RDJRFDJY.js.map → chunk-IQ4NVWEF.js.map} +0 -0
  625. /package/dist/{chunk-CGVHPCP2.js.map → chunk-JYG4OLWH.js.map} +0 -0
  626. /package/dist/{chunk-WOPA3SGI.js.map → chunk-K26NWEOC.js.map} +0 -0
  627. /package/dist/{chunk-G7A5HLUS.js.map → chunk-KJH6W2I7.js.map} +0 -0
  628. /package/dist/{chunk-HOIRB77A.js.map → chunk-L6Z5OAS4.js.map} +0 -0
  629. /package/dist/{chunk-227UFSEQ.js.map → chunk-LEPOP46W.js.map} +0 -0
  630. /package/dist/{chunk-3JLPGJ43.js.map → chunk-MIH3CJPN.js.map} +0 -0
  631. /package/dist/{chunk-QHFV6VNU.js.map → chunk-MK5VEWCR.js.map} +0 -0
  632. /package/dist/{chunk-GUKBW4HL.js.map → chunk-NQMSEB5D.js.map} +0 -0
  633. /package/dist/{chunk-WRJVB3C2.js.map → chunk-PO7NXBG2.js.map} +0 -0
  634. /package/dist/{chunk-AZM4CCAC.js.map → chunk-QZLDRQ4I.js.map} +0 -0
  635. /package/dist/{chunk-THPPCISA.js.map → chunk-RBII7637.js.map} +0 -0
  636. /package/dist/{chunk-VMMQDEN5.js.map → chunk-TO7ZTWJW.js.map} +0 -0
  637. /package/dist/{chunk-K2TDK7GG.js.map → chunk-TWTUGCTY.js.map} +0 -0
  638. /package/dist/{chunk-HLYR2TQL.js.map → chunk-UCTS3DDH.js.map} +0 -0
  639. /package/dist/{chunk-JYIJNNN3.js.map → chunk-UG6VXIOK.js.map} +0 -0
  640. /package/dist/{chunk-WM65LU67.js.map → chunk-UKYS3NU5.js.map} +0 -0
  641. /package/dist/{chunk-WDBX6VER.js.map → chunk-UPLZNJKN.js.map} +0 -0
  642. /package/dist/{chunk-2GFK22OZ.js.map → chunk-V6ERBR7U.js.map} +0 -0
  643. /package/dist/{chunk-ZMYDYNI4.js.map → chunk-XZHE2DEN.js.map} +0 -0
  644. /package/dist/{chunk-MAXVH44E.js.map → chunk-Z54EM5YZ.js.map} +0 -0
  645. /package/dist/{chunk-YGLY6QFV.js.map → chunk-ZRZVLB7O.js.map} +0 -0
  646. /package/dist/{chunk-4IIFL7GC.js.map → chunk-ZUKIUXHQ.js.map} +0 -0
  647. /package/dist/{contradiction-scan-HYLIRMJ2.js.map → contradiction-scan-JDTBXRGW.js.map} +0 -0
  648. /package/dist/{purge-533FZLS4.js.map → purge-GB7PZHT2.js.map} +0 -0
@@ -0,0 +1,1184 @@
1
+ import { randomUUID } from "node:crypto";
2
+
3
+ import type { StorageManager } from "../index.js";
4
+ import { log } from "../logger.js";
5
+ import type { MemoryFile } from "../types.js";
6
+ import type { HeldFileLockController } from "../utils/serialize-mutations.js";
7
+ import { composeMemoryEnvelope } from "../write-envelope.js";
8
+ import {
9
+ SUPPORT_PASSPORT_ATTRIBUTE_KEYS,
10
+ SUPPORT_PASSPORT_CARD_TAG,
11
+ type StoredSupportPassportCard,
12
+ computeSupportPassportOwnerKey,
13
+ encodeSupportPassportNamespaceAttributes,
14
+ } from "./card-projection.js";
15
+ import {
16
+ completeSupportPassportReplacementPrior,
17
+ prepareSupportPassportReplacementPrior,
18
+ validateSupportPassportReplacementPrior,
19
+ } from "./card-replacement.js";
20
+ import {
21
+ MAX_OWNER_VISIBLE_CARDS,
22
+ type SupportPassportCardServiceDependencies,
23
+ type SupportPassportOwnerScope,
24
+ invalidInput,
25
+ isStorageConflict,
26
+ once,
27
+ ownerListCards,
28
+ ownerVisibleCards,
29
+ ownsMemory,
30
+ projectOwnedCard,
31
+ projectRequiredCard,
32
+ requireRevision,
33
+ requireStatus,
34
+ revisionFor,
35
+ validateOwnerScope,
36
+ } from "./card-state.js";
37
+ import {
38
+ type SupportPassportCard,
39
+ type SupportPassportCardCategory,
40
+ SupportPassportCardListSchema,
41
+ type SupportPassportCardMutationInput,
42
+ SupportPassportCardMutationInputSchema,
43
+ SupportPassportListCardsInputSchema,
44
+ type SupportPassportManualDraftInput,
45
+ SupportPassportManualDraftInputSchema,
46
+ type SupportPassportReplaceCardInput,
47
+ SupportPassportReplaceCardInputSchema,
48
+ } from "./contracts.js";
49
+ import { SupportPassportError } from "./errors.js";
50
+ import {
51
+ type GeneratedBatchMarker,
52
+ commitSupportPassportGeneratedBatch,
53
+ isCommittedGeneratedCard,
54
+ persistSupportPassportGeneratedBatchMarker,
55
+ projectCommittedSupportPassportCards,
56
+ readCommittedSupportPassportCards,
57
+ recoverSupportPassportGeneratedBatches,
58
+ rollbackSupportPassportGeneratedBatch,
59
+ } from "./generated-batch.js";
60
+ import { type SupportPassportDraftCard, SupportPassportDraftOutputSchema } from "./model-contracts.js";
61
+ import { withSupportPassportOwnerLock } from "./owner-lock.js";
62
+ export type { SupportPassportCardServiceDependencies, SupportPassportOwnerScope } from "./card-state.js";
63
+ export class SupportPassportCardService {
64
+ private readonly resolveOwner: SupportPassportCardServiceDependencies["resolveOwner"];
65
+ private readonly now: () => Date;
66
+ constructor(dependencies: SupportPassportCardServiceDependencies) {
67
+ this.resolveOwner = dependencies.resolveOwner;
68
+ this.now = dependencies.now ?? (() => new Date());
69
+ }
70
+
71
+ async listCards(input: {
72
+ principal: string;
73
+ }): Promise<SupportPassportCard[]> {
74
+ const parsed = SupportPassportListCardsInputSchema.safeParse(input);
75
+ if (!parsed.success) throw invalidInput();
76
+ const { principal, namespace, storage } = await this.resolveOwnerScope(parsed.data.principal);
77
+ return await withSupportPassportOwnerLock(storage, { namespace, principal }, async () => {
78
+ const memories = await storage.readAllMemories();
79
+ const stored = await projectCommittedSupportPassportCards(storage, memories, namespace, principal);
80
+ const cards = ownerListCards(stored)
81
+ .sort((a, b) => a.order - b.order || a.card.cardId.localeCompare(b.card.cardId))
82
+ .map((item) => item.card);
83
+ const output = SupportPassportCardListSchema.safeParse(cards);
84
+ if (!output.success) {
85
+ throw new SupportPassportError("card_data_invalid", "The support card data is invalid.", 500);
86
+ }
87
+ return output.data;
88
+ });
89
+ }
90
+
91
+ async createManualDraft(
92
+ input: SupportPassportManualDraftInput,
93
+ options: { signal?: AbortSignal; onCommitted?: () => void } = {}
94
+ ): Promise<SupportPassportCard> {
95
+ const parsed = SupportPassportManualDraftInputSchema.safeParse(input);
96
+ if (!parsed.success) throw invalidInput();
97
+ const { principal, namespace, storage } = await this.resolveOwnerScope(parsed.data.principal);
98
+ const onCommitted = once(options.onCommitted);
99
+ return await withSupportPassportOwnerLock(storage, { namespace, principal }, async (lock) => {
100
+ options.signal?.throwIfAborted();
101
+ const created = await this.createDraft(
102
+ storage,
103
+ {
104
+ title: parsed.data.title,
105
+ statement: parsed.data.statement,
106
+ category: parsed.data.category,
107
+ reviewBy: parsed.data.reviewBy,
108
+ sourceMemoryIds: [],
109
+ onCommitted,
110
+ },
111
+ lock,
112
+ principal,
113
+ namespace
114
+ );
115
+ if (!options.signal?.aborted) return created;
116
+ if (!(await this.rejectGeneratedDraft(storage, created.cardId, lock, principal, namespace))) {
117
+ throw new SupportPassportError("storage_conflict", "A cancelled support card could not be rolled back.", 500);
118
+ }
119
+ options.signal.throwIfAborted();
120
+ return created;
121
+ });
122
+ }
123
+
124
+ async createGeneratedDrafts(input: {
125
+ principal: string;
126
+ cards: SupportPassportDraftCard[];
127
+ }): Promise<SupportPassportCard[]> {
128
+ const principal = SupportPassportListCardsInputSchema.safeParse({
129
+ principal: input.principal,
130
+ });
131
+ if (!principal.success) throw invalidInput();
132
+ const owner = await this.resolveOwnerScope(principal.data.principal);
133
+ return await this.createGeneratedDraftsForOwner({
134
+ authenticatedPrincipal: principal.data.principal,
135
+ owner,
136
+ cards: input.cards,
137
+ });
138
+ }
139
+
140
+ async createGeneratedDraftsForOwner(input: {
141
+ authenticatedPrincipal: string;
142
+ owner: SupportPassportOwnerScope;
143
+ cards: SupportPassportDraftCard[];
144
+ signal?: AbortSignal;
145
+ onCommitted?: () => void;
146
+ commitWithValidatedSources?: (commit: () => Promise<void>) => Promise<void>;
147
+ }): Promise<SupportPassportCard[]> {
148
+ const output = SupportPassportDraftOutputSchema.safeParse({
149
+ cards: input.cards,
150
+ });
151
+ if (!output.success) throw invalidInput();
152
+ const owner = validateOwnerScope(input.owner, input.authenticatedPrincipal);
153
+ const { principal, namespace, storage } = owner;
154
+ const onCommitted = once(input.onCommitted);
155
+ return await withSupportPassportOwnerLock(storage, { namespace, principal }, async (lock) => {
156
+ const batchContext = this.generatedBatchContext(storage, lock, principal, namespace, onCommitted);
157
+ const batchId = randomUUID();
158
+ const created: SupportPassportCard[] = [];
159
+ const createdIds: string[] = [];
160
+ const createdRecords: StoredSupportPassportCard[] = [];
161
+ let marker: GeneratedBatchMarker | null = null;
162
+ try {
163
+ input.signal?.throwIfAborted();
164
+ input.signal?.throwIfAborted();
165
+ const storedCards = await this.readStoredCards(storage, lock, principal, namespace, onCommitted);
166
+ if (ownerVisibleCards(storedCards).length + output.data.cards.length > MAX_OWNER_VISIBLE_CARDS) {
167
+ throw new SupportPassportError(
168
+ "invalid_input",
169
+ "A support passport can contain at most 100 visible cards.",
170
+ 400
171
+ );
172
+ }
173
+ let nextOrder = storedCards.reduce((maximum, card) => Math.max(maximum, card.order), -1) + 1;
174
+ marker = await persistSupportPassportGeneratedBatchMarker(batchContext, batchId, output.data.cards.length);
175
+ for (const card of output.data.cards) {
176
+ input.signal?.throwIfAborted();
177
+ created.push(
178
+ await this.persistDraft(
179
+ storage,
180
+ {
181
+ title: card.title,
182
+ statement: card.statement,
183
+ category: card.category,
184
+ sourceMemoryIds: card.sourceMemoryIds,
185
+ order: nextOrder,
186
+ generatedBatch: { batchId, size: output.data.cards.length },
187
+ onPersisted: (record) => {
188
+ createdIds.push(record.card.cardId);
189
+ createdRecords.push(record);
190
+ onCommitted();
191
+ },
192
+ },
193
+ lock,
194
+ principal,
195
+ namespace
196
+ )
197
+ );
198
+ nextOrder += 1;
199
+ }
200
+ input.signal?.throwIfAborted();
201
+ const commit = async () =>
202
+ await commitSupportPassportGeneratedBatch(batchContext, marker!, createdRecords);
203
+ if (input.commitWithValidatedSources) await input.commitWithValidatedSources(commit);
204
+ else await commit();
205
+ return created;
206
+ } catch (error) {
207
+ if (!marker) throw error;
208
+ if (
209
+ !(await rollbackSupportPassportGeneratedBatch(batchContext, batchId, createdIds))
210
+ ) {
211
+ throw new SupportPassportError("storage_conflict", "A generated draft batch could not be rolled back.", 500);
212
+ }
213
+ throw error;
214
+ }
215
+ });
216
+ }
217
+
218
+ async replaceCard(
219
+ input: SupportPassportReplaceCardInput,
220
+ options: { signal?: AbortSignal; onCommitted?: () => void } = {}
221
+ ): Promise<SupportPassportCard> {
222
+ const parsed = SupportPassportReplaceCardInputSchema.safeParse(input);
223
+ if (!parsed.success) throw invalidInput();
224
+ const { principal, namespace, storage } = await this.resolveOwnerScope(parsed.data.principal);
225
+ const onCommitted = once(options.onCommitted);
226
+ return await withSupportPassportOwnerLock(storage, { namespace, principal }, async (lock) => {
227
+ options.signal?.throwIfAborted();
228
+ const loadedPrior = await this.requireCard(storage, parsed.data.cardId, namespace, principal);
229
+ const storedCards = await readCommittedSupportPassportCards(storage, namespace, principal);
230
+ const interruptedReplacements = storedCards.filter(
231
+ (item) =>
232
+ item.card.status === "pending_review" &&
233
+ (item.replacesDraftId === loadedPrior.card.cardId ||
234
+ item.memory.frontmatter.supersedes === loadedPrior.card.cardId)
235
+ );
236
+ if (interruptedReplacements.length > 1) {
237
+ throw new SupportPassportError(
238
+ "storage_conflict",
239
+ "Multiple support card edits already completed. Reload the support passport.",
240
+ 409
241
+ );
242
+ }
243
+ const [interruptedReplacement] = interruptedReplacements;
244
+ if (interruptedReplacement) {
245
+ if (interruptedReplacement.replacedRevision !== parsed.data.expectedRevision) {
246
+ throw new SupportPassportError("revision_conflict", "The support card changed after it was loaded.", 409);
247
+ }
248
+ const matchesRetry =
249
+ interruptedReplacement.card.title === parsed.data.title &&
250
+ interruptedReplacement.card.statement === parsed.data.statement &&
251
+ interruptedReplacement.card.category === parsed.data.category &&
252
+ interruptedReplacement.card.reviewBy === parsed.data.reviewBy;
253
+ if (!matchesRetry) {
254
+ throw new SupportPassportError(
255
+ "storage_conflict",
256
+ "A different support card edit already completed. Reload the support passport.",
257
+ 409
258
+ );
259
+ }
260
+ if (!interruptedReplacement.draftReplacementPrepared) return interruptedReplacement.card;
261
+ const recovered = await this.recoverReplacementTransition(
262
+ storage,
263
+ interruptedReplacement.memory,
264
+ lock,
265
+ principal,
266
+ namespace,
267
+ {},
268
+ onCommitted
269
+ );
270
+ return projectRequiredCard(recovered, namespace, principal).card;
271
+ }
272
+ requireRevision(loadedPrior, parsed.data.expectedRevision);
273
+ await this.readStoredCards(storage, lock, principal, namespace, onCommitted);
274
+ const refreshedPrior = await this.requireCard(storage, parsed.data.cardId, namespace, principal);
275
+ requireRevision(refreshedPrior, parsed.data.expectedRevision);
276
+ const recoveredMemory = await this.recoverReplacementTransition(
277
+ storage,
278
+ refreshedPrior.memory,
279
+ lock,
280
+ principal,
281
+ namespace,
282
+ {},
283
+ onCommitted
284
+ );
285
+ const prior = projectRequiredCard(recoveredMemory, namespace, principal);
286
+ if (prior.card.status !== "active" && prior.card.status !== "pending_review") {
287
+ throw new SupportPassportError(
288
+ "invalid_card_status",
289
+ "Only a draft or approved support card can be edited.",
290
+ 409
291
+ );
292
+ }
293
+ const replacement = await this.createDraft(
294
+ storage,
295
+ {
296
+ title: parsed.data.title,
297
+ statement: parsed.data.statement,
298
+ category: parsed.data.category,
299
+ reviewBy: parsed.data.reviewBy,
300
+ sourceMemoryIds: prior.sourceMemoryIds,
301
+ supersedes: prior.card.status === "active" ? prior.card.cardId : prior.memory.frontmatter.supersedes,
302
+ replacesDraftId: prior.card.status === "pending_review" ? prior.card.cardId : undefined,
303
+ replacedRevision: prior.card.revision,
304
+ order: prior.order,
305
+ draftReplacementPrepared: prior.card.status === "pending_review",
306
+ onCommitted,
307
+ },
308
+ lock,
309
+ principal,
310
+ namespace
311
+ );
312
+ if (options.signal?.aborted) {
313
+ if (!(await this.rejectGeneratedDraft(storage, replacement.cardId, lock, principal, namespace))) {
314
+ throw new SupportPassportError(
315
+ "storage_conflict",
316
+ "A cancelled support card edit could not be rolled back.",
317
+ 500
318
+ );
319
+ }
320
+ options.signal.throwIfAborted();
321
+ }
322
+ if (prior.card.status === "active") return replacement;
323
+
324
+ const replacedAt = this.now().toISOString();
325
+ await this.requireOwnerLock(lock);
326
+ const rejected = await storage.writeMemoryFrontmatterIfUnchanged(
327
+ prior.memory,
328
+ { status: "rejected", updated: replacedAt },
329
+ { actor: principal, reasonCode: "owner-replaced-draft" }
330
+ );
331
+ if (rejected) {
332
+ onCommitted();
333
+ return await this.finishPreparedDraftReplacement(
334
+ storage,
335
+ replacement.cardId,
336
+ lock,
337
+ principal,
338
+ namespace,
339
+ onCommitted
340
+ );
341
+ }
342
+ const currentPrior = await storage.getMemoryById(prior.card.cardId);
343
+ const currentPriorCard = currentPrior ? projectOwnedCard(currentPrior, namespace, principal) : null;
344
+ if (currentPriorCard?.card.status === "rejected") {
345
+ return await this.finishPreparedDraftReplacement(
346
+ storage,
347
+ replacement.cardId,
348
+ lock,
349
+ principal,
350
+ namespace,
351
+ onCommitted
352
+ );
353
+ }
354
+
355
+ await this.rejectCreatedDraft(
356
+ storage,
357
+ replacement.cardId,
358
+ "draft-replacement-failed",
359
+ lock,
360
+ principal,
361
+ namespace,
362
+ onCommitted
363
+ );
364
+ throw new SupportPassportError("storage_conflict", "The support card changed before it was edited.", 409);
365
+ });
366
+ }
367
+
368
+ async approveCard(
369
+ input: SupportPassportCardMutationInput,
370
+ options: { signal?: AbortSignal; onCommitted?: () => void } = {}
371
+ ): Promise<SupportPassportCard> {
372
+ const parsed = SupportPassportCardMutationInputSchema.safeParse(input);
373
+ if (!parsed.success) throw invalidInput();
374
+ const { principal, namespace, storage } = await this.resolveOwnerScope(parsed.data.principal);
375
+ const onCommitted = once(options.onCommitted);
376
+ return await withSupportPassportOwnerLock(storage, { namespace, principal }, async (lock) => {
377
+ options.signal?.throwIfAborted();
378
+ const loadedCard = await this.requireCard(storage, parsed.data.cardId, namespace, principal);
379
+ requireRevision(loadedCard, parsed.data.expectedRevision);
380
+ requireStatus(loadedCard, "pending_review");
381
+ const recoveredMemory = await this.recoverReplacementTransition(
382
+ storage,
383
+ loadedCard.memory,
384
+ lock,
385
+ principal,
386
+ namespace,
387
+ {},
388
+ onCommitted
389
+ );
390
+ const card = projectRequiredCard(recoveredMemory, namespace, principal);
391
+ if (card.card.status === "active") return card.card;
392
+ if (card.card.status === "rejected") {
393
+ throw new SupportPassportError(
394
+ "storage_conflict",
395
+ "The support card was rejected while its replacement state was recovered.",
396
+ 409
397
+ );
398
+ }
399
+ requireStatus(card, "pending_review");
400
+ await validateSupportPassportReplacementPrior(storage, card, namespace, principal);
401
+ const updatedAt = this.now().toISOString();
402
+ await this.requireOwnerLock(lock);
403
+ let approved: boolean;
404
+ try {
405
+ approved = await storage.writeMemoryFrontmatterIfUnchanged(
406
+ card.memory,
407
+ { status: "active", updated: updatedAt },
408
+ {
409
+ actor: principal,
410
+ reasonCode: parsed.data.reasonCode ?? "owner-approved",
411
+ }
412
+ );
413
+ } catch (error) {
414
+ const current = await storage.getMemoryById(card.card.cardId);
415
+ const currentCard = current ? projectOwnedCard(current, namespace, principal) : null;
416
+ if (currentCard?.card.status === "active") {
417
+ onCommitted();
418
+ return await this.finishCommittedApproval(storage, currentCard, lock, principal, namespace, onCommitted);
419
+ }
420
+ throw error;
421
+ }
422
+ if (!approved) {
423
+ const current = await storage.getMemoryById(card.card.cardId);
424
+ const currentCard = current ? projectOwnedCard(current, namespace, principal) : null;
425
+ if (currentCard?.card.status === "active") {
426
+ onCommitted();
427
+ return await this.finishCommittedApproval(storage, currentCard, lock, principal, namespace, onCommitted);
428
+ }
429
+ throw new SupportPassportError("storage_conflict", "The support card changed before approval.", 409);
430
+ }
431
+ const committedCard: SupportPassportCard = {
432
+ ...card.card,
433
+ status: "active",
434
+ updatedAt,
435
+ revision: revisionFor(card.card, "active", updatedAt),
436
+ };
437
+ onCommitted();
438
+ try {
439
+ const current = await this.requireCard(storage, card.card.cardId, namespace, principal);
440
+ return await this.finishCommittedApproval(storage, current, lock, principal, namespace, onCommitted);
441
+ } catch (error) {
442
+ if (isStorageConflict(error)) throw error;
443
+ log.warn(
444
+ `support passport could not finish replacement approval side effects: ${error instanceof Error ? error.message : String(error)}`
445
+ );
446
+ return committedCard;
447
+ }
448
+ });
449
+ }
450
+
451
+ async rejectCard(
452
+ input: SupportPassportCardMutationInput,
453
+ options: { signal?: AbortSignal; onCommitted?: () => void } = {}
454
+ ): Promise<SupportPassportCard> {
455
+ return await this.changeStatus(input, "pending_review", "rejected", "owner-rejected", options);
456
+ }
457
+
458
+ async withdrawCard(
459
+ input: SupportPassportCardMutationInput,
460
+ options: { signal?: AbortSignal; onCommitted?: () => void } = {}
461
+ ): Promise<SupportPassportCard> {
462
+ return await this.changeStatus(input, "active", "archived", "owner-withdrew", options);
463
+ }
464
+
465
+ private async createDraft(
466
+ storage: StorageManager,
467
+ input: {
468
+ title: string;
469
+ statement: string;
470
+ category: SupportPassportCardCategory;
471
+ reviewBy?: string;
472
+ sourceMemoryIds: string[];
473
+ supersedes?: string;
474
+ replacesDraftId?: string;
475
+ replacedRevision?: string;
476
+ order?: number;
477
+ draftReplacementPrepared?: boolean;
478
+ generatedBatch?: { batchId: string; size: number };
479
+ onPersisted?: (card: StoredSupportPassportCard) => void;
480
+ onCommitted?: () => void;
481
+ },
482
+ lock: HeldFileLockController,
483
+ principal: string,
484
+ namespace: string
485
+ ): Promise<SupportPassportCard> {
486
+ const now = this.now();
487
+ const reviewBy = input.reviewBy ?? now.toISOString();
488
+ const storedCards = await this.readStoredCards(storage, lock, principal, namespace, input.onCommitted);
489
+ const visibleCards = ownerListCards(storedCards);
490
+ const replacesVisibleCard = visibleCards.some(
491
+ (item) =>
492
+ (input.replacesDraftId === item.card.cardId && item.card.status === "pending_review") ||
493
+ (input.supersedes === item.card.cardId && item.card.status === "active")
494
+ );
495
+ if (visibleCards.length - (replacesVisibleCard ? 1 : 0) >= MAX_OWNER_VISIBLE_CARDS) {
496
+ throw new SupportPassportError("invalid_input", "A support passport can contain at most 100 visible cards.", 400);
497
+ }
498
+ const order = input.order ?? storedCards.reduce((maximum, card) => Math.max(maximum, card.order), -1) + 1;
499
+ return await this.persistDraft(storage, { ...input, order }, lock, principal, namespace);
500
+ }
501
+
502
+ private async persistDraft(
503
+ storage: StorageManager,
504
+ input: {
505
+ title: string;
506
+ statement: string;
507
+ category: SupportPassportCardCategory;
508
+ reviewBy?: string;
509
+ sourceMemoryIds: string[];
510
+ supersedes?: string;
511
+ replacesDraftId?: string;
512
+ replacedRevision?: string;
513
+ order: number;
514
+ draftReplacementPrepared?: boolean;
515
+ generatedBatch?: { batchId: string; size: number };
516
+ onPersisted?: (card: StoredSupportPassportCard) => void;
517
+ onCommitted?: () => void;
518
+ },
519
+ lock: HeldFileLockController,
520
+ principal: string,
521
+ namespace: string
522
+ ): Promise<SupportPassportCard> {
523
+ const now = this.now();
524
+ const reviewBy = input.reviewBy ?? now.toISOString();
525
+ const order = input.order;
526
+ if (!Number.isSafeInteger(order)) {
527
+ throw new SupportPassportError("storage_conflict", "The support card order range is exhausted.", 409);
528
+ }
529
+ const envelope = composeMemoryEnvelope(
530
+ {
531
+ content: input.statement,
532
+ category: "preference",
533
+ tags: [SUPPORT_PASSPORT_CARD_TAG],
534
+ structuredAttributes: {
535
+ ...encodeSupportPassportNamespaceAttributes(namespace),
536
+ [SUPPORT_PASSPORT_ATTRIBUTE_KEYS.owner]: computeSupportPassportOwnerKey(principal),
537
+ [SUPPORT_PASSPORT_ATTRIBUTE_KEYS.title]: input.title,
538
+ [SUPPORT_PASSPORT_ATTRIBUTE_KEYS.category]: input.category,
539
+ [SUPPORT_PASSPORT_ATTRIBUTE_KEYS.order]: String(order),
540
+ [SUPPORT_PASSPORT_ATTRIBUTE_KEYS.reviewBy]: reviewBy,
541
+ ...(input.replacesDraftId
542
+ ? {
543
+ [SUPPORT_PASSPORT_ATTRIBUTE_KEYS.replacesDraftId]: input.replacesDraftId,
544
+ }
545
+ : {}),
546
+ ...(input.replacedRevision
547
+ ? {
548
+ [SUPPORT_PASSPORT_ATTRIBUTE_KEYS.replacedRevision]: input.replacedRevision,
549
+ }
550
+ : {}),
551
+ ...(input.draftReplacementPrepared
552
+ ? {
553
+ [SUPPORT_PASSPORT_ATTRIBUTE_KEYS.draftReplacementPrepared]: "true",
554
+ }
555
+ : {}),
556
+ ...(input.generatedBatch
557
+ ? {
558
+ [SUPPORT_PASSPORT_ATTRIBUTE_KEYS.generatedBatchId]: input.generatedBatch.batchId,
559
+ [SUPPORT_PASSPORT_ATTRIBUTE_KEYS.generatedBatchSize]: String(input.generatedBatch.size),
560
+ }
561
+ : {}),
562
+ },
563
+ sourceReason: "support-passport",
564
+ },
565
+ { source: "support-passport", now: this.now }
566
+ );
567
+ if (envelope.sanitizeViolations.length > 0) throw invalidInput();
568
+ await this.requireOwnerLock(lock);
569
+ const written = await storage.writeSealedMemory(envelope, {
570
+ actor: principal,
571
+ status: "pending_review",
572
+ lineage: input.sourceMemoryIds.length > 0 ? input.sourceMemoryIds : undefined,
573
+ supersedes: input.supersedes,
574
+ });
575
+ if (written.tombstoneBlocked) {
576
+ throw new SupportPassportError("storage_conflict", "The support card needs memory review before use.", 409);
577
+ }
578
+ const stored = projectRequiredCard(written.memory, namespace, principal);
579
+ input.onPersisted?.(stored);
580
+ if (!input.generatedBatch) input.onCommitted?.();
581
+ return stored.card;
582
+ }
583
+
584
+ private async changeStatus(
585
+ input: SupportPassportCardMutationInput,
586
+ expectedStatus: "pending_review" | "active",
587
+ nextStatus: "rejected" | "archived",
588
+ defaultReasonCode: string,
589
+ options: { signal?: AbortSignal; onCommitted?: () => void }
590
+ ): Promise<SupportPassportCard> {
591
+ const parsed = SupportPassportCardMutationInputSchema.safeParse(input);
592
+ if (!parsed.success) throw invalidInput();
593
+ const { principal, namespace, storage } = await this.resolveOwnerScope(parsed.data.principal);
594
+ const onCommitted = once(options.onCommitted);
595
+ return await withSupportPassportOwnerLock(storage, { namespace, principal }, async (lock) => {
596
+ options.signal?.throwIfAborted();
597
+ let card = await this.requireCard(storage, parsed.data.cardId, namespace, principal);
598
+ requireRevision(card, parsed.data.expectedRevision);
599
+ requireStatus(card, expectedStatus);
600
+ if (expectedStatus === "pending_review" && nextStatus === "rejected") {
601
+ await this.rejectPendingReplacementForPredecessor(storage, card, lock, principal, namespace, onCommitted);
602
+ card = await this.requireCard(storage, card.card.cardId, namespace, principal);
603
+ requireRevision(card, parsed.data.expectedRevision);
604
+ requireStatus(card, expectedStatus);
605
+ }
606
+ if (
607
+ expectedStatus === "pending_review" ||
608
+ (expectedStatus === "active" && (card.replacesDraftId || card.memory.frontmatter.supersedes))
609
+ ) {
610
+ card = projectRequiredCard(
611
+ await this.recoverReplacementTransition(
612
+ storage,
613
+ card.memory,
614
+ lock,
615
+ principal,
616
+ namespace,
617
+ {
618
+ rollbackConflictedApproval: expectedStatus !== "active",
619
+ },
620
+ onCommitted
621
+ ),
622
+ namespace,
623
+ principal
624
+ );
625
+ }
626
+ if (card.card.status === nextStatus) return card.card;
627
+ requireStatus(card, expectedStatus);
628
+ if (expectedStatus === "active" && nextStatus === "archived") {
629
+ await this.rejectPendingReplacementForPredecessor(storage, card, lock, principal, namespace, onCommitted);
630
+ card = await this.requireCard(storage, card.card.cardId, namespace, principal);
631
+ requireRevision(card, parsed.data.expectedRevision);
632
+ requireStatus(card, expectedStatus);
633
+ }
634
+ const updatedAt = this.now().toISOString();
635
+ await this.requireOwnerLock(lock);
636
+ const changed = await storage.writeMemoryFrontmatterIfUnchanged(
637
+ card.memory,
638
+ {
639
+ status: nextStatus,
640
+ updated: updatedAt,
641
+ ...(nextStatus === "archived" ? { archivedAt: updatedAt } : {}),
642
+ },
643
+ {
644
+ actor: principal,
645
+ reasonCode: parsed.data.reasonCode ?? defaultReasonCode,
646
+ }
647
+ );
648
+ if (!changed)
649
+ throw new SupportPassportError(
650
+ "storage_conflict",
651
+ "The support card changed before the request completed.",
652
+ 409
653
+ );
654
+ onCommitted();
655
+ return {
656
+ ...card.card,
657
+ status: nextStatus,
658
+ updatedAt,
659
+ revision: revisionFor(card.card, nextStatus, updatedAt),
660
+ };
661
+ });
662
+ }
663
+
664
+ private async resolveOwnerScope(principal: string): Promise<SupportPassportOwnerScope> {
665
+ const owner = await this.resolveOwner(principal);
666
+ return validateOwnerScope(owner, principal);
667
+ }
668
+
669
+ private async rejectCreatedDraft(
670
+ storage: StorageManager,
671
+ cardId: string,
672
+ reasonCode: string,
673
+ lock: HeldFileLockController,
674
+ principal: string,
675
+ namespace: string,
676
+ onCommitted?: () => void
677
+ ): Promise<void> {
678
+ try {
679
+ const current = await this.requireCard(storage, cardId, namespace, principal);
680
+ await this.requireOwnerLock(lock);
681
+ const rejected = await storage.writeMemoryFrontmatterIfUnchanged(
682
+ current.memory,
683
+ { status: "rejected", updated: this.now().toISOString() },
684
+ { actor: principal, reasonCode }
685
+ );
686
+ if (rejected) onCommitted?.();
687
+ else log.warn("support passport could not roll back a replacement draft");
688
+ } catch (error) {
689
+ log.warn(
690
+ `support passport could not roll back a replacement draft: ${error instanceof Error ? error.message : String(error)}`
691
+ );
692
+ }
693
+ }
694
+
695
+ private async rejectGeneratedDraft(
696
+ storage: StorageManager,
697
+ cardId: string,
698
+ lock: HeldFileLockController,
699
+ principal: string,
700
+ namespace: string
701
+ ): Promise<boolean> {
702
+ for (let attempt = 0; attempt < 2; attempt += 1) {
703
+ const memory = await storage.getMemoryById(cardId);
704
+ if (!memory) return true;
705
+ const stored = projectOwnedCard(memory, namespace, principal);
706
+ if (!stored) return false;
707
+ if (stored.card.status === "rejected") return true;
708
+ if (stored.card.status !== "pending_review") return false;
709
+ await this.requireOwnerLock(lock);
710
+ const rejected = await storage.writeMemoryFrontmatterIfUnchanged(
711
+ memory,
712
+ { status: "rejected", updated: this.now().toISOString() },
713
+ { actor: principal, reasonCode: "draft-batch-failed" }
714
+ );
715
+ if (rejected) return true;
716
+ }
717
+ return false;
718
+ }
719
+
720
+ private async readStoredCards(
721
+ storage: StorageManager,
722
+ lock: HeldFileLockController,
723
+ principal: string,
724
+ namespace: string,
725
+ onCommitted?: () => void
726
+ ): Promise<StoredSupportPassportCard[]> {
727
+ const initialVersion = storage.getCorpusScanVersion();
728
+ const initial = await storage.readAllMemories();
729
+ await recoverSupportPassportGeneratedBatches(
730
+ this.generatedBatchContext(storage, lock, principal, namespace, onCommitted),
731
+ initial
732
+ );
733
+ for (const memory of initial) {
734
+ const card = projectOwnedCard(memory, namespace, principal);
735
+ if (card) {
736
+ await this.recoverReplacementTransition(storage, memory, lock, principal, namespace, {}, onCommitted);
737
+ }
738
+ }
739
+ const memories: MemoryFile[] =
740
+ storage.getCorpusScanVersion() === initialVersion ? initial : await storage.readAllMemories();
741
+ return await projectCommittedSupportPassportCards(storage, memories, namespace, principal);
742
+ }
743
+
744
+ private generatedBatchContext(
745
+ storage: StorageManager,
746
+ lock: HeldFileLockController,
747
+ principal: string,
748
+ namespace: string,
749
+ onCommitted?: () => void
750
+ ) {
751
+ return {
752
+ storage,
753
+ principal,
754
+ namespace,
755
+ now: this.now,
756
+ requireOwnerLock: async () => await this.requireOwnerLock(lock),
757
+ ...(onCommitted ? { onCommitted } : {}),
758
+ };
759
+ }
760
+
761
+ private async rejectPendingReplacementForPredecessor(
762
+ storage: StorageManager,
763
+ predecessor: StoredSupportPassportCard,
764
+ lock: HeldFileLockController,
765
+ principal: string,
766
+ namespace: string,
767
+ onCommitted?: () => void
768
+ ): Promise<void> {
769
+ const storedCards =
770
+ predecessor.card.status === "active"
771
+ ? await this.readStoredCards(storage, lock, principal, namespace, onCommitted)
772
+ : await readCommittedSupportPassportCards(storage, namespace, principal);
773
+ const replacements = storedCards.filter((item) => {
774
+ if (item.card.status !== "pending_review") return false;
775
+ return predecessor.card.status === "pending_review"
776
+ ? item.replacesDraftId === predecessor.card.cardId
777
+ : item.memory.frontmatter.supersedes === predecessor.card.cardId;
778
+ });
779
+ if (replacements.length > 1) {
780
+ throw new SupportPassportError(
781
+ "storage_conflict",
782
+ "Multiple support card edits target the card being withdrawn.",
783
+ 409
784
+ );
785
+ }
786
+ const [replacement] = replacements;
787
+ if (!replacement) return;
788
+ await this.requireOwnerLock(lock);
789
+ const rejected = await storage.writeMemoryFrontmatterIfUnchanged(
790
+ replacement.memory,
791
+ { status: "rejected", updated: this.now().toISOString() },
792
+ {
793
+ actor: principal,
794
+ reasonCode: predecessor.card.status === "pending_review" ? "source-draft-rejected" : "predecessor-withdrawn",
795
+ }
796
+ );
797
+ if (rejected) {
798
+ onCommitted?.();
799
+ return;
800
+ }
801
+ const current = await storage.getMemoryById(replacement.card.cardId);
802
+ const currentCard = current ? projectOwnedCard(current, namespace, principal) : null;
803
+ if (currentCard?.card.status !== "rejected") {
804
+ throw new SupportPassportError("storage_conflict", "The pending support card edit could not be cancelled.", 409);
805
+ }
806
+ }
807
+
808
+ private async recoverReplacementTransition(
809
+ storage: StorageManager,
810
+ memory: MemoryFile,
811
+ lock: HeldFileLockController,
812
+ principal: string,
813
+ namespace: string,
814
+ options: { rollbackConflictedApproval?: boolean } = {},
815
+ onCommitted?: () => void
816
+ ): Promise<MemoryFile> {
817
+ const replacement = projectOwnedCard(memory, namespace, principal);
818
+ if (replacement?.card.status !== "pending_review" && replacement?.card.status !== "active") return memory;
819
+ if (!replacement.replacesDraftId && !memory.frontmatter.supersedes) return memory;
820
+ if (
821
+ replacement.card.status === "active" &&
822
+ memory.frontmatter.structuredAttributes?.[SUPPORT_PASSPORT_ATTRIBUTE_KEYS.replacementComplete] === "true"
823
+ ) {
824
+ return memory;
825
+ }
826
+ await this.recoverReplacedDraft(storage, replacement, lock, principal, namespace, onCommitted);
827
+ const currentMemory = (await storage.getMemoryById(replacement.card.cardId)) ?? memory;
828
+ const currentCard = projectOwnedCard(currentMemory, namespace, principal);
829
+ if (currentCard?.card.status !== "pending_review" && currentCard?.card.status !== "active") {
830
+ return currentMemory;
831
+ }
832
+ if (currentCard.card.status === "pending_review") {
833
+ const priorId = currentMemory.frontmatter.supersedes;
834
+ if (!priorId) return currentMemory;
835
+ const prior = await storage.getMemoryById(priorId);
836
+ if (
837
+ prior &&
838
+ ownsMemory(prior, namespace, principal) &&
839
+ prior.frontmatter.status === "superseded" &&
840
+ prior.frontmatter.supersededBy === replacement.card.cardId
841
+ ) {
842
+ await this.restorePriorAfterApprovalFailure(
843
+ storage,
844
+ priorId,
845
+ replacement.card.cardId,
846
+ lock,
847
+ principal,
848
+ namespace,
849
+ onCommitted
850
+ );
851
+ }
852
+ return (await storage.getMemoryById(replacement.card.cardId)) ?? currentMemory;
853
+ }
854
+ try {
855
+ await this.completeReplacementAfterActivation(storage, currentCard, lock, principal, namespace, onCommitted);
856
+ } catch (error) {
857
+ if (!isStorageConflict(error)) throw error;
858
+ if (options.rollbackConflictedApproval === false) throw error;
859
+ await this.rollbackConflictedApproval(storage, currentCard.card.cardId, lock, principal, namespace, onCommitted);
860
+ }
861
+ return (await storage.getMemoryById(replacement.card.cardId)) ?? currentMemory;
862
+ }
863
+
864
+ private async completeReplacementAfterActivation(
865
+ storage: StorageManager,
866
+ replacement: StoredSupportPassportCard,
867
+ lock: HeldFileLockController,
868
+ principal: string,
869
+ namespace: string,
870
+ onCommitted?: () => void
871
+ ): Promise<void> {
872
+ const priorId = await prepareSupportPassportReplacementPrior({
873
+ storage,
874
+ replacement,
875
+ principal,
876
+ namespace,
877
+ now: this.now,
878
+ requireOwnerLock: () => this.requireOwnerLock(lock),
879
+ onCommitted,
880
+ });
881
+ if (
882
+ priorId &&
883
+ !(await completeSupportPassportReplacementPrior({
884
+ storage,
885
+ priorId,
886
+ replacement,
887
+ principal,
888
+ namespace,
889
+ requireOwnerLock: () => this.requireOwnerLock(lock),
890
+ }))
891
+ ) {
892
+ throw new SupportPassportError("storage_conflict", "The prior support card changed before replacement.", 409);
893
+ }
894
+ if (priorId) onCommitted?.();
895
+ await this.markReplacementComplete(storage, replacement.card.cardId, lock, principal, namespace, onCommitted);
896
+ }
897
+
898
+ private async finishCommittedApproval(
899
+ storage: StorageManager,
900
+ replacement: StoredSupportPassportCard,
901
+ lock: HeldFileLockController,
902
+ principal: string,
903
+ namespace: string,
904
+ onCommitted?: () => void
905
+ ): Promise<SupportPassportCard> {
906
+ try {
907
+ if (replacement.replacesDraftId || replacement.memory.frontmatter.supersedes) {
908
+ await this.completeReplacementAfterActivation(storage, replacement, lock, principal, namespace, onCommitted);
909
+ }
910
+ } catch (error) {
911
+ if (isStorageConflict(error)) {
912
+ await this.rollbackConflictedApproval(
913
+ storage,
914
+ replacement.card.cardId,
915
+ lock,
916
+ principal,
917
+ namespace,
918
+ onCommitted
919
+ );
920
+ throw error;
921
+ }
922
+ log.warn(
923
+ `support passport could not finish replacement approval side effects: ${error instanceof Error ? error.message : String(error)}`
924
+ );
925
+ }
926
+ return replacement.card;
927
+ }
928
+
929
+ private async rollbackConflictedApproval(
930
+ storage: StorageManager,
931
+ replacementId: string,
932
+ lock: HeldFileLockController,
933
+ principal: string,
934
+ namespace: string,
935
+ onCommitted?: () => void
936
+ ): Promise<void> {
937
+ const replacement = await this.requireCard(storage, replacementId, namespace, principal);
938
+ if (replacement.card.status !== "active") return;
939
+ await this.requireOwnerLock(lock);
940
+ const rolledBack = await storage.writeMemoryFrontmatterIfUnchanged(
941
+ replacement.memory,
942
+ { status: "pending_review", updated: this.now().toISOString() },
943
+ { actor: principal, reasonCode: "replacement-predecessor-conflict" }
944
+ );
945
+ if (!rolledBack) {
946
+ throw new SupportPassportError(
947
+ "storage_conflict",
948
+ "The replacement changed while its approval was rolled back.",
949
+ 409
950
+ );
951
+ }
952
+ onCommitted?.();
953
+ const priorId = replacement.memory.frontmatter.supersedes;
954
+ if (priorId) {
955
+ await this.restorePriorAfterApprovalFailure(
956
+ storage,
957
+ priorId,
958
+ replacementId,
959
+ lock,
960
+ principal,
961
+ namespace,
962
+ onCommitted
963
+ );
964
+ }
965
+ }
966
+
967
+ private async recoverReplacedDraft(
968
+ storage: StorageManager,
969
+ replacement: StoredSupportPassportCard,
970
+ lock: HeldFileLockController,
971
+ principal: string,
972
+ namespace: string,
973
+ onCommitted?: () => void
974
+ ): Promise<void> {
975
+ if (!replacement.replacesDraftId) return;
976
+ const replacedDraft = await storage.getMemoryById(replacement.replacesDraftId);
977
+ const projectedDraft = replacedDraft ? projectOwnedCard(replacedDraft, namespace, principal) : null;
978
+ if (
979
+ replacedDraft &&
980
+ projectedDraft?.card.status === "pending_review" &&
981
+ projectedDraft.card.revision === replacement.replacedRevision
982
+ ) {
983
+ await this.requireOwnerLock(lock);
984
+ const rejected = await storage.writeMemoryFrontmatterIfUnchanged(
985
+ replacedDraft,
986
+ { status: "rejected", updated: this.now().toISOString() },
987
+ { actor: principal, reasonCode: "complete-draft-replacement" }
988
+ );
989
+ if (rejected) {
990
+ onCommitted?.();
991
+ await this.finishPreparedDraftReplacement(
992
+ storage,
993
+ replacement.card.cardId,
994
+ lock,
995
+ principal,
996
+ namespace,
997
+ onCommitted
998
+ );
999
+ return;
1000
+ }
1001
+ }
1002
+ const currentDraft = await storage.getMemoryById(replacement.replacesDraftId);
1003
+ if (
1004
+ currentDraft &&
1005
+ ownsMemory(currentDraft, namespace, principal) &&
1006
+ currentDraft.frontmatter.status === "rejected"
1007
+ ) {
1008
+ await this.finishPreparedDraftReplacement(
1009
+ storage,
1010
+ replacement.card.cardId,
1011
+ lock,
1012
+ principal,
1013
+ namespace,
1014
+ onCommitted
1015
+ );
1016
+ return;
1017
+ }
1018
+ if (
1019
+ currentDraft &&
1020
+ ownsMemory(currentDraft, namespace, principal) &&
1021
+ currentDraft.frontmatter.status === "pending_review"
1022
+ ) {
1023
+ throw new SupportPassportError("storage_conflict", "The replaced draft changed during recovery.", 409);
1024
+ }
1025
+ await this.rejectOrphanedReplacement(storage, replacement.card.cardId, lock, principal, namespace, onCommitted);
1026
+ }
1027
+
1028
+ private async finishPreparedDraftReplacement(
1029
+ storage: StorageManager,
1030
+ replacementId: string,
1031
+ lock: HeldFileLockController,
1032
+ principal: string,
1033
+ namespace: string,
1034
+ onCommitted?: () => void
1035
+ ): Promise<SupportPassportCard> {
1036
+ const replacement = await this.requireCard(storage, replacementId, namespace, principal);
1037
+ if (!replacement.draftReplacementPrepared) return replacement.card;
1038
+ const structuredAttributes = {
1039
+ ...replacement.memory.frontmatter.structuredAttributes,
1040
+ };
1041
+ delete structuredAttributes[SUPPORT_PASSPORT_ATTRIBUTE_KEYS.draftReplacementPrepared];
1042
+ await this.requireOwnerLock(lock);
1043
+ const finished = await storage.writeMemoryFrontmatterIfUnchanged(
1044
+ replacement.memory,
1045
+ { structuredAttributes },
1046
+ { actor: principal, reasonCode: "draft-replacement-complete" }
1047
+ );
1048
+ if (finished) {
1049
+ onCommitted?.();
1050
+ return projectRequiredCard(
1051
+ {
1052
+ ...replacement.memory,
1053
+ frontmatter: {
1054
+ ...replacement.memory.frontmatter,
1055
+ structuredAttributes,
1056
+ },
1057
+ },
1058
+ namespace,
1059
+ principal
1060
+ ).card;
1061
+ }
1062
+ const current = await this.requireCard(storage, replacementId, namespace, principal);
1063
+ if (!current.draftReplacementPrepared) return current.card;
1064
+ throw new SupportPassportError("storage_conflict", "The support card edit could not be completed.", 409);
1065
+ }
1066
+
1067
+ private async rejectOrphanedReplacement(
1068
+ storage: StorageManager,
1069
+ replacementId: string,
1070
+ lock: HeldFileLockController,
1071
+ principal: string,
1072
+ namespace: string,
1073
+ onCommitted?: () => void
1074
+ ): Promise<void> {
1075
+ const currentReplacement = await this.requireCard(storage, replacementId, namespace, principal);
1076
+ if (currentReplacement.card.status === "rejected") return;
1077
+ requireStatus(currentReplacement, "pending_review");
1078
+ await this.requireOwnerLock(lock);
1079
+ const rejected = await storage.writeMemoryFrontmatterIfUnchanged(
1080
+ currentReplacement.memory,
1081
+ { status: "rejected", updated: this.now().toISOString() },
1082
+ { actor: principal, reasonCode: "replaced-draft-approved" }
1083
+ );
1084
+ if (rejected) {
1085
+ onCommitted?.();
1086
+ return;
1087
+ }
1088
+ const latest = await storage.getMemoryById(replacementId);
1089
+ if (latest?.frontmatter.status !== "rejected") {
1090
+ throw new SupportPassportError("storage_conflict", "The orphaned replacement could not be rejected.", 409);
1091
+ }
1092
+ }
1093
+
1094
+ private async restorePriorAfterApprovalFailure(
1095
+ storage: StorageManager,
1096
+ priorId: string,
1097
+ replacementId: string,
1098
+ lock: HeldFileLockController,
1099
+ principal: string,
1100
+ namespace: string,
1101
+ onCommitted?: () => void
1102
+ ): Promise<void> {
1103
+ const replacement = await storage.getMemoryById(replacementId);
1104
+ if (replacement && !ownsMemory(replacement, namespace, principal)) {
1105
+ throw new SupportPassportError("storage_conflict", "The replacement support card changed ownership.", 409);
1106
+ }
1107
+ if (replacement?.frontmatter.status === "active") return;
1108
+ const prior = await storage.getMemoryById(priorId);
1109
+ if (prior && !ownsMemory(prior, namespace, principal)) {
1110
+ throw new SupportPassportError("storage_conflict", "The prior support card changed ownership.", 409);
1111
+ }
1112
+ if (prior?.frontmatter.status === "active" && prior.frontmatter.supersededBy === undefined) return;
1113
+ if (prior?.frontmatter.status !== "superseded" || prior.frontmatter.supersededBy !== replacementId) {
1114
+ throw new SupportPassportError("storage_conflict", "The prior support card could not be restored.", 409);
1115
+ }
1116
+ await this.requireOwnerLock(lock);
1117
+ const restored = await storage.writeMemoryFrontmatterIfUnchanged(
1118
+ prior,
1119
+ {
1120
+ status: "active",
1121
+ supersededBy: undefined,
1122
+ supersededAt: undefined,
1123
+ supersessionCause: undefined,
1124
+ invalidatedBy: undefined,
1125
+ updated: this.now().toISOString(),
1126
+ },
1127
+ { actor: principal, reasonCode: "replacement-activation-failed" }
1128
+ );
1129
+ if (restored) {
1130
+ onCommitted?.();
1131
+ return;
1132
+ }
1133
+ const currentPrior = await storage.getMemoryById(priorId);
1134
+ if (currentPrior?.frontmatter.status === "active" && currentPrior.frontmatter.supersededBy === undefined) return;
1135
+ throw new SupportPassportError("storage_conflict", "The prior support card could not be restored.", 409);
1136
+ }
1137
+
1138
+ private async markReplacementComplete(
1139
+ storage: StorageManager,
1140
+ replacementId: string,
1141
+ lock: HeldFileLockController,
1142
+ principal: string,
1143
+ namespace: string,
1144
+ onCommitted?: () => void
1145
+ ): Promise<void> {
1146
+ const replacement = await this.requireCard(storage, replacementId, namespace, principal);
1147
+ if (
1148
+ replacement.memory.frontmatter.structuredAttributes?.[SUPPORT_PASSPORT_ATTRIBUTE_KEYS.replacementComplete] ===
1149
+ "true"
1150
+ ) {
1151
+ return;
1152
+ }
1153
+ await this.requireOwnerLock(lock);
1154
+ const marked = await storage.writeMemoryFrontmatterIfUnchanged(
1155
+ replacement.memory,
1156
+ {
1157
+ structuredAttributes: {
1158
+ ...replacement.memory.frontmatter.structuredAttributes,
1159
+ [SUPPORT_PASSPORT_ATTRIBUTE_KEYS.replacementComplete]: "true",
1160
+ },
1161
+ },
1162
+ { actor: principal, reasonCode: "replacement-side-effects-complete" }
1163
+ );
1164
+ if (marked) onCommitted?.();
1165
+ else log.warn("support passport could not mark replacement side effects complete");
1166
+ }
1167
+
1168
+ private async requireOwnerLock(lock: HeldFileLockController): Promise<void> {
1169
+ if (await lock.refresh()) return;
1170
+ throw new SupportPassportError("storage_conflict", "The support passport lock changed. Try again.", 409);
1171
+ }
1172
+
1173
+ private async requireCard(
1174
+ storage: StorageManager,
1175
+ cardId: string,
1176
+ namespace: string,
1177
+ principal: string
1178
+ ): Promise<StoredSupportPassportCard> {
1179
+ const memory = await storage.getMemoryById(cardId);
1180
+ const card = memory ? projectOwnedCard(memory, namespace, principal) : null;
1181
+ if (card && (await isCommittedGeneratedCard(storage, card))) return card;
1182
+ throw new SupportPassportError("card_not_found", "The support card was not found.", 404);
1183
+ }
1184
+ }