@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,185 @@
1
+ import assert from "node:assert/strict";
2
+ import { chmod, mkdir, mkdtemp, readFile, rm, stat, writeFile } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import path from "node:path";
5
+ import { test } from "node:test";
6
+
7
+ import { StorageManager } from "../storage.js";
8
+ import type { StoredSupportPassportCard } from "./card-projection.js";
9
+ import { computeSupportPassportOwnerKey } from "./card-projection.js";
10
+ import { SupportPassportCardService } from "./card-service.js";
11
+ import { SupportPassportError } from "./errors.js";
12
+ import {
13
+ commitSupportPassportGeneratedBatch,
14
+ persistSupportPassportGeneratedBatchMarker,
15
+ rollbackSupportPassportGeneratedBatch,
16
+ } from "./generated-batch.js";
17
+
18
+ test("generated batch setup hardens an existing writable directory", async () => {
19
+ StorageManager.clearAllStaticCaches();
20
+ const root = await mkdtemp(path.join(tmpdir(), "remnic-support-passport-batch-mode-"));
21
+ const storage = new StorageManager(path.join(root, "shared"));
22
+ await storage.ensureDirectories();
23
+ const batchRoot = path.join(storage.dir, "state", "support-passport", "generated-batches");
24
+ await mkdir(batchRoot, { recursive: true, mode: 0o777 });
25
+ await chmod(batchRoot, 0o777);
26
+
27
+ try {
28
+ await persistSupportPassportGeneratedBatchMarker(
29
+ {
30
+ storage,
31
+ principal: "owner:alice",
32
+ namespace: "team",
33
+ now: () => new Date("2026-08-13T12:00:00.000Z"),
34
+ requireOwnerLock: async () => undefined,
35
+ },
36
+ "00000000-0000-4000-8000-000000000000",
37
+ 1
38
+ );
39
+
40
+ assert.equal((await stat(batchRoot)).mode & 0o777, 0o700);
41
+ } finally {
42
+ StorageManager.clearAllStaticCaches();
43
+ await rm(root, { recursive: true, force: true });
44
+ }
45
+ });
46
+
47
+ test("a visible generated batch marker reconciles its durability error as success", async () => {
48
+ StorageManager.clearAllStaticCaches();
49
+ const root = await mkdtemp(path.join(tmpdir(), "remnic-support-passport-batch-durability-"));
50
+ const storage = new StorageManager(path.join(root, "shared"));
51
+ await storage.ensureDirectories();
52
+ const principal = "owner:alice";
53
+ const namespace = "team";
54
+ const context = {
55
+ storage,
56
+ principal,
57
+ namespace,
58
+ now: () => new Date("2026-08-13T12:00:00.000Z"),
59
+ requireOwnerLock: async () => undefined,
60
+ };
61
+ const batchId = "00000000-0000-4000-8000-000000000001";
62
+
63
+ try {
64
+ const marker = await persistSupportPassportGeneratedBatchMarker(context, batchId, 1);
65
+ const markerPath = path.join(storage.dir, "state", "support-passport", "generated-batches", `${batchId}.json`);
66
+ const card = {
67
+ namespace,
68
+ owner: computeSupportPassportOwnerKey(principal),
69
+ generatedBatchId: batchId,
70
+ generatedBatchSize: 1,
71
+ card: { cardId: "00000000-0000-4000-8000-000000000002", status: "pending_review" },
72
+ } as StoredSupportPassportCard;
73
+ const durabilityError = Object.assign(new Error("simulated directory sync failure"), { code: "EIO" });
74
+
75
+ await commitSupportPassportGeneratedBatch(context, marker, [card], async (_storage, committed) => {
76
+ await writeFile(markerPath, `${JSON.stringify(committed)}\n`, "utf8");
77
+ throw durabilityError;
78
+ });
79
+ assert.equal((JSON.parse(await readFile(markerPath, "utf8")) as { complete: boolean }).complete, true);
80
+ assert.equal(await rollbackSupportPassportGeneratedBatch(context, batchId, [card.card.cardId]), false);
81
+ assert.equal((JSON.parse(await readFile(markerPath, "utf8")) as { complete: boolean }).complete, true);
82
+ } finally {
83
+ StorageManager.clearAllStaticCaches();
84
+ await rm(root, { recursive: true, force: true });
85
+ }
86
+ });
87
+
88
+ test("generated batch recovery reads only markers referenced by the requested owner", async () => {
89
+ StorageManager.clearAllStaticCaches();
90
+ const root = await mkdtemp(path.join(tmpdir(), "remnic-support-passport-batches-"));
91
+ const storage = new StorageManager(path.join(root, "shared"));
92
+ await storage.ensureDirectories();
93
+ const service = new SupportPassportCardService({
94
+ resolveOwner: async (principal) => ({ principal, namespace: "team", storage }),
95
+ });
96
+
97
+ try {
98
+ const cards = new Map<string, Awaited<ReturnType<typeof service.createGeneratedDrafts>>>();
99
+ for (const principal of ["owner:alice", "owner:bob"]) {
100
+ cards.set(
101
+ principal,
102
+ await service.createGeneratedDrafts({
103
+ principal,
104
+ cards: [
105
+ {
106
+ title: `${principal} support`,
107
+ statement: "Give me time to answer.",
108
+ category: "communication",
109
+ sourceMemoryIds: ["source-1"],
110
+ },
111
+ ],
112
+ })
113
+ );
114
+ }
115
+
116
+ const markerRoot = path.join(storage.dir, "state", "support-passport", "generated-batches");
117
+ const [bobCard] = cards.get("owner:bob") ?? [];
118
+ assert.ok(bobCard);
119
+ const bobMemory = await storage.getMemoryById(bobCard.cardId);
120
+ const bobBatchId = bobMemory?.frontmatter.structuredAttributes?.["support-passport-generated-batch-id"];
121
+ assert.ok(bobBatchId);
122
+ const bobMarkerPath = path.join(markerRoot, `${bobBatchId}.json`);
123
+ await writeFile(bobMarkerPath, "not-json\n", "utf8");
124
+
125
+ assert.equal((await service.listCards({ principal: "owner:alice" })).length, 1);
126
+ await assert.rejects(
127
+ service.listCards({ principal: "owner:bob" }),
128
+ (error: unknown) => error instanceof SupportPassportError && error.code === "card_data_invalid"
129
+ );
130
+ } finally {
131
+ StorageManager.clearAllStaticCaches();
132
+ await rm(root, { recursive: true, force: true });
133
+ }
134
+ });
135
+
136
+ test("a missing marker hides an approved generated card without blocking manual cards", async () => {
137
+ StorageManager.clearAllStaticCaches();
138
+ const root = await mkdtemp(path.join(tmpdir(), "remnic-support-passport-missing-batch-"));
139
+ const storage = new StorageManager(path.join(root, "shared"));
140
+ await storage.ensureDirectories();
141
+ const principal = "owner:alice";
142
+ const service = new SupportPassportCardService({
143
+ resolveOwner: async () => ({ principal, namespace: "team", storage }),
144
+ });
145
+
146
+ try {
147
+ const manual = await service.createManualDraft({
148
+ principal,
149
+ title: "Manual support",
150
+ statement: "Give me time to answer.",
151
+ category: "communication",
152
+ reviewBy: "2026-09-01T00:00:00.000Z",
153
+ });
154
+ const [generated] = await service.createGeneratedDrafts({
155
+ principal,
156
+ cards: [
157
+ {
158
+ title: "Generated support",
159
+ statement: "Tell me before plans change.",
160
+ category: "transitions",
161
+ sourceMemoryIds: ["source-1"],
162
+ },
163
+ ],
164
+ });
165
+ assert.ok(generated);
166
+ await service.approveCard({
167
+ principal,
168
+ cardId: generated.cardId,
169
+ expectedRevision: generated.revision,
170
+ });
171
+
172
+ const memory = await storage.getMemoryById(generated.cardId);
173
+ const batchId = memory?.frontmatter.structuredAttributes?.["support-passport-generated-batch-id"];
174
+ assert.equal(typeof batchId, "string");
175
+ await rm(path.join(storage.dir, "state", "support-passport", "generated-batches", `${batchId}.json`));
176
+
177
+ assert.deepEqual(
178
+ (await service.listCards({ principal })).map((card) => card.cardId),
179
+ [manual.cardId],
180
+ );
181
+ } finally {
182
+ StorageManager.clearAllStaticCaches();
183
+ await rm(root, { recursive: true, force: true });
184
+ }
185
+ });
@@ -0,0 +1,338 @@
1
+ import path from "node:path";
2
+
3
+ import { z } from "zod";
4
+
5
+ import type { StorageManager } from "../index.js";
6
+ import type { MemoryFile } from "../types.js";
7
+ import {
8
+ type StoredSupportPassportCard,
9
+ computeSupportPassportOwnerKey,
10
+ projectSupportPassportCard,
11
+ } from "./card-projection.js";
12
+ import { SupportPassportNamespaceSchema } from "./contracts.js";
13
+ import { SupportPassportError } from "./errors.js";
14
+ import {
15
+ ensurePrivateDirectoryNoFollow,
16
+ ensurePrivateDirectoryTreeNoFollow,
17
+ readPrivateFileNoFollow,
18
+ removePrivateFilesNoFollow,
19
+ writePrivateFileAtomicallyNoFollow,
20
+ } from "./private-file.js";
21
+
22
+ const BatchIdSchema = z
23
+ .string()
24
+ .uuid()
25
+ .transform((value) => value.toLowerCase());
26
+ const GeneratedBatchMarkerSchema = z
27
+ .object({
28
+ schemaVersion: z.literal(1),
29
+ batchId: BatchIdSchema,
30
+ size: z.number().int().min(1).max(8),
31
+ namespace: SupportPassportNamespaceSchema,
32
+ owner: z.string().regex(/^[a-f0-9]{64}$/),
33
+ complete: z.boolean(),
34
+ })
35
+ .strict();
36
+
37
+ export type GeneratedBatchMarker = z.infer<typeof GeneratedBatchMarkerSchema>;
38
+
39
+ export interface GeneratedBatchContext {
40
+ storage: StorageManager;
41
+ principal: string;
42
+ namespace: string;
43
+ now: () => Date;
44
+ requireOwnerLock: () => Promise<void>;
45
+ onCommitted?: () => void;
46
+ }
47
+
48
+ type GeneratedBatchMarkerWriter = (storage: StorageManager, marker: GeneratedBatchMarker) => Promise<void>;
49
+
50
+ const BATCH_ERROR = "The generated draft batch state is not safe.";
51
+
52
+ function batchDirectory(storage: StorageManager): string {
53
+ return path.join(storage.dir, "state", "support-passport", "generated-batches");
54
+ }
55
+
56
+ function batchFileName(batchId: string): string {
57
+ return `${BatchIdSchema.parse(batchId)}.json`;
58
+ }
59
+
60
+ function batchPath(storage: StorageManager, batchId: string): string {
61
+ return path.join(batchDirectory(storage), batchFileName(batchId));
62
+ }
63
+
64
+ function markerFor(context: GeneratedBatchContext, batchId: string, size: number, complete: boolean) {
65
+ return GeneratedBatchMarkerSchema.parse({
66
+ schemaVersion: 1,
67
+ batchId,
68
+ size,
69
+ namespace: context.namespace,
70
+ owner: computeSupportPassportOwnerKey(context.principal),
71
+ complete,
72
+ });
73
+ }
74
+
75
+ function sameOwner(marker: GeneratedBatchMarker, context: GeneratedBatchContext): boolean {
76
+ return marker.namespace === context.namespace && marker.owner === computeSupportPassportOwnerKey(context.principal);
77
+ }
78
+
79
+ async function ensureBatchDirectory(storage: StorageManager): Promise<void> {
80
+ const directory = batchDirectory(storage);
81
+ await ensurePrivateDirectoryTreeNoFollow(directory, BATCH_ERROR);
82
+ await ensurePrivateDirectoryNoFollow(storage.dir, directory, BATCH_ERROR);
83
+ }
84
+
85
+ export async function readSupportPassportGeneratedBatchMarker(
86
+ storage: StorageManager,
87
+ batchId: string
88
+ ): Promise<GeneratedBatchMarker | null> {
89
+ const directory = batchDirectory(storage);
90
+ try {
91
+ const content = await readPrivateFileNoFollow(directory, batchPath(storage, batchId), BATCH_ERROR, storage.dir);
92
+ let value: unknown;
93
+ try {
94
+ value = JSON.parse(content);
95
+ } catch {
96
+ throw new SupportPassportError("card_data_invalid", "The generated draft batch state is invalid.", 500);
97
+ }
98
+ const parsed = GeneratedBatchMarkerSchema.safeParse(value);
99
+ if (!parsed.success || parsed.data.batchId !== BatchIdSchema.parse(batchId)) {
100
+ throw new SupportPassportError("card_data_invalid", "The generated draft batch state is invalid.", 500);
101
+ }
102
+ return parsed.data;
103
+ } catch (error) {
104
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return null;
105
+ throw error;
106
+ }
107
+ }
108
+
109
+ export async function isSupportPassportGeneratedBatchCommitted(
110
+ context: GeneratedBatchContext,
111
+ marker: GeneratedBatchMarker
112
+ ): Promise<boolean> {
113
+ const current = await readSupportPassportGeneratedBatchMarker(context.storage, marker.batchId);
114
+ return Boolean(current?.complete && sameOwner(current, context) && current.size === marker.size);
115
+ }
116
+
117
+ async function writeBatchMarker(storage: StorageManager, marker: GeneratedBatchMarker): Promise<void> {
118
+ const directory = batchDirectory(storage);
119
+ await writePrivateFileAtomicallyNoFollow(
120
+ directory,
121
+ batchPath(storage, marker.batchId),
122
+ `${JSON.stringify(marker)}\n`,
123
+ BATCH_ERROR,
124
+ storage.dir
125
+ );
126
+ }
127
+
128
+ async function removeBatchMarker(storage: StorageManager, batchId: string): Promise<void> {
129
+ await removePrivateFilesNoFollow(batchDirectory(storage), [batchFileName(batchId)], BATCH_ERROR, storage.dir);
130
+ }
131
+
132
+ function projectOwnedCard(memory: MemoryFile, namespace: string, principal: string): StoredSupportPassportCard | null {
133
+ const card = projectSupportPassportCard(memory);
134
+ return card?.namespace === namespace && card.owner === computeSupportPassportOwnerKey(principal) ? card : null;
135
+ }
136
+
137
+ export async function persistSupportPassportGeneratedBatchMarker(
138
+ context: GeneratedBatchContext,
139
+ batchId: string,
140
+ size: number,
141
+ writeMarker: GeneratedBatchMarkerWriter = writeBatchMarker
142
+ ): Promise<GeneratedBatchMarker> {
143
+ const marker = markerFor(context, batchId, size, false);
144
+ await context.requireOwnerLock();
145
+ await ensureBatchDirectory(context.storage);
146
+ await writeMarker(context.storage, marker);
147
+ context.onCommitted?.();
148
+ return marker;
149
+ }
150
+
151
+ export async function commitSupportPassportGeneratedBatch(
152
+ context: GeneratedBatchContext,
153
+ marker: GeneratedBatchMarker,
154
+ cards: readonly StoredSupportPassportCard[],
155
+ writeMarker: GeneratedBatchMarkerWriter = writeBatchMarker
156
+ ): Promise<void> {
157
+ const cardIds = cards.map((card) => card.card.cardId);
158
+ if (!sameOwner(marker, context) || cards.length !== marker.size || new Set(cardIds).size !== cards.length) {
159
+ throw new SupportPassportError("storage_conflict", "The generated draft batch is incomplete.", 409);
160
+ }
161
+ for (const card of cards) {
162
+ if (
163
+ card.namespace !== context.namespace ||
164
+ card.owner !== computeSupportPassportOwnerKey(context.principal) ||
165
+ card.card.status !== "pending_review" ||
166
+ card.generatedBatchId !== marker.batchId ||
167
+ card.generatedBatchSize !== marker.size
168
+ ) {
169
+ throw new SupportPassportError("storage_conflict", "The generated draft batch is incomplete.", 409);
170
+ }
171
+ }
172
+ await context.requireOwnerLock();
173
+ const committed = { ...marker, complete: true };
174
+ try {
175
+ await writeMarker(context.storage, committed);
176
+ } catch (error) {
177
+ if (!(await isSupportPassportGeneratedBatchCommitted(context, marker))) throw error;
178
+ }
179
+ context.onCommitted?.();
180
+ }
181
+
182
+ async function rejectGeneratedDraft(context: GeneratedBatchContext, cardId: string): Promise<boolean> {
183
+ for (let attempt = 0; attempt < 2; attempt += 1) {
184
+ const memory = await context.storage.getMemoryById(cardId);
185
+ if (!memory) return true;
186
+ const stored = projectOwnedCard(memory, context.namespace, context.principal);
187
+ if (!stored) return false;
188
+ if (stored.card.status === "rejected") return true;
189
+ if (stored.card.status !== "pending_review") return false;
190
+ await context.requireOwnerLock();
191
+ if (
192
+ await context.storage.writeMemoryFrontmatterIfUnchanged(
193
+ memory,
194
+ { status: "rejected", updated: context.now().toISOString() },
195
+ { actor: context.principal, reasonCode: "draft-batch-failed" }
196
+ )
197
+ ) {
198
+ context.onCommitted?.();
199
+ return true;
200
+ }
201
+ }
202
+ return false;
203
+ }
204
+
205
+ export async function rollbackSupportPassportGeneratedBatch(
206
+ context: GeneratedBatchContext,
207
+ batchId: string,
208
+ knownCardIds: readonly string[]
209
+ ): Promise<boolean> {
210
+ const marker = await readSupportPassportGeneratedBatchMarker(context.storage, batchId);
211
+ if (marker && !sameOwner(marker, context)) return false;
212
+ if (marker?.complete) return false;
213
+ const cardIds = new Set(knownCardIds);
214
+ let scanComplete = true;
215
+ try {
216
+ for (const memory of await context.storage.readAllMemories()) {
217
+ const card = projectOwnedCard(memory, context.namespace, context.principal);
218
+ if (card?.generatedBatchId === batchId) cardIds.add(card.card.cardId);
219
+ }
220
+ } catch {
221
+ scanComplete = false;
222
+ }
223
+ let complete = scanComplete;
224
+ for (const cardId of cardIds) {
225
+ try {
226
+ if (!(await rejectGeneratedDraft(context, cardId))) complete = false;
227
+ } catch {
228
+ complete = false;
229
+ }
230
+ }
231
+ if (!complete) return false;
232
+ try {
233
+ await removeBatchMarker(context.storage, batchId);
234
+ context.onCommitted?.();
235
+ } catch {
236
+ complete = false;
237
+ }
238
+ return complete;
239
+ }
240
+
241
+ export async function isCommittedGeneratedCard(
242
+ storage: StorageManager,
243
+ card: StoredSupportPassportCard,
244
+ markerCache?: Map<string, GeneratedBatchMarker | null>
245
+ ): Promise<boolean> {
246
+ if (!card.generatedBatchId) return true;
247
+ let marker = markerCache?.get(card.generatedBatchId);
248
+ if (!markerCache?.has(card.generatedBatchId)) {
249
+ marker = await readSupportPassportGeneratedBatchMarker(storage, card.generatedBatchId);
250
+ markerCache?.set(card.generatedBatchId, marker);
251
+ }
252
+ return Boolean(
253
+ marker?.complete &&
254
+ marker.size === card.generatedBatchSize &&
255
+ marker.namespace === card.namespace &&
256
+ marker.owner === card.owner
257
+ );
258
+ }
259
+
260
+ export async function projectCommittedSupportPassportCards(
261
+ storage: StorageManager,
262
+ memories: readonly MemoryFile[],
263
+ namespace: string,
264
+ principal: string
265
+ ): Promise<StoredSupportPassportCard[]> {
266
+ const projected = memories
267
+ .map(projectSupportPassportCard)
268
+ .filter(
269
+ (card): card is StoredSupportPassportCard =>
270
+ card?.namespace === namespace && card.owner === computeSupportPassportOwnerKey(principal)
271
+ );
272
+ const markers = new Map<string, GeneratedBatchMarker | null>();
273
+ const committed: StoredSupportPassportCard[] = [];
274
+ for (const card of projected) {
275
+ if (await isCommittedGeneratedCard(storage, card, markers)) committed.push(card);
276
+ }
277
+ const ids = new Set<string>();
278
+ for (const card of committed) {
279
+ if (ids.has(card.card.cardId)) {
280
+ throw new SupportPassportError("card_data_invalid", "Support card IDs must be unique.", 500);
281
+ }
282
+ ids.add(card.card.cardId);
283
+ }
284
+ return committed;
285
+ }
286
+
287
+ export async function readCommittedSupportPassportCards(
288
+ storage: StorageManager,
289
+ namespace: string,
290
+ principal: string
291
+ ): Promise<StoredSupportPassportCard[]> {
292
+ return await projectCommittedSupportPassportCards(
293
+ storage,
294
+ await storage.readAllMemories(),
295
+ namespace,
296
+ principal
297
+ );
298
+ }
299
+
300
+ export async function recoverSupportPassportGeneratedBatches(
301
+ context: GeneratedBatchContext,
302
+ memories: readonly MemoryFile[]
303
+ ): Promise<void> {
304
+ const cardsByBatch = new Map<string, StoredSupportPassportCard[]>();
305
+ for (const memory of memories) {
306
+ const card = projectOwnedCard(memory, context.namespace, context.principal);
307
+ if (!card?.generatedBatchId) continue;
308
+ const cards = cardsByBatch.get(card.generatedBatchId) ?? [];
309
+ cards.push(card);
310
+ cardsByBatch.set(card.generatedBatchId, cards);
311
+ }
312
+ for (const [batchId, cards] of cardsByBatch) {
313
+ const marker = await readSupportPassportGeneratedBatchMarker(context.storage, batchId);
314
+ if (marker?.complete === true && sameOwner(marker, context)) continue;
315
+ if (!marker) {
316
+ let recovered = true;
317
+ for (const card of cards) {
318
+ if (card.card.status !== "pending_review") continue;
319
+ try {
320
+ if (!(await rejectGeneratedDraft(context, card.card.cardId))) recovered = false;
321
+ } catch {
322
+ recovered = false;
323
+ }
324
+ }
325
+ if (recovered) continue;
326
+ throw new SupportPassportError("storage_conflict", "An incomplete generated draft batch could not recover.", 500);
327
+ }
328
+ if (
329
+ !(await rollbackSupportPassportGeneratedBatch(
330
+ context,
331
+ batchId,
332
+ cards.map((card) => card.card.cardId)
333
+ ))
334
+ ) {
335
+ throw new SupportPassportError("storage_conflict", "An incomplete generated draft batch could not recover.", 500);
336
+ }
337
+ }
338
+ }
@@ -0,0 +1,183 @@
1
+ import { z } from "zod";
2
+
3
+ import { parseIsoOffsetTimestamp } from "../utils/iso-timestamp.js";
4
+ import {
5
+ SupportPassportCardCategorySchema,
6
+ SupportPassportMemoryIdSchema,
7
+ SupportPassportNamespaceSchema,
8
+ } from "./contracts.js";
9
+
10
+ const IsoTimestampSchema = z
11
+ .string()
12
+ .datetime({ offset: true })
13
+ .refine((value) => parseIsoOffsetTimestamp(value) !== null, "timestamp must be a real date");
14
+ const RevisionSchema = z.string().regex(/^[a-f0-9]{64}$/);
15
+ const GrantIdSchema = z
16
+ .string()
17
+ .uuid()
18
+ .transform((value) => value.toLowerCase());
19
+
20
+ export const SupportPassportGrantCardRefSchema = z
21
+ .object({
22
+ cardId: SupportPassportMemoryIdSchema,
23
+ revision: RevisionSchema,
24
+ })
25
+ .strict();
26
+
27
+ export const SupportPassportGrantStateSchema = z
28
+ .object({
29
+ schemaVersion: z.literal(1),
30
+ stateVersion: z.number().int().positive(),
31
+ grantId: GrantIdSchema,
32
+ namespace: SupportPassportNamespaceSchema,
33
+ principalHash: RevisionSchema,
34
+ ownerLockKey: RevisionSchema,
35
+ secretHash: RevisionSchema,
36
+ cards: z.array(SupportPassportGrantCardRefSchema).min(1).max(8),
37
+ createdAt: IsoTimestampSchema,
38
+ expiresAt: IsoTimestampSchema,
39
+ revokedAt: IsoTimestampSchema.optional(),
40
+ })
41
+ .strict()
42
+ .superRefine((grant, ctx) => {
43
+ const ids = new Set<string>();
44
+ for (const [index, card] of grant.cards.entries()) {
45
+ if (ids.has(card.cardId)) {
46
+ ctx.addIssue({
47
+ code: z.ZodIssueCode.custom,
48
+ message: "card IDs must be unique",
49
+ path: ["cards", index, "cardId"],
50
+ });
51
+ }
52
+ ids.add(card.cardId);
53
+ }
54
+ if (Date.parse(grant.expiresAt) <= Date.parse(grant.createdAt)) {
55
+ ctx.addIssue({ code: z.ZodIssueCode.custom, message: "expiresAt must follow createdAt", path: ["expiresAt"] });
56
+ }
57
+ });
58
+
59
+ export const SupportPassportCreateGrantInputSchema = z
60
+ .object({
61
+ principal: z.string().trim().min(1).max(512),
62
+ cards: z.array(SupportPassportGrantCardRefSchema).min(1).max(8),
63
+ expiresAt: IsoTimestampSchema.optional(),
64
+ durationMs: z.number().int().min(300_000).max(604_800_000).optional(),
65
+ })
66
+ .strict()
67
+ .superRefine((input, ctx) => {
68
+ const ids = new Set<string>();
69
+ for (const [index, card] of input.cards.entries()) {
70
+ if (ids.has(card.cardId)) {
71
+ ctx.addIssue({
72
+ code: z.ZodIssueCode.custom,
73
+ message: "card IDs must be unique",
74
+ path: ["cards", index, "cardId"],
75
+ });
76
+ }
77
+ ids.add(card.cardId);
78
+ }
79
+ if ((input.expiresAt === undefined) === (input.durationMs === undefined)) {
80
+ ctx.addIssue({
81
+ code: z.ZodIssueCode.custom,
82
+ message: "one expiry value is required",
83
+ path: ["expiresAt"],
84
+ });
85
+ }
86
+ });
87
+
88
+ export const SupportPassportCreateGrantRequestSchema = z
89
+ .object({
90
+ cardIds: z.array(SupportPassportMemoryIdSchema).min(1).max(8),
91
+ cardRevisions: z.array(SupportPassportGrantCardRefSchema).min(1).max(8),
92
+ expiresAt: IsoTimestampSchema.optional(),
93
+ durationMs: z.number().int().min(300_000).max(604_800_000).optional(),
94
+ })
95
+ .strict()
96
+ .superRefine((input, ctx) => {
97
+ const cardIds = new Set(input.cardIds);
98
+ const revisionIds = new Set(input.cardRevisions.map((card) => card.cardId));
99
+ if (
100
+ cardIds.size !== input.cardIds.length ||
101
+ revisionIds.size !== input.cardRevisions.length ||
102
+ cardIds.size !== revisionIds.size ||
103
+ input.cardIds.some((cardId) => !revisionIds.has(cardId))
104
+ ) {
105
+ ctx.addIssue({
106
+ code: z.ZodIssueCode.custom,
107
+ message: "card revisions must match the selected card IDs",
108
+ path: ["cardRevisions"],
109
+ });
110
+ }
111
+ if ((input.expiresAt === undefined) === (input.durationMs === undefined)) {
112
+ ctx.addIssue({
113
+ code: z.ZodIssueCode.custom,
114
+ message: "one expiry value is required",
115
+ path: ["expiresAt"],
116
+ });
117
+ }
118
+ });
119
+
120
+ export const SupportPassportOwnerCreateGrantRequestSchema = SupportPassportCreateGrantRequestSchema;
121
+
122
+ export const SupportPassportOwnerGrantSchema = z
123
+ .object({
124
+ grantId: GrantIdSchema,
125
+ stateVersion: z.number().int().positive(),
126
+ cards: z.array(SupportPassportGrantCardRefSchema).min(1).max(8),
127
+ createdAt: IsoTimestampSchema,
128
+ expiresAt: IsoTimestampSchema,
129
+ revokedAt: IsoTimestampSchema.optional(),
130
+ status: z.enum(["active", "expired", "revoked"]),
131
+ })
132
+ .strict();
133
+
134
+ export const SupportPassportCreatedGrantSchema = z
135
+ .object({
136
+ grant: SupportPassportOwnerGrantSchema,
137
+ secret: z.string().regex(/^[A-Za-z0-9_-]{43}$/),
138
+ })
139
+ .strict();
140
+
141
+ export const SupportPassportPublicCardSchema = z
142
+ .object({
143
+ cardId: SupportPassportMemoryIdSchema,
144
+ title: z.string().trim().min(1).max(80),
145
+ statement: z.string().trim().min(1).max(500),
146
+ category: SupportPassportCardCategorySchema,
147
+ updatedAt: IsoTimestampSchema,
148
+ })
149
+ .strict();
150
+
151
+ export const SupportPassportPublicGuideSchema = z
152
+ .object({
153
+ schemaVersion: z.literal(1),
154
+ grantId: GrantIdSchema,
155
+ expiresAt: IsoTimestampSchema,
156
+ updatedAt: IsoTimestampSchema,
157
+ cards: z.array(SupportPassportPublicCardSchema).min(1).max(8),
158
+ })
159
+ .strict();
160
+
161
+ export const SupportPassportRevokeGrantInputSchema = z
162
+ .object({
163
+ principal: z.string().trim().min(1).max(512),
164
+ grantId: GrantIdSchema,
165
+ expectedStateVersion: z.number().int().positive().optional(),
166
+ })
167
+ .strict();
168
+
169
+ export const SupportPassportListGrantsInputSchema = z
170
+ .object({
171
+ principal: z.string().trim().min(1).max(512),
172
+ })
173
+ .strict();
174
+
175
+ export type SupportPassportGrantCardRef = z.infer<typeof SupportPassportGrantCardRefSchema>;
176
+ export type SupportPassportGrantState = z.infer<typeof SupportPassportGrantStateSchema>;
177
+ export type SupportPassportCreateGrantInput = z.input<typeof SupportPassportCreateGrantInputSchema>;
178
+ export type SupportPassportCreateGrantRequest = z.input<typeof SupportPassportCreateGrantRequestSchema>;
179
+ export type SupportPassportOwnerCreateGrantRequest = z.input<typeof SupportPassportOwnerCreateGrantRequestSchema>;
180
+ export type SupportPassportOwnerGrant = z.infer<typeof SupportPassportOwnerGrantSchema>;
181
+ export type SupportPassportCreatedGrant = z.infer<typeof SupportPassportCreatedGrantSchema>;
182
+ export type SupportPassportPublicGuide = z.infer<typeof SupportPassportPublicGuideSchema>;
183
+ export type SupportPassportRevokeGrantInput = z.input<typeof SupportPassportRevokeGrantInputSchema>;