@remnic/core 9.54.4 → 9.54.5

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 (526) hide show
  1. package/dist/access-admin-ops-surface.d.ts +12 -11
  2. package/dist/access-admin-ops-surface.js +46 -44
  3. package/dist/access-authorization-probe.d.ts +12 -11
  4. package/dist/access-authorization-probe.js +47 -45
  5. package/dist/access-boundary.d.ts +12 -11
  6. package/dist/access-boundary.js +46 -44
  7. package/dist/access-cli.js +92 -90
  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 +12 -11
  11. package/dist/access-extraction-force-flush.js +46 -44
  12. package/dist/access-health-types.d.ts +1 -1
  13. package/dist/access-http-lcm-compaction.d.ts +12 -11
  14. package/dist/access-http-lifecycle-flush.d.ts +12 -11
  15. package/dist/access-http-offline-stream.d.ts +12 -11
  16. package/dist/access-http-query.js +46 -44
  17. package/dist/access-http.d.ts +12 -11
  18. package/dist/access-http.js +56 -54
  19. package/dist/access-identity-continuity-surface.d.ts +9 -9
  20. package/dist/access-identity-continuity-surface.js +46 -44
  21. package/dist/access-lcm-surface.d.ts +12 -11
  22. package/dist/access-lcm-surface.js +46 -44
  23. package/dist/access-mcp.d.ts +12 -11
  24. package/dist/access-mcp.js +52 -50
  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-BdHlGd_T.d.ts} +1 -1
  28. package/dist/access-namespace-preflight.d.ts +3 -3
  29. package/dist/access-namespace-preflight.js +46 -44
  30. package/dist/access-observe-write-surface.d.ts +12 -11
  31. package/dist/access-observe-write-surface.js +46 -44
  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 +48 -46
  35. package/dist/access-operations.d.ts +15 -14
  36. package/dist/access-operations.js +51 -49
  37. package/dist/access-recall-concurrency.d.ts +12 -11
  38. package/dist/access-recall-concurrency.js +46 -44
  39. package/dist/access-recall-response.d.ts +12 -11
  40. package/dist/access-recall-response.js +46 -44
  41. package/dist/access-recall-surface.d.ts +12 -11
  42. package/dist/access-recall-surface.js +46 -44
  43. package/dist/access-schema.d.ts +90 -90
  44. package/dist/access-schema.js +3 -2
  45. package/dist/{access-service-CXvbxLK-.d.ts → access-service-DL7X9hrg.d.ts} +7 -7
  46. package/dist/access-service-helpers.d.ts +12 -11
  47. package/dist/access-service.d.ts +12 -11
  48. package/dist/access-service.js +46 -44
  49. package/dist/access-surface-catalog.d.ts +12 -11
  50. package/dist/access-wearables-meetings-surface.d.ts +3 -3
  51. package/dist/action-confidence.d.ts +1 -1
  52. package/dist/active-memory-bridge.d.ts +13 -1
  53. package/dist/active-memory-bridge.js +6 -1
  54. package/dist/active-recall.d.ts +1 -1
  55. package/dist/active-recall.js +3 -2
  56. package/dist/active-recall.js.map +1 -1
  57. package/dist/adapters/index.js +4 -4
  58. package/dist/adapters/registry.js +2 -2
  59. package/dist/ambient-provenance.d.ts +1 -1
  60. package/dist/artifact-search.d.ts +1 -1
  61. package/dist/behavior-learner.d.ts +1 -1
  62. package/dist/behavior-signals.d.ts +1 -1
  63. package/dist/bootstrap.d.ts +9 -9
  64. package/dist/briefing.d.ts +2 -2
  65. package/dist/briefing.js +30 -9
  66. package/dist/buffer-surprise-report.d.ts +1 -1
  67. package/dist/buffer-turn-helpers.d.ts +1 -1
  68. package/dist/buffer.d.ts +2 -2
  69. package/dist/buffer.js +3 -3
  70. package/dist/bulk-import/index.d.ts +3 -3
  71. package/dist/calibration.d.ts +1 -1
  72. package/dist/capabilities.d.ts +1 -1
  73. package/dist/{catalog-BOOxl-I2.d.ts → catalog-B90is4d8.d.ts} +1 -1
  74. package/dist/causal-behavior.d.ts +1 -1
  75. package/dist/causal-consolidation.d.ts +1 -1
  76. package/dist/causal-consolidation.js +31 -10
  77. package/dist/causal-consolidation.js.map +1 -1
  78. package/dist/causal-trajectory-graph.d.ts +1 -1
  79. package/dist/{chunk-6LAPLZOS.js → chunk-2DD6ZHOM.js} +8 -3
  80. package/dist/chunk-2DD6ZHOM.js.map +1 -0
  81. package/dist/{chunk-47P3RYZP.js → chunk-2INWPC6E.js} +2 -2
  82. package/dist/{chunk-3CSX3ETE.js → chunk-2LWQSV6A.js} +23 -11
  83. package/dist/chunk-2LWQSV6A.js.map +1 -0
  84. package/dist/{chunk-7BZOBA5J.js → chunk-2PNXOQ4P.js} +69 -11
  85. package/dist/chunk-2PNXOQ4P.js.map +1 -0
  86. package/dist/{chunk-WOPA3SGI.js → chunk-3OTSVCPK.js} +8 -8
  87. package/dist/{chunk-PX2LSHYM.js → chunk-3SXLD5T3.js} +3 -3
  88. package/dist/{chunk-T2JHZWH6.js → chunk-3WGI7F4V.js} +237 -93
  89. package/dist/chunk-3WGI7F4V.js.map +1 -0
  90. package/dist/{chunk-C4ZNGVK3.js → chunk-5JKUSBMX.js} +2 -2
  91. package/dist/{chunk-S75M5ZRK.js → chunk-6LEIWWAF.js} +16 -1
  92. package/dist/chunk-6LEIWWAF.js.map +1 -0
  93. package/dist/{chunk-MAXVH44E.js → chunk-6NNNURLK.js} +4 -4
  94. package/dist/{chunk-LJS7KUPV.js → chunk-6PZGKGAO.js} +2 -2
  95. package/dist/{chunk-YN6ASZUG.js → chunk-6QPI2ITJ.js} +5 -5
  96. package/dist/{chunk-CYF6WVE7.js → chunk-7HG7MGAP.js} +2688 -496
  97. package/dist/chunk-7HG7MGAP.js.map +1 -0
  98. package/dist/{chunk-CGVHPCP2.js → chunk-7Q7JWLQ4.js} +2 -2
  99. package/dist/{chunk-227UFSEQ.js → chunk-7RZJWZ46.js} +5 -5
  100. package/dist/{chunk-JBPKEARU.js → chunk-AU7Q3LSC.js} +4 -4
  101. package/dist/{chunk-PDDTI7IC.js → chunk-B4T3FQMT.js} +1 -1
  102. package/dist/{chunk-UU3G6GUP.js → chunk-BIF4SHMD.js} +1 -1
  103. package/dist/{chunk-UU3G6GUP.js.map → chunk-BIF4SHMD.js.map} +1 -1
  104. package/dist/{chunk-APPFNGX6.js → chunk-BSXGTDVJ.js} +2 -2
  105. package/dist/{chunk-4IIFL7GC.js → chunk-CLKBV3Z3.js} +10 -10
  106. package/dist/{chunk-ZYLC7NFO.js → chunk-CSY44OKU.js} +4 -4
  107. package/dist/{chunk-HLYR2TQL.js → chunk-CUTFSLSD.js} +2 -2
  108. package/dist/{chunk-RDJRFDJY.js → chunk-DBY26JJJ.js} +2 -2
  109. package/dist/{chunk-QWGE2PUH.js → chunk-DDA55IVB.js} +10 -10
  110. package/dist/{chunk-VMMQDEN5.js → chunk-DN2IDKI5.js} +2 -2
  111. package/dist/{chunk-2GFK22OZ.js → chunk-DOOWFDWN.js} +2 -2
  112. package/dist/{chunk-7FGL6CGA.js → chunk-DVYRD4HY.js} +2 -2
  113. package/dist/{chunk-YGLY6QFV.js → chunk-F2Y6I74C.js} +2 -2
  114. package/dist/{chunk-UU7TRFNE.js → chunk-FFEBSFVT.js} +2 -2
  115. package/dist/chunk-HNDIND7P.js +331 -0
  116. package/dist/chunk-HNDIND7P.js.map +1 -0
  117. package/dist/{chunk-NIS256NW.js → chunk-JKW663ZN.js} +2 -2
  118. package/dist/{chunk-G7A5HLUS.js → chunk-KJH6W2I7.js} +2 -2
  119. package/dist/{chunk-IXEBUYO4.js → chunk-KM55SMLG.js} +11 -2
  120. package/dist/{chunk-IXEBUYO4.js.map → chunk-KM55SMLG.js.map} +1 -1
  121. package/dist/{chunk-G2LUMAUF.js → chunk-L7RTUEDG.js} +12 -5
  122. package/dist/chunk-L7RTUEDG.js.map +1 -0
  123. package/dist/chunk-LC2BDILZ.js +57 -0
  124. package/dist/chunk-LC2BDILZ.js.map +1 -0
  125. package/dist/{chunk-JV5YUBIZ.js → chunk-LC3FD4BV.js} +52 -46
  126. package/dist/chunk-LC3FD4BV.js.map +1 -0
  127. package/dist/{chunk-HWRD23DW.js → chunk-LVKYLMSM.js} +3 -3
  128. package/dist/{chunk-RUMNY5DT.js → chunk-MRGJZ75M.js} +6 -2
  129. package/dist/chunk-MRGJZ75M.js.map +1 -0
  130. package/dist/{chunk-ZMYDYNI4.js → chunk-N7CXQ5TA.js} +4 -4
  131. package/dist/{chunk-3JLPGJ43.js → chunk-NGT35IGQ.js} +5 -5
  132. package/dist/{chunk-GUKBW4HL.js → chunk-NQMSEB5D.js} +6 -6
  133. package/dist/{chunk-WRJVB3C2.js → chunk-PO7NXBG2.js} +2 -2
  134. package/dist/{chunk-WM65LU67.js → chunk-QOQQMVR2.js} +2 -2
  135. package/dist/{chunk-QHFV6VNU.js → chunk-QPAQSG3F.js} +2 -2
  136. package/dist/{chunk-UTRO5UJU.js → chunk-QPW3PAIH.js} +5 -1
  137. package/dist/chunk-QPW3PAIH.js.map +1 -0
  138. package/dist/{chunk-6R4G7N4S.js → chunk-QQXWFDRD.js} +128 -74
  139. package/dist/chunk-QQXWFDRD.js.map +1 -0
  140. package/dist/{chunk-UES4BHA2.js → chunk-QTO6BMQZ.js} +2 -2
  141. package/dist/{chunk-THPPCISA.js → chunk-RBII7637.js} +5 -5
  142. package/dist/{chunk-QT2FRYI4.js → chunk-RG426DJO.js} +2 -2
  143. package/dist/{chunk-XUAMCLY4.js → chunk-TKFGFDPJ.js} +17 -13
  144. package/dist/chunk-TKFGFDPJ.js.map +1 -0
  145. package/dist/{chunk-VKXWK44Q.js → chunk-TY6MKIWP.js} +3 -3
  146. package/dist/{chunk-AZM4CCAC.js → chunk-UWJNKGBA.js} +5 -5
  147. package/dist/{chunk-JDZPNCMA.js → chunk-UYOXFFEY.js} +6 -3
  148. package/dist/chunk-UYOXFFEY.js.map +1 -0
  149. package/dist/{chunk-ZPJ4QSGP.js → chunk-VTU5IEKY.js} +2 -2
  150. package/dist/{chunk-RZ4XGKOJ.js → chunk-VYQ4URQB.js} +8 -8
  151. package/dist/{chunk-WDBX6VER.js → chunk-VZRFGJCH.js} +5 -5
  152. package/dist/{chunk-IBKR2TFR.js → chunk-WM5LD6AT.js} +2 -2
  153. package/dist/{chunk-K4QS7LXU.js → chunk-WZWZRZ2V.js} +2 -2
  154. package/dist/{chunk-G4T7L557.js → chunk-XKAR4RF6.js} +2 -2
  155. package/dist/{chunk-DZD576ZU.js → chunk-XSV2YDCJ.js} +2 -2
  156. package/dist/{chunk-G7Z6EENO.js → chunk-YDWPYDML.js} +4 -4
  157. package/dist/{chunk-6HPHEFXT.js → chunk-YKZLOPTC.js} +2 -2
  158. package/dist/{chunk-NH5IR2WM.js → chunk-YR65W7BV.js} +6 -2
  159. package/dist/chunk-YR65W7BV.js.map +1 -0
  160. package/dist/{chunk-GYPQL6XN.js → chunk-Z4N7SVVF.js} +35 -47
  161. package/dist/chunk-Z4N7SVVF.js.map +1 -0
  162. package/dist/{cli-DVUFIa5E.d.ts → cli-jfuZXixq.d.ts} +5 -5
  163. package/dist/cli.d.ts +14 -13
  164. package/dist/cli.js +74 -72
  165. package/dist/coding/pre-action-gate.d.ts +1 -1
  166. package/dist/compounding/engine.d.ts +2 -2
  167. package/dist/compounding/engine.js +30 -9
  168. package/dist/compounding/preference-consolidator.d.ts +1 -1
  169. package/dist/compression-optimizer.d.ts +1 -1
  170. package/dist/config.d.ts +1 -1
  171. package/dist/config.js +3 -2
  172. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  173. package/dist/connectors/codex-materialize-runner.js +30 -9
  174. package/dist/connectors/codex-materialize.d.ts +1 -1
  175. package/dist/connectors/index.d.ts +1 -1
  176. package/dist/connectors/index.js +29 -9
  177. package/dist/consolidation-provenance-check.d.ts +2 -2
  178. package/dist/consolidation-undo.d.ts +2 -2
  179. package/dist/contradiction/index.d.ts +2 -2
  180. package/dist/contradiction/index.js +3 -1
  181. package/dist/contradiction-scan-KCADHXPE.js +20 -0
  182. package/dist/converge-config.d.ts +1 -1
  183. package/dist/convergence-refresh.d.ts +2 -2
  184. package/dist/convergence-refresh.js +32 -11
  185. package/dist/conversation-index/backend.d.ts +1 -1
  186. package/dist/conversation-index/backend.js +2 -2
  187. package/dist/conversation-index/chunker.d.ts +1 -1
  188. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  189. package/dist/conversation-index/indexer.d.ts +1 -1
  190. package/dist/conversation-index/search.d.ts +1 -1
  191. package/dist/corpus-watermark.d.ts +1 -1
  192. package/dist/corpus-watermark.js +21 -20
  193. package/dist/day-summary.d.ts +1 -1
  194. package/dist/delinearize.d.ts +1 -1
  195. package/dist/dependency-propagation-config.d.ts +1 -1
  196. package/dist/{dependency-propagation-delivery-XzF76C9n.d.ts → dependency-propagation-delivery-CTDuAVJc.d.ts} +1 -1
  197. package/dist/direct-answer-wiring.d.ts +1 -1
  198. package/dist/direct-answer.d.ts +1 -1
  199. package/dist/embedding-fallback.d.ts +1 -1
  200. package/dist/enrichment/index.d.ts +1 -1
  201. package/dist/entity-retrieval.d.ts +2 -2
  202. package/dist/entity-retrieval.js +30 -9
  203. package/dist/entity-schema.d.ts +1 -1
  204. package/dist/explicit-capture.d.ts +9 -9
  205. package/dist/explicit-capture.js +6 -4
  206. package/dist/external-wiki-access.d.ts +12 -11
  207. package/dist/external-wiki-access.js +47 -45
  208. package/dist/external-wiki-collection-registration.d.ts +1 -1
  209. package/dist/external-wiki-collection.d.ts +1 -1
  210. package/dist/external-wiki-mcp-tools.d.ts +12 -11
  211. package/dist/extraction-error-classification.d.ts +1 -1
  212. package/dist/extraction-faithfulness.d.ts +1 -1
  213. package/dist/extraction-judge-telemetry.d.ts +1 -1
  214. package/dist/extraction-judge-training.d.ts +1 -1
  215. package/dist/extraction-judge.d.ts +1 -1
  216. package/dist/extraction-liveness.d.ts +1 -1
  217. package/dist/extraction-normalization.d.ts +1 -1
  218. package/dist/extraction-prompt.d.ts +1 -1
  219. package/dist/extraction-source-grounding-rules.d.ts +1 -1
  220. package/dist/extraction-source-grounding.d.ts +1 -1
  221. package/dist/extraction.d.ts +1 -1
  222. package/dist/extraction.js +29 -13
  223. package/dist/fallback-llm.d.ts +1 -1
  224. package/dist/{first-start-migration-626C5554.js → first-start-migration-LMMZFLKK.js} +13 -5
  225. package/dist/first-start-migration-LMMZFLKK.js.map +1 -0
  226. package/dist/graph-dashboard-diff.d.ts +1 -1
  227. package/dist/graph-dashboard-key.d.ts +1 -1
  228. package/dist/graph-dashboard-parser.d.ts +1 -1
  229. package/dist/graph-edge-reinforcement.d.ts +1 -1
  230. package/dist/graph-path-reconstruction.d.ts +1 -1
  231. package/dist/graph-path-scoring.d.ts +1 -1
  232. package/dist/graph-snapshot.d.ts +1 -1
  233. package/dist/graph.d.ts +1 -1
  234. package/dist/harmonic-retrieval.js +1 -1
  235. package/dist/importance.d.ts +1 -1
  236. package/dist/importers/index.d.ts +1 -1
  237. package/dist/in-flight-reads.d.ts +1 -1
  238. package/dist/index.d.ts +1439 -716
  239. package/dist/index.js +207 -121
  240. package/dist/intent.d.ts +1 -1
  241. package/dist/lcm/engine.d.ts +1 -1
  242. package/dist/lcm/engine.js +2 -2
  243. package/dist/lcm/index.d.ts +1 -1
  244. package/dist/lcm/index.js +5 -5
  245. package/dist/lcm/tools.d.ts +1 -1
  246. package/dist/lifecycle.d.ts +1 -1
  247. package/dist/live-connectors-runner.d.ts +1 -1
  248. package/dist/local-llm.d.ts +1 -1
  249. package/dist/local-model-endpoint.d.ts +1 -1
  250. package/dist/maintenance/memory-governance.d.ts +1 -1
  251. package/dist/maintenance/memory-governance.js +30 -9
  252. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  253. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +30 -9
  254. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
  255. package/dist/maintenance/rebuild-memory-projection.js +31 -10
  256. package/dist/{maintenance-BJzNIKBE.d.ts → maintenance-heMZSq7G.d.ts} +3 -3
  257. package/dist/mcp-memory-inspector-app.d.ts +12 -11
  258. package/dist/memory-action-policy.d.ts +1 -1
  259. package/dist/memory-cache.d.ts +1 -1
  260. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  261. package/dist/memory-projection-mutations.js +2 -2
  262. package/dist/memory-projection-store.d.ts +6 -2
  263. package/dist/memory-projection-store.js +1 -1
  264. package/dist/memory-provenance.d.ts +1 -1
  265. package/dist/memory-snapshot.d.ts +1 -1
  266. package/dist/memory-worth-outcomes.d.ts +2 -2
  267. package/dist/models-json.d.ts +1 -1
  268. package/dist/namespaces/migrate.d.ts +3 -3
  269. package/dist/namespaces/migrate.js +20 -19
  270. package/dist/namespaces/principal.d.ts +1 -1
  271. package/dist/namespaces/search.d.ts +1 -1
  272. package/dist/namespaces/search.js +6 -6
  273. package/dist/namespaces/storage.d.ts +3 -3
  274. package/dist/namespaces/storage.js +30 -9
  275. package/dist/native-knowledge.d.ts +1 -1
  276. package/dist/offline-sync-file-io.d.ts +20 -0
  277. package/dist/offline-sync-file-io.js +18 -0
  278. package/dist/offline-sync-file-io.js.map +1 -0
  279. package/dist/offline-sync-impression-drain.d.ts +1 -1
  280. package/dist/offline-sync-impression-drain.js +5 -5
  281. package/dist/offline-sync.d.ts +8 -6
  282. package/dist/offline-sync.js +2 -1
  283. package/dist/operator-doctor-corpus.d.ts +1 -1
  284. package/dist/operator-doctor-corpus.js +22 -21
  285. package/dist/operator-doctor-replica.d.ts +1 -1
  286. package/dist/operator-toolkit.d.ts +3 -3
  287. package/dist/operator-toolkit.js +34 -32
  288. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  289. package/dist/orchestration/maintenance.d.ts +4 -4
  290. package/dist/orchestration/maintenance.js +35 -15
  291. package/dist/{orchestrator-BiXgBJBQ.d.ts → orchestrator-BQQPsSjs.d.ts} +11 -8
  292. package/dist/orchestrator.d.ts +9 -9
  293. package/dist/orchestrator.js +93 -91
  294. package/dist/patterns-cli.d.ts +1 -1
  295. package/dist/{pipeline-sz_dcuLg.d.ts → pipeline-DFfmsnGk.d.ts} +1 -1
  296. package/dist/policy-runtime.d.ts +1 -1
  297. package/dist/proactive-contention.d.ts +1 -1
  298. package/dist/provenance.d.ts +1 -1
  299. package/dist/{purge-533FZLS4.js → purge-GB7PZHT2.js} +2 -2
  300. package/dist/{qmd-eAWObK4M.d.ts → qmd-BF5bcVRs.d.ts} +1 -1
  301. package/dist/qmd-preflight.d.ts +2 -2
  302. package/dist/qmd-recall-cache.d.ts +1 -1
  303. package/dist/qmd.d.ts +2 -2
  304. package/dist/recall-concurrency-config.d.ts +1 -1
  305. package/dist/recall-disclosure-escalation.d.ts +1 -1
  306. package/dist/recall-explain-renderer.d.ts +1 -1
  307. package/dist/recall-explain-renderer.js +3 -3
  308. package/dist/recall-memory-map.d.ts +1 -1
  309. package/dist/recall-planner-llm.d.ts +1 -1
  310. package/dist/recall-state.d.ts +1 -1
  311. package/dist/recall-tag-filter.d.ts +1 -1
  312. package/dist/recall-timings.d.ts +1 -1
  313. package/dist/recall-xray-cli.d.ts +1 -1
  314. package/dist/recall-xray-cli.js +4 -4
  315. package/dist/recall-xray-renderer.d.ts +1 -1
  316. package/dist/recall-xray-renderer.js +3 -3
  317. package/dist/recall-xray.d.ts +1 -1
  318. package/dist/recall-xray.js +2 -2
  319. package/dist/reconcile/cursor.d.ts +2 -1
  320. package/dist/reconcile/manifest.d.ts +2 -1
  321. package/dist/reconcile/manifest.js +6 -5
  322. package/dist/reconcile/plan.d.ts +2 -1
  323. package/dist/reconcile/plan.js +3 -2
  324. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  325. package/dist/replay/normalizers/claude.d.ts +1 -1
  326. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  327. package/dist/replay/normalizers/shared.d.ts +1 -1
  328. package/dist/replay/runner.d.ts +1 -1
  329. package/dist/replay/types.d.ts +1 -1
  330. package/dist/replica-divergence.d.ts +1 -1
  331. package/dist/replica-peers-config.d.ts +1 -1
  332. package/dist/resolve-auth-token.d.ts +1 -1
  333. package/dist/resume-bundles.js +4 -3
  334. package/dist/retrieval-agents.d.ts +2 -2
  335. package/dist/retrieval-tiers.d.ts +1 -1
  336. package/dist/routing/engine.d.ts +1 -1
  337. package/dist/routing/store.d.ts +1 -1
  338. package/dist/salvage-envelope.d.ts +1 -1
  339. package/dist/schemas.d.ts +138 -138
  340. package/dist/{scope-profiles-BBQsXuyj.d.ts → scope-profiles-CbUOsE_E.d.ts} +1 -1
  341. package/dist/search/embed-helper.d.ts +1 -1
  342. package/dist/search/factory.d.ts +1 -1
  343. package/dist/search/factory.js +4 -4
  344. package/dist/search/index.d.ts +1 -1
  345. package/dist/search/index.js +6 -6
  346. package/dist/search/lancedb-backend.d.ts +1 -1
  347. package/dist/search/meilisearch-backend.d.ts +1 -1
  348. package/dist/search/noop-backend.d.ts +1 -1
  349. package/dist/search/orama-backend.d.ts +1 -1
  350. package/dist/search/port.d.ts +1 -1
  351. package/dist/search/remote-backend.d.ts +1 -1
  352. package/dist/{semantic-consolidation-HD8RkzVA.d.ts → semantic-consolidation-DAB3xdKM.d.ts} +1 -1
  353. package/dist/semantic-consolidation.d.ts +2 -2
  354. package/dist/semantic-consolidation.js +31 -10
  355. package/dist/semantic-rule-promotion.js +30 -9
  356. package/dist/semantic-rule-verifier.d.ts +1 -1
  357. package/dist/semantic-rule-verifier.js +30 -9
  358. package/dist/{service-DIrtHHEg.d.ts → service-DGKg2O6r.d.ts} +2 -2
  359. package/dist/session-observer-bands.d.ts +1 -1
  360. package/dist/session-observer-state.d.ts +1 -1
  361. package/dist/shared-context/manager.d.ts +9 -9
  362. package/dist/signal.d.ts +1 -1
  363. package/dist/source-agent-qualifier.d.ts +1 -1
  364. package/dist/source-agent-qualifier.js +28 -12
  365. package/dist/{storage-DqCzXi56.d.ts → storage-CC1jKcWg.d.ts} +46 -13
  366. package/dist/storage.d.ts +2 -2
  367. package/dist/storage.js +30 -9
  368. package/dist/summarizer.d.ts +1 -1
  369. package/dist/summary-snapshot.d.ts +1 -1
  370. package/dist/temporal-supersession.d.ts +2 -2
  371. package/dist/temporal-timeline-recall.d.ts +1 -1
  372. package/dist/temporal-validity.d.ts +1 -1
  373. package/dist/threading.d.ts +1 -1
  374. package/dist/tier-migration.d.ts +2 -2
  375. package/dist/tier-routing.d.ts +2 -2
  376. package/dist/tier-routing.js +7 -1
  377. package/dist/{tier-stats-2JCZYEF7.js → tier-stats-JDN6HRNT.js} +8 -2
  378. package/dist/{tier-stats-2JCZYEF7.js.map → tier-stats-JDN6HRNT.js.map} +1 -1
  379. package/dist/topics.d.ts +1 -1
  380. package/dist/transcript.d.ts +1 -1
  381. package/dist/transfer/types.d.ts +66 -66
  382. package/dist/trust-score-stage.d.ts +1 -1
  383. package/dist/trust-score.d.ts +1 -1
  384. package/dist/{types-d_j4vC6N.d.ts → types-BnQza1y8.d.ts} +2 -1
  385. package/dist/types.d.ts +1 -1
  386. package/dist/types.js +1 -1
  387. package/dist/utility-runtime.d.ts +2 -2
  388. package/dist/verified-recall.js +30 -9
  389. package/dist/write-envelope.d.ts +1 -1
  390. package/package.json +2 -2
  391. package/src/access-http.test.ts +31 -0
  392. package/src/access-memory-search-fanout.ts +24 -1
  393. package/src/access-offline-manifest.ts +5 -0
  394. package/src/access-service-namespace.test.ts +14 -0
  395. package/src/access-service-observe-scope.test.ts +2 -0
  396. package/src/access-service-offline-file-content.test.ts +211 -0
  397. package/src/access-service.ts +20 -43
  398. package/src/active-memory-bridge.test.ts +151 -0
  399. package/src/active-memory-bridge.ts +87 -11
  400. package/src/briefing.test.ts +38 -0
  401. package/src/briefing.ts +3 -3
  402. package/src/cli.ts +6 -1
  403. package/src/connectors/codex-materialize-runner.ts +2 -0
  404. package/src/contradiction/contradiction-scan.ts +2 -0
  405. package/src/contradiction/contradiction.test.ts +42 -0
  406. package/src/correction/correction-access-wiring.ts +8 -2
  407. package/src/correction/correction-storage-integration.test.ts +7 -0
  408. package/src/explicit-capture.test.ts +24 -0
  409. package/src/explicit-capture.ts +2 -0
  410. package/src/index.ts +3 -0
  411. package/src/maintenance/first-start-migration.ts +2 -1
  412. package/src/maintenance/memory-governance.test.ts +25 -0
  413. package/src/maintenance/memory-governance.ts +4 -1
  414. package/src/maintenance/pattern-reinforcement.test.ts +20 -0
  415. package/src/maintenance/pattern-reinforcement.ts +2 -1
  416. package/src/maintenance/rebuild-memory-projection.ts +8 -8
  417. package/src/memory-projection-store.ts +25 -27
  418. package/src/offline-sync-file-io.ts +68 -0
  419. package/src/offline-sync.ts +43 -57
  420. package/src/orchestration/consolidation-run.ts +5 -4
  421. package/src/orchestration/contradiction-linking-coordinator.ts +7 -0
  422. package/src/orchestration/contradiction-localization.integration.test.ts +115 -0
  423. package/src/orchestration/lifecycle-policy-coordinator.ts +2 -1
  424. package/src/orchestration/qmd-result-resolver.test.ts +215 -14
  425. package/src/orchestration/qmd-result-resolver.ts +142 -82
  426. package/src/orchestration/recall-search-pipeline.test.ts +41 -0
  427. package/src/orchestration/recall-search-pipeline.ts +12 -0
  428. package/src/orchestration/semantic-consolidation-coordinator.ts +2 -1
  429. package/src/orchestration/tier-migration-coordinator.ts +23 -56
  430. package/src/orchestration/workspace-ops.test.ts +37 -0
  431. package/src/orchestration/workspace-ops.ts +5 -29
  432. package/src/orchestrator.ts +7 -8
  433. package/src/storage/supersession-audit.ts +7 -1
  434. package/src/storage/supersession-side-effects.ts +17 -5
  435. package/src/storage.ts +18 -19
  436. package/src/support-passport/card-projection.test.ts +129 -0
  437. package/src/support-passport/card-projection.ts +287 -0
  438. package/src/support-passport/card-service.test.ts +2462 -0
  439. package/src/support-passport/card-service.ts +1042 -0
  440. package/src/support-passport/contracts.test.ts +143 -0
  441. package/src/support-passport/contracts.ts +136 -0
  442. package/src/support-passport/errors.ts +24 -0
  443. package/src/support-passport/grant-contracts.ts +139 -0
  444. package/src/support-passport/grant-service-cache.test.ts +148 -0
  445. package/src/support-passport/grant-service-cancellation.test.ts +81 -0
  446. package/src/support-passport/grant-service.test.ts +2882 -0
  447. package/src/support-passport/grant-service.ts +364 -0
  448. package/src/support-passport/grant-store-commit-hook.test.ts +123 -0
  449. package/src/support-passport/grant-store-order.test.ts +60 -0
  450. package/src/support-passport/grant-store-path-safety.test.ts +30 -0
  451. package/src/support-passport/grant-store-recovery.test.ts +448 -0
  452. package/src/support-passport/grant-store.ts +902 -0
  453. package/src/support-passport/index.ts +7 -0
  454. package/src/support-passport/offline-sync-guard.ts +230 -0
  455. package/src/support-passport/owner-lock.ts +53 -0
  456. package/src/support-passport/private-file.ts +371 -0
  457. package/src/tier-routing.ts +28 -17
  458. package/src/training-export/converter.test.ts +24 -0
  459. package/src/training-export/converter.ts +2 -0
  460. package/src/types.ts +1 -1
  461. package/src/wearables/service.test.ts +13 -0
  462. package/src/wearables/service.ts +2 -0
  463. package/dist/chunk-3CSX3ETE.js.map +0 -1
  464. package/dist/chunk-6LAPLZOS.js.map +0 -1
  465. package/dist/chunk-6R4G7N4S.js.map +0 -1
  466. package/dist/chunk-7BZOBA5J.js.map +0 -1
  467. package/dist/chunk-CYF6WVE7.js.map +0 -1
  468. package/dist/chunk-G2LUMAUF.js.map +0 -1
  469. package/dist/chunk-GYPQL6XN.js.map +0 -1
  470. package/dist/chunk-JDZPNCMA.js.map +0 -1
  471. package/dist/chunk-JV5YUBIZ.js.map +0 -1
  472. package/dist/chunk-NH5IR2WM.js.map +0 -1
  473. package/dist/chunk-RUMNY5DT.js.map +0 -1
  474. package/dist/chunk-S75M5ZRK.js.map +0 -1
  475. package/dist/chunk-T2JHZWH6.js.map +0 -1
  476. package/dist/chunk-UTRO5UJU.js.map +0 -1
  477. package/dist/chunk-XUAMCLY4.js.map +0 -1
  478. package/dist/contradiction-scan-HYLIRMJ2.js +0 -14
  479. package/dist/first-start-migration-626C5554.js.map +0 -1
  480. /package/dist/{chunk-47P3RYZP.js.map → chunk-2INWPC6E.js.map} +0 -0
  481. /package/dist/{chunk-WOPA3SGI.js.map → chunk-3OTSVCPK.js.map} +0 -0
  482. /package/dist/{chunk-PX2LSHYM.js.map → chunk-3SXLD5T3.js.map} +0 -0
  483. /package/dist/{chunk-C4ZNGVK3.js.map → chunk-5JKUSBMX.js.map} +0 -0
  484. /package/dist/{chunk-MAXVH44E.js.map → chunk-6NNNURLK.js.map} +0 -0
  485. /package/dist/{chunk-LJS7KUPV.js.map → chunk-6PZGKGAO.js.map} +0 -0
  486. /package/dist/{chunk-YN6ASZUG.js.map → chunk-6QPI2ITJ.js.map} +0 -0
  487. /package/dist/{chunk-CGVHPCP2.js.map → chunk-7Q7JWLQ4.js.map} +0 -0
  488. /package/dist/{chunk-227UFSEQ.js.map → chunk-7RZJWZ46.js.map} +0 -0
  489. /package/dist/{chunk-JBPKEARU.js.map → chunk-AU7Q3LSC.js.map} +0 -0
  490. /package/dist/{chunk-PDDTI7IC.js.map → chunk-B4T3FQMT.js.map} +0 -0
  491. /package/dist/{chunk-APPFNGX6.js.map → chunk-BSXGTDVJ.js.map} +0 -0
  492. /package/dist/{chunk-4IIFL7GC.js.map → chunk-CLKBV3Z3.js.map} +0 -0
  493. /package/dist/{chunk-ZYLC7NFO.js.map → chunk-CSY44OKU.js.map} +0 -0
  494. /package/dist/{chunk-HLYR2TQL.js.map → chunk-CUTFSLSD.js.map} +0 -0
  495. /package/dist/{chunk-RDJRFDJY.js.map → chunk-DBY26JJJ.js.map} +0 -0
  496. /package/dist/{chunk-QWGE2PUH.js.map → chunk-DDA55IVB.js.map} +0 -0
  497. /package/dist/{chunk-VMMQDEN5.js.map → chunk-DN2IDKI5.js.map} +0 -0
  498. /package/dist/{chunk-2GFK22OZ.js.map → chunk-DOOWFDWN.js.map} +0 -0
  499. /package/dist/{chunk-7FGL6CGA.js.map → chunk-DVYRD4HY.js.map} +0 -0
  500. /package/dist/{chunk-YGLY6QFV.js.map → chunk-F2Y6I74C.js.map} +0 -0
  501. /package/dist/{chunk-UU7TRFNE.js.map → chunk-FFEBSFVT.js.map} +0 -0
  502. /package/dist/{chunk-NIS256NW.js.map → chunk-JKW663ZN.js.map} +0 -0
  503. /package/dist/{chunk-G7A5HLUS.js.map → chunk-KJH6W2I7.js.map} +0 -0
  504. /package/dist/{chunk-HWRD23DW.js.map → chunk-LVKYLMSM.js.map} +0 -0
  505. /package/dist/{chunk-ZMYDYNI4.js.map → chunk-N7CXQ5TA.js.map} +0 -0
  506. /package/dist/{chunk-3JLPGJ43.js.map → chunk-NGT35IGQ.js.map} +0 -0
  507. /package/dist/{chunk-GUKBW4HL.js.map → chunk-NQMSEB5D.js.map} +0 -0
  508. /package/dist/{chunk-WRJVB3C2.js.map → chunk-PO7NXBG2.js.map} +0 -0
  509. /package/dist/{chunk-WM65LU67.js.map → chunk-QOQQMVR2.js.map} +0 -0
  510. /package/dist/{chunk-QHFV6VNU.js.map → chunk-QPAQSG3F.js.map} +0 -0
  511. /package/dist/{chunk-UES4BHA2.js.map → chunk-QTO6BMQZ.js.map} +0 -0
  512. /package/dist/{chunk-THPPCISA.js.map → chunk-RBII7637.js.map} +0 -0
  513. /package/dist/{chunk-QT2FRYI4.js.map → chunk-RG426DJO.js.map} +0 -0
  514. /package/dist/{chunk-VKXWK44Q.js.map → chunk-TY6MKIWP.js.map} +0 -0
  515. /package/dist/{chunk-AZM4CCAC.js.map → chunk-UWJNKGBA.js.map} +0 -0
  516. /package/dist/{chunk-ZPJ4QSGP.js.map → chunk-VTU5IEKY.js.map} +0 -0
  517. /package/dist/{chunk-RZ4XGKOJ.js.map → chunk-VYQ4URQB.js.map} +0 -0
  518. /package/dist/{chunk-WDBX6VER.js.map → chunk-VZRFGJCH.js.map} +0 -0
  519. /package/dist/{chunk-IBKR2TFR.js.map → chunk-WM5LD6AT.js.map} +0 -0
  520. /package/dist/{chunk-K4QS7LXU.js.map → chunk-WZWZRZ2V.js.map} +0 -0
  521. /package/dist/{chunk-G4T7L557.js.map → chunk-XKAR4RF6.js.map} +0 -0
  522. /package/dist/{chunk-DZD576ZU.js.map → chunk-XSV2YDCJ.js.map} +0 -0
  523. /package/dist/{chunk-G7Z6EENO.js.map → chunk-YDWPYDML.js.map} +0 -0
  524. /package/dist/{chunk-6HPHEFXT.js.map → chunk-YKZLOPTC.js.map} +0 -0
  525. /package/dist/{contradiction-scan-HYLIRMJ2.js.map → contradiction-scan-KCADHXPE.js.map} +0 -0
  526. /package/dist/{purge-533FZLS4.js.map → purge-GB7PZHT2.js.map} +0 -0
@@ -0,0 +1,7 @@
1
+ export * from "./card-projection.js";
2
+ export * from "./card-service.js";
3
+ export * from "./contracts.js";
4
+ export * from "./errors.js";
5
+ export * from "./grant-contracts.js";
6
+ export * from "./grant-service.js";
7
+ export * from "./grant-store.js";
@@ -0,0 +1,230 @@
1
+ import path from "node:path";
2
+
3
+ import type { OfflineSyncFileTarget } from "../offline-sync-file-io.js";
4
+ import {
5
+ applyOfflineSyncChangeset,
6
+ applyOfflineSyncFileContentChunk,
7
+ buildOfflineSyncSnapshot,
8
+ normalizeOfflineSyncChangeset,
9
+ type OfflineSyncApplyChangesetResult,
10
+ type OfflineSyncApplyFileContentChunkResult,
11
+ } from "../offline-sync.js";
12
+ import { validateArchiveRelativePath } from "../transfer/fs-utils.js";
13
+ import type { MemoryFile } from "../types.js";
14
+ import { createSupportPassportPrivateFileExclusion } from "./card-projection.js";
15
+
16
+ const MAX_SUPPORT_PASSPORT_FRONTMATTER_BYTES = 1_048_576;
17
+ const SUPPORT_PASSPORT_MARKER = "support-passport-";
18
+ const FRONTMATTER_PREFIXES = ["---\n", "---\r\n"] as const;
19
+
20
+ type FrontmatterDecision = "allow" | "wait";
21
+
22
+ interface SupportPassportOfflineSyncStorage {
23
+ dir: string;
24
+ readMemoryByPath(filePath: string): Promise<MemoryFile | null>;
25
+ readOfflineSyncFile(filePath: string): Promise<Buffer>;
26
+ digestOfflineSyncFile(filePath: string): Promise<{ sha256: string; bytes: number }>;
27
+ writeOfflineSyncFile(filePath: string, content: Buffer): Promise<void>;
28
+ writeOfflineSyncStagingFile(filePath: string, content: Buffer): Promise<void>;
29
+ writeOfflineSyncFileChunks(filePath: string, chunks: AsyncIterable<Buffer>): Promise<void>;
30
+ deleteOfflineSyncFile(filePath: string, deletionMtimeMs?: number | null): Promise<void>;
31
+ recordReplicatedDeletionRevision(filePath: string, mtimeMs: number): Promise<void>;
32
+ }
33
+
34
+ interface SupportPassportOfflineSyncFileContentInput {
35
+ includeTranscripts?: boolean;
36
+ sourceId: string;
37
+ path: string;
38
+ sha256: string;
39
+ bytes: number;
40
+ mtimeMs: number;
41
+ offset?: number;
42
+ baseSha256?: string;
43
+ content: Buffer;
44
+ }
45
+
46
+ interface SupportPassportOfflineSyncApplyInput {
47
+ changeset: unknown;
48
+ returnCurrentFiles?: boolean;
49
+ }
50
+
51
+ function frontmatterPrefixState(raw: Buffer): "absent" | "present" | "pending" {
52
+ const prefix = raw.subarray(0, Math.min(raw.length, 5)).toString("utf8");
53
+ if (FRONTMATTER_PREFIXES.some((candidate) => prefix.startsWith(candidate))) return "present";
54
+ if (FRONTMATTER_PREFIXES.some((candidate) => candidate.startsWith(prefix))) return "pending";
55
+ return "absent";
56
+ }
57
+
58
+ function completeFrontmatter(raw: Buffer): string | null {
59
+ const text = raw.toString("utf8");
60
+ return /^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/.exec(text)?.[0] ?? null;
61
+ }
62
+
63
+ function assertFrontmatterAllowed(frontmatter: string, relativePath: string): void {
64
+ if (frontmatter.includes(SUPPORT_PASSPORT_MARKER)) {
65
+ throw new Error(`offline sync cannot modify private support-passport record: ${relativePath}`);
66
+ }
67
+ }
68
+
69
+ function inspectBufferedFrontmatter(
70
+ raw: Buffer,
71
+ relativePath: string,
72
+ endOfFile: boolean,
73
+ ): FrontmatterDecision {
74
+ const prefixState = frontmatterPrefixState(raw);
75
+ if (prefixState === "absent") return "allow";
76
+ if (prefixState === "pending" && !endOfFile) return "wait";
77
+
78
+ const frontmatter = completeFrontmatter(raw);
79
+ if (frontmatter !== null) {
80
+ assertFrontmatterAllowed(frontmatter, relativePath);
81
+ return "allow";
82
+ }
83
+ if (raw.length > MAX_SUPPORT_PASSPORT_FRONTMATTER_BYTES) {
84
+ throw new Error(`offline sync frontmatter is too large: ${relativePath}`);
85
+ }
86
+ if (endOfFile) {
87
+ assertFrontmatterAllowed(raw.toString("utf8"), relativePath);
88
+ return "allow";
89
+ }
90
+ return "wait";
91
+ }
92
+
93
+ async function* guardSupportPassportChunks(
94
+ chunks: AsyncIterable<Buffer>,
95
+ relativePath: string,
96
+ ): AsyncIterable<Buffer> {
97
+ const buffered: Buffer[] = [];
98
+ let bufferedBytes = 0;
99
+ let passThrough = false;
100
+ for await (const chunk of chunks) {
101
+ if (passThrough) {
102
+ yield chunk;
103
+ continue;
104
+ }
105
+ buffered.push(chunk);
106
+ bufferedBytes += chunk.length;
107
+ const raw = Buffer.concat(buffered, bufferedBytes);
108
+ if (inspectBufferedFrontmatter(raw, relativePath, false) === "wait") continue;
109
+ for (const bufferedChunk of buffered) yield bufferedChunk;
110
+ passThrough = true;
111
+ }
112
+ if (!passThrough && bufferedBytes > 0) {
113
+ const raw = Buffer.concat(buffered, bufferedBytes);
114
+ inspectBufferedFrontmatter(raw, relativePath, true);
115
+ for (const bufferedChunk of buffered) yield bufferedChunk;
116
+ }
117
+ }
118
+
119
+ export function createSupportPassportOfflineSyncGuard(storage: {
120
+ dir: string;
121
+ readMemoryByPath(filePath: string): Promise<MemoryFile | null>;
122
+ }) {
123
+ const excludePrivateFile = createSupportPassportPrivateFileExclusion(storage);
124
+
125
+ const targetForPath = (relativePath: string): OfflineSyncFileTarget => {
126
+ const normalizedPath = validateArchiveRelativePath(relativePath, "path");
127
+ return {
128
+ root: storage.dir,
129
+ path: normalizedPath,
130
+ filePath: path.resolve(storage.dir, ...normalizedPath.split("/")),
131
+ };
132
+ };
133
+
134
+ const assertTargetAllowed = async (target: OfflineSyncFileTarget): Promise<void> => {
135
+ if (await excludePrivateFile(target)) {
136
+ throw new Error(`offline sync cannot modify private support-passport record: ${target.path}`);
137
+ }
138
+ };
139
+
140
+ return {
141
+ async assertPathAllowed(relativePath: string): Promise<void> {
142
+ await assertTargetAllowed(targetForPath(relativePath));
143
+ },
144
+ assertContentAllowed(relativePath: string, content: Buffer): void {
145
+ inspectBufferedFrontmatter(content, relativePath, true);
146
+ },
147
+ assertTargetAllowed,
148
+ guardChunks(relativePath: string, chunks: AsyncIterable<Buffer>): AsyncIterable<Buffer> {
149
+ return guardSupportPassportChunks(chunks, relativePath);
150
+ },
151
+ excludePrivateFile,
152
+ };
153
+ }
154
+
155
+ export async function applySupportPassportOfflineSyncFileContent(
156
+ storage: SupportPassportOfflineSyncStorage,
157
+ options: SupportPassportOfflineSyncFileContentInput,
158
+ ): Promise<OfflineSyncApplyFileContentChunkResult> {
159
+ const guard = createSupportPassportOfflineSyncGuard(storage);
160
+ await guard.assertPathAllowed(options.path);
161
+ return applyOfflineSyncFileContentChunk({
162
+ root: storage.dir,
163
+ sourceId: options.sourceId,
164
+ path: options.path,
165
+ sha256: options.sha256,
166
+ bytes: options.bytes,
167
+ mtimeMs: options.mtimeMs,
168
+ offset: options.offset,
169
+ baseSha256: options.baseSha256,
170
+ content: options.content,
171
+ includeTranscripts: options.includeTranscripts !== false,
172
+ readFile: async ({ filePath }) => storage.readOfflineSyncFile(filePath),
173
+ readFileDigest: async ({ filePath }) => storage.digestOfflineSyncFile(filePath),
174
+ writeFile: async ({ filePath, content }) => storage.writeOfflineSyncFile(filePath, content),
175
+ writeStagingFile: async ({ filePath, content }) => storage.writeOfflineSyncStagingFile(filePath, content),
176
+ writeFileChunks: async (target) => {
177
+ await guard.assertTargetAllowed(target);
178
+ await storage.writeOfflineSyncFileChunks(
179
+ target.filePath,
180
+ guard.guardChunks(target.path, target.chunks),
181
+ );
182
+ },
183
+ });
184
+ }
185
+
186
+ export async function applySupportPassportOfflineSyncChangeset(
187
+ storage: SupportPassportOfflineSyncStorage,
188
+ options: SupportPassportOfflineSyncApplyInput,
189
+ ): Promise<OfflineSyncApplyChangesetResult> {
190
+ const guard = createSupportPassportOfflineSyncGuard(storage);
191
+ const changeset = normalizeOfflineSyncChangeset(options.changeset);
192
+ for (const change of changeset.changes) {
193
+ await guard.assertPathAllowed(change.path);
194
+ if (change.type === "upsert") {
195
+ guard.assertContentAllowed(change.path, Buffer.from(change.file.contentBase64, "base64"));
196
+ }
197
+ }
198
+ const result = await applyOfflineSyncChangeset({
199
+ root: storage.dir,
200
+ changeset,
201
+ returnCurrentFiles: false,
202
+ readFile: async ({ filePath }) => storage.readOfflineSyncFile(filePath),
203
+ readFileDigest: async ({ filePath }) => storage.digestOfflineSyncFile(filePath),
204
+ writeFile: async (target) => {
205
+ await guard.assertTargetAllowed(target);
206
+ guard.assertContentAllowed(target.path, target.content);
207
+ await storage.writeOfflineSyncFile(target.filePath, target.content);
208
+ },
209
+ deleteFile: async (target) => {
210
+ await guard.assertTargetAllowed(target);
211
+ await storage.deleteOfflineSyncFile(target.filePath, target.mtimeMs ?? null);
212
+ },
213
+ recordDeletionRevision: async ({ filePath, mtimeMs }) =>
214
+ storage.recordReplicatedDeletionRevision(filePath, mtimeMs),
215
+ });
216
+ if (options.returnCurrentFiles === false) return result;
217
+
218
+ const current = await buildOfflineSyncSnapshot({
219
+ root: storage.dir,
220
+ sourceId: "local",
221
+ includeContent: false,
222
+ includeTranscripts: changeset.includeTranscripts,
223
+ excludeNodeLocalState: false,
224
+ readFile: async ({ filePath }) => storage.readOfflineSyncFile(filePath),
225
+ readFileDigest: async ({ filePath }) => storage.digestOfflineSyncFile(filePath),
226
+ excludeFile: guard.excludePrivateFile,
227
+ });
228
+ const { currentFiles: _partialFiles, currentFilesComplete: _incomplete, ...counts } = result;
229
+ return { ...counts, currentFiles: current.files };
230
+ }
@@ -0,0 +1,53 @@
1
+ import { createHash } from "node:crypto";
2
+ import path from "node:path";
3
+
4
+ import type { StorageManager } from "../index.js";
5
+ import { type HeldFileLockController, serializeMutations, withHeldFileLock } from "../utils/serialize-mutations.js";
6
+ import { SupportPassportError } from "./errors.js";
7
+
8
+ const CARD_MUTATION_LOCK_STALE_MS = 60_000;
9
+ const CARD_MUTATION_LOCK_MAX_WAIT_MS = 30_000;
10
+
11
+ export type SupportPassportOwnerLockScope =
12
+ | { namespace: string; principal: string; ownerKey?: never }
13
+ | { namespace: string; ownerKey: string; principal?: never };
14
+
15
+ export function computeSupportPassportOwnerLockKey(namespace: string, principal: string): string {
16
+ return createHash("sha256").update(JSON.stringify([namespace, principal])).digest("hex");
17
+ }
18
+
19
+ export function supportPassportOwnerLockPath(
20
+ storage: StorageManager,
21
+ scope: SupportPassportOwnerLockScope
22
+ ): string {
23
+ const ownerLockKey = scope.ownerKey ?? computeSupportPassportOwnerLockKey(scope.namespace, scope.principal);
24
+ if (!/^[a-f0-9]{64}$/.test(ownerLockKey)) {
25
+ throw new SupportPassportError("card_data_invalid", "The support passport owner scope is invalid.", 500);
26
+ }
27
+ return path.join(storage.dir, "state", `support-passport-cards-${ownerLockKey}.lock`);
28
+ }
29
+
30
+ export async function withSupportPassportOwnerLock<T>(
31
+ storage: StorageManager,
32
+ scope: SupportPassportOwnerLockScope,
33
+ task: (lock: HeldFileLockController) => Promise<T>
34
+ ): Promise<T> {
35
+ const lockPath = supportPassportOwnerLockPath(storage, scope);
36
+ return await serializeMutations(lockPath, () =>
37
+ withHeldFileLock(
38
+ lockPath,
39
+ { staleMs: CARD_MUTATION_LOCK_STALE_MS, maxWaitMs: CARD_MUTATION_LOCK_MAX_WAIT_MS },
40
+ async (acquired, lock) => {
41
+ if (!acquired) {
42
+ throw new SupportPassportError("storage_conflict", "The support passport is busy. Try again.", 409);
43
+ }
44
+ return await task(lock);
45
+ }
46
+ )
47
+ );
48
+ }
49
+
50
+ export async function requireSupportPassportOwnerLock(lock: HeldFileLockController): Promise<void> {
51
+ if (await lock.refresh()) return;
52
+ throw new SupportPassportError("storage_conflict", "The support passport changed during the request.", 409);
53
+ }
@@ -0,0 +1,371 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { type Stats, constants as fsConstants } from "node:fs";
3
+ import { type FileHandle, lstat, mkdir, open, rename, rm, stat } from "node:fs/promises";
4
+ import path from "node:path";
5
+
6
+ const UNSUPPORTED_DIRECTORY_SYNC_ERRORS = new Set(["EINVAL", "ENOSYS", "ENOTSUP", "EOPNOTSUPP"]);
7
+ const NON_WRITABLE_ANCESTOR_SYNC_ERRORS = new Set(["EROFS", "EPERM", "EACCES"]);
8
+
9
+ function assertStableDirectory(before: Stats, opened: Stats, after: Stats, errorMessage: string): void {
10
+ if (
11
+ before.isSymbolicLink() ||
12
+ !before.isDirectory() ||
13
+ after.isSymbolicLink() ||
14
+ !after.isDirectory() ||
15
+ before.dev !== opened.dev ||
16
+ before.ino !== opened.ino ||
17
+ after.dev !== opened.dev ||
18
+ after.ino !== opened.ino
19
+ ) {
20
+ throw new Error(errorMessage);
21
+ }
22
+ }
23
+
24
+ function assertStableRegularFile(before: Stats, opened: Stats, after: Stats, errorMessage: string): void {
25
+ if (
26
+ before.isSymbolicLink() ||
27
+ !before.isFile() ||
28
+ after.isSymbolicLink() ||
29
+ !after.isFile() ||
30
+ before.dev !== opened.dev ||
31
+ before.ino !== opened.ino ||
32
+ after.dev !== opened.dev ||
33
+ after.ino !== opened.ino ||
34
+ opened.nlink !== 1
35
+ ) {
36
+ throw new Error(errorMessage);
37
+ }
38
+ }
39
+
40
+ function openFlags(...flags: Array<number | undefined>): number {
41
+ let combined = 0;
42
+ for (const flag of flags) combined |= typeof flag === "number" ? flag : 0;
43
+ return combined;
44
+ }
45
+
46
+ function assertContainedPath(trustedRoot: string, directory: string, errorMessage: string): void {
47
+ const relative = path.relative(path.resolve(trustedRoot), path.resolve(directory));
48
+ if (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
49
+ throw new Error(errorMessage);
50
+ }
51
+ }
52
+
53
+ async function openDirectoryNoFollow(
54
+ directory: string,
55
+ errorMessage: string
56
+ ): Promise<{
57
+ before: Stats;
58
+ opened: Stats;
59
+ handle: FileHandle;
60
+ }> {
61
+ const before = await lstat(directory);
62
+ if (before.isSymbolicLink() || !before.isDirectory()) throw new Error(errorMessage);
63
+ const handle = await open(
64
+ directory,
65
+ openFlags(fsConstants.O_RDONLY, fsConstants.O_DIRECTORY, fsConstants.O_NOFOLLOW),
66
+ );
67
+ try {
68
+ const opened = await handle.stat();
69
+ assertStableDirectory(before, opened, await lstat(directory), errorMessage);
70
+ return { before, opened, handle };
71
+ } catch (error) {
72
+ await handle.close().catch(() => undefined);
73
+ throw error;
74
+ }
75
+ }
76
+
77
+ async function closeDirectoryHandles(handles: FileHandle[]): Promise<void> {
78
+ for (const handle of handles.reverse()) await handle.close().catch(() => undefined);
79
+ }
80
+
81
+ async function syncDirectoryHandle(handle: FileHandle): Promise<void> {
82
+ try {
83
+ await handle.sync();
84
+ } catch (error) {
85
+ const code = (error as NodeJS.ErrnoException).code;
86
+ if (!UNSUPPORTED_DIRECTORY_SYNC_ERRORS.has(code ?? "")) throw error;
87
+ }
88
+ }
89
+
90
+ export async function resolvePrivateDirectoryPath(
91
+ directory: string,
92
+ handle: FileHandle,
93
+ opened: Stats,
94
+ errorMessage: string,
95
+ platform: NodeJS.Platform = process.platform
96
+ ): Promise<string> {
97
+ const descriptorRoot = requirePrivateFileDescriptorRoot(platform, errorMessage);
98
+ const pinnedPath = path.join(descriptorRoot, String(handle.fd));
99
+ const metadata = await stat(pinnedPath);
100
+ if (!metadata.isDirectory() || metadata.dev !== opened.dev || metadata.ino !== opened.ino) {
101
+ throw new Error(errorMessage);
102
+ }
103
+ return pinnedPath;
104
+ }
105
+
106
+ export function requirePrivateFileDescriptorRoot(platform: NodeJS.Platform, errorMessage: string): string {
107
+ if (platform === "linux") return "/proc/self/fd";
108
+ if (platform === "darwin" || platform === "freebsd" || platform === "openbsd") return "/dev/fd";
109
+ throw new Error(errorMessage);
110
+ }
111
+
112
+ async function openStableDirectoryFromRoot(
113
+ trustedRoot: string,
114
+ directory: string,
115
+ errorMessage: string,
116
+ platform: NodeJS.Platform = process.platform,
117
+ ): Promise<{
118
+ before: Stats;
119
+ opened: Stats;
120
+ handle?: FileHandle;
121
+ handles: FileHandle[];
122
+ pinnedDirectory: string;
123
+ }> {
124
+ const root = path.resolve(trustedRoot);
125
+ const target = path.resolve(directory);
126
+ assertContainedPath(root, target, errorMessage);
127
+ requirePrivateFileDescriptorRoot(platform, errorMessage);
128
+ const relative = path.relative(root, target);
129
+ const components = relative === "" ? [] : relative.split(path.sep);
130
+ const handles: FileHandle[] = [];
131
+ let currentPath = root;
132
+ try {
133
+ let current = await openDirectoryNoFollow(root, errorMessage);
134
+ handles.push(current.handle);
135
+ for (const component of components) {
136
+ const pinnedParent = await resolvePrivateDirectoryPath(currentPath, current.handle, current.opened, errorMessage);
137
+ const child = await openDirectoryNoFollow(path.join(pinnedParent, component), errorMessage);
138
+ handles.push(child.handle);
139
+ assertStableDirectory(current.before, current.opened, await lstat(currentPath), errorMessage);
140
+ currentPath = path.join(currentPath, component);
141
+ current = child;
142
+ }
143
+ assertStableDirectory(current.before, current.opened, await lstat(target), errorMessage);
144
+ return {
145
+ ...current,
146
+ handles,
147
+ pinnedDirectory: await resolvePrivateDirectoryPath(
148
+ target,
149
+ current.handle,
150
+ current.opened,
151
+ errorMessage,
152
+ platform,
153
+ ),
154
+ };
155
+ } catch (error) {
156
+ await closeDirectoryHandles(handles);
157
+ throw error;
158
+ }
159
+ }
160
+
161
+ export async function ensurePrivateDirectoryNoFollow(
162
+ trustedRoot: string,
163
+ directory: string,
164
+ errorMessage: string,
165
+ syncVerifiedParent: (handle: FileHandle) => Promise<void> = syncDirectoryHandle,
166
+ hardenExistingChildren = true,
167
+ platform: NodeJS.Platform = process.platform,
168
+ ): Promise<void> {
169
+ const root = path.resolve(trustedRoot);
170
+ const target = path.resolve(directory);
171
+ assertContainedPath(root, target, errorMessage);
172
+ const relative = path.relative(root, target);
173
+ requirePrivateFileDescriptorRoot(platform, errorMessage);
174
+ const components = relative === "" ? [] : relative.split(path.sep);
175
+ const handles: FileHandle[] = [];
176
+ let currentPath = root;
177
+ try {
178
+ let current = await openDirectoryNoFollow(root, errorMessage);
179
+ handles.push(current.handle);
180
+ for (const component of components) {
181
+ const pinnedParent = await resolvePrivateDirectoryPath(currentPath, current.handle, current.opened, errorMessage);
182
+ const childPath = path.join(pinnedParent, component);
183
+ let created = false;
184
+ try {
185
+ await mkdir(childPath, { mode: 0o700 });
186
+ created = true;
187
+ } catch (error) {
188
+ if ((error as NodeJS.ErrnoException).code !== "EEXIST") throw error;
189
+ }
190
+ await syncVerifiedParent(current.handle);
191
+ const child = await openDirectoryNoFollow(childPath, errorMessage);
192
+ handles.push(child.handle);
193
+ if (created || (hardenExistingChildren && (child.opened.mode & 0o777) !== 0o700)) {
194
+ await child.handle.chmod(0o700);
195
+ }
196
+ assertStableDirectory(current.before, current.opened, await lstat(currentPath), errorMessage);
197
+ currentPath = path.join(currentPath, component);
198
+ current = child;
199
+ }
200
+ assertStableDirectory(current.before, current.opened, await lstat(target), errorMessage);
201
+ } finally {
202
+ await closeDirectoryHandles(handles);
203
+ }
204
+ }
205
+
206
+ export async function ensurePrivateDirectoryTreeNoFollow(
207
+ directory: string,
208
+ errorMessage: string,
209
+ syncVerifiedParent: (handle: FileHandle) => Promise<void> = syncDirectoryHandle,
210
+ platform: NodeJS.Platform = process.platform,
211
+ ): Promise<void> {
212
+ const target = path.resolve(directory);
213
+ const filesystemRoot = path.parse(target).root;
214
+ const rootMetadata = await stat(filesystemRoot);
215
+ await ensurePrivateDirectoryNoFollow(
216
+ filesystemRoot,
217
+ target,
218
+ errorMessage,
219
+ async (handle) => {
220
+ try {
221
+ await syncVerifiedParent(handle);
222
+ } catch (error) {
223
+ const code = (error as NodeJS.ErrnoException).code;
224
+ const metadata = await handle.stat();
225
+ if (
226
+ metadata.ino === rootMetadata.ino &&
227
+ metadata.dev === rootMetadata.dev &&
228
+ NON_WRITABLE_ANCESTOR_SYNC_ERRORS.has(code ?? "")
229
+ ) {
230
+ return;
231
+ }
232
+ throw error;
233
+ }
234
+ },
235
+ false,
236
+ platform,
237
+ );
238
+ }
239
+
240
+ export async function withPrivateDirectoryNoFollow<T>(
241
+ trustedRoot: string,
242
+ directory: string,
243
+ errorMessage: string,
244
+ task: (pinnedDirectory: string) => Promise<T>,
245
+ platform: NodeJS.Platform = process.platform,
246
+ ): Promise<T> {
247
+ let directoryHandles: FileHandle[] = [];
248
+ try {
249
+ const stableDirectory = await openStableDirectoryFromRoot(trustedRoot, directory, errorMessage, platform);
250
+ directoryHandles = stableDirectory.handles;
251
+ const result = await task(stableDirectory.pinnedDirectory);
252
+ assertStableDirectory(stableDirectory.before, stableDirectory.opened, await lstat(directory), errorMessage);
253
+ return result;
254
+ } finally {
255
+ await closeDirectoryHandles(directoryHandles);
256
+ }
257
+ }
258
+
259
+ export async function readPrivateFileNoFollow(
260
+ directory: string,
261
+ filePath: string,
262
+ errorMessage: string,
263
+ trustedRoot = directory,
264
+ platform: NodeJS.Platform = process.platform,
265
+ ): Promise<string> {
266
+ if (path.dirname(filePath) !== path.resolve(directory)) throw new Error(errorMessage);
267
+ const targetName = path.basename(filePath);
268
+ let directoryHandles: FileHandle[] = [];
269
+ let fileHandle: FileHandle | undefined;
270
+ try {
271
+ const stableDirectory = await openStableDirectoryFromRoot(trustedRoot, directory, errorMessage, platform);
272
+ directoryHandles = stableDirectory.handles;
273
+ const pinnedDirectory = stableDirectory.pinnedDirectory;
274
+ const targetPath = path.join(pinnedDirectory, targetName);
275
+ const before = await lstat(targetPath);
276
+ if (before.isSymbolicLink() || !before.isFile()) throw new Error(errorMessage);
277
+ try {
278
+ fileHandle = await open(targetPath, openFlags(fsConstants.O_RDONLY, fsConstants.O_NOFOLLOW));
279
+ } catch (error) {
280
+ if ((error as NodeJS.ErrnoException).code === "ELOOP") throw new Error(errorMessage);
281
+ throw error;
282
+ }
283
+ const fileMetadata = await fileHandle.stat();
284
+ assertStableRegularFile(before, fileMetadata, await lstat(targetPath), errorMessage);
285
+ assertStableDirectory(stableDirectory.before, stableDirectory.opened, await lstat(directory), errorMessage);
286
+ return await fileHandle.readFile("utf8");
287
+ } finally {
288
+ await fileHandle?.close().catch(() => undefined);
289
+ await closeDirectoryHandles(directoryHandles);
290
+ }
291
+ }
292
+
293
+ export async function writePrivateFileAtomicallyNoFollow(
294
+ directory: string,
295
+ filePath: string,
296
+ content: string,
297
+ errorMessage: string,
298
+ trustedRoot = directory,
299
+ platform: NodeJS.Platform = process.platform,
300
+ ): Promise<void> {
301
+ if (path.dirname(filePath) !== path.resolve(directory)) throw new Error(errorMessage);
302
+ const targetName = path.basename(filePath);
303
+ const tempName = `.${targetName}.${randomUUID()}.tmp`;
304
+ let tempPath: string | undefined;
305
+ let directoryHandles: FileHandle[] = [];
306
+ let fileHandle: FileHandle | undefined;
307
+ try {
308
+ const stableDirectory = await openStableDirectoryFromRoot(trustedRoot, directory, errorMessage, platform);
309
+ directoryHandles = stableDirectory.handles;
310
+ const pinnedDirectory = stableDirectory.pinnedDirectory;
311
+ tempPath = path.join(pinnedDirectory, tempName);
312
+ const targetPath = path.join(pinnedDirectory, targetName);
313
+ try {
314
+ fileHandle = await open(
315
+ tempPath,
316
+ openFlags(fsConstants.O_WRONLY, fsConstants.O_CREAT, fsConstants.O_EXCL, fsConstants.O_NOFOLLOW),
317
+ 0o600
318
+ );
319
+ } catch (error) {
320
+ if ((error as NodeJS.ErrnoException).code === "ELOOP") throw new Error(errorMessage);
321
+ throw error;
322
+ }
323
+ const fileMetadata = await fileHandle.stat();
324
+ const tempMetadata = await lstat(tempPath);
325
+ assertStableRegularFile(tempMetadata, fileMetadata, await lstat(tempPath), errorMessage);
326
+ assertStableDirectory(stableDirectory.before, stableDirectory.opened, await lstat(directory), errorMessage);
327
+ await fileHandle.chmod(0o600);
328
+ await fileHandle.writeFile(content, "utf8");
329
+ await fileHandle.sync();
330
+ await fileHandle.close();
331
+ fileHandle = undefined;
332
+ assertStableDirectory(stableDirectory.before, stableDirectory.opened, await lstat(directory), errorMessage);
333
+ await rename(tempPath, targetPath);
334
+ assertStableDirectory(stableDirectory.before, stableDirectory.opened, await lstat(directory), errorMessage);
335
+ if (stableDirectory.handle) await syncDirectoryHandle(stableDirectory.handle);
336
+ } finally {
337
+ await fileHandle?.close().catch(() => undefined);
338
+ if (tempPath) await rm(tempPath, { force: true }).catch(() => undefined);
339
+ await closeDirectoryHandles(directoryHandles);
340
+ }
341
+ }
342
+
343
+ export async function removePrivateFilesNoFollow(
344
+ directory: string,
345
+ fileNames: string[],
346
+ errorMessage: string,
347
+ trustedRoot = directory,
348
+ platform: NodeJS.Platform = process.platform,
349
+ ): Promise<void> {
350
+ if (
351
+ fileNames.some(
352
+ (fileName) =>
353
+ fileName.length === 0 || fileName === "." || fileName === ".." || path.basename(fileName) !== fileName
354
+ )
355
+ ) {
356
+ throw new Error(errorMessage);
357
+ }
358
+ let directoryHandles: FileHandle[] = [];
359
+ try {
360
+ const stableDirectory = await openStableDirectoryFromRoot(trustedRoot, directory, errorMessage, platform);
361
+ directoryHandles = stableDirectory.handles;
362
+ const pinnedDirectory = stableDirectory.pinnedDirectory;
363
+ for (const fileName of fileNames) {
364
+ await rm(path.join(pinnedDirectory, fileName), { force: true });
365
+ }
366
+ assertStableDirectory(stableDirectory.before, stableDirectory.opened, await lstat(directory), errorMessage);
367
+ if (stableDirectory.handle) await syncDirectoryHandle(stableDirectory.handle);
368
+ } finally {
369
+ await closeDirectoryHandles(directoryHandles);
370
+ }
371
+ }