@remnic/core 9.6.0 → 9.6.2

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 (333) hide show
  1. package/dist/access-admin-ops-surface.d.ts +7 -8
  2. package/dist/access-admin-ops-surface.js +8 -8
  3. package/dist/access-boundary.d.ts +9 -8
  4. package/dist/access-boundary.js +9 -9
  5. package/dist/access-cli.js +40 -40
  6. package/dist/access-http.d.ts +47 -16
  7. package/dist/access-http.js +13 -13
  8. package/dist/access-identity-continuity-surface.d.ts +6 -7
  9. package/dist/access-identity-continuity-surface.js +8 -8
  10. package/dist/access-lcm-surface.d.ts +7 -8
  11. package/dist/access-lcm-surface.js +8 -8
  12. package/dist/access-mcp.d.ts +13 -8
  13. package/dist/access-mcp.js +12 -12
  14. package/dist/access-observe-write-surface.d.ts +7 -8
  15. package/dist/access-observe-write-surface.js +8 -8
  16. package/dist/access-operations-batch.js +10 -10
  17. package/dist/access-operations.d.ts +8 -9
  18. package/dist/access-operations.js +11 -11
  19. package/dist/access-recall-surface.d.ts +7 -8
  20. package/dist/access-recall-surface.js +8 -8
  21. package/dist/access-schema.d.ts +6 -6
  22. package/dist/{access-service-CXJaql3A.d.ts → access-service-B_sc1w_k.d.ts} +9 -9
  23. package/dist/access-service.d.ts +7 -8
  24. package/dist/access-service.js +8 -8
  25. package/dist/access-surface-catalog.d.ts +7 -8
  26. package/dist/action-confidence.d.ts +1 -2
  27. package/dist/active-memory-bridge.d.ts +1 -2
  28. package/dist/active-recall.d.ts +1 -2
  29. package/dist/behavior-learner.d.ts +1 -2
  30. package/dist/behavior-signals.d.ts +1 -2
  31. package/dist/bootstrap.d.ts +6 -7
  32. package/dist/briefing.d.ts +2 -3
  33. package/dist/briefing.js +3 -3
  34. package/dist/buffer-surprise-report.d.ts +1 -2
  35. package/dist/buffer.d.ts +2 -3
  36. package/dist/buffer.js +1 -1
  37. package/dist/bulk-import/index.d.ts +3 -3
  38. package/dist/bulk-import/index.js +2 -2
  39. package/dist/calibration.d.ts +1 -2
  40. package/dist/capabilities.d.ts +1 -2
  41. package/dist/{catalog-C9cu67Ig.d.ts → catalog-9WanSGtt.d.ts} +1 -1
  42. package/dist/causal-behavior.d.ts +1 -2
  43. package/dist/causal-consolidation.d.ts +1 -2
  44. package/dist/causal-consolidation.js +4 -4
  45. package/dist/causal-trajectory-graph.d.ts +1 -2
  46. package/dist/{chunk-PNLFN2PZ.js → chunk-23G3T2Q5.js} +2 -2
  47. package/dist/{chunk-SIRPLF54.js → chunk-2K3OSLHE.js} +2 -2
  48. package/dist/{chunk-JS2HKKOK.js → chunk-3AC5UYKI.js} +1 -1
  49. package/dist/{chunk-JS2HKKOK.js.map → chunk-3AC5UYKI.js.map} +1 -1
  50. package/dist/{chunk-FKCRGLRD.js → chunk-4WRKKRTD.js} +266 -160
  51. package/dist/chunk-4WRKKRTD.js.map +1 -0
  52. package/dist/{chunk-LQHDIS7L.js → chunk-54BGIBCR.js} +2 -2
  53. package/dist/{chunk-PVUJ6WVV.js → chunk-5MH5NF3U.js} +5 -5
  54. package/dist/{chunk-PCLIWBGD.js → chunk-7ARV32PI.js} +8 -6
  55. package/dist/chunk-7ARV32PI.js.map +1 -0
  56. package/dist/{chunk-Y7UNNAZD.js → chunk-7ZYBDQ7V.js} +2 -2
  57. package/dist/{chunk-2PRQG7PV.js → chunk-AJVLDJU6.js} +1 -1
  58. package/dist/chunk-AJVLDJU6.js.map +1 -0
  59. package/dist/{chunk-LR5DZ56F.js → chunk-AXALUFAH.js} +2 -2
  60. package/dist/{chunk-AYZJID4S.js → chunk-B5GBWBCZ.js} +2 -2
  61. package/dist/{chunk-TLUDFPZL.js → chunk-CAZ3Z5M6.js} +2 -2
  62. package/dist/{chunk-RGK27ELN.js → chunk-DEKIXXIG.js} +2 -2
  63. package/dist/{chunk-2KK5WNQB.js → chunk-DQ42IQSK.js} +2 -2
  64. package/dist/{chunk-UFUKHGZD.js → chunk-F4I5NYBI.js} +89 -33
  65. package/dist/chunk-F4I5NYBI.js.map +1 -0
  66. package/dist/{chunk-HOJZMQ4J.js → chunk-FGDKJJZS.js} +2 -2
  67. package/dist/{chunk-ABP6QMVM.js → chunk-FQ7HAWWC.js} +2 -2
  68. package/dist/{chunk-CYWA2CXR.js → chunk-FVTLSFWU.js} +2 -2
  69. package/dist/{chunk-JJEJJ7RK.js → chunk-FXZTL7F7.js} +2 -2
  70. package/dist/{chunk-LADFWYHY.js → chunk-GOEV7CYF.js} +6 -6
  71. package/dist/chunk-GOEV7CYF.js.map +1 -0
  72. package/dist/{chunk-DANV2HTH.js → chunk-GQGDRLDM.js} +3 -3
  73. package/dist/{chunk-7F7Z6MOS.js → chunk-H4CKS5B2.js} +2 -2
  74. package/dist/{chunk-SVOHGUMI.js → chunk-H4FHR4UM.js} +174 -197
  75. package/dist/chunk-H4FHR4UM.js.map +1 -0
  76. package/dist/{chunk-CKITWVWJ.js → chunk-HSSERO3E.js} +2 -2
  77. package/dist/{chunk-23JFRB73.js → chunk-JODHPNLN.js} +2 -2
  78. package/dist/{chunk-DS7MM2ES.js → chunk-JZKR6ZAV.js} +2 -2
  79. package/dist/{chunk-BEM4D2QG.js → chunk-KJIJNLXT.js} +3 -3
  80. package/dist/{chunk-JSNVWNGX.js → chunk-KVSVVKHA.js} +2 -2
  81. package/dist/{chunk-4GNEDXDI.js → chunk-M67TLMP6.js} +2 -2
  82. package/dist/chunk-M67TLMP6.js.map +1 -0
  83. package/dist/{chunk-MC4FJXPA.js → chunk-MMACM5G2.js} +2 -2
  84. package/dist/{chunk-OUELRE5E.js → chunk-NOUJNHWG.js} +1 -1
  85. package/dist/chunk-NOUJNHWG.js.map +1 -0
  86. package/dist/{chunk-3XIY7MDQ.js → chunk-O6YI4CVI.js} +2 -2
  87. package/dist/{chunk-F53UF7CI.js → chunk-QLVLW7UD.js} +6 -2
  88. package/dist/{chunk-F53UF7CI.js.map → chunk-QLVLW7UD.js.map} +1 -1
  89. package/dist/{chunk-XCL57M6Q.js → chunk-RRKPLLCC.js} +21 -20
  90. package/dist/chunk-RRKPLLCC.js.map +1 -0
  91. package/dist/{chunk-72WG5QKN.js → chunk-SDAXPXER.js} +2 -2
  92. package/dist/{chunk-4LV23CHK.js → chunk-VHJARF5R.js} +2 -2
  93. package/dist/{chunk-H2DXDQCQ.js → chunk-VRJG3HIZ.js} +46 -42
  94. package/dist/chunk-VRJG3HIZ.js.map +1 -0
  95. package/dist/{chunk-6MMONPHM.js → chunk-W2AHSCKY.js} +2 -2
  96. package/dist/{chunk-P454KXD6.js → chunk-YAWJMR3Y.js} +21 -21
  97. package/dist/{chunk-K5LLP4CY.js → chunk-ZGPDSEKG.js} +20 -9
  98. package/dist/chunk-ZGPDSEKG.js.map +1 -0
  99. package/dist/{cli-CqdPA6z9.d.ts → cli-CnRsWREp.d.ts} +4 -5
  100. package/dist/cli.d.ts +9 -10
  101. package/dist/cli.js +32 -32
  102. package/dist/compounding/engine.d.ts +2 -3
  103. package/dist/compounding/engine.js +3 -3
  104. package/dist/compounding/preference-consolidator.d.ts +1 -2
  105. package/dist/compression-optimizer.d.ts +1 -2
  106. package/dist/config.d.ts +1 -2
  107. package/dist/connectors/codex-materialize-runner.d.ts +1 -2
  108. package/dist/connectors/codex-materialize-runner.js +3 -3
  109. package/dist/connectors/codex-materialize.d.ts +1 -2
  110. package/dist/connectors/index.d.ts +1 -2
  111. package/dist/connectors/index.js +3 -3
  112. package/dist/consolidation-provenance-check.d.ts +2 -3
  113. package/dist/consolidation-undo.d.ts +2 -3
  114. package/dist/contradiction/index.d.ts +3 -4
  115. package/dist/conversation-index/backend.d.ts +1 -2
  116. package/dist/conversation-index/chunker.d.ts +1 -2
  117. package/dist/conversation-index/faiss-adapter.d.ts +1 -2
  118. package/dist/conversation-index/indexer.d.ts +1 -2
  119. package/dist/conversation-index/search.d.ts +1 -2
  120. package/dist/day-summary.d.ts +1 -2
  121. package/dist/delinearize.d.ts +1 -2
  122. package/dist/direct-answer-wiring.d.ts +1 -2
  123. package/dist/direct-answer.d.ts +1 -2
  124. package/dist/embedding-fallback.d.ts +1 -2
  125. package/dist/enrichment/index.d.ts +1 -2
  126. package/dist/entity-retrieval.d.ts +2 -3
  127. package/dist/entity-retrieval.js +3 -3
  128. package/dist/entity-schema.d.ts +1 -2
  129. package/dist/explicit-capture.d.ts +8 -7
  130. package/dist/explicit-capture.js +1 -1
  131. package/dist/extraction-faithfulness.d.ts +1 -2
  132. package/dist/extraction-judge-telemetry.d.ts +1 -2
  133. package/dist/extraction-judge-training.d.ts +1 -2
  134. package/dist/extraction-judge.d.ts +1 -2
  135. package/dist/extraction.d.ts +1 -2
  136. package/dist/fallback-llm.d.ts +1 -2
  137. package/dist/graph-dashboard-diff.d.ts +1 -2
  138. package/dist/graph-dashboard-key.d.ts +1 -2
  139. package/dist/graph-dashboard-parser.d.ts +1 -2
  140. package/dist/graph-edge-reinforcement.d.ts +1 -2
  141. package/dist/graph-snapshot.d.ts +1 -2
  142. package/dist/graph.d.ts +1 -2
  143. package/dist/identity-continuity.d.ts +1 -2
  144. package/dist/importance.d.ts +1 -2
  145. package/dist/importers/index.d.ts +1 -1
  146. package/dist/importers/index.js +2 -2
  147. package/dist/index.d.ts +14 -15
  148. package/dist/index.js +40 -40
  149. package/dist/intent.d.ts +1 -2
  150. package/dist/lcm/engine.d.ts +1 -2
  151. package/dist/lcm/index.d.ts +1 -2
  152. package/dist/lcm/tools.d.ts +1 -2
  153. package/dist/lifecycle.d.ts +1 -2
  154. package/dist/live-connectors-runner.d.ts +1 -2
  155. package/dist/local-llm.d.ts +1 -2
  156. package/dist/local-model-endpoint.d.ts +1 -2
  157. package/dist/maintenance/memory-governance.d.ts +1 -2
  158. package/dist/maintenance/memory-governance.js +3 -3
  159. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -3
  160. package/dist/maintenance/rebuild-memory-projection.js +4 -4
  161. package/dist/mcp-memory-inspector-app.d.ts +7 -8
  162. package/dist/memory-action-policy.d.ts +1 -2
  163. package/dist/memory-cache.d.ts +1 -2
  164. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -2
  165. package/dist/memory-projection-store.d.ts +1 -2
  166. package/dist/memory-provenance.d.ts +1 -2
  167. package/dist/memory-worth-outcomes.d.ts +2 -3
  168. package/dist/models-json.d.ts +1 -2
  169. package/dist/namespaces/migrate.d.ts +3 -4
  170. package/dist/namespaces/migrate.js +4 -4
  171. package/dist/namespaces/principal.d.ts +1 -2
  172. package/dist/namespaces/search.d.ts +1 -2
  173. package/dist/namespaces/storage.d.ts +3 -4
  174. package/dist/namespaces/storage.js +3 -3
  175. package/dist/native-knowledge.d.ts +1 -2
  176. package/dist/operator-toolkit.d.ts +2 -3
  177. package/dist/operator-toolkit.js +7 -7
  178. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -3
  179. package/dist/orchestration/maintenance.d.ts +2 -3
  180. package/dist/orchestration/maintenance.js +5 -5
  181. package/dist/{orchestrator-CWFrT8AF.d.ts → orchestrator-NRLVXPpH.d.ts} +40 -15
  182. package/dist/orchestrator.d.ts +6 -7
  183. package/dist/orchestrator.js +40 -40
  184. package/dist/patterns-cli.d.ts +1 -2
  185. package/dist/{pipeline-DmqtvION.d.ts → pipeline-CiD86zIk.d.ts} +1 -1
  186. package/dist/policy-runtime.d.ts +1 -2
  187. package/dist/provenance.d.ts +1 -2
  188. package/dist/{qmd--fnPMK60.d.ts → qmd-Bef7DDuQ.d.ts} +1 -1
  189. package/dist/qmd-preflight.d.ts +2 -3
  190. package/dist/qmd-recall-cache.d.ts +1 -2
  191. package/dist/qmd.d.ts +2 -3
  192. package/dist/recall-disclosure-escalation.d.ts +1 -2
  193. package/dist/recall-explain-renderer.d.ts +1 -2
  194. package/dist/recall-explain-renderer.js +3 -3
  195. package/dist/recall-planner-llm.d.ts +1 -2
  196. package/dist/recall-state.d.ts +1 -2
  197. package/dist/recall-tag-filter.d.ts +1 -2
  198. package/dist/recall-timings.d.ts +1 -2
  199. package/dist/recall-xray-cli.d.ts +1 -2
  200. package/dist/recall-xray-cli.js +4 -4
  201. package/dist/recall-xray-renderer.d.ts +1 -2
  202. package/dist/recall-xray-renderer.js +3 -3
  203. package/dist/recall-xray.d.ts +1 -2
  204. package/dist/recall-xray.js +2 -2
  205. package/dist/replay/normalizers/chatgpt.d.ts +1 -0
  206. package/dist/replay/normalizers/chatgpt.js +3 -3
  207. package/dist/replay/normalizers/claude.d.ts +1 -0
  208. package/dist/replay/normalizers/claude.js +3 -3
  209. package/dist/replay/normalizers/openclaw.d.ts +1 -0
  210. package/dist/replay/normalizers/openclaw.js +3 -3
  211. package/dist/replay/normalizers/shared.d.ts +1 -0
  212. package/dist/replay/normalizers/shared.js +2 -2
  213. package/dist/replay/runner.d.ts +1 -0
  214. package/dist/replay/runner.js +2 -2
  215. package/dist/replay/types.d.ts +2 -1
  216. package/dist/replay/types.js +1 -1
  217. package/dist/resolve-auth-token.d.ts +1 -2
  218. package/dist/retrieval-agents.d.ts +2 -3
  219. package/dist/retrieval-tiers.d.ts +1 -2
  220. package/dist/routing/engine.d.ts +1 -2
  221. package/dist/routing/store.d.ts +1 -2
  222. package/dist/schemas.d.ts +44 -44
  223. package/dist/search/embed-helper.d.ts +1 -2
  224. package/dist/search/factory.d.ts +1 -2
  225. package/dist/search/index.d.ts +1 -2
  226. package/dist/search/lancedb-backend.d.ts +1 -2
  227. package/dist/search/meilisearch-backend.d.ts +1 -2
  228. package/dist/search/noop-backend.d.ts +1 -2
  229. package/dist/search/orama-backend.d.ts +1 -2
  230. package/dist/search/port.d.ts +1 -2
  231. package/dist/search/remote-backend.d.ts +1 -2
  232. package/dist/{semantic-DJR8_DMQ.d.ts → semantic-TddhF0y7.d.ts} +17 -1
  233. package/dist/{semantic-consolidation-O5lMZ4LG.d.ts → semantic-consolidation-BTShF2Fo.d.ts} +1 -1
  234. package/dist/semantic-consolidation.d.ts +2 -3
  235. package/dist/semantic-consolidation.js +4 -4
  236. package/dist/semantic-rule-promotion.js +3 -3
  237. package/dist/semantic-rule-verifier.d.ts +1 -2
  238. package/dist/semantic-rule-verifier.js +3 -3
  239. package/dist/session-observer-bands.d.ts +1 -2
  240. package/dist/session-observer-state.d.ts +1 -2
  241. package/dist/shared-context/manager.d.ts +3 -4
  242. package/dist/signal.d.ts +1 -2
  243. package/dist/{storage-C1maCNbc.d.ts → storage-DxPDAiU9.d.ts} +5 -1
  244. package/dist/storage.d.ts +2 -3
  245. package/dist/storage.js +2 -2
  246. package/dist/summarizer.d.ts +1 -2
  247. package/dist/summary-snapshot.d.ts +1 -2
  248. package/dist/temporal-supersession.d.ts +2 -3
  249. package/dist/temporal-validity.d.ts +1 -2
  250. package/dist/threading.d.ts +1 -2
  251. package/dist/tier-migration.d.ts +2 -3
  252. package/dist/tier-routing.d.ts +1 -2
  253. package/dist/topics.d.ts +1 -2
  254. package/dist/transcript.d.ts +1 -2
  255. package/dist/transfer/types.d.ts +12 -12
  256. package/dist/trust-score-stage.d.ts +1 -2
  257. package/dist/trust-score.d.ts +1 -2
  258. package/dist/{types-CGgcNWCG.d.ts → types-DDUDgd7T.d.ts} +93 -4
  259. package/dist/types.d.ts +1 -2
  260. package/dist/types.js +1 -1
  261. package/dist/utility-runtime.d.ts +1 -2
  262. package/dist/verified-recall.js +3 -3
  263. package/package.json +2 -2
  264. package/src/access-admin-ops-surface.ts +1 -0
  265. package/src/access-boundary.ts +2 -0
  266. package/src/access-http.test.ts +129 -0
  267. package/src/access-http.ts +92 -23
  268. package/src/access-mcp.ts +11 -2
  269. package/src/access-observe-write-surface.ts +87 -113
  270. package/src/access-operations-batch.ts +2 -2
  271. package/src/access-operations.ts +17 -16
  272. package/src/access-service.ts +11 -3
  273. package/src/admin/admin-surfaces.ts +2 -0
  274. package/src/buffer.ts +6 -1
  275. package/src/bulk-import/types.ts +2 -1
  276. package/src/coding/architecture-surfaces.test.ts +79 -5
  277. package/src/coding/architecture-surfaces.ts +7 -1
  278. package/src/coding/decision-surfaces.test.ts +1 -0
  279. package/src/coding/decision-surfaces.ts +4 -0
  280. package/src/connector-provenance-lifecycle.test.ts +618 -0
  281. package/src/connector-provenance.test.ts +219 -0
  282. package/src/dedup/semantic.test.ts +105 -0
  283. package/src/dedup/semantic.ts +69 -1
  284. package/src/explicit-capture.ts +21 -4
  285. package/src/orchestration/extraction-persist.ts +154 -6
  286. package/src/orchestration/extraction-run.ts +138 -228
  287. package/src/orchestration/persistence-index.ts +40 -5
  288. package/src/orchestration/turn-ingestion.ts +16 -9
  289. package/src/orchestrator-connector-dedup.test.ts +1082 -0
  290. package/src/orchestrator.ts +7 -11
  291. package/src/replay/types.ts +2 -1
  292. package/src/storage.ts +426 -553
  293. package/src/types.ts +11 -2
  294. package/src/utils/yaml-scalar.ts +20 -0
  295. package/dist/chunk-2PRQG7PV.js.map +0 -1
  296. package/dist/chunk-4GNEDXDI.js.map +0 -1
  297. package/dist/chunk-FKCRGLRD.js.map +0 -1
  298. package/dist/chunk-H2DXDQCQ.js.map +0 -1
  299. package/dist/chunk-K5LLP4CY.js.map +0 -1
  300. package/dist/chunk-LADFWYHY.js.map +0 -1
  301. package/dist/chunk-OUELRE5E.js.map +0 -1
  302. package/dist/chunk-PCLIWBGD.js.map +0 -1
  303. package/dist/chunk-SVOHGUMI.js.map +0 -1
  304. package/dist/chunk-UFUKHGZD.js.map +0 -1
  305. package/dist/chunk-XCL57M6Q.js.map +0 -1
  306. package/dist/types-gb_SNtjR.d.ts +0 -85
  307. /package/dist/{chunk-PNLFN2PZ.js.map → chunk-23G3T2Q5.js.map} +0 -0
  308. /package/dist/{chunk-SIRPLF54.js.map → chunk-2K3OSLHE.js.map} +0 -0
  309. /package/dist/{chunk-LQHDIS7L.js.map → chunk-54BGIBCR.js.map} +0 -0
  310. /package/dist/{chunk-PVUJ6WVV.js.map → chunk-5MH5NF3U.js.map} +0 -0
  311. /package/dist/{chunk-Y7UNNAZD.js.map → chunk-7ZYBDQ7V.js.map} +0 -0
  312. /package/dist/{chunk-LR5DZ56F.js.map → chunk-AXALUFAH.js.map} +0 -0
  313. /package/dist/{chunk-AYZJID4S.js.map → chunk-B5GBWBCZ.js.map} +0 -0
  314. /package/dist/{chunk-TLUDFPZL.js.map → chunk-CAZ3Z5M6.js.map} +0 -0
  315. /package/dist/{chunk-RGK27ELN.js.map → chunk-DEKIXXIG.js.map} +0 -0
  316. /package/dist/{chunk-2KK5WNQB.js.map → chunk-DQ42IQSK.js.map} +0 -0
  317. /package/dist/{chunk-HOJZMQ4J.js.map → chunk-FGDKJJZS.js.map} +0 -0
  318. /package/dist/{chunk-ABP6QMVM.js.map → chunk-FQ7HAWWC.js.map} +0 -0
  319. /package/dist/{chunk-CYWA2CXR.js.map → chunk-FVTLSFWU.js.map} +0 -0
  320. /package/dist/{chunk-JJEJJ7RK.js.map → chunk-FXZTL7F7.js.map} +0 -0
  321. /package/dist/{chunk-DANV2HTH.js.map → chunk-GQGDRLDM.js.map} +0 -0
  322. /package/dist/{chunk-7F7Z6MOS.js.map → chunk-H4CKS5B2.js.map} +0 -0
  323. /package/dist/{chunk-CKITWVWJ.js.map → chunk-HSSERO3E.js.map} +0 -0
  324. /package/dist/{chunk-23JFRB73.js.map → chunk-JODHPNLN.js.map} +0 -0
  325. /package/dist/{chunk-DS7MM2ES.js.map → chunk-JZKR6ZAV.js.map} +0 -0
  326. /package/dist/{chunk-BEM4D2QG.js.map → chunk-KJIJNLXT.js.map} +0 -0
  327. /package/dist/{chunk-JSNVWNGX.js.map → chunk-KVSVVKHA.js.map} +0 -0
  328. /package/dist/{chunk-MC4FJXPA.js.map → chunk-MMACM5G2.js.map} +0 -0
  329. /package/dist/{chunk-3XIY7MDQ.js.map → chunk-O6YI4CVI.js.map} +0 -0
  330. /package/dist/{chunk-72WG5QKN.js.map → chunk-SDAXPXER.js.map} +0 -0
  331. /package/dist/{chunk-4LV23CHK.js.map → chunk-VHJARF5R.js.map} +0 -0
  332. /package/dist/{chunk-6MMONPHM.js.map → chunk-W2AHSCKY.js.map} +0 -0
  333. /package/dist/{chunk-P454KXD6.js.map → chunk-YAWJMR3Y.js.map} +0 -0
@@ -2585,3 +2585,132 @@ test("HTTP chat/message gates the NEW session's namespace — scoped token canno
2585
2585
  await rm(dir, { recursive: true, force: true });
2586
2586
  }
2587
2587
  });
2588
+
2589
+ // ---------------------------------------------------------------------------
2590
+ // PR #1852: token-rotation race — authorized entry must be reused for provenance
2591
+ // ---------------------------------------------------------------------------
2592
+
2593
+ test("PR #1852: token rotation between authorization and write does not stamp the wrong connector", async () => {
2594
+ // Race: the dynamic-token authorization resolves an entry (connector A),
2595
+ // then the provenance resolver re-reads the token store. If the store
2596
+ // rotated between the two reads, the OLD code stamped connector B. The
2597
+ // fix caches the matched entry per-request so the provenance comes from
2598
+ // the SAME entry that authorized.
2599
+ let getterCalls = 0;
2600
+ const entriesGetter = () => {
2601
+ getterCalls++;
2602
+ // First call (authorization): token -> "chatgpt".
2603
+ // Subsequent call (provenance in the OLD code): token -> "codex-cli".
2604
+ // With the fix the getter is called only once; the second call never
2605
+ // happens and the cached "chatgpt" entry is reused.
2606
+ if (getterCalls <= 1) {
2607
+ return [{ token: "race_token", connector: "chatgpt" }];
2608
+ }
2609
+ return [{ token: "race_token", connector: "codex-cli" }];
2610
+ };
2611
+
2612
+ let capturedSourceConnector: string | undefined;
2613
+ const service = {
2614
+ memoryStore: (req: { sourceConnector?: string }) => {
2615
+ capturedSourceConnector = req.sourceConnector;
2616
+ return Promise.resolve({
2617
+ schemaVersion: 1,
2618
+ operation: "memory_store",
2619
+ namespace: "default",
2620
+ dryRun: false,
2621
+ accepted: true,
2622
+ queued: false,
2623
+ status: "stored",
2624
+ });
2625
+ },
2626
+ } as unknown as EngramAccessService;
2627
+
2628
+ const server = new EngramAccessHttpServer({
2629
+ service,
2630
+ port: 0,
2631
+ authTokenEntriesGetter: entriesGetter,
2632
+ adminConsoleEnabled: false,
2633
+ });
2634
+ const status = await server.start();
2635
+ try {
2636
+ const res = await fetch(`http://127.0.0.1:${status.port}/engram/v1/memories`, {
2637
+ method: "POST",
2638
+ headers: {
2639
+ authorization: "Bearer race_token",
2640
+ "content-type": "application/json",
2641
+ },
2642
+ body: JSON.stringify({
2643
+ content: "race-test memory",
2644
+ schemaVersion: 1,
2645
+ idempotencyKey: "race-key-1852",
2646
+ }),
2647
+ });
2648
+ assert.equal(res.status, 201, "memory_store must succeed with a valid entry token");
2649
+
2650
+ // The provenance must come from the entry that AUTHORIZED the request
2651
+ // ("chatgpt"), not from the rotated store ("codex-cli").
2652
+ assert.equal(
2653
+ capturedSourceConnector,
2654
+ "chatgpt",
2655
+ "sourceConnector must be from the authorized entry, not the rotated store",
2656
+ );
2657
+ // The getter must have been called only once — the matched entry is
2658
+ // cached per-request.
2659
+ assert.equal(getterCalls, 1, "authTokenEntriesGetter must be called once (cached per-request)");
2660
+ } finally {
2661
+ await server.stop();
2662
+ }
2663
+ });
2664
+
2665
+ test("PR #1852: static operator token has no connector provenance under rotation", async () => {
2666
+ // An operator-supplied static token must never acquire connector provenance,
2667
+ // even when an entries getter is also configured and the static token
2668
+ // appears there under a different connector. This guards the short-circuit
2669
+ // in resolveMatchedEntry: static tokens return { token } (no connector).
2670
+ let capturedSourceConnector: string | undefined;
2671
+ const service = {
2672
+ memoryStore: (req: { sourceConnector?: string }) => {
2673
+ capturedSourceConnector = req.sourceConnector;
2674
+ return Promise.resolve({
2675
+ schemaVersion: 1,
2676
+ operation: "memory_store",
2677
+ namespace: "default",
2678
+ dryRun: false,
2679
+ accepted: true,
2680
+ queued: false,
2681
+ status: "stored",
2682
+ });
2683
+ },
2684
+ } as unknown as EngramAccessService;
2685
+
2686
+ const server = new EngramAccessHttpServer({
2687
+ service,
2688
+ port: 0,
2689
+ authToken: "operator-static",
2690
+ authTokenEntriesGetter: () => [{ token: "operator-static", connector: "chatgpt" }],
2691
+ adminConsoleEnabled: false,
2692
+ });
2693
+ const status = await server.start();
2694
+ try {
2695
+ const res = await fetch(`http://127.0.0.1:${status.port}/engram/v1/memories`, {
2696
+ method: "POST",
2697
+ headers: {
2698
+ authorization: "Bearer operator-static",
2699
+ "content-type": "application/json",
2700
+ },
2701
+ body: JSON.stringify({
2702
+ content: "operator-token memory",
2703
+ schemaVersion: 1,
2704
+ idempotencyKey: "static-key-1852",
2705
+ }),
2706
+ });
2707
+ assert.equal(res.status, 201);
2708
+ assert.equal(
2709
+ capturedSourceConnector,
2710
+ undefined,
2711
+ "static operator token must carry no connector provenance",
2712
+ );
2713
+ } finally {
2714
+ await server.stop();
2715
+ }
2716
+ });
@@ -1566,6 +1566,9 @@ export class EngramAccessHttpServer {
1566
1566
  // Forward cwd/projectTag for auto git-context resolution (issue #569).
1567
1567
  cwd: body.cwd,
1568
1568
  projectTag: body.projectTag,
1569
+ // Phase 1 provenance: server-resolved connector identity from the
1570
+ // bearer token (REST path, mirroring the MCP tools/call dispatch).
1571
+ sourceConnector: this.resolveConnector(req),
1569
1572
  },
1570
1573
  // Enforce the write-quota INSIDE the service's idempotency lock
1571
1574
  // (beforeExecute, only on a real miss). A retried observe that hits the
@@ -1663,6 +1666,9 @@ export class EngramAccessHttpServer {
1663
1666
  service: this.service,
1664
1667
  authenticatedPrincipal: this.resolveRequestPrincipal(req),
1665
1668
  hooks: { enforceWriteQuota: () => this.ensureWriteRateLimitAvailable() },
1669
+ // Phase 1 provenance: server-resolved connector identity from the
1670
+ // bearer token (REST path, mirroring the MCP tools/call dispatch).
1671
+ sourceConnector: this.resolveConnector(req),
1666
1672
  })) as { result: EngramAccessWriteResponse };
1667
1673
  const response = output.result;
1668
1674
  if (this.shouldCountWriteRateLimit(response as { dryRun?: boolean; idempotencyReplay?: boolean })) {
@@ -1693,6 +1699,7 @@ export class EngramAccessHttpServer {
1693
1699
  const output = (await op.run(this.gatedBodyNamespace(req, body), {
1694
1700
  service: this.service,
1695
1701
  authenticatedPrincipal: this.resolveRequestPrincipal(req),
1702
+ sourceConnector: this.resolveConnector(req),
1696
1703
  })) as { result: unknown };
1697
1704
  if (isWriteSubcommand) {
1698
1705
  this.recordWriteRateLimitHit();
@@ -1717,6 +1724,7 @@ export class EngramAccessHttpServer {
1717
1724
  const output = (await op.run(this.gatedBodyNamespace(req, body), {
1718
1725
  service: this.service,
1719
1726
  authenticatedPrincipal: this.resolveRequestPrincipal(req),
1727
+ sourceConnector: this.resolveConnector(req),
1720
1728
  })) as { result: unknown };
1721
1729
  if (isWriteSubcommand) {
1722
1730
  this.recordWriteRateLimitHit();
@@ -1824,6 +1832,9 @@ export class EngramAccessHttpServer {
1824
1832
  sourceReason: body.sourceReason,
1825
1833
  cwd: body.cwd,
1826
1834
  projectTag: body.projectTag,
1835
+ // Phase 1 provenance: server-resolved connector identity from the
1836
+ // bearer token (REST path, mirroring the MCP tools/call dispatch).
1837
+ sourceConnector: this.resolveConnector(req),
1827
1838
  };
1828
1839
  // Quota enforcement is solely authoritative inside suggestionSubmit
1829
1840
  // (enforceWriteQuota), atomic with the real miss and never on a replay; no
@@ -3106,6 +3117,7 @@ export class EngramAccessHttpServer {
3106
3117
  enforceWriteQuota: observeSelfEnforcesQuota
3107
3118
  ? () => this.ensureWriteRateLimitAvailable()
3108
3119
  : undefined,
3120
+ sourceConnector: this.resolveConnector(req),
3109
3121
  });
3110
3122
 
3111
3123
  if (isMcpWrite && response !== null) {
@@ -3446,13 +3458,44 @@ export class EngramAccessHttpServer {
3446
3458
  }
3447
3459
 
3448
3460
  /**
3449
- * Resolve the presenting token's entry for an authorized request, or null.
3450
- * Captures the matched entry including its capabilities record — so the
3451
- * op/namespace capability enforcement (issue #1837) uses the SAME entry
3452
- * that validated. Static operator tokens (`authToken`/`authTokens`) and
3453
- * the string-token getter carry no capabilities unrestricted.
3461
+ * Per-request cache of the matched token entry (the entry whose token
3462
+ * matched the bearer credential, BEFORE any path-policy check). Pinning
3463
+ * the entry to the first read means authorization, capability
3464
+ * enforcement, and connector provenance all observe the SAME token-store
3465
+ * snapshot — a rotation between the auth check and the write handler can
3466
+ * no longer stamp the wrong connector (PR #1852 race).
3454
3467
  */
3455
- private resolveAuthorizedEntry(
3468
+ private matchedEntryCache = new WeakMap<
3469
+ IncomingMessage,
3470
+ { token: string; connector?: string; capabilities?: TokenCapabilities } | null
3471
+ >();
3472
+
3473
+ /**
3474
+ * Resolve the matched token entry for this request, caching the result so
3475
+ * every downstream consumer (authorization, capability enforcement,
3476
+ * connector provenance) sees the same snapshot entry (PR #1852).
3477
+ */
3478
+ private resolveMatchedEntry(
3479
+ req: IncomingMessage,
3480
+ pathname?: string,
3481
+ ): { token: string; connector?: string; capabilities?: TokenCapabilities } | null {
3482
+ if (this.matchedEntryCache.has(req)) {
3483
+ return this.matchedEntryCache.get(req) ?? null;
3484
+ }
3485
+ const entry = this.computeMatchedEntry(req, pathname);
3486
+ this.matchedEntryCache.set(req, entry);
3487
+ return entry;
3488
+ }
3489
+
3490
+ /**
3491
+ * Find the entry whose token matches the request's bearer credential.
3492
+ * Static operator tokens (`authToken`/`authTokens`) and the string-token
3493
+ * getter carry no capabilities ⇒ unrestricted. Dynamic entry-based tokens
3494
+ * capture connector identity and capabilities. A corrupt or unreadable
3495
+ * token store returns null rather than propagating an error — provenance
3496
+ * must never block an already-authenticated request.
3497
+ */
3498
+ private computeMatchedEntry(
3456
3499
  req: IncomingMessage,
3457
3500
  pathname?: string,
3458
3501
  ): { token: string; connector?: string; capabilities?: TokenCapabilities } | null {
@@ -3513,13 +3556,13 @@ export class EngramAccessHttpServer {
3513
3556
  // identity it scopes (mint/revoke coherence). Capabilities ride on the
3514
3557
  // same entry so enforcement can never lag the token that validated.
3515
3558
  if (this.authTokenEntriesGetter) {
3516
- for (const entry of this.authTokenEntriesGetter()) {
3517
- if (!this.timingSafeStringEqual(token, entry.token)) continue;
3518
- const matched = { token: entry.token, connector: entry.connector, capabilities: entry.capabilities };
3519
- if (!this.tokenPathPolicy) return matched;
3520
- // Fail closed: a policy without a connector identity denies.
3521
- if (typeof entry.connector !== "string" || entry.connector.length === 0) return null;
3522
- return this.tokenPathPolicy(entry.connector, pathname) ? matched : null;
3559
+ try {
3560
+ for (const entry of this.authTokenEntriesGetter()) {
3561
+ if (!this.timingSafeStringEqual(token, entry.token)) continue;
3562
+ return { token: entry.token, connector: entry.connector, capabilities: entry.capabilities };
3563
+ }
3564
+ } catch {
3565
+ // Corrupt or unreadable tokens.json no match.
3523
3566
  }
3524
3567
  return null;
3525
3568
  }
@@ -3533,25 +3576,40 @@ export class EngramAccessHttpServer {
3533
3576
  return null;
3534
3577
  }
3535
3578
 
3536
- /** Cache for per-request capability resolution (avoids re-resolving). */
3537
- private capabilityCache = new WeakMap<IncomingMessage, TokenCapabilities | null>();
3579
+ /**
3580
+ * Resolve the presenting token's entry for an authorized request, or null.
3581
+ * Applies the path-policy gate (if configured) on top of the per-request
3582
+ * cached matched entry so the identity that is authorized is the same one
3583
+ * whose connector later stamps frontmatter. Static operator tokens and the
3584
+ * string-token getter carry no capabilities ⇒ unrestricted.
3585
+ */
3586
+ private resolveAuthorizedEntry(
3587
+ req: IncomingMessage,
3588
+ pathname?: string,
3589
+ ): { token: string; connector?: string; capabilities?: TokenCapabilities } | null {
3590
+ const matched = this.resolveMatchedEntry(req, pathname);
3591
+ if (!matched) return null;
3592
+ // Apply the path-policy gate for dynamic entry-based tokens.
3593
+ if ("connector" in matched && this.tokenPathPolicy) {
3594
+ // Fail closed: a policy without a connector identity denies.
3595
+ if (typeof matched.connector !== "string" || matched.connector.length === 0) return null;
3596
+ return this.tokenPathPolicy(matched.connector, pathname) ? matched : null;
3597
+ }
3598
+ return matched;
3599
+ }
3538
3600
 
3539
3601
  /**
3540
3602
  * Resolve the presenting token's capabilities for this request, or
3541
3603
  * undefined when the token is unrestricted (legacy / static operator /
3542
- * explicit-unrestricted record). Cached per-request. `null` sentinel
3543
- * distinguishes "resolved as unrestricted" from "not yet resolved".
3604
+ * explicit-unrestricted record). Reads from the per-request cached matched
3605
+ * entry so capabilities come from the same snapshot as authorization and
3606
+ * connector provenance (PR #1852).
3544
3607
  */
3545
3608
  private resolveTokenCapabilities(
3546
3609
  req: IncomingMessage,
3547
3610
  pathname?: string,
3548
3611
  ): TokenCapabilities | undefined {
3549
- if (this.capabilityCache.has(req)) {
3550
- return this.capabilityCache.get(req) ?? undefined;
3551
- }
3552
- const caps = this.resolveAuthorizedEntry(req, pathname)?.capabilities;
3553
- this.capabilityCache.set(req, caps ?? null);
3554
- return caps;
3612
+ return this.resolveMatchedEntry(req, pathname)?.capabilities;
3555
3613
  }
3556
3614
 
3557
3615
  /**
@@ -3578,6 +3636,17 @@ export class EngramAccessHttpServer {
3578
3636
  );
3579
3637
  }
3580
3638
  }
3639
+ /**
3640
+ * Resolve the connector identity for the request's bearer token (Phase 1
3641
+ * provenance). Reuses the per-request cached matched entry so a token
3642
+ * rotation between the auth check and the write handler cannot stamp the
3643
+ * wrong connector (PR #1852 race). Returns `undefined` for operator-
3644
+ * supplied static tokens or when no entry getter is configured — those
3645
+ * writes are operator-initiated.
3646
+ */
3647
+ private resolveConnector(req: IncomingMessage): string | undefined {
3648
+ return this.resolveMatchedEntry(req)?.connector;
3649
+ }
3581
3650
 
3582
3651
  private timingSafeStringEqual(a: string, b: string): boolean {
3583
3652
  const left = this.encodeSecret(a);
package/src/access-mcp.ts CHANGED
@@ -61,6 +61,12 @@ type McpRequestOptions = {
61
61
  * the write-rate-limit window); the standalone MCP server has no quota.
62
62
  */
63
63
  enforceWriteQuota?: () => void | Promise<void>;
64
+ /**
65
+ * Server-resolved connector identity (Phase 1 provenance). Set by the HTTP
66
+ * auth boundary from the matched token entry's connector; threaded into
67
+ * the operation context so write handlers stamp it onto frontmatter.
68
+ */
69
+ sourceConnector?: string;
64
70
  };
65
71
 
66
72
  type McpTool = {
@@ -2645,7 +2651,8 @@ export class EngramMcpServer {
2645
2651
  effectivePrincipal,
2646
2652
  options?.sessionId,
2647
2653
  mcpScope,
2648
- options?.enforceWriteQuota
2654
+ options?.enforceWriteQuota,
2655
+ options?.sourceConnector
2649
2656
  );
2650
2657
  return {
2651
2658
  jsonrpc: "2.0",
@@ -2853,7 +2860,8 @@ export class EngramMcpServer {
2853
2860
  effectivePrincipal?: string,
2854
2861
  mcpSessionId?: string,
2855
2862
  scope?: { namespace?: string; sessionKey?: string },
2856
- enforceWriteQuota?: () => void | Promise<void>
2863
+ enforceWriteQuota?: () => void | Promise<void>,
2864
+ sourceConnector?: string,
2857
2865
  ): Promise<unknown> {
2858
2866
  const migrated = MCP_MIGRATED_OPERATIONS[toLegacyToolName(name)];
2859
2867
  if (!migrated) {
@@ -2952,6 +2960,7 @@ export class EngramMcpServer {
2952
2960
  service: this.service,
2953
2961
  authenticatedPrincipal: effectivePrincipal,
2954
2962
  ...(enforceWriteQuota ? { hooks: { enforceWriteQuota } } : {}),
2963
+ ...(sourceConnector ? { sourceConnector } : {}),
2955
2964
  })) as { result: unknown };
2956
2965
  return output.result;
2957
2966
  }