hippo-memory 1.70.0 → 1.72.0

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 (855) hide show
  1. package/README.md +2 -2
  2. package/dist/agent-memories/apply.d.ts +0 -11
  3. package/dist/agent-memories/apply.js +6 -21
  4. package/dist/agent-memories/claude-code.d.ts +4 -2
  5. package/dist/agent-memories/claude-code.js +15 -6
  6. package/dist/agent-memories/codex.js +1 -1
  7. package/dist/agent-memories/copilot.d.ts +1 -3
  8. package/dist/agent-memories/copilot.js +1 -17
  9. package/dist/agent-memories/files.js +23 -12
  10. package/dist/agent-memories/markdown.d.ts +1 -3
  11. package/dist/agent-memories/markdown.js +1 -3
  12. package/dist/agent-memories/project-folds.d.ts +10 -0
  13. package/dist/agent-memories/project-folds.js +34 -0
  14. package/dist/agent-memories/report.js +2 -1
  15. package/dist/agent-memories/sync.d.ts +4 -2
  16. package/dist/agent-memories/sync.js +18 -11
  17. package/dist/api/assemble.d.ts +7 -44
  18. package/dist/api/assemble.js +3 -23
  19. package/dist/api/audit.d.ts +33 -1
  20. package/dist/api/audit.js +48 -1
  21. package/dist/api/auth.d.ts +20 -26
  22. package/dist/api/auth.js +43 -29
  23. package/dist/api/auto-sleep.d.ts +5 -2
  24. package/dist/api/auto-sleep.js +9 -5
  25. package/dist/api/availability.d.ts +2 -15
  26. package/dist/api/availability.js +4 -18
  27. package/dist/api/cards.d.ts +42 -0
  28. package/dist/api/cards.js +52 -0
  29. package/dist/api/conflicts.d.ts +28 -0
  30. package/dist/api/conflicts.js +61 -0
  31. package/dist/api/context-render.js +4 -3
  32. package/dist/api/context-select.js +12 -15
  33. package/dist/api/context-types.d.ts +10 -35
  34. package/dist/api/context.d.ts +5 -22
  35. package/dist/api/context.js +38 -46
  36. package/dist/api/continuity.d.ts +47 -0
  37. package/dist/api/continuity.js +66 -0
  38. package/dist/{cli → api}/correction-latency.d.ts +2 -14
  39. package/dist/{cli → api}/correction-latency.js +2 -14
  40. package/dist/api/dormant.d.ts +5 -21
  41. package/dist/api/dormant.js +11 -28
  42. package/dist/api/drill-down.d.ts +7 -46
  43. package/dist/api/drill-down.js +6 -27
  44. package/dist/api/embeddings.d.ts +17 -0
  45. package/dist/api/embeddings.js +28 -0
  46. package/dist/api/error-reply.d.ts +8 -0
  47. package/dist/api/error-reply.js +21 -0
  48. package/dist/api/forget.d.ts +11 -26
  49. package/dist/api/forget.js +23 -35
  50. package/dist/api/goals.d.ts +1 -1
  51. package/dist/api/goals.js +5 -9
  52. package/dist/api/graph.d.ts +8 -0
  53. package/dist/api/graph.js +7 -0
  54. package/dist/api/index.d.ts +6 -2
  55. package/dist/api/index.js +6 -2
  56. package/dist/api/instruction-detect.js +21 -6
  57. package/dist/api/learn.d.ts +4 -0
  58. package/dist/api/learn.js +53 -27
  59. package/dist/api/ledger-db.d.ts +2 -5
  60. package/dist/api/ledger-db.js +5 -35
  61. package/dist/api/memories.d.ts +23 -0
  62. package/dist/api/memories.js +46 -0
  63. package/dist/api/objects.d.ts +9 -0
  64. package/dist/api/objects.js +11 -0
  65. package/dist/api/on-store.js +5 -3
  66. package/dist/api/outcome.js +1 -1
  67. package/dist/api/pilot-arm.d.ts +1 -11
  68. package/dist/api/pilot-arm.js +5 -45
  69. package/dist/api/predictions.d.ts +11 -0
  70. package/dist/api/predictions.js +24 -0
  71. package/dist/api/projects.d.ts +21 -0
  72. package/dist/api/projects.js +24 -0
  73. package/dist/api/promote.d.ts +13 -17
  74. package/dist/api/promote.js +12 -20
  75. package/dist/api/prompt-hook.d.ts +19 -6
  76. package/dist/api/prompt-hook.js +54 -13
  77. package/dist/api/provenance-coverage.d.ts +14 -0
  78. package/dist/{cli → api}/provenance-coverage.js +2 -6
  79. package/dist/api/recall-cli.d.ts +58 -0
  80. package/dist/api/recall-cli.js +103 -0
  81. package/dist/api/recall-core.js +17 -9
  82. package/dist/api/recall-finish.d.ts +53 -0
  83. package/dist/api/recall-finish.js +30 -0
  84. package/dist/api/recall-history.d.ts +17 -84
  85. package/dist/api/recall-history.js +15 -88
  86. package/dist/api/recall-pipeline.d.ts +2 -3
  87. package/dist/api/recall-pipeline.js +21 -15
  88. package/dist/api/recall-request.js +1 -1
  89. package/dist/api/recall-types.d.ts +64 -304
  90. package/dist/api/recall.d.ts +3 -34
  91. package/dist/api/recall.js +63 -89
  92. package/dist/api/refine.d.ts +7 -0
  93. package/dist/api/refine.js +10 -0
  94. package/dist/api/remember-local.d.ts +57 -0
  95. package/dist/api/remember-local.js +90 -0
  96. package/dist/api/remember.d.ts +20 -2
  97. package/dist/api/remember.js +16 -3
  98. package/dist/api/session-end.d.ts +22 -0
  99. package/dist/api/session-end.js +101 -0
  100. package/dist/api/sleep-run.d.ts +2 -4
  101. package/dist/api/sleep-run.js +28 -28
  102. package/dist/api/sleep.d.ts +9 -28
  103. package/dist/api/status.d.ts +24 -0
  104. package/dist/api/status.js +40 -0
  105. package/dist/api/store-init.d.ts +4 -0
  106. package/dist/api/store-init.js +9 -0
  107. package/dist/api/tokens.d.ts +3 -10
  108. package/dist/api/tokens.js +4 -11
  109. package/dist/api/types.d.ts +8 -29
  110. package/dist/api/types.js +10 -23
  111. package/dist/capture/caller-session.d.ts +0 -3
  112. package/dist/capture/caller-session.js +1 -12
  113. package/dist/capture/capture-error.d.ts +2 -2
  114. package/dist/capture/capture-error.js +23 -18
  115. package/dist/capture/codex-patch.js +3 -1
  116. package/dist/capture/command.d.ts +4 -12
  117. package/dist/capture/command.js +39 -114
  118. package/dist/capture/compact.d.ts +4 -15
  119. package/dist/capture/compact.js +26 -30
  120. package/dist/capture/compaction-items-caller.js +11 -20
  121. package/dist/capture/compaction-record.d.ts +7 -93
  122. package/dist/capture/compaction-record.js +34 -399
  123. package/dist/capture/compaction-spool.d.ts +5 -3
  124. package/dist/capture/compaction-spool.js +21 -7
  125. package/dist/capture/copilot-transcript.d.ts +2 -1
  126. package/dist/capture/copilot-transcript.js +2 -1
  127. package/dist/capture/extract.d.ts +5 -2
  128. package/dist/capture/extract.js +4 -3
  129. package/dist/capture/failure-caller.d.ts +1 -1
  130. package/dist/capture/failure-caller.js +21 -16
  131. package/dist/capture/failure-reading.d.ts +2 -1
  132. package/dist/capture/failure-reading.js +7 -9
  133. package/dist/capture/pre-compact-caller.js +5 -4
  134. package/dist/capture/session-digest.d.ts +1 -1
  135. package/dist/capture/session-digest.js +17 -10
  136. package/dist/capture/session-end-caller.js +2 -1
  137. package/dist/capture/session-worker.js +3 -4
  138. package/dist/capture/transcript.d.ts +4 -11
  139. package/dist/capture/transcript.js +10 -21
  140. package/dist/capture/working-state.d.ts +4 -2
  141. package/dist/capture/working-state.js +4 -2
  142. package/dist/cli/api-context.d.ts +3 -0
  143. package/dist/cli/api-context.js +6 -0
  144. package/dist/cli/audit-prune.d.ts +1 -59
  145. package/dist/cli/audit-prune.js +2 -61
  146. package/dist/cli/audit.d.ts +1 -1
  147. package/dist/cli/audit.js +42 -43
  148. package/dist/cli/auth.d.ts +2 -2
  149. package/dist/cli/auth.js +61 -44
  150. package/dist/cli/briefs.d.ts +1 -4
  151. package/dist/cli/briefs.js +42 -301
  152. package/dist/cli/card.d.ts +2 -2
  153. package/dist/cli/card.js +63 -56
  154. package/dist/cli/client.d.ts +12 -27
  155. package/dist/cli/client.js +41 -44
  156. package/dist/cli/compact-resume-payload.js +4 -3
  157. package/dist/cli/context.d.ts +2 -3
  158. package/dist/cli/context.js +22 -18
  159. package/dist/cli/continuity.d.ts +6 -6
  160. package/dist/cli/continuity.js +81 -86
  161. package/dist/cli/curate.d.ts +13 -17
  162. package/dist/cli/curate.js +88 -116
  163. package/dist/cli/dag.d.ts +4 -4
  164. package/dist/cli/dag.js +55 -34
  165. package/dist/cli/decisions.d.ts +2 -4
  166. package/dist/cli/decisions.js +18 -309
  167. package/dist/cli/eval.d.ts +1 -1
  168. package/dist/cli/eval.js +27 -26
  169. package/dist/cli/exit.d.ts +6 -0
  170. package/dist/cli/exit.js +11 -0
  171. package/dist/cli/explain.d.ts +2 -3
  172. package/dist/cli/explain.js +25 -27
  173. package/dist/cli/flag-values.d.ts +6 -1
  174. package/dist/cli/flag-values.js +42 -15
  175. package/dist/cli/flags.d.ts +0 -288
  176. package/dist/cli/flags.js +3 -138
  177. package/dist/cli/github.d.ts +14 -0
  178. package/dist/{connectors/github/cli-impl.js → cli/github.js} +43 -71
  179. package/dist/cli/goals.d.ts +2 -2
  180. package/dist/cli/goals.js +46 -50
  181. package/dist/cli/graph.d.ts +3 -0
  182. package/dist/cli/graph.js +83 -0
  183. package/dist/cli/hook-runtime.d.ts +12 -32
  184. package/dist/cli/hook-runtime.js +21 -64
  185. package/dist/cli/incidents.d.ts +3 -0
  186. package/dist/cli/incidents.js +112 -0
  187. package/dist/cli/init.d.ts +2 -2
  188. package/dist/cli/init.js +33 -30
  189. package/dist/cli/install-steps.d.ts +2 -1
  190. package/dist/cli/install-steps.js +13 -14
  191. package/dist/cli/last-sleep.d.ts +2 -1
  192. package/dist/cli/last-sleep.js +4 -1
  193. package/dist/cli/lenient-id.d.ts +2 -0
  194. package/dist/cli/lenient-id.js +13 -0
  195. package/dist/cli/maintenance.d.ts +5 -5
  196. package/dist/cli/maintenance.js +37 -43
  197. package/dist/cli/notes.d.ts +2 -0
  198. package/dist/cli/notes.js +41 -0
  199. package/dist/cli/object-verbs.js +4 -3
  200. package/dist/cli/open-browser.d.ts +14 -0
  201. package/dist/cli/open-browser.js +26 -0
  202. package/dist/cli/owner-validation.d.ts +5 -28
  203. package/dist/cli/owner-validation.js +5 -28
  204. package/dist/cli/playbooks.d.ts +3 -4
  205. package/dist/cli/playbooks.js +131 -300
  206. package/dist/cli/predictions.d.ts +3 -0
  207. package/dist/cli/predictions.js +175 -0
  208. package/dist/cli/print.d.ts +2 -5
  209. package/dist/cli/print.js +3 -5
  210. package/dist/cli/projects.d.ts +2 -2
  211. package/dist/cli/projects.js +31 -25
  212. package/dist/cli/quality-repair-once.d.ts +1 -1
  213. package/dist/cli/quality-repair-once.js +7 -6
  214. package/dist/cli/recall.d.ts +2 -4
  215. package/dist/cli/recall.js +67 -137
  216. package/dist/cli/refine-llm.d.ts +5 -31
  217. package/dist/cli/refine-llm.js +23 -50
  218. package/dist/cli/remember.d.ts +3 -3
  219. package/dist/cli/remember.js +134 -192
  220. package/dist/cli/scheduler.d.ts +2 -17
  221. package/dist/cli/scheduler.js +14 -19
  222. package/dist/cli/serve.js +23 -14
  223. package/dist/cli/session-hooks.d.ts +11 -19
  224. package/dist/cli/session-hooks.js +143 -214
  225. package/dist/cli/setup.d.ts +4 -4
  226. package/dist/cli/setup.js +35 -30
  227. package/dist/cli/shared.d.ts +7 -25
  228. package/dist/cli/shared.js +17 -60
  229. package/dist/cli/slack.d.ts +2 -2
  230. package/dist/cli/slack.js +19 -23
  231. package/dist/cli/sleep-render.js +6 -3
  232. package/dist/cli/sleep.d.ts +3 -2
  233. package/dist/cli/sleep.js +17 -49
  234. package/dist/cli/status.d.ts +11 -14
  235. package/dist/cli/status.js +74 -120
  236. package/dist/cli/stdin.d.ts +4 -6
  237. package/dist/cli/stdin.js +2 -3
  238. package/dist/cli/transfer.d.ts +9 -9
  239. package/dist/cli/transfer.js +87 -108
  240. package/dist/cli/usage.d.ts +0 -79
  241. package/dist/cli/usage.js +1 -689
  242. package/dist/cli/verb-row.d.ts +32 -0
  243. package/dist/cli/verb-row.js +6 -0
  244. package/dist/cli/verbs/health.d.ts +27 -0
  245. package/dist/cli/verbs/health.js +232 -0
  246. package/dist/cli/verbs/memory.d.ts +16 -0
  247. package/dist/cli/verbs/memory.js +244 -0
  248. package/dist/cli/verbs/objects.d.ts +20 -0
  249. package/dist/cli/verbs/objects.js +254 -0
  250. package/dist/cli/verbs/sessions.d.ts +31 -0
  251. package/dist/cli/verbs/sessions.js +312 -0
  252. package/dist/cli/verbs.d.ts +81 -0
  253. package/dist/cli/verbs.js +7 -0
  254. package/dist/cli/versioned-verbs.d.ts +51 -0
  255. package/dist/cli/versioned-verbs.js +79 -0
  256. package/dist/cli.d.ts +1 -654
  257. package/dist/cli.js +44 -510
  258. package/dist/connectors/dlq.d.ts +39 -3
  259. package/dist/connectors/dlq.js +37 -3
  260. package/dist/connectors/github/backfill.d.ts +5 -25
  261. package/dist/connectors/github/backfill.js +26 -52
  262. package/dist/connectors/github/deletion.d.ts +4 -18
  263. package/dist/connectors/github/deletion.js +2 -15
  264. package/dist/connectors/github/dlq.d.ts +8 -33
  265. package/dist/connectors/github/dlq.js +34 -93
  266. package/dist/connectors/github/ingest.d.ts +4 -12
  267. package/dist/connectors/github/ingest.js +5 -36
  268. package/dist/connectors/github/octokit-client.d.ts +4 -16
  269. package/dist/connectors/github/octokit-client.js +27 -24
  270. package/dist/connectors/github/ratelimit.d.ts +3 -14
  271. package/dist/connectors/github/ratelimit.js +3 -14
  272. package/dist/connectors/github/scope.d.ts +3 -5
  273. package/dist/connectors/github/scope.js +3 -5
  274. package/dist/connectors/github/signature.d.ts +4 -26
  275. package/dist/connectors/github/signature.js +4 -26
  276. package/dist/connectors/github/tenant-routing.d.ts +2 -24
  277. package/dist/connectors/github/tenant-routing.js +4 -26
  278. package/dist/connectors/github/transform.js +2 -16
  279. package/dist/connectors/github/types.d.ts +3 -15
  280. package/dist/connectors/github/types.js +2 -9
  281. package/dist/connectors/github/webhook.d.ts +3 -16
  282. package/dist/connectors/github/webhook.js +38 -23
  283. package/dist/connectors/ingest.d.ts +10 -0
  284. package/dist/connectors/ingest.js +28 -0
  285. package/dist/connectors/slack/backfill.d.ts +4 -17
  286. package/dist/connectors/slack/backfill.js +4 -13
  287. package/dist/connectors/slack/dlq.d.ts +2 -19
  288. package/dist/connectors/slack/dlq.js +51 -90
  289. package/dist/connectors/slack/ingest.d.ts +4 -9
  290. package/dist/connectors/slack/ingest.js +4 -30
  291. package/dist/connectors/slack/scope.d.ts +2 -8
  292. package/dist/connectors/slack/scope.js +2 -8
  293. package/dist/connectors/slack/signature.d.ts +1 -6
  294. package/dist/connectors/slack/tenant-routing.d.ts +2 -19
  295. package/dist/connectors/slack/tenant-routing.js +2 -21
  296. package/dist/connectors/slack/transform.d.ts +2 -18
  297. package/dist/connectors/slack/transform.js +2 -18
  298. package/dist/connectors/slack/types.d.ts +3 -9
  299. package/dist/connectors/slack/types.js +2 -4
  300. package/dist/connectors/slack/web-client.js +33 -27
  301. package/dist/connectors/slack/webhook.d.ts +3 -19
  302. package/dist/connectors/slack/webhook.js +6 -26
  303. package/dist/connectors/slack/workspaces.d.ts +4 -24
  304. package/dist/connectors/slack/workspaces.js +4 -24
  305. package/dist/consolidate/conflicts.js +7 -15
  306. package/dist/consolidate/dag-summary.d.ts +8 -0
  307. package/dist/consolidate/dag-summary.js +41 -0
  308. package/dist/consolidate/dag.d.ts +5 -28
  309. package/dist/consolidate/dag.js +29 -84
  310. package/dist/consolidate/decay.js +7 -19
  311. package/dist/consolidate/dedupe.d.ts +13 -52
  312. package/dist/consolidate/dedupe.js +18 -74
  313. package/dist/consolidate/flush-units.d.ts +3 -4
  314. package/dist/consolidate/flush-units.js +3 -3
  315. package/dist/consolidate/half-life-migration.d.ts +3 -26
  316. package/dist/consolidate/half-life-migration.js +11 -28
  317. package/dist/consolidate/llm-passes.js +49 -40
  318. package/dist/consolidate/memory-value-weights.d.ts +2 -13
  319. package/dist/consolidate/memory-value-weights.js +2 -13
  320. package/dist/consolidate/memory-value.d.ts +11 -84
  321. package/dist/consolidate/memory-value.js +18 -105
  322. package/dist/consolidate/merge.js +12 -33
  323. package/dist/consolidate/physics-pass.d.ts +6 -1
  324. package/dist/consolidate/physics-pass.js +27 -9
  325. package/dist/consolidate/replay.d.ts +6 -38
  326. package/dist/consolidate/replay.js +25 -56
  327. package/dist/consolidate/run.js +1 -1
  328. package/dist/consolidate/sleep.d.ts +1 -8
  329. package/dist/consolidate/sleep.js +13 -22
  330. package/dist/consolidate/trace.d.ts +3 -18
  331. package/dist/consolidate/trace.js +3 -18
  332. package/dist/consolidate/traces.js +9 -25
  333. package/dist/core/ablation.d.ts +14 -91
  334. package/dist/core/ablation.js +16 -91
  335. package/dist/core/active-scope.d.ts +7 -0
  336. package/dist/{sharing/scope.js → core/active-scope.js} +5 -12
  337. package/dist/core/ambient.d.ts +5 -8
  338. package/dist/core/ambient.js +40 -26
  339. package/dist/core/api-errors.d.ts +16 -0
  340. package/dist/core/api-errors.js +20 -0
  341. package/dist/core/capture-contract.d.ts +4 -2
  342. package/dist/core/capture-contract.js +4 -2
  343. package/dist/core/card.d.ts +4 -1
  344. package/dist/core/card.js +11 -1
  345. package/dist/core/compaction-timing.d.ts +7 -0
  346. package/dist/core/compaction-timing.js +9 -0
  347. package/dist/core/compare.d.ts +11 -67
  348. package/dist/core/compare.js +9 -63
  349. package/dist/core/config.d.ts +10 -24
  350. package/dist/core/config.js +20 -16
  351. package/dist/core/cosine.d.ts +3 -0
  352. package/dist/core/cosine.js +19 -0
  353. package/dist/core/handoff.d.ts +1 -7
  354. package/dist/core/handoff.js +1 -7
  355. package/dist/core/markdown.d.ts +6 -0
  356. package/dist/{store → core}/markdown.js +23 -22
  357. package/dist/core/memory-audit.d.ts +17 -0
  358. package/dist/core/memory-audit.js +54 -0
  359. package/dist/core/memory-quality.js +1 -1
  360. package/dist/core/memory.d.ts +51 -168
  361. package/dist/core/memory.js +76 -239
  362. package/dist/{consolidate → core}/merged-row.d.ts +1 -1
  363. package/dist/{consolidate → core}/merged-row.js +3 -2
  364. package/dist/core/package-root.d.ts +3 -0
  365. package/dist/core/package-root.js +5 -0
  366. package/dist/core/physics-config.d.ts +1 -4
  367. package/dist/core/physics-config.js +3 -8
  368. package/dist/core/physics.d.ts +15 -61
  369. package/dist/core/physics.js +65 -138
  370. package/dist/core/prediction.d.ts +3 -0
  371. package/dist/core/prediction.js +6 -0
  372. package/dist/core/project-identity.d.ts +20 -58
  373. package/dist/core/project-identity.js +27 -39
  374. package/dist/core/project-remote.js +13 -2
  375. package/dist/core/raw-append-only.d.ts +5 -0
  376. package/dist/core/raw-append-only.js +7 -0
  377. package/dist/core/recall-scope.d.ts +69 -0
  378. package/dist/core/recall-scope.js +138 -0
  379. package/dist/core/salience.d.ts +1 -7
  380. package/dist/core/salience.js +1 -7
  381. package/dist/dashboard/dashboard-actions.js +2 -2
  382. package/dist/dashboard/dashboard-snapshot.d.ts +2 -1
  383. package/dist/dashboard/dashboard-snapshot.js +11 -2
  384. package/dist/dashboard/dashboard-types.d.ts +2 -1
  385. package/dist/dashboard/dashboard.d.ts +1 -0
  386. package/dist/dashboard/dashboard.js +50 -4
  387. package/dist/db/busy.d.ts +3 -8
  388. package/dist/db/busy.js +37 -33
  389. package/dist/db/connect.js +7 -8
  390. package/dist/db/index.d.ts +3 -3
  391. package/dist/db/index.js +3 -3
  392. package/dist/db/migrate.js +3 -3
  393. package/dist/db/migrations/index.d.ts +1 -1
  394. package/dist/db/migrations/index.js +3 -1
  395. package/dist/db/migrations/types.d.ts +2 -5
  396. package/dist/db/migrations/v14.js +2 -3
  397. package/dist/db/migrations/v15.js +2 -8
  398. package/dist/db/migrations/v16.js +2 -3
  399. package/dist/db/migrations/v17.js +2 -3
  400. package/dist/db/migrations/v19.js +2 -5
  401. package/dist/db/migrations/v20.js +2 -7
  402. package/dist/db/migrations/v22.js +4 -17
  403. package/dist/db/migrations/v23.js +3 -14
  404. package/dist/db/migrations/v24.js +2 -4
  405. package/dist/db/migrations/v25.js +3 -8
  406. package/dist/db/migrations/v26.js +2 -13
  407. package/dist/db/migrations/v27.js +3 -11
  408. package/dist/db/migrations/v28.js +2 -14
  409. package/dist/db/migrations/v29.js +4 -18
  410. package/dist/db/migrations/v30.js +4 -16
  411. package/dist/db/migrations/v31.js +2 -15
  412. package/dist/db/migrations/v32.js +4 -22
  413. package/dist/db/migrations/v33.js +2 -15
  414. package/dist/db/migrations/v34.js +2 -11
  415. package/dist/db/migrations/v35.js +2 -11
  416. package/dist/db/migrations/v36.js +2 -11
  417. package/dist/db/migrations/v37.js +8 -33
  418. package/dist/db/migrations/v38.js +5 -38
  419. package/dist/db/migrations/v39.js +9 -20
  420. package/dist/db/migrations/v40.js +2 -9
  421. package/dist/db/migrations/v41.js +2 -24
  422. package/dist/db/migrations/v43.js +1 -1
  423. package/dist/db/migrations/v44.js +2 -8
  424. package/dist/db/migrations/v45.js +2 -7
  425. package/dist/db/migrations/v47.js +2 -3
  426. package/dist/db/migrations/v51.js +1 -1
  427. package/dist/db/migrations/v55.d.ts +3 -0
  428. package/dist/db/migrations/v55.js +17 -0
  429. package/dist/db/open.d.ts +2 -2
  430. package/dist/db/open.js +21 -9
  431. package/dist/db/physics-state.d.ts +6 -22
  432. package/dist/db/physics-state.js +28 -39
  433. package/dist/db/raw-archive-mirror-cleanup.d.ts +2 -17
  434. package/dist/db/raw-archive-mirror-cleanup.js +2 -17
  435. package/dist/db/tables.d.ts +2 -0
  436. package/dist/db/tables.js +6 -2
  437. package/dist/db/vector-store.d.ts +2 -0
  438. package/dist/db/vector-store.js +25 -5
  439. package/dist/db/wal-checkpointer.js +2 -1
  440. package/dist/doctor.js +85 -27
  441. package/dist/embeddings/local.d.ts +62 -0
  442. package/dist/embeddings/local.js +146 -0
  443. package/dist/embeddings/provider.d.ts +43 -0
  444. package/dist/{store/embeddings → embeddings}/provider.js +58 -83
  445. package/dist/embeddings/transformers.d.ts +26 -0
  446. package/dist/embeddings/transformers.js +89 -0
  447. package/dist/entry/session-text.d.ts +1 -1
  448. package/dist/entry/session-text.js +3 -2
  449. package/dist/eval/eval-stats.d.ts +15 -53
  450. package/dist/eval/eval-stats.js +12 -42
  451. package/dist/eval/eval-suite.d.ts +2 -13
  452. package/dist/eval/eval-suite.js +91 -45
  453. package/dist/eval/eval.d.ts +6 -24
  454. package/dist/eval/eval.js +8 -35
  455. package/dist/eval/judgment.d.ts +0 -3
  456. package/dist/eval/judgment.js +30 -15
  457. package/dist/extensions/openclaw-plugin/index.js +1 -1
  458. package/dist/graph/extract.d.ts +5 -27
  459. package/dist/graph/extract.js +10 -36
  460. package/dist/graph/recall.d.ts +7 -20
  461. package/dist/graph/recall.js +15 -77
  462. package/dist/graph/stream.d.ts +7 -39
  463. package/dist/graph/stream.js +11 -34
  464. package/dist/graph/view.d.ts +9 -35
  465. package/dist/graph/view.js +24 -44
  466. package/dist/graph/write.d.ts +1 -1
  467. package/dist/graph/write.js +9 -9
  468. package/dist/hooks/codex-session.js +3 -2
  469. package/dist/hooks/codex-wrapper.js +4 -3
  470. package/dist/hooks/copilot.js +2 -1
  471. package/dist/hooks/hook-blocks.d.ts +6 -2
  472. package/dist/hooks/hook-blocks.js +37 -124
  473. package/dist/hooks/json-hooks.d.ts +4 -36
  474. package/dist/hooks/json-hooks.js +22 -59
  475. package/dist/hooks/opencode.d.ts +0 -38
  476. package/dist/hooks/opencode.js +17 -81
  477. package/dist/hooks/shared.d.ts +6 -21
  478. package/dist/hooks/shared.js +31 -33
  479. package/dist/importers/core.d.ts +12 -37
  480. package/dist/importers/core.js +10 -28
  481. package/dist/importers/markdown-parse.d.ts +8 -22
  482. package/dist/importers/markdown-parse.js +8 -25
  483. package/dist/importers/markdown.js +3 -12
  484. package/dist/importers/sources.js +12 -39
  485. package/dist/importers/vault.d.ts +2 -8
  486. package/dist/importers/vault.js +31 -85
  487. package/dist/index.d.ts +8 -3
  488. package/dist/index.js +8 -3
  489. package/dist/learn/autolearn.d.ts +23 -42
  490. package/dist/learn/autolearn.js +45 -52
  491. package/dist/learn/churn-git.js +13 -4
  492. package/dist/learn/extract.d.ts +3 -2
  493. package/dist/learn/extract.js +8 -8
  494. package/dist/learn/forward-claim-detector.d.ts +6 -30
  495. package/dist/learn/forward-claim-detector.js +18 -68
  496. package/dist/learn/invalidation.d.ts +6 -18
  497. package/dist/learn/invalidation.js +18 -31
  498. package/dist/mcp/admin-tools.d.ts +2 -2
  499. package/dist/mcp/admin-tools.js +30 -53
  500. package/dist/mcp/format.js +3 -2
  501. package/dist/mcp/framing.d.ts +1 -0
  502. package/dist/mcp/framing.js +1 -1
  503. package/dist/mcp/memory-tools.js +7 -10
  504. package/dist/mcp/protocol.d.ts +15 -29
  505. package/dist/mcp/protocol.js +26 -16
  506. package/dist/mcp/recall-tools.js +14 -11
  507. package/dist/mcp/request.d.ts +3 -11
  508. package/dist/mcp/request.js +12 -27
  509. package/dist/mcp/server.d.ts +3 -9
  510. package/dist/mcp/server.js +5 -16
  511. package/dist/mcp/session-state.d.ts +1 -1
  512. package/dist/mcp/session-state.js +5 -11
  513. package/dist/mcp/stdio.d.ts +2 -6
  514. package/dist/mcp/stdio.js +68 -16
  515. package/dist/mcp/tool-args.js +2 -1
  516. package/dist/mcp/tools.js +47 -22
  517. package/dist/objects/customer-notes.d.ts +9 -44
  518. package/dist/objects/customer-notes.js +7 -48
  519. package/dist/objects/decisions.d.ts +14 -52
  520. package/dist/objects/decisions.js +15 -53
  521. package/dist/objects/descriptor.d.ts +1 -1
  522. package/dist/objects/incidents.d.ts +9 -40
  523. package/dist/objects/incidents.js +7 -41
  524. package/dist/objects/lifecycle.d.ts +1 -1
  525. package/dist/objects/lifecycle.js +2 -1
  526. package/dist/objects/policies.d.ts +13 -91
  527. package/dist/objects/policies.js +13 -99
  528. package/dist/objects/processes.d.ts +9 -54
  529. package/dist/objects/processes.js +7 -61
  530. package/dist/objects/project-briefs.d.ts +13 -57
  531. package/dist/objects/project-briefs.js +16 -78
  532. package/dist/objects/skills.d.ts +9 -44
  533. package/dist/objects/skills.js +8 -54
  534. package/dist/postinstall.js +7 -20
  535. package/dist/predictions/planning-fallacy.d.ts +11 -34
  536. package/dist/rerankers/clef.js +6 -37
  537. package/dist/rerankers/cross-encoder.d.ts +31 -2
  538. package/dist/rerankers/cross-encoder.js +65 -101
  539. package/dist/rerankers/index.js +5 -4
  540. package/dist/rerankers/jev.js +11 -10
  541. package/dist/rerankers/llm.d.ts +2 -11
  542. package/dist/rerankers/llm.js +14 -14
  543. package/dist/rerankers/outage-warning.d.ts +5 -2
  544. package/dist/rerankers/outage-warning.js +7 -4
  545. package/dist/rerankers/remote.d.ts +1 -0
  546. package/dist/rerankers/remote.js +2 -0
  547. package/dist/rerankers/types.d.ts +2 -14
  548. package/dist/search/bm25-search.js +1 -1
  549. package/dist/search/boosts.d.ts +0 -2
  550. package/dist/search/boosts.js +3 -3
  551. package/dist/search/embed-memories.d.ts +9 -0
  552. package/dist/search/embed-memories.js +377 -0
  553. package/dist/search/goal-boost.d.ts +23 -0
  554. package/dist/search/goal-boost.js +93 -0
  555. package/dist/search/hybrid.d.ts +11 -2
  556. package/dist/search/hybrid.js +9 -4
  557. package/dist/search/multihop.js +2 -3
  558. package/dist/search/path-context.d.ts +5 -18
  559. package/dist/search/path-context.js +5 -18
  560. package/dist/search/physics-search.d.ts +6 -3
  561. package/dist/search/physics-search.js +29 -19
  562. package/dist/search/rerank.js +1 -1
  563. package/dist/search/rrf.d.ts +7 -35
  564. package/dist/search/rrf.js +5 -30
  565. package/dist/search/vector.d.ts +13 -4
  566. package/dist/search/vector.js +40 -13
  567. package/dist/server/auth.d.ts +11 -28
  568. package/dist/server/auth.js +49 -32
  569. package/dist/server/boot.d.ts +2 -21
  570. package/dist/server/boot.js +69 -161
  571. package/dist/server/client-ip.d.ts +3 -21
  572. package/dist/server/client-ip.js +8 -30
  573. package/dist/server/deadline.d.ts +0 -2
  574. package/dist/server/deadline.js +1 -7
  575. package/dist/server/defaults.d.ts +4 -0
  576. package/dist/server/defaults.js +5 -0
  577. package/dist/server/key-check-bounds.d.ts +2 -1
  578. package/dist/server/lifecycle.d.ts +5 -4
  579. package/dist/server/lifecycle.js +19 -4
  580. package/dist/server/mcp-http.js +24 -53
  581. package/dist/server/rate-limit.d.ts +5 -18
  582. package/dist/server/rate-limit.js +4 -13
  583. package/dist/server/request.d.ts +4 -8
  584. package/dist/server/request.js +16 -19
  585. package/dist/server/route-checks.d.ts +7 -0
  586. package/dist/server/route-checks.js +42 -0
  587. package/dist/server/route-table.d.ts +9 -8
  588. package/dist/server/route-table.js +127 -139
  589. package/dist/server/routes/admin.d.ts +8 -8
  590. package/dist/server/routes/admin.js +35 -49
  591. package/dist/server/routes/customer-notes.d.ts +6 -6
  592. package/dist/server/routes/customer-notes.js +8 -14
  593. package/dist/server/routes/decisions.d.ts +6 -6
  594. package/dist/server/routes/decisions.js +12 -21
  595. package/dist/server/routes/incidents.d.ts +6 -6
  596. package/dist/server/routes/incidents.js +14 -25
  597. package/dist/server/routes/memories.d.ts +9 -9
  598. package/dist/server/routes/memories.js +20 -63
  599. package/dist/server/routes/object-routes.d.ts +6 -11
  600. package/dist/server/routes/object-routes.js +11 -22
  601. package/dist/server/routes/policies.d.ts +7 -7
  602. package/dist/server/routes/policies.js +12 -22
  603. package/dist/server/routes/predictions.d.ts +6 -6
  604. package/dist/server/routes/predictions.js +22 -38
  605. package/dist/server/routes/processes.d.ts +6 -6
  606. package/dist/server/routes/processes.js +17 -28
  607. package/dist/server/routes/project-briefs.d.ts +7 -7
  608. package/dist/server/routes/project-briefs.js +11 -20
  609. package/dist/server/routes/recall.d.ts +5 -5
  610. package/dist/server/routes/recall.js +16 -45
  611. package/dist/server/routes/skills.d.ts +7 -7
  612. package/dist/server/routes/skills.js +10 -22
  613. package/dist/server/server-detect.d.ts +15 -53
  614. package/dist/server/server-detect.js +55 -96
  615. package/dist/server/sleep-child.js +26 -7
  616. package/dist/server/sleep-offload.d.ts +11 -5
  617. package/dist/server/sleep-offload.js +21 -12
  618. package/dist/server/types.d.ts +32 -18
  619. package/dist/server/validation.d.ts +3 -2
  620. package/dist/server/validation.js +15 -33
  621. package/dist/server.d.ts +7 -6
  622. package/dist/server.js +8 -6
  623. package/dist/sharing/global-store.d.ts +19 -0
  624. package/dist/sharing/global-store.js +75 -0
  625. package/dist/sharing/global-sync.d.ts +6 -0
  626. package/dist/sharing/global-sync.js +73 -0
  627. package/dist/sharing/project-merge.d.ts +11 -19
  628. package/dist/sharing/project-merge.js +63 -125
  629. package/dist/sharing/search-both.d.ts +60 -0
  630. package/dist/sharing/search-both.js +138 -0
  631. package/dist/sharing/share.d.ts +40 -0
  632. package/dist/sharing/share.js +229 -0
  633. package/dist/store/ambient.js +9 -15
  634. package/dist/store/audit-event.d.ts +5 -13
  635. package/dist/store/audit-event.js +4 -12
  636. package/dist/store/audit.d.ts +2 -21
  637. package/dist/store/audit.js +8 -67
  638. package/dist/store/auth.d.ts +10 -8
  639. package/dist/store/auth.js +17 -12
  640. package/dist/store/candidates.d.ts +23 -5
  641. package/dist/store/candidates.js +119 -71
  642. package/dist/store/capture-write.d.ts +17 -0
  643. package/dist/store/capture-write.js +35 -0
  644. package/dist/store/card-detail.d.ts +2 -1
  645. package/dist/store/card-detail.js +2 -1
  646. package/dist/store/cards.d.ts +14 -9
  647. package/dist/store/cards.js +72 -126
  648. package/dist/store/compaction-caller.d.ts +18 -0
  649. package/dist/store/compaction-caller.js +29 -0
  650. package/dist/store/compactions-record.d.ts +115 -0
  651. package/dist/store/compactions-record.js +417 -0
  652. package/dist/store/compactions.js +6 -4
  653. package/dist/store/conflicts.d.ts +4 -21
  654. package/dist/store/conflicts.js +76 -152
  655. package/dist/store/connectors/dlq.d.ts +10 -0
  656. package/dist/store/connectors/dlq.js +32 -0
  657. package/dist/store/connectors/github.d.ts +14 -16
  658. package/dist/store/connectors/github.js +34 -57
  659. package/dist/store/connectors/slack.d.ts +2 -11
  660. package/dist/store/connectors/slack.js +18 -47
  661. package/dist/store/dashboard-reads.js +11 -14
  662. package/dist/store/delete-and-batch.d.ts +17 -31
  663. package/dist/store/delete-and-batch.js +84 -67
  664. package/dist/store/delivery-recorder.d.ts +15 -4
  665. package/dist/store/delivery-recorder.js +34 -17
  666. package/dist/store/descendant-page.js +6 -3
  667. package/dist/store/diagnostics.js +6 -13
  668. package/dist/store/dormant.d.ts +8 -30
  669. package/dist/store/dormant.js +18 -57
  670. package/dist/store/embeddings/index.d.ts +11 -90
  671. package/dist/store/embeddings/index.js +18 -523
  672. package/dist/store/entry-reads.d.ts +34 -61
  673. package/dist/store/entry-reads.js +111 -136
  674. package/dist/store/entry-row.d.ts +6 -35
  675. package/dist/store/entry-row.js +9 -37
  676. package/dist/store/entry-writes.d.ts +12 -18
  677. package/dist/store/entry-writes.js +46 -44
  678. package/dist/store/failure-log-at.d.ts +8 -0
  679. package/dist/store/failure-log-at.js +16 -0
  680. package/dist/store/failure-log.d.ts +2 -2
  681. package/dist/store/failure-log.js +5 -3
  682. package/dist/{trust → store}/gated-write.d.ts +3 -1
  683. package/dist/{trust → store}/gated-write.js +7 -5
  684. package/dist/store/goals.d.ts +3 -40
  685. package/dist/store/goals.js +41 -178
  686. package/dist/store/graph-queue.d.ts +6 -22
  687. package/dist/store/graph-queue.js +14 -45
  688. package/dist/store/graph-reads.d.ts +11 -35
  689. package/dist/store/graph-reads.js +24 -60
  690. package/dist/store/graph-rows.d.ts +3 -6
  691. package/dist/store/graph-rows.js +6 -9
  692. package/dist/store/graph-view-rows.d.ts +2 -1
  693. package/dist/store/graph-view-rows.js +2 -1
  694. package/dist/store/graph-writes.d.ts +10 -35
  695. package/dist/store/graph-writes.js +59 -106
  696. package/dist/store/half-life.d.ts +2 -1
  697. package/dist/store/half-life.js +14 -16
  698. package/dist/store/handoffs.d.ts +6 -12
  699. package/dist/store/handoffs.js +22 -40
  700. package/dist/store/index-and-stats.d.ts +6 -19
  701. package/dist/store/index-and-stats.js +36 -84
  702. package/dist/store/key-writes.js +1 -1
  703. package/dist/store/ledger-turn.d.ts +9 -0
  704. package/dist/store/ledger-turn.js +38 -0
  705. package/dist/store/mirrors.d.ts +2 -6
  706. package/dist/store/mirrors.js +24 -29
  707. package/dist/store/open.d.ts +0 -4
  708. package/dist/store/open.js +42 -62
  709. package/dist/store/pilot-arm.d.ts +12 -0
  710. package/dist/store/pilot-arm.js +42 -0
  711. package/dist/store/planning-fallacy-evidence.d.ts +2 -30
  712. package/dist/store/planning-fallacy-evidence.js +8 -37
  713. package/dist/store/port.d.ts +91 -82
  714. package/dist/store/port.js +8 -0
  715. package/dist/store/predictions.d.ts +12 -53
  716. package/dist/store/predictions.js +41 -125
  717. package/dist/store/project-tags.d.ts +62 -0
  718. package/dist/store/project-tags.js +67 -0
  719. package/dist/{cli → store}/quality-repair.js +15 -31
  720. package/dist/store/quarantine.js +2 -1
  721. package/dist/store/raw-archive.d.ts +4 -16
  722. package/dist/store/raw-archive.js +14 -29
  723. package/dist/store/recall-trace.d.ts +12 -77
  724. package/dist/store/recall-trace.js +37 -97
  725. package/dist/store/rejected-values.js +9 -20
  726. package/dist/store/rejection-probe.d.ts +4 -0
  727. package/dist/store/rejection-probe.js +19 -0
  728. package/dist/store/rejection.d.ts +10 -73
  729. package/dist/store/rejection.js +12 -84
  730. package/dist/store/report-reads.d.ts +6 -0
  731. package/dist/store/report-reads.js +29 -0
  732. package/dist/store/rows.d.ts +9 -19
  733. package/dist/store/rows.js +36 -34
  734. package/dist/store/rule-sql.d.ts +14 -0
  735. package/dist/store/rule-sql.js +56 -0
  736. package/dist/store/search-rows.d.ts +7 -38
  737. package/dist/store/search-rows.js +23 -54
  738. package/dist/store/sessions.d.ts +10 -47
  739. package/dist/store/sessions.js +21 -75
  740. package/dist/store/set-aside.d.ts +14 -0
  741. package/dist/store/set-aside.js +23 -0
  742. package/dist/store/sqlite/busy.d.ts +3 -0
  743. package/dist/store/sqlite/busy.js +8 -0
  744. package/dist/store/sqlite/connector-events-group.js +5 -8
  745. package/dist/store/sqlite/connector-writes-group.js +3 -3
  746. package/dist/store/sqlite/entry-writes-group.js +4 -4
  747. package/dist/store/sqlite/error-codec.js +8 -5
  748. package/dist/store/sqlite/executor.d.ts +2 -1
  749. package/dist/store/sqlite/executor.js +12 -5
  750. package/dist/store/sqlite/graph-reads-group.js +1 -1
  751. package/dist/store/sqlite/held-connection.d.ts +9 -0
  752. package/dist/store/sqlite/held-connection.js +41 -0
  753. package/dist/store/sqlite/local.d.ts +3 -3
  754. package/dist/store/sqlite/local.js +1 -0
  755. package/dist/store/sqlite/object-rows.d.ts +1 -1
  756. package/dist/store/sqlite/object-rows.js +6 -3
  757. package/dist/store/sqlite/objects-group.d.ts +1 -1
  758. package/dist/store/sqlite/objects-group.js +5 -3
  759. package/dist/store/sqlite/quarantine-group.js +2 -2
  760. package/dist/store/sqlite/store.d.ts +1 -4
  761. package/dist/store/sqlite/store.js +16 -15
  762. package/dist/store/sqlite/vector-reads-group.js +2 -2
  763. package/dist/store/sqlite/worker-jobs.js +1 -1
  764. package/dist/store/sqlite/worker-ops.d.ts +13 -2
  765. package/dist/store/sqlite/worker-ops.js +13 -2
  766. package/dist/store/sqlite/worker-store.js +5 -2
  767. package/dist/store/summaries.d.ts +11 -63
  768. package/dist/store/summaries.js +37 -148
  769. package/dist/store/summary-dirty.js +1 -1
  770. package/dist/store/tenant-lookup.d.ts +6 -1
  771. package/dist/store/tenant-lookup.js +7 -0
  772. package/dist/store/tenant.d.ts +2 -16
  773. package/dist/store/tenant.js +4 -19
  774. package/dist/store/token-ledger.d.ts +13 -50
  775. package/dist/store/token-ledger.js +19 -85
  776. package/dist/store/usage-reports.js +5 -13
  777. package/dist/store/vector-index.d.ts +46 -0
  778. package/dist/store/vector-index.js +171 -0
  779. package/dist/store/working-memory.d.ts +6 -25
  780. package/dist/store/working-memory.js +18 -52
  781. package/dist/support-bundle.js +9 -8
  782. package/dist/trust/reject-flow.js +3 -5
  783. package/dist/util/agent-homes.d.ts +15 -0
  784. package/dist/util/agent-homes.js +34 -0
  785. package/dist/util/anthropic-messages.d.ts +3 -0
  786. package/dist/util/anthropic-messages.js +35 -6
  787. package/dist/util/atomic-write.d.ts +2 -1
  788. package/dist/util/atomic-write.js +35 -4
  789. package/dist/util/capped-json.d.ts +6 -0
  790. package/dist/util/capped-json.js +46 -0
  791. package/dist/util/chunked.d.ts +3 -0
  792. package/dist/util/chunked.js +10 -0
  793. package/dist/util/crash-handlers.d.ts +8 -1
  794. package/dist/util/crash-handlers.js +52 -10
  795. package/dist/util/ellipsize.d.ts +3 -0
  796. package/dist/util/ellipsize.js +5 -0
  797. package/dist/util/env.d.ts +14 -6
  798. package/dist/util/env.js +15 -7
  799. package/dist/util/format.d.ts +3 -0
  800. package/dist/util/format.js +6 -0
  801. package/dist/util/home-path.d.ts +2 -1
  802. package/dist/util/home-path.js +4 -2
  803. package/dist/util/hook-payload.d.ts +8 -0
  804. package/dist/util/hook-payload.js +37 -0
  805. package/dist/util/http-retry.d.ts +9 -1
  806. package/dist/util/http-retry.js +67 -8
  807. package/dist/util/http-util.d.ts +0 -8
  808. package/dist/util/http-util.js +10 -21
  809. package/dist/util/limits.d.ts +7 -0
  810. package/dist/util/limits.js +14 -0
  811. package/dist/util/log.d.ts +7 -2
  812. package/dist/util/log.js +34 -9
  813. package/dist/util/request-scope.d.ts +5 -2
  814. package/dist/util/request-scope.js +13 -7
  815. package/dist/util/secret-detect.d.ts +5 -30
  816. package/dist/util/secret-detect.js +19 -40
  817. package/dist/util/sqlite-blocked.d.ts +2 -0
  818. package/dist/util/sqlite-blocked.js +5 -0
  819. package/dist/util/stored-json.d.ts +1 -1
  820. package/dist/util/stored-json.js +1 -1
  821. package/dist/util/stream-tee.d.ts +3 -0
  822. package/dist/util/stream-tee.js +35 -0
  823. package/dist/util/time.d.ts +4 -0
  824. package/dist/util/time.js +4 -0
  825. package/dist/util/token-text.d.ts +1 -4
  826. package/dist/util/token-text.js +1 -4
  827. package/dist/util/transcript-tail.d.ts +2 -0
  828. package/dist/util/transcript-tail.js +24 -23
  829. package/dist/util/version.d.ts +5 -20
  830. package/dist/util/version.js +5 -20
  831. package/dist/{store → util}/yaml.d.ts +1 -5
  832. package/dist/{store → util}/yaml.js +2 -6
  833. package/extensions/openclaw-plugin/index.ts +1 -1
  834. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  835. package/extensions/openclaw-plugin/package.json +1 -1
  836. package/openclaw.plugin.json +1 -1
  837. package/package.json +2 -2
  838. package/dist/cli/provenance-coverage.d.ts +0 -18
  839. package/dist/connectors/github/cli-impl.d.ts +0 -25
  840. package/dist/sharing/scope.d.ts +0 -14
  841. package/dist/sharing/shared.d.ts +0 -187
  842. package/dist/sharing/shared.js +0 -563
  843. package/dist/store/embeddings/local.d.ts +0 -15
  844. package/dist/store/embeddings/local.js +0 -192
  845. package/dist/store/embeddings/provider.d.ts +0 -77
  846. package/dist/store/markdown.d.ts +0 -10
  847. package/dist/store/recall-scope.d.ts +0 -138
  848. package/dist/store/recall-scope.js +0 -216
  849. package/dist/store/vector-writes.d.ts +0 -13
  850. package/dist/store/vector-writes.js +0 -89
  851. /package/dist/{store → core}/object-types.d.ts +0 -0
  852. /package/dist/{store → core}/object-types.js +0 -0
  853. /package/dist/{cli → store}/quality-repair.d.ts +0 -0
  854. /package/dist/{capture → util}/compaction-items.d.ts +0 -0
  855. /package/dist/{capture → util}/compaction-items.js +0 -0
@@ -1,8 +1,10 @@
1
+ import { handleGitHubEventsWebhook } from '../connectors/github/webhook.js';
2
+ import { handleSlackEventsWebhook } from '../connectors/slack/webhook.js';
1
3
  import { withSqliteOffLoop } from '../db/index.js';
2
- import { hasGroup } from '../store/index.js';
4
+ import { hasGroup, requireGroup } from '../store/index.js';
3
5
  import { runsOffLoop } from '../store/sqlite/worker-store.js';
4
6
  import { HttpError, JSON_HEADERS, sendJson, STORE_NOT_PORTED_MESSAGE } from '../util/http-util.js';
5
- import { buildContextWithAuth, requireAuth } from './auth.js';
7
+ import { assertCrossTenantAdmin, buildContextWithAuth, isLoopback } from './auth.js';
6
8
  import { matchPath, noteAccess } from './request.js';
7
9
  import { handleApproveQuarantine, handleCreateAuthKey, handleListAudit, handleListAuthKeys, handleListQuarantine, handleRejectQuarantine, handleRevokeAuthKey } from './routes/admin.js';
8
10
  import { handleCloseCustomerNote, handleCreateCustomerNote, handleGetCustomerNote, handleListCustomerNotes, handleSupersedeCustomerNote } from './routes/customer-notes.js';
@@ -16,102 +18,134 @@ import { handleCloseProjectBrief, handleCreateProjectBrief, handleGetProjectBrie
16
18
  import { handleAssembleSession, handleDrillRecall, handleGetContext, handleRecallMemories } from './routes/recall.js';
17
19
  import { handleCloseSkill, handleCreateSkill, handleExportSkills, handleGetSkill, handleListSkills, handleSupersedeSkill } from './routes/skills.js';
18
20
  import { parseJsonBody } from './validation.js';
19
- // Review patch #2: explicit allow-list for unauthenticated /v1/* routes.
20
- // New unauth routes MUST be added here AND get a corresponding entry in
21
- // tests/server-bearer-lockdown.test.ts. Do not gate auth elsewhere by
22
- // `path.startsWith` — pattern-positional auth is bypass-by-accident.
23
- //
24
- // The route handlers consult `isPublicRoute` before invoking
25
- // `buildContextWithAuth` / `requireAuth`. Adding a route here without
26
- // adding the corresponding `isPublicRoute` short-circuit in a handler is
27
- // a no-op (auth still applies), so the failure mode is fail-closed.
28
- // The only other unauthenticated paths are ServeOpts.publicJson's: GET only, checked at boot by assertPublicJson.
29
- const PUBLIC_ROUTES = new Set([
30
- 'POST /v1/connectors/slack/events',
31
- 'POST /v1/connectors/github/events',
32
- ]);
33
- export function isPublicRoute(method, path) {
34
- return PUBLIC_ROUTES.has(`${method} ${path}`);
21
+ const WEBHOOK_GROUPS = ['entryWrites', 'connectorWrites', 'connectorEvents'];
22
+ /** A store missing a group a delivery writes through refuses the webhook up front, so no delivery is acknowledged and then half stored. */
23
+ function webhook(handle) {
24
+ return async ({ req, res, opts }) => {
25
+ for (const group of WEBHOOK_GROUPS)
26
+ requireGroup(opts.store, group);
27
+ await handle({ req, res, opts }, opts.store);
28
+ };
35
29
  }
36
- /** The /v1 routes in dispatch order; the first entry whose method and path match handles the request. */
37
- const V1_ROUTES = [
38
- { method: 'POST', path: '/v1/memories', storeReady: 'entryWrites', loop: 'off', handler: handleCreateMemory },
39
- { method: 'GET', path: '/v1/graph', storeReady: 'graphReads', loop: 'off', handler: handleGetGraph },
40
- { method: 'GET', path: '/v1/memories', storeReady: 'base', loop: 'off', handler: handleRecallMemories },
41
- { method: 'GET', pattern: '/v1/sessions/:id/assemble', storeReady: 'dagReads', loop: 'off', handler: handleAssembleSession },
42
- { method: 'GET', pattern: '/v1/recall/drill/:id', storeReady: 'dagReads', handler: handleDrillRecall },
43
- { method: 'POST', pattern: '/v1/memories/:id/archive', storeReady: 'entryWrites', loop: 'off', handler: handleArchiveMemory },
44
- { method: 'POST', pattern: '/v1/memories/:id/supersede', storeReady: 'entryWrites', loop: 'off', handler: handleSupersedeMemory },
45
- { method: 'POST', pattern: '/v1/memories/:id/promote', sqliteOnly: 'copies a memory between the two local hippo.db files', handler: handlePromoteMemory },
46
- { method: 'DELETE', pattern: '/v1/memories/:id', storeReady: 'entryWrites', loop: 'off', handler: handleForgetMemory },
47
- { method: 'POST', path: '/v1/outcome', storeReady: 'entryWrites', handler: handleApplyOutcome },
48
- { method: 'GET', path: '/v1/context', storeReady: 'contextReads', handler: handleGetContext },
49
- { method: 'POST', path: '/v1/sleep', sqliteOnly: 'consolidates every tenant under the local hippo root in this process', handler: handleSleep },
50
- { method: 'POST', path: '/v1/auth/keys', storeReady: 'keyWrites', loop: 'off', handler: handleCreateAuthKey },
51
- { method: 'GET', path: '/v1/auth/keys', storeReady: 'keyWrites', loop: 'off', handler: handleListAuthKeys },
52
- { method: 'DELETE', pattern: '/v1/auth/keys/:keyId', storeReady: 'keyAudit', loop: 'off', handler: handleRevokeAuthKey },
53
- { method: 'GET', path: '/v1/quarantine', storeReady: 'quarantine', loop: 'off', handler: handleListQuarantine },
54
- { method: 'POST', pattern: '/v1/quarantine/:id/approve', storeReady: 'quarantine', loop: 'off', handler: handleApproveQuarantine },
55
- { method: 'POST', pattern: '/v1/quarantine/:id/reject', storeReady: 'quarantine', loop: 'off', handler: handleRejectQuarantine },
56
- { method: 'GET', path: '/v1/audit', storeReady: 'auditLog', loop: 'off', handler: handleListAudit },
57
- { method: 'POST', path: '/v1/predictions', storeReady: 'predictions', loop: 'off', handler: handleCreatePrediction },
58
- { method: 'GET', path: '/v1/predictions', storeReady: 'predictions', loop: 'off', handler: handleListPredictions },
59
- { method: 'GET', path: '/v1/predictions/stats', storeReady: 'predictions', loop: 'off', handler: handlePredictionStats },
60
- { method: 'GET', regex: /^\/v1\/predictions\/(\d+)$/, storeReady: 'predictions', loop: 'off', handler: handleGetPrediction },
61
- { method: 'POST', regex: /^\/v1\/predictions\/(\d+)\/close$/, storeReady: 'predictions', loop: 'off', handler: handleClosePrediction },
62
- { method: 'POST', path: '/v1/decisions', storeReady: 'objects', handler: handleCreateDecision },
63
- { method: 'GET', path: '/v1/decisions', storeReady: 'objects', handler: handleListDecisions },
64
- { method: 'POST', regex: /^\/v1\/decisions\/(\d+)\/supersede$/, storeReady: 'objects', handler: handleSupersedeDecision },
65
- { method: 'POST', regex: /^\/v1\/decisions\/(\d+)\/close$/, storeReady: 'objects', handler: handleCloseDecision },
66
- { method: 'GET', regex: /^\/v1\/decisions\/(\d+)$/, storeReady: 'objects', handler: handleGetDecision },
67
- { method: 'POST', path: '/v1/incidents', storeReady: 'objects', handler: handleCreateIncident },
68
- { method: 'GET', path: '/v1/incidents', storeReady: 'objects', handler: handleListIncidents },
69
- { method: 'POST', regex: /^\/v1\/incidents\/(\d+)\/resolve$/, storeReady: 'objects', handler: handleResolveIncident },
70
- { method: 'POST', regex: /^\/v1\/incidents\/(\d+)\/close$/, storeReady: 'objects', handler: handleCloseIncident },
71
- { method: 'GET', regex: /^\/v1\/incidents\/(\d+)$/, storeReady: 'objects', handler: handleGetIncident },
72
- { method: 'POST', path: '/v1/processes', storeReady: 'objects', handler: handleCreateProcess },
73
- { method: 'GET', path: '/v1/processes', storeReady: 'objects', handler: handleListProcesses },
74
- { method: 'POST', regex: /^\/v1\/processes\/(\d+)\/supersede$/, storeReady: 'objects', handler: handleSupersedeProcess },
75
- { method: 'POST', regex: /^\/v1\/processes\/(\d+)\/close$/, storeReady: 'objects', handler: handleCloseProcess },
76
- { method: 'GET', regex: /^\/v1\/processes\/(\d+)$/, storeReady: 'objects', handler: handleGetProcess },
77
- { method: 'POST', path: '/v1/policies', storeReady: 'objects', handler: handleCreatePolicy },
78
- { method: 'GET', path: '/v1/policies', storeReady: 'objects', handler: handleListPolicies },
79
- { method: 'GET', path: '/v1/policies/asof', storeReady: 'objects', handler: handlePoliciesAsOf },
80
- { method: 'POST', regex: /^\/v1\/policies\/(\d+)\/supersede$/, storeReady: 'objects', handler: handleSupersedePolicy },
81
- { method: 'POST', regex: /^\/v1\/policies\/(\d+)\/close$/, storeReady: 'objects', handler: handleClosePolicy },
82
- { method: 'GET', regex: /^\/v1\/policies\/(\d+)$/, storeReady: 'objects', handler: handleGetPolicy },
83
- { method: 'POST', path: '/v1/skills', storeReady: 'objects', handler: handleCreateSkill },
84
- { method: 'GET', path: '/v1/skills', storeReady: 'objects', handler: handleListSkills },
85
- { method: 'GET', path: '/v1/skills/export', storeReady: 'objects', handler: handleExportSkills },
86
- { method: 'POST', regex: /^\/v1\/skills\/(\d+)\/supersede$/, storeReady: 'objects', handler: handleSupersedeSkill },
87
- { method: 'POST', regex: /^\/v1\/skills\/(\d+)\/close$/, storeReady: 'objects', handler: handleCloseSkill },
88
- { method: 'GET', regex: /^\/v1\/skills\/(\d+)$/, storeReady: 'objects', handler: handleGetSkill },
89
- { method: 'POST', path: '/v1/project-briefs', storeReady: 'objects', handler: handleCreateProjectBrief },
90
- { method: 'GET', path: '/v1/project-briefs', storeReady: 'objects', handler: handleListProjectBriefs },
91
- { method: 'POST', path: '/v1/project-briefs/refresh', storeReady: 'objects', handler: handleRefreshProjectBrief },
92
- { method: 'POST', regex: /^\/v1\/project-briefs\/(\d+)\/supersede$/, storeReady: 'objects', handler: handleSupersedeProjectBrief },
93
- { method: 'POST', regex: /^\/v1\/project-briefs\/(\d+)\/close$/, storeReady: 'objects', handler: handleCloseProjectBrief },
94
- { method: 'GET', regex: /^\/v1\/project-briefs\/(\d+)$/, storeReady: 'objects', handler: handleGetProjectBrief },
95
- { method: 'POST', path: '/v1/customer-notes', storeReady: 'objects', handler: handleCreateCustomerNote },
96
- { method: 'GET', path: '/v1/customer-notes', storeReady: 'objects', handler: handleListCustomerNotes },
97
- { method: 'POST', regex: /^\/v1\/customer-notes\/(\d+)\/supersede$/, storeReady: 'objects', handler: handleSupersedeCustomerNote },
98
- { method: 'POST', regex: /^\/v1\/customer-notes\/(\d+)\/close$/, storeReady: 'objects', handler: handleCloseCustomerNote },
99
- { method: 'GET', regex: /^\/v1\/customer-notes\/(\d+)$/, storeReady: 'objects', handler: handleGetCustomerNote },
30
+ /** The /v1 routes in dispatch order; the first entry whose method and path match handles the request. Each row's `auth` is what the
31
+ * dispatch gate proves before its handler runs, so a handler never checks the caller itself. */
32
+ export const V1_ROUTES = [
33
+ { method: 'POST', path: '/v1/memories', auth: 'caller', storeReady: 'entryWrites', loop: 'off', handler: handleCreateMemory },
34
+ { method: 'GET', path: '/v1/graph', auth: 'caller', storeReady: 'graphReads', loop: 'off', handler: handleGetGraph },
35
+ { method: 'GET', path: '/v1/memories', auth: 'caller', storeReady: 'base', loop: 'off', handler: handleRecallMemories },
36
+ { method: 'GET', pattern: '/v1/sessions/:id/assemble', auth: 'caller', storeReady: 'dagReads', loop: 'off', handler: handleAssembleSession },
37
+ { method: 'GET', pattern: '/v1/recall/drill/:id', auth: 'caller', storeReady: 'dagReads', handler: handleDrillRecall },
38
+ { method: 'POST', pattern: '/v1/memories/:id/archive', auth: 'caller', storeReady: 'entryWrites', loop: 'off', handler: handleArchiveMemory },
39
+ { method: 'POST', pattern: '/v1/memories/:id/supersede', auth: 'caller', storeReady: 'entryWrites', loop: 'off', handler: handleSupersedeMemory },
40
+ { method: 'POST', pattern: '/v1/memories/:id/promote', auth: 'caller', sqliteOnly: 'copies a memory between the two local hippo.db files',
41
+ handler: handlePromoteMemory },
42
+ { method: 'DELETE', pattern: '/v1/memories/:id', auth: 'caller', storeReady: 'entryWrites', loop: 'off', handler: handleForgetMemory },
43
+ { method: 'POST', path: '/v1/outcome', auth: 'caller', storeReady: 'entryWrites', handler: handleApplyOutcome },
44
+ { method: 'GET', path: '/v1/context', auth: 'caller', storeReady: 'contextReads', handler: handleGetContext },
45
+ { method: 'POST', path: '/v1/sleep', auth: 'host-admin-local', sqliteOnly: 'consolidates every tenant under the local hippo root in this process',
46
+ handler: handleSleep },
47
+ { method: 'POST', path: '/v1/auth/keys', auth: 'caller', storeReady: 'keyWrites', loop: 'off', handler: handleCreateAuthKey },
48
+ { method: 'GET', path: '/v1/auth/keys', auth: 'caller', storeReady: 'keyWrites', loop: 'off', handler: handleListAuthKeys },
49
+ { method: 'DELETE', pattern: '/v1/auth/keys/:keyId', auth: 'caller', storeReady: 'keyAudit', loop: 'off', handler: handleRevokeAuthKey },
50
+ { method: 'GET', path: '/v1/quarantine', auth: 'admin', storeReady: 'quarantine', loop: 'off', handler: handleListQuarantine },
51
+ { method: 'POST', pattern: '/v1/quarantine/:id/approve', auth: 'admin', storeReady: 'quarantine', loop: 'off', handler: handleApproveQuarantine },
52
+ { method: 'POST', pattern: '/v1/quarantine/:id/reject', auth: 'admin', storeReady: 'quarantine', loop: 'off', handler: handleRejectQuarantine },
53
+ { method: 'GET', path: '/v1/audit', auth: 'caller', storeReady: 'auditLog', loop: 'off', handler: handleListAudit },
54
+ { method: 'POST', path: '/v1/predictions', auth: 'caller', storeReady: 'predictions', loop: 'off', handler: handleCreatePrediction },
55
+ { method: 'GET', path: '/v1/predictions', auth: 'caller', storeReady: 'predictions', loop: 'off', handler: handleListPredictions },
56
+ { method: 'GET', path: '/v1/predictions/stats', auth: 'caller', storeReady: 'predictions', loop: 'off', handler: handlePredictionStats },
57
+ { method: 'GET', regex: /^\/v1\/predictions\/(\d+)$/, auth: 'caller', storeReady: 'predictions', loop: 'off', handler: handleGetPrediction },
58
+ { method: 'POST', regex: /^\/v1\/predictions\/(\d+)\/close$/, auth: 'caller', storeReady: 'predictions', loop: 'off', handler: handleClosePrediction },
59
+ { method: 'POST', path: '/v1/decisions', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCreateDecision },
60
+ { method: 'GET', path: '/v1/decisions', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleListDecisions },
61
+ { method: 'POST', regex: /^\/v1\/decisions\/(\d+)\/supersede$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleSupersedeDecision },
62
+ { method: 'POST', regex: /^\/v1\/decisions\/(\d+)\/close$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCloseDecision },
63
+ { method: 'GET', regex: /^\/v1\/decisions\/(\d+)$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleGetDecision },
64
+ { method: 'POST', path: '/v1/incidents', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCreateIncident },
65
+ { method: 'GET', path: '/v1/incidents', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleListIncidents },
66
+ { method: 'POST', regex: /^\/v1\/incidents\/(\d+)\/resolve$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleResolveIncident },
67
+ { method: 'POST', regex: /^\/v1\/incidents\/(\d+)\/close$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCloseIncident },
68
+ { method: 'GET', regex: /^\/v1\/incidents\/(\d+)$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleGetIncident },
69
+ { method: 'POST', path: '/v1/processes', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCreateProcess },
70
+ { method: 'GET', path: '/v1/processes', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleListProcesses },
71
+ { method: 'POST', regex: /^\/v1\/processes\/(\d+)\/supersede$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleSupersedeProcess },
72
+ { method: 'POST', regex: /^\/v1\/processes\/(\d+)\/close$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCloseProcess },
73
+ { method: 'GET', regex: /^\/v1\/processes\/(\d+)$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleGetProcess },
74
+ { method: 'POST', path: '/v1/policies', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCreatePolicy },
75
+ { method: 'GET', path: '/v1/policies', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleListPolicies },
76
+ { method: 'GET', path: '/v1/policies/asof', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handlePoliciesAsOf },
77
+ { method: 'POST', regex: /^\/v1\/policies\/(\d+)\/supersede$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleSupersedePolicy },
78
+ { method: 'POST', regex: /^\/v1\/policies\/(\d+)\/close$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleClosePolicy },
79
+ { method: 'GET', regex: /^\/v1\/policies\/(\d+)$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleGetPolicy },
80
+ { method: 'POST', path: '/v1/skills', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCreateSkill },
81
+ { method: 'GET', path: '/v1/skills', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleListSkills },
82
+ { method: 'GET', path: '/v1/skills/export', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleExportSkills },
83
+ { method: 'POST', regex: /^\/v1\/skills\/(\d+)\/supersede$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleSupersedeSkill },
84
+ { method: 'POST', regex: /^\/v1\/skills\/(\d+)\/close$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCloseSkill },
85
+ { method: 'GET', regex: /^\/v1\/skills\/(\d+)$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleGetSkill },
86
+ { method: 'POST', path: '/v1/project-briefs', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCreateProjectBrief },
87
+ { method: 'GET', path: '/v1/project-briefs', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleListProjectBriefs },
88
+ { method: 'POST', path: '/v1/project-briefs/refresh', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleRefreshProjectBrief },
89
+ { method: 'POST', regex: /^\/v1\/project-briefs\/(\d+)\/supersede$/, auth: 'caller', storeReady: 'objects', loop: 'off',
90
+ handler: handleSupersedeProjectBrief },
91
+ { method: 'POST', regex: /^\/v1\/project-briefs\/(\d+)\/close$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCloseProjectBrief },
92
+ { method: 'GET', regex: /^\/v1\/project-briefs\/(\d+)$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleGetProjectBrief },
93
+ { method: 'POST', path: '/v1/customer-notes', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCreateCustomerNote },
94
+ { method: 'GET', path: '/v1/customer-notes', auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleListCustomerNotes },
95
+ { method: 'POST', regex: /^\/v1\/customer-notes\/(\d+)\/supersede$/, auth: 'caller', storeReady: 'objects', loop: 'off',
96
+ handler: handleSupersedeCustomerNote },
97
+ { method: 'POST', regex: /^\/v1\/customer-notes\/(\d+)\/close$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleCloseCustomerNote },
98
+ { method: 'GET', regex: /^\/v1\/customer-notes\/(\d+)$/, auth: 'caller', storeReady: 'objects', loop: 'off', handler: handleGetCustomerNote },
99
+ { method: 'POST', path: '/v1/connectors/slack/events', auth: 'webhook-signature', storeReady: 'connectorEvents', handler: webhook(handleSlackEventsWebhook) },
100
+ { method: 'POST', path: '/v1/connectors/github/events', auth: 'webhook-signature', storeReady: 'connectorEvents',
101
+ handler: webhook(handleGitHubEventsWebhook) },
100
102
  ];
101
- /** The route's handler bound to this request's path params, or null when method or path differ. The matcher runs before the
102
- * method check, as the inline route blocks did, so a malformed `%` escape still throws from matchPath on any method. */
103
- function routeMatches(route, method, path) {
103
+ /** The handler bound to this path's params, or null when the path differs. */
104
+ function bindPath(route, path) {
104
105
  if ('path' in route)
105
- return method === route.method && path === route.path ? route.handler : null;
106
+ return path === route.path ? route.handler : null;
106
107
  if ('pattern' in route) {
107
108
  const params = matchPath(route.pattern, path);
108
- return method === route.method && params ? (r) => route.handler(r, params) : null;
109
+ return params ? (r) => route.handler(r, params) : null;
109
110
  }
110
111
  const match = path.match(route.regex);
111
- return method === route.method && match ? (r) => route.handler(r, match) : null;
112
+ return match ? (r) => route.handler(r, match) : null;
113
+ }
114
+ /** The route's run for this request, gate first, or null when method or path differ. The matcher runs before the method check,
115
+ * as the inline route blocks did, so a malformed `%` escape still throws from matchPath on any method. */
116
+ export function routeMatches(route, method, path) {
117
+ if (route.auth === 'webhook-signature') {
118
+ const run = bindPath(route, path);
119
+ if (run === null || method !== route.method)
120
+ return null;
121
+ return async (r) => {
122
+ assertRoutePorted(r.opts, route.storeReady);
123
+ await run(r);
124
+ };
125
+ }
126
+ const run = bindPath(route, path);
127
+ if (run === null || method !== route.method)
128
+ return null;
129
+ return async (r) => run({ ...r, ctx: await passAuthGate(route, r) });
130
+ }
131
+ /** The one caller check a gated route passes: sleep refuses a caller off this host before any key work, then one charged auth,
132
+ * then 501 for an unported route, so a bad key is still a 401 there, and the row's role last. */
133
+ async function passAuthGate(route, { req, opts }) {
134
+ const label = routeLabel(route);
135
+ // Defence in depth, not the boundary: a socket address says where a request came from, never who sent it.
136
+ if (route.auth === 'host-admin-local' && !isLoopback(req.socket.remoteAddress)) {
137
+ throw new HttpError(403, `${label} is loopback-only (host-wide consolidation; see CHANGELOG v1.11.4)`);
138
+ }
139
+ const ctx = await buildContextWithAuth(req, opts);
140
+ assertRoutePorted(opts, route.storeReady);
141
+ if (route.auth === 'admin' && ctx.actor.role !== 'admin')
142
+ throw new HttpError(403, `${label} requires admin role`);
143
+ if (route.auth === 'host-admin-local')
144
+ assertCrossTenantAdmin(ctx, label);
145
+ return ctx;
112
146
  }
113
147
  /** The route as the access line names it; a regex route reads as its pattern would, so no line carries a caller's id. */
114
- function routeLabel(route) {
148
+ export function routeLabel(route) {
115
149
  if ('path' in route)
116
150
  return route.path;
117
151
  if ('pattern' in route)
@@ -125,61 +159,20 @@ export async function dispatchV1Route(r, method, path) {
125
159
  if (run === null)
126
160
  continue;
127
161
  noteAccess(r.req, { route: routeLabel(route) });
128
- await refuseUnportedRoute(r.req, r.opts, route.storeReady);
129
162
  // Only a store with worker threads has moved the route's SQLite work; under any other the handler still opens hippo.db itself.
130
163
  await (route.loop === 'off' && runsOffLoop(r.opts.store) ? withSqliteOffLoop(() => run(r)) : run(r));
131
164
  return true;
132
165
  }
133
166
  return false;
134
167
  }
135
- const PLAIN_SEGMENT_RE = /^[A-Za-z0-9._~-]+$/;
136
- function isPlainV1Path(path) {
137
- return path.startsWith('/v1/') && new URL(path, 'http://h').pathname === path
138
- && path.slice('/v1/'.length).split('/').every((segment) => PLAIN_SEGMENT_RE.test(segment));
139
- }
140
- // A plain path never holds a `%`, so matchPath cannot throw here.
141
- function isCorePath(method, path) {
142
- return PUBLIC_ROUTES.has(`${method} ${path}`) || V1_ROUTES.some((route) => routeMatches(route, method, path) !== null);
143
- }
144
- /** Boot-time check: an add-on path must be plain, unique and not one core serves, so no add-on shadows a core route or hides from dispatch. */
145
- export function assertAddonRoutes(routes) {
146
- const seen = new Set();
147
- for (const { path } of routes) {
148
- if (!isPlainV1Path(path))
149
- throw new Error(`add-on route '${path}' is not a plain /v1/ path (segments use A-Z a-z 0-9 . _ ~ -)`);
150
- if (seen.has(path))
151
- throw new Error(`add-on route '${path}' is registered twice`);
152
- if (isCorePath('POST', path))
153
- throw new Error(`add-on route '${path}' is already served by core`);
154
- seen.add(path);
155
- }
156
- }
157
- const PUBLIC_JSON_MAX_BYTES = 64 * 1024;
158
- /** Boot-time check and serialization: a public path that a core GET route serves would open that route to anyone. */
159
- export function assertPublicJson(publicJson) {
160
- const bodies = new Map();
161
- for (const [path, value] of Object.entries(publicJson)) {
162
- if (!isPlainV1Path(path))
163
- throw new Error(`public JSON path '${path}' is not a plain /v1/ path (segments use A-Z a-z 0-9 . _ ~ -)`);
164
- if (isCorePath('GET', path))
165
- throw new Error(`public JSON path '${path}' is already served by core`);
166
- const text = JSON.stringify(value);
167
- if (text === undefined)
168
- throw new Error(`public JSON at '${path}' is not JSON`);
169
- if (Buffer.byteLength(text) > PUBLIC_JSON_MAX_BYTES)
170
- throw new Error(`public JSON at '${path}' is over 64 KiB`);
171
- bodies.set(path, text);
172
- }
173
- return bodies;
174
- }
175
168
  /** Core authenticates and parses before the handler runs, so an add-on route gets the same 401, 400 and 501 as a core one. */
176
169
  export async function dispatchAddonRoute({ req, res, opts }, method, path) {
177
170
  const route = method === 'POST' ? opts.routes?.find((r) => r.path === path) : undefined;
178
171
  if (!route)
179
172
  return false;
180
173
  noteAccess(req, { route: route.path });
181
- await refuseUnportedRoute(req, opts, route.storeReady);
182
174
  const ctx = await buildContextWithAuth(req, opts);
175
+ assertRoutePorted(opts, route.storeReady);
183
176
  noteAccess(req, { tenant: ctx.tenantId });
184
177
  const body = await parseJsonBody(req, ctx);
185
178
  sendJson(res, 200, await route.handler({ ctx, body }));
@@ -195,15 +188,10 @@ export function dispatchPublicJson({ req, res, opts }, method, path) {
195
188
  res.end(text);
196
189
  return true;
197
190
  }
198
- export function assertSqliteStore(opts) {
199
- if (opts.store.kind !== 'sqlite')
200
- throw new HttpError(501, STORE_NOT_PORTED_MESSAGE);
201
- }
202
- /** Under another store, a route that names no group, or one the store lacks, answers 501 without running; the caller is checked first, so a bad key is still a 401. */
203
- async function refuseUnportedRoute(req, opts, group) {
191
+ /** Under another store, a route that names no group, or one the store lacks, answers 501 without running. */
192
+ function assertRoutePorted(opts, group) {
204
193
  if (opts.store.kind === 'sqlite' || (group !== undefined && hasGroup(opts.store, group)))
205
194
  return;
206
- await requireAuth(req, opts);
207
- assertSqliteStore(opts);
195
+ throw new HttpError(501, STORE_NOT_PORTED_MESSAGE);
208
196
  }
209
197
  //# sourceMappingURL=route-table.js.map
@@ -1,9 +1,9 @@
1
- import type { RouteRequest } from '../types.js';
2
- export declare function handleCreateAuthKey({ req, res, opts }: RouteRequest): Promise<void>;
3
- export declare function handleListAuthKeys({ req, res, opts, query }: RouteRequest): Promise<void>;
4
- export declare function handleRevokeAuthKey({ req, res, opts }: RouteRequest, keyMatch: Record<string, string>): Promise<void>;
5
- export declare function handleListQuarantine({ req, res, opts, query }: RouteRequest): Promise<void>;
6
- export declare function handleApproveQuarantine({ req, res, opts }: RouteRequest, quarantineApproveMatch: Record<string, string>): Promise<void>;
7
- export declare function handleRejectQuarantine({ req, res, opts }: RouteRequest, quarantineRejectMatch: Record<string, string>): Promise<void>;
8
- export declare function handleListAudit({ req, res, opts, query }: RouteRequest): Promise<void>;
1
+ import type { AuthedRouteRequest } from '../types.js';
2
+ export declare function handleCreateAuthKey({ req, res, opts }: AuthedRouteRequest): Promise<void>;
3
+ export declare function handleListAuthKeys({ res, ctx, query }: AuthedRouteRequest): Promise<void>;
4
+ export declare function handleRevokeAuthKey({ res, ctx }: AuthedRouteRequest, keyMatch: Record<string, string>): Promise<void>;
5
+ export declare function handleListQuarantine({ res, ctx, query }: AuthedRouteRequest): Promise<void>;
6
+ export declare function handleApproveQuarantine({ res, ctx }: AuthedRouteRequest, quarantineApproveMatch: Record<string, string>): Promise<void>;
7
+ export declare function handleRejectQuarantine({ res, ctx }: AuthedRouteRequest, quarantineRejectMatch: Record<string, string>): Promise<void>;
8
+ export declare function handleListAudit({ res, ctx, query }: AuthedRouteRequest): Promise<void>;
9
9
  //# sourceMappingURL=admin.d.ts.map
@@ -1,38 +1,33 @@
1
1
  // Admin routes: API keys, quarantine and the audit log.
2
+ import { DEFAULT_LIST_LIMIT } from '../../util/limits.js';
2
3
  import { AUDIT_OPS } from '../../store/audit.js';
3
4
  import { auditList, authCreate, authListRows, authRevoke, quarantineApprove, quarantineList, quarantineReject } from '../../api/index.js';
4
5
  import { HttpError, readBody, sendJson } from '../../util/http-util.js';
5
- import { log } from '../../util/log.js';
6
- import { assertCrossTenantAdmin, buildContextWithAuth } from '../auth.js';
6
+ import { assertCrossTenantAdmin, recheckContextWithAuth } from '../auth.js';
7
7
  import { pageOf, parseCursor, setNextCursorHeader } from '../cursor.js';
8
8
  import { isSetMember, parseJsonObjectText, parseListLimit, validateIdSegment } from '../validation.js';
9
- import { isJsonString } from '../../util/json.js';
9
+ import { isJsonBoolean, isJsonNumber, isJsonString } from '../../util/json.js';
10
10
  const VALID_AUDIT_OPS = new Set(AUDIT_OPS);
11
- // POST /v1/auth/keys reads its body before auth, so an unauthenticated caller can make the server buffer at most this many bytes and wait at most this many ms.
11
+ // A key mint is a few short fields, so even an authenticated caller gets a small cap and a short wait.
12
12
  // ServeOpts.mintBodyDeadlineMs overrides the wait for tests only, so a 408 test need not sit through it.
13
13
  const MINT_BODY_MAX_BYTES = 4 * 1024;
14
14
  const MINT_BODY_DEADLINE_MS = 10_000;
15
- // Cap on GET /v1/audit?limit=. Matches docs/api.md (when written) and is large
16
- // enough to dump a small deployment's full audit log without paginating, but
17
- // small enough that a malicious client can't ask for the world.
15
+ // Cap on GET /v1/audit?limit=: large enough to dump a small deployment's audit log unpaginated, small enough that a client cannot ask for the world.
18
16
  const MAX_AUDIT_LIMIT = 10000;
19
17
  // GET /v1/auth/keys had no limit, so its default page is the cap: a deployment below 1000 keys sees no change.
20
18
  const MAX_AUTH_KEYS_PAGE = 1000;
21
- // POST /v1/auth/keys — mint a new API key. Plaintext lands in the response
22
- // body: the HTTP layer hands it to the client; the user-facing
23
- // "store this somewhere safe" warning belongs in the CLI client, not here.
19
+ // POST /v1/auth/keys: mints a key; plaintext is in the response body (the CLI client, not this layer, carries the "store this somewhere safe" warning).
24
20
  export async function handleCreateAuthKey({ req, res, opts }) {
25
- // Body first, so the resolver's check (and any gate in it) runs right before the mint with no wait between.
21
+ // The dispatch gate authenticated before the body, so an unknown caller costs no read; this recheck runs the resolver right before the mint.
26
22
  const raw = await readBody(req, { maxBytes: MINT_BODY_MAX_BYTES, deadlineMs: opts.mintBodyDeadlineMs ?? MINT_BODY_DEADLINE_MS });
27
- const ctx = await buildContextWithAuth(req, opts);
23
+ const ctx = await recheckContextWithAuth(req, opts);
28
24
  const body = parseJsonObjectText(raw);
29
25
  const labelRaw = body['label'];
30
26
  if (labelRaw !== undefined && !isJsonString(labelRaw)) {
31
27
  throw new HttpError(400, 'label must be a string');
32
28
  }
33
- // Optional body.role mirrors the --role CLI flag. Validated
34
- // strictly — anything other than 'admin'|'member' is a 400 (no silent
35
- // fallback to admin). authCreate refuses a member caller with a 403.
29
+ // Optional body.role mirrors the --role CLI flag and is validated strictly: anything but 'admin'|'member' is a 400; authCreate refuses a member caller
30
+ // with a 403.
36
31
  const roleRaw = body['role'];
37
32
  let role;
38
33
  if (roleRaw !== undefined) {
@@ -41,25 +36,28 @@ export async function handleCreateAuthKey({ req, res, opts }) {
41
36
  }
42
37
  role = roleRaw;
43
38
  }
44
- // Security: any `tenantId` in the body is IGNORED. The minted key is
45
- // bound to the caller's authenticated tenant (ctx.tenantId, resolved
46
- // from the Bearer token). Forwarding body.tenantId here would let
47
- // tenant A mint a key for tenant B — see authCreate doc comment.
39
+ // A null is a 400 too: a client that serialises an unset field as null must not get a key that never expires.
40
+ const ttlDays = body['ttlDays'];
41
+ if (ttlDays !== undefined && !isJsonNumber(ttlDays)) {
42
+ throw new HttpError(400, 'ttlDays must be a number');
43
+ }
44
+ const noExpiry = body['noExpiry'];
45
+ if (noExpiry !== undefined && !isJsonBoolean(noExpiry)) {
46
+ throw new HttpError(400, 'noExpiry must be true or false');
47
+ }
48
+ // Security: any body `tenantId` is IGNORED; the key is bound to the caller's authenticated tenant, or tenant A could mint a key for tenant B (see
49
+ // authCreate).
48
50
  const result = await authCreate(ctx, {
49
51
  label: labelRaw,
50
52
  role,
53
+ ttlDays,
54
+ noExpiry,
51
55
  });
52
- // The reply cannot change shape, so the server log is where a defaulted admin key gets noticed.
53
- if (role === undefined && result.role === 'admin') {
54
- log.warn(`auth key ${result.keyId} was minted with no role in the body, so it is an admin key, and it never expires; send "role": "member" for a narrower one`);
55
- }
56
56
  sendJson(res, 200, result);
57
57
  return;
58
58
  }
59
- // GET /v1/auth/keys?active=true&limit=&cursor=: list keys visible to ctx.tenantId.
60
- // `active` defaults to true so the common case (show me usable keys) is
61
- // a single GET; ?active=false includes revoked and expired rows.
62
- export async function handleListAuthKeys({ req, res, opts, query }) {
59
+ // GET /v1/auth/keys?active=true&limit=&cursor=: lists keys visible to ctx.tenantId; `active` defaults to true, ?active=false includes revoked and expired rows.
60
+ export async function handleListAuthKeys({ res, ctx, query }) {
63
61
  const activeRaw = query.get('active');
64
62
  let active = true;
65
63
  if (activeRaw !== null) {
@@ -72,28 +70,21 @@ export async function handleListAuthKeys({ req, res, opts, query }) {
72
70
  }
73
71
  const limit = parseListLimit(query.get('limit'), MAX_AUTH_KEYS_PAGE, MAX_AUTH_KEYS_PAGE);
74
72
  const after = parseCursor(query.get('cursor'), 'integer', 'integer');
75
- const ctx = await buildContextWithAuth(req, opts);
76
73
  const page = pageOf(await authListRows(ctx, { active, limit: limit + 1, after }), limit, (r) => ({ key: r.rowId, id: r.rowId }));
77
74
  setNextCursorHeader(res, page.nextCursor);
78
75
  sendJson(res, 200, page.items.map((r) => r.key));
79
76
  return;
80
77
  }
81
- // DELETE /v1/auth/keys/:keyId — revoke. Missing or cross-tenant keys are 404 (no info leak); a member
82
- // is 403 on any key but its own key or, signed in through the resolver, the keys it minted.
83
- // 200 with the body rather than 204 so the caller sees revokedAt.
84
- export async function handleRevokeAuthKey({ req, res, opts }, keyMatch) {
78
+ // DELETE /v1/auth/keys/:keyId revokes: missing or cross-tenant keys are 404 (no leak); a member is 403 on any key but its own or, via the resolver, those it
79
+ // minted. Returns 200 with the body rather than 204 so the caller sees revokedAt.
80
+ export async function handleRevokeAuthKey({ res, ctx }, keyMatch) {
85
81
  validateIdSegment(keyMatch.keyId, 'key id');
86
- const ctx = await buildContextWithAuth(req, opts);
87
82
  const result = await authRevoke(ctx, keyMatch.keyId);
88
83
  sendJson(res, 200, result);
89
84
  return;
90
85
  }
91
- // GET /v1/quarantine?status=&limit=&cursor=: quarantine review queue. quarantineList carries no role gate itself, so it's checked here.
92
- export async function handleListQuarantine({ req, res, opts, query }) {
93
- const ctx = await buildContextWithAuth(req, opts);
94
- if (ctx.actor.role !== 'admin') {
95
- throw new HttpError(403, '/v1/quarantine requires admin role');
96
- }
86
+ // GET /v1/quarantine?status=&limit=&cursor=: quarantine review queue. quarantineList carries no role gate itself, so its row's admin gate is the check.
87
+ export async function handleListQuarantine({ res, ctx, query }) {
97
88
  const statusRaw = query.get('status');
98
89
  let status = 'pending';
99
90
  if (statusRaw !== null) {
@@ -109,25 +100,21 @@ export async function handleListQuarantine({ req, res, opts, query }) {
109
100
  return;
110
101
  }
111
102
  // POST /v1/quarantine/:id/approve: admin only; ForbiddenError falls through to mapApiError's 403.
112
- export async function handleApproveQuarantine({ req, res, opts }, quarantineApproveMatch) {
103
+ export async function handleApproveQuarantine({ res, ctx }, quarantineApproveMatch) {
113
104
  validateIdSegment(quarantineApproveMatch.id, 'memory id');
114
- const ctx = await buildContextWithAuth(req, opts);
115
105
  await quarantineApprove(ctx, quarantineApproveMatch.id);
116
106
  sendJson(res, 200, { approved: quarantineApproveMatch.id });
117
107
  return;
118
108
  }
119
109
  // POST /v1/quarantine/:id/reject: admin only; ForbiddenError falls through to mapApiError's 403.
120
- export async function handleRejectQuarantine({ req, res, opts }, quarantineRejectMatch) {
110
+ export async function handleRejectQuarantine({ res, ctx }, quarantineRejectMatch) {
121
111
  validateIdSegment(quarantineRejectMatch.id, 'memory id');
122
- const ctx = await buildContextWithAuth(req, opts);
123
112
  await quarantineReject(ctx, quarantineRejectMatch.id);
124
113
  sendJson(res, 200, { rejected: quarantineRejectMatch.id });
125
114
  return;
126
115
  }
127
- // GET /v1/audit?op=&since=&limit=&cursor=: read audit events. All three filters
128
- // validated at the route boundary so an invalid value lands a 400 before
129
- // we hit the DB.
130
- export async function handleListAudit({ req, res, opts, query }) {
116
+ // GET /v1/audit?op=&since=&limit=&cursor=: all three filters are validated at the route boundary so an invalid value is a 400 before the DB is hit.
117
+ export async function handleListAudit({ res, ctx, query }) {
131
118
  const opRaw = query.get('op');
132
119
  let op;
133
120
  if (opRaw !== null) {
@@ -146,7 +133,7 @@ export async function handleListAudit({ req, res, opts, query }) {
146
133
  since = sinceRaw;
147
134
  }
148
135
  const limitRaw = query.get('limit');
149
- let limit = 100;
136
+ let limit = DEFAULT_LIST_LIMIT;
150
137
  if (limitRaw !== null) {
151
138
  const parsed = Number(limitRaw);
152
139
  if (!Number.isFinite(parsed) || !Number.isInteger(parsed) || parsed < 1 || parsed > MAX_AUDIT_LIMIT) {
@@ -155,7 +142,6 @@ export async function handleListAudit({ req, res, opts, query }) {
155
142
  limit = parsed;
156
143
  }
157
144
  const after = parseCursor(query.get('cursor'), 'string', 'integer');
158
- const ctx = await buildContextWithAuth(req, opts);
159
145
  // ?tenant=<t> reads another tenant (e.g. '__host__' for consolidate rows); admin only.
160
146
  const tenantOverride = query.get('tenant');
161
147
  const crossTenant = tenantOverride !== null && tenantOverride !== '' && tenantOverride !== ctx.tenantId;
@@ -1,7 +1,7 @@
1
- import type { RouteRequest } from '../types.js';
2
- export declare function handleCreateCustomerNote(rr: RouteRequest): Promise<void>;
3
- export declare function handleListCustomerNotes(rr: RouteRequest): Promise<void>;
4
- export declare function handleSupersedeCustomerNote(rr: RouteRequest, match: RegExpMatchArray): Promise<void>;
5
- export declare function handleCloseCustomerNote(rr: RouteRequest, match: RegExpMatchArray): Promise<void>;
6
- export declare function handleGetCustomerNote(rr: RouteRequest, match: RegExpMatchArray): Promise<void>;
1
+ import type { AuthedRouteRequest } from '../types.js';
2
+ export declare function handleCreateCustomerNote(rr: AuthedRouteRequest): Promise<void>;
3
+ export declare function handleListCustomerNotes(rr: AuthedRouteRequest): Promise<void>;
4
+ export declare function handleSupersedeCustomerNote(rr: AuthedRouteRequest, match: RegExpMatchArray): Promise<void>;
5
+ export declare function handleCloseCustomerNote(rr: AuthedRouteRequest, match: RegExpMatchArray): Promise<void>;
6
+ export declare function handleGetCustomerNote(rr: AuthedRouteRequest, match: RegExpMatchArray): Promise<void>;
7
7
  //# sourceMappingURL=customer-notes.d.ts.map
@@ -1,9 +1,9 @@
1
1
  // /v1/customer-notes routes.
2
- import { CUSTOMER_NOTE, MAX_CUSTOMER_LEN } from '../../objects/customer-notes.js';
2
+ import { CUSTOMER_NOTE, MAX_CHANGE_SUMMARY_LEN, MAX_CUSTOMER_LEN } from '../../objects/customer-notes.js';
3
3
  import { sendJson } from '../../util/http-util.js';
4
- import { buildContextWithAuth } from '../auth.js';
5
4
  import { parseJsonBody } from '../validation.js';
6
- import { closeRoute, getRoute, listRoute, optionalString, requiredString, saveFor, supersedeRoute } from './object-routes.js';
5
+ import { saveFor } from '../../api/objects.js';
6
+ import { closeRoute, getRoute, listRoute, optionalString, requiredString, supersedeRoute } from './object-routes.js';
7
7
  const noteRoutes = {
8
8
  noun: 'customer note',
9
9
  field: 'note',
@@ -12,22 +12,16 @@ const noteRoutes = {
12
12
  filterParam: 'customer',
13
13
  revise: (body) => {
14
14
  const note = requiredString(body, 'note', { max: 8192 });
15
- const changeSummary = optionalString(body, 'changeSummary', 4096);
15
+ const changeSummary = optionalString(body, 'changeSummary', MAX_CHANGE_SUMMARY_LEN);
16
16
  return (existing, id) => ({ customer: existing.customer, note, changeSummary, supersedesNoteId: id });
17
17
  },
18
18
  };
19
- // ── customer_note routes ──
20
- //
21
- // 5 routes (no assembler/refresh): POST /v1/customer-notes (new; body customer +
22
- // note), GET /v1/customer-notes (list; status + customer filter; shared
23
- // parseListLimit), GET /v1/customer-notes/:id, POST /v1/customer-notes/:id/supersede,
24
- // POST /v1/customer-notes/:id/close. DoS caps: customer 256, note 8192,
25
- // changeSummary 4096. The store validates + throws; the boundary maps validation ->
26
- // 400, not-found -> 404, not-active -> 409. Mirrors /v1/project-briefs.
19
+ // Routes: customer notes under /v1/customer-notes (create, list, show, supersede, close), mirroring /v1/project-briefs. The store validates and throws;
20
+ // the boundary maps validation -> 400, not-found -> 404, not-active -> 409.
27
21
  export async function handleCreateCustomerNote(rr) {
28
- const ctx = await buildContextWithAuth(rr.req, rr.opts);
22
+ const { ctx } = rr;
29
23
  const body = await parseJsonBody(rr.req, ctx);
30
- const customerNote = await saveFor(rr, CUSTOMER_NOTE, ctx.tenantId, ctx.actor.subject, {
24
+ const customerNote = await saveFor(ctx, CUSTOMER_NOTE, {
31
25
  customer: requiredString(body, 'customer', { max: MAX_CUSTOMER_LEN }),
32
26
  note: requiredString(body, 'note', { max: 8192 }),
33
27
  });