@nxuss/lemma 1.16.1 → 1.18.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 (483) hide show
  1. package/bin/init.js +101 -11
  2. package/dist/cjs/cli/lemma-proxy.d.ts.map +1 -1
  3. package/dist/cjs/cli/lemma-proxy.js +19 -11
  4. package/dist/cjs/cli/lemma-proxy.js.map +1 -1
  5. package/dist/cjs/cloud/TenantCache.d.ts.map +1 -1
  6. package/dist/cjs/cloud/TenantCache.js +0 -4
  7. package/dist/cjs/cloud/TenantCache.js.map +1 -1
  8. package/dist/cjs/cloud/identity/ApiKey.d.ts +32 -0
  9. package/dist/cjs/cloud/identity/ApiKey.d.ts.map +1 -0
  10. package/dist/cjs/cloud/identity/ApiKey.js +59 -0
  11. package/dist/cjs/cloud/identity/ApiKey.js.map +1 -0
  12. package/dist/cjs/cloud/identity/PlanPolicy.d.ts +79 -0
  13. package/dist/cjs/cloud/identity/PlanPolicy.d.ts.map +1 -0
  14. package/dist/cjs/cloud/identity/PlanPolicy.js +135 -0
  15. package/dist/cjs/cloud/identity/PlanPolicy.js.map +1 -0
  16. package/dist/cjs/cloud/identity/RateLimiter.d.ts +49 -0
  17. package/dist/cjs/cloud/identity/RateLimiter.d.ts.map +1 -0
  18. package/dist/cjs/cloud/identity/RateLimiter.js +75 -0
  19. package/dist/cjs/cloud/identity/RateLimiter.js.map +1 -0
  20. package/dist/cjs/cloud/identity/TenantResolver.d.ts +19 -0
  21. package/dist/cjs/cloud/identity/TenantResolver.d.ts.map +1 -0
  22. package/dist/cjs/cloud/identity/TenantResolver.js +40 -0
  23. package/dist/cjs/cloud/identity/TenantResolver.js.map +1 -0
  24. package/dist/cjs/cloud/identity/authenticateV2.d.ts +48 -0
  25. package/dist/cjs/cloud/identity/authenticateV2.d.ts.map +1 -0
  26. package/dist/cjs/cloud/identity/authenticateV2.js +66 -0
  27. package/dist/cjs/cloud/identity/authenticateV2.js.map +1 -0
  28. package/dist/cjs/cloud/identity/identityStore.d.ts +56 -0
  29. package/dist/cjs/cloud/identity/identityStore.d.ts.map +1 -0
  30. package/dist/cjs/cloud/identity/identityStore.js +99 -0
  31. package/dist/cjs/cloud/identity/identityStore.js.map +1 -0
  32. package/dist/cjs/cloud/identity/index.d.ts +14 -0
  33. package/dist/cjs/cloud/identity/index.d.ts.map +1 -0
  34. package/dist/cjs/cloud/identity/index.js +30 -0
  35. package/dist/cjs/cloud/identity/index.js.map +1 -0
  36. package/dist/cjs/cloud/metering/TokenCounter.d.ts +26 -0
  37. package/dist/cjs/cloud/metering/TokenCounter.d.ts.map +1 -0
  38. package/dist/cjs/cloud/metering/TokenCounter.js +80 -0
  39. package/dist/cjs/cloud/metering/TokenCounter.js.map +1 -0
  40. package/dist/cjs/cloud/metering/UsageLedger.d.ts +68 -0
  41. package/dist/cjs/cloud/metering/UsageLedger.d.ts.map +1 -0
  42. package/dist/cjs/cloud/metering/UsageLedger.js +106 -0
  43. package/dist/cjs/cloud/metering/UsageLedger.js.map +1 -0
  44. package/dist/cjs/cloud/metering/index.d.ts +12 -0
  45. package/dist/cjs/cloud/metering/index.d.ts.map +1 -0
  46. package/dist/cjs/cloud/metering/index.js +28 -0
  47. package/dist/cjs/cloud/metering/index.js.map +1 -0
  48. package/dist/cjs/cloud/scrub/StatelessScrubber.d.ts +53 -0
  49. package/dist/cjs/cloud/scrub/StatelessScrubber.d.ts.map +1 -0
  50. package/dist/cjs/cloud/scrub/StatelessScrubber.js +203 -0
  51. package/dist/cjs/cloud/scrub/StatelessScrubber.js.map +1 -0
  52. package/dist/cjs/cloud/scrub/index.d.ts +5 -0
  53. package/dist/cjs/cloud/scrub/index.d.ts.map +1 -0
  54. package/dist/cjs/cloud/scrub/index.js +21 -0
  55. package/dist/cjs/cloud/scrub/index.js.map +1 -0
  56. package/dist/cjs/cloud/store/FileBrainStore.d.ts +26 -0
  57. package/dist/cjs/cloud/store/FileBrainStore.d.ts.map +1 -0
  58. package/dist/cjs/cloud/store/FileBrainStore.js +219 -0
  59. package/dist/cjs/cloud/store/FileBrainStore.js.map +1 -0
  60. package/dist/cjs/cloud/store/PostgresBrainStore.d.ts +50 -0
  61. package/dist/cjs/cloud/store/PostgresBrainStore.d.ts.map +1 -0
  62. package/dist/cjs/cloud/store/PostgresBrainStore.js +181 -0
  63. package/dist/cjs/cloud/store/PostgresBrainStore.js.map +1 -0
  64. package/dist/cjs/cloud/store/index.d.ts +6 -0
  65. package/dist/cjs/cloud/store/index.d.ts.map +1 -0
  66. package/dist/cjs/cloud/store/index.js +22 -0
  67. package/dist/cjs/cloud/store/index.js.map +1 -0
  68. package/dist/cjs/cloud/types.d.ts +0 -4
  69. package/dist/cjs/cloud/types.d.ts.map +1 -1
  70. package/dist/cjs/cloud/types.js +1 -3
  71. package/dist/cjs/cloud/types.js.map +1 -1
  72. package/dist/cjs/cloud/v2/app.d.ts +15 -0
  73. package/dist/cjs/cloud/v2/app.d.ts.map +1 -0
  74. package/dist/cjs/cloud/v2/app.js +63 -0
  75. package/dist/cjs/cloud/v2/app.js.map +1 -0
  76. package/dist/cjs/cloud/v2/routes/index.d.ts +24 -0
  77. package/dist/cjs/cloud/v2/routes/index.d.ts.map +1 -0
  78. package/dist/cjs/cloud/v2/routes/index.js +35 -0
  79. package/dist/cjs/cloud/v2/routes/index.js.map +1 -0
  80. package/dist/cjs/cloud/v2/routes/memories.d.ts +83 -0
  81. package/dist/cjs/cloud/v2/routes/memories.d.ts.map +1 -0
  82. package/dist/cjs/cloud/v2/routes/memories.js +249 -0
  83. package/dist/cjs/cloud/v2/routes/memories.js.map +1 -0
  84. package/dist/cjs/cloud/v2/routes/recall.d.ts +33 -0
  85. package/dist/cjs/cloud/v2/routes/recall.d.ts.map +1 -0
  86. package/dist/cjs/cloud/v2/routes/recall.js +51 -0
  87. package/dist/cjs/cloud/v2/routes/recall.js.map +1 -0
  88. package/dist/cjs/cloud/v2/routes/scrub.d.ts +13 -0
  89. package/dist/cjs/cloud/v2/routes/scrub.d.ts.map +1 -0
  90. package/dist/cjs/cloud/v2/routes/scrub.js +82 -0
  91. package/dist/cjs/cloud/v2/routes/scrub.js.map +1 -0
  92. package/dist/cjs/cloud/v2/routes/usage.d.ts +18 -0
  93. package/dist/cjs/cloud/v2/routes/usage.d.ts.map +1 -0
  94. package/dist/cjs/cloud/v2/routes/usage.js +18 -0
  95. package/dist/cjs/cloud/v2/routes/usage.js.map +1 -0
  96. package/dist/cjs/cloud/v2/routes/verify.d.ts +35 -0
  97. package/dist/cjs/cloud/v2/routes/verify.d.ts.map +1 -0
  98. package/dist/cjs/cloud/v2/routes/verify.js +43 -0
  99. package/dist/cjs/cloud/v2/routes/verify.js.map +1 -0
  100. package/dist/cjs/cloud/v2/server.d.ts +27 -0
  101. package/dist/cjs/cloud/v2/server.d.ts.map +1 -0
  102. package/dist/cjs/cloud/v2/server.js +47 -0
  103. package/dist/cjs/cloud/v2/server.js.map +1 -0
  104. package/dist/cjs/contracts/api-v2.types.d.ts +103 -0
  105. package/dist/cjs/contracts/api-v2.types.d.ts.map +1 -0
  106. package/dist/cjs/contracts/api-v2.types.js +3 -0
  107. package/dist/cjs/contracts/api-v2.types.js.map +1 -0
  108. package/dist/cjs/contracts/errors.d.ts +40 -0
  109. package/dist/cjs/contracts/errors.d.ts.map +1 -0
  110. package/dist/cjs/contracts/errors.js +50 -0
  111. package/dist/cjs/contracts/errors.js.map +1 -0
  112. package/dist/cjs/contracts/evidence.d.ts +49 -0
  113. package/dist/cjs/contracts/evidence.d.ts.map +1 -0
  114. package/dist/cjs/contracts/evidence.js +12 -0
  115. package/dist/cjs/contracts/evidence.js.map +1 -0
  116. package/dist/cjs/contracts/index.d.ts +10 -0
  117. package/dist/cjs/contracts/index.d.ts.map +1 -0
  118. package/dist/cjs/contracts/index.js +26 -0
  119. package/dist/cjs/contracts/index.js.map +1 -0
  120. package/dist/cjs/contracts/store.d.ts +30 -0
  121. package/dist/cjs/contracts/store.d.ts.map +1 -0
  122. package/dist/cjs/contracts/store.js +3 -0
  123. package/dist/cjs/contracts/store.js.map +1 -0
  124. package/dist/cjs/mcp/tool-profiles.d.ts.map +1 -1
  125. package/dist/cjs/mcp/tool-profiles.js +46 -1
  126. package/dist/cjs/mcp/tool-profiles.js.map +1 -1
  127. package/dist/cjs/mcp/tools.d.ts +2 -0
  128. package/dist/cjs/mcp/tools.d.ts.map +1 -1
  129. package/dist/cjs/mcp/tools.js +319 -30
  130. package/dist/cjs/mcp/tools.js.map +1 -1
  131. package/dist/cjs/pr-review/bridge/BrainBridge.js +1 -1
  132. package/dist/cjs/pr-review/bridge/BrainBridge.js.map +1 -1
  133. package/dist/cjs/subconscious/BrainEmbeddings.d.ts +59 -0
  134. package/dist/cjs/subconscious/BrainEmbeddings.d.ts.map +1 -0
  135. package/dist/cjs/subconscious/BrainEmbeddings.js +222 -0
  136. package/dist/cjs/subconscious/BrainEmbeddings.js.map +1 -0
  137. package/dist/cjs/subconscious/GitIngest.js +2 -2
  138. package/dist/cjs/subconscious/GitIngest.js.map +1 -1
  139. package/dist/cjs/subconscious/TheBrainV2.d.ts +327 -9
  140. package/dist/cjs/subconscious/TheBrainV2.d.ts.map +1 -1
  141. package/dist/cjs/subconscious/TheBrainV2.js +952 -98
  142. package/dist/cjs/subconscious/TheBrainV2.js.map +1 -1
  143. package/dist/cjs/subconscious/freshness/LocalFsResolver.d.ts +16 -0
  144. package/dist/cjs/subconscious/freshness/LocalFsResolver.d.ts.map +1 -0
  145. package/dist/cjs/subconscious/freshness/LocalFsResolver.js +74 -0
  146. package/dist/cjs/subconscious/freshness/LocalFsResolver.js.map +1 -0
  147. package/dist/cjs/subconscious/freshness/SuppliedEvidenceResolver.d.ts +23 -0
  148. package/dist/cjs/subconscious/freshness/SuppliedEvidenceResolver.d.ts.map +1 -0
  149. package/dist/cjs/subconscious/freshness/SuppliedEvidenceResolver.js +24 -0
  150. package/dist/cjs/subconscious/freshness/SuppliedEvidenceResolver.js.map +1 -0
  151. package/dist/cjs/subconscious/freshness/index.d.ts +10 -0
  152. package/dist/cjs/subconscious/freshness/index.d.ts.map +1 -0
  153. package/dist/cjs/subconscious/freshness/index.js +26 -0
  154. package/dist/cjs/subconscious/freshness/index.js.map +1 -0
  155. package/dist/cjs/utils/ConversationCheckpoint.js +1 -1
  156. package/dist/cjs/utils/ConversationCheckpoint.js.map +1 -1
  157. package/dist/cjs/utils/ProjectIdentity.d.ts +12 -0
  158. package/dist/cjs/utils/ProjectIdentity.d.ts.map +1 -0
  159. package/dist/cjs/utils/ProjectIdentity.js +44 -0
  160. package/dist/cjs/utils/ProjectIdentity.js.map +1 -0
  161. package/dist/cjs/utils/PromptPatternCache.d.ts.map +1 -1
  162. package/dist/cjs/utils/PromptPatternCache.js +12 -2
  163. package/dist/cjs/utils/PromptPatternCache.js.map +1 -1
  164. package/dist/cjs/utils/RepeatGuard.d.ts.map +1 -1
  165. package/dist/cjs/utils/RepeatGuard.js +10 -2
  166. package/dist/cjs/utils/RepeatGuard.js.map +1 -1
  167. package/dist/cjs/utils/StateHashCache.d.ts +5 -0
  168. package/dist/cjs/utils/StateHashCache.d.ts.map +1 -1
  169. package/dist/cjs/utils/StateHashCache.js +40 -16
  170. package/dist/cjs/utils/StateHashCache.js.map +1 -1
  171. package/dist/esm/api/dashboardRoutes.d.ts +3 -3
  172. package/dist/esm/api/dashboardRoutes.js +1 -1
  173. package/dist/esm/api/server.d.ts +4 -4
  174. package/dist/esm/api/server.js +3 -3
  175. package/dist/esm/autopilot/AutopilotWatcher.js +3 -3
  176. package/dist/esm/autopilot/Notifier.d.ts +1 -1
  177. package/dist/esm/cli/lemma-proxy.d.ts.map +1 -1
  178. package/dist/esm/cli/lemma-proxy.js +33 -25
  179. package/dist/esm/cli/lemma-proxy.js.map +1 -1
  180. package/dist/esm/cli/stack.d.ts +4 -4
  181. package/dist/esm/cli/stack.js +5 -5
  182. package/dist/esm/cloud/KeyManager.d.ts +1 -1
  183. package/dist/esm/cloud/KeyManager.js +1 -1
  184. package/dist/esm/cloud/TenantCache.d.ts +1 -1
  185. package/dist/esm/cloud/TenantCache.d.ts.map +1 -1
  186. package/dist/esm/cloud/TenantCache.js +0 -4
  187. package/dist/esm/cloud/TenantCache.js.map +1 -1
  188. package/dist/esm/cloud/identity/ApiKey.d.ts +32 -0
  189. package/dist/esm/cloud/identity/ApiKey.d.ts.map +1 -0
  190. package/dist/esm/cloud/identity/ApiKey.js +49 -0
  191. package/dist/esm/cloud/identity/ApiKey.js.map +1 -0
  192. package/dist/esm/cloud/identity/PlanPolicy.d.ts +79 -0
  193. package/dist/esm/cloud/identity/PlanPolicy.d.ts.map +1 -0
  194. package/dist/esm/cloud/identity/PlanPolicy.js +129 -0
  195. package/dist/esm/cloud/identity/PlanPolicy.js.map +1 -0
  196. package/dist/esm/cloud/identity/RateLimiter.d.ts +49 -0
  197. package/dist/esm/cloud/identity/RateLimiter.d.ts.map +1 -0
  198. package/dist/esm/cloud/identity/RateLimiter.js +69 -0
  199. package/dist/esm/cloud/identity/RateLimiter.js.map +1 -0
  200. package/dist/esm/cloud/identity/TenantResolver.d.ts +19 -0
  201. package/dist/esm/cloud/identity/TenantResolver.d.ts.map +1 -0
  202. package/dist/esm/cloud/identity/TenantResolver.js +36 -0
  203. package/dist/esm/cloud/identity/TenantResolver.js.map +1 -0
  204. package/dist/esm/cloud/identity/authenticateV2.d.ts +48 -0
  205. package/dist/esm/cloud/identity/authenticateV2.d.ts.map +1 -0
  206. package/dist/esm/cloud/identity/authenticateV2.js +62 -0
  207. package/dist/esm/cloud/identity/authenticateV2.js.map +1 -0
  208. package/dist/esm/cloud/identity/identityStore.d.ts +56 -0
  209. package/dist/esm/cloud/identity/identityStore.d.ts.map +1 -0
  210. package/dist/esm/cloud/identity/identityStore.js +94 -0
  211. package/dist/esm/cloud/identity/identityStore.js.map +1 -0
  212. package/dist/esm/cloud/identity/index.d.ts +14 -0
  213. package/dist/esm/cloud/identity/index.d.ts.map +1 -0
  214. package/dist/esm/cloud/identity/index.js +14 -0
  215. package/dist/esm/cloud/identity/index.js.map +1 -0
  216. package/dist/esm/cloud/index.d.ts +3 -3
  217. package/dist/esm/cloud/index.js +3 -3
  218. package/dist/esm/cloud/metering/TokenCounter.d.ts +26 -0
  219. package/dist/esm/cloud/metering/TokenCounter.d.ts.map +1 -0
  220. package/dist/esm/cloud/metering/TokenCounter.js +76 -0
  221. package/dist/esm/cloud/metering/TokenCounter.js.map +1 -0
  222. package/dist/esm/cloud/metering/UsageLedger.d.ts +68 -0
  223. package/dist/esm/cloud/metering/UsageLedger.d.ts.map +1 -0
  224. package/dist/esm/cloud/metering/UsageLedger.js +98 -0
  225. package/dist/esm/cloud/metering/UsageLedger.js.map +1 -0
  226. package/dist/esm/cloud/metering/index.d.ts +12 -0
  227. package/dist/esm/cloud/metering/index.d.ts.map +1 -0
  228. package/dist/esm/cloud/metering/index.js +12 -0
  229. package/dist/esm/cloud/metering/index.js.map +1 -0
  230. package/dist/esm/cloud/scrub/StatelessScrubber.d.ts +53 -0
  231. package/dist/esm/cloud/scrub/StatelessScrubber.d.ts.map +1 -0
  232. package/dist/esm/cloud/scrub/StatelessScrubber.js +199 -0
  233. package/dist/esm/cloud/scrub/StatelessScrubber.js.map +1 -0
  234. package/dist/esm/cloud/scrub/index.d.ts +5 -0
  235. package/dist/esm/cloud/scrub/index.d.ts.map +1 -0
  236. package/dist/esm/cloud/scrub/index.js +5 -0
  237. package/dist/esm/cloud/scrub/index.js.map +1 -0
  238. package/dist/esm/cloud/server.d.ts +3 -3
  239. package/dist/esm/cloud/server.js +5 -5
  240. package/dist/esm/cloud/store/FileBrainStore.d.ts +26 -0
  241. package/dist/esm/cloud/store/FileBrainStore.d.ts.map +1 -0
  242. package/dist/esm/cloud/store/FileBrainStore.js +212 -0
  243. package/dist/esm/cloud/store/FileBrainStore.js.map +1 -0
  244. package/dist/esm/cloud/store/PostgresBrainStore.d.ts +50 -0
  245. package/dist/esm/cloud/store/PostgresBrainStore.d.ts.map +1 -0
  246. package/dist/esm/cloud/store/PostgresBrainStore.js +176 -0
  247. package/dist/esm/cloud/store/PostgresBrainStore.js.map +1 -0
  248. package/dist/esm/cloud/store/index.d.ts +6 -0
  249. package/dist/esm/cloud/store/index.d.ts.map +1 -0
  250. package/dist/esm/cloud/store/index.js +6 -0
  251. package/dist/esm/cloud/store/index.js.map +1 -0
  252. package/dist/esm/cloud/types.d.ts +0 -4
  253. package/dist/esm/cloud/types.d.ts.map +1 -1
  254. package/dist/esm/cloud/types.js +0 -2
  255. package/dist/esm/cloud/types.js.map +1 -1
  256. package/dist/esm/cloud/v2/app.d.ts +15 -0
  257. package/dist/esm/cloud/v2/app.d.ts.map +1 -0
  258. package/dist/esm/cloud/v2/app.js +57 -0
  259. package/dist/esm/cloud/v2/app.js.map +1 -0
  260. package/dist/esm/cloud/v2/routes/index.d.ts +24 -0
  261. package/dist/esm/cloud/v2/routes/index.d.ts.map +1 -0
  262. package/dist/esm/cloud/v2/routes/index.js +32 -0
  263. package/dist/esm/cloud/v2/routes/index.js.map +1 -0
  264. package/dist/esm/cloud/v2/routes/memories.d.ts +83 -0
  265. package/dist/esm/cloud/v2/routes/memories.d.ts.map +1 -0
  266. package/dist/esm/cloud/v2/routes/memories.js +238 -0
  267. package/dist/esm/cloud/v2/routes/memories.js.map +1 -0
  268. package/dist/esm/cloud/v2/routes/recall.d.ts +33 -0
  269. package/dist/esm/cloud/v2/routes/recall.d.ts.map +1 -0
  270. package/dist/esm/cloud/v2/routes/recall.js +47 -0
  271. package/dist/esm/cloud/v2/routes/recall.js.map +1 -0
  272. package/dist/esm/cloud/v2/routes/scrub.d.ts +13 -0
  273. package/dist/esm/cloud/v2/routes/scrub.d.ts.map +1 -0
  274. package/dist/esm/cloud/v2/routes/scrub.js +79 -0
  275. package/dist/esm/cloud/v2/routes/scrub.js.map +1 -0
  276. package/dist/esm/cloud/v2/routes/usage.d.ts +18 -0
  277. package/dist/esm/cloud/v2/routes/usage.d.ts.map +1 -0
  278. package/dist/esm/cloud/v2/routes/usage.js +15 -0
  279. package/dist/esm/cloud/v2/routes/usage.js.map +1 -0
  280. package/dist/esm/cloud/v2/routes/verify.d.ts +35 -0
  281. package/dist/esm/cloud/v2/routes/verify.d.ts.map +1 -0
  282. package/dist/esm/cloud/v2/routes/verify.js +39 -0
  283. package/dist/esm/cloud/v2/routes/verify.js.map +1 -0
  284. package/dist/esm/cloud/v2/server.d.ts +27 -0
  285. package/dist/esm/cloud/v2/server.d.ts.map +1 -0
  286. package/dist/esm/cloud/v2/server.js +44 -0
  287. package/dist/esm/cloud/v2/server.js.map +1 -0
  288. package/dist/esm/config/index.d.ts +1 -1
  289. package/dist/esm/config/index.js +1 -1
  290. package/dist/esm/consensus/index.d.ts +2 -2
  291. package/dist/esm/consensus/index.js +2 -2
  292. package/dist/esm/contracts/api-v2.types.d.ts +103 -0
  293. package/dist/esm/contracts/api-v2.types.d.ts.map +1 -0
  294. package/dist/esm/contracts/api-v2.types.js +2 -0
  295. package/dist/esm/contracts/api-v2.types.js.map +1 -0
  296. package/dist/esm/contracts/errors.d.ts +40 -0
  297. package/dist/esm/contracts/errors.d.ts.map +1 -0
  298. package/dist/esm/contracts/errors.js +45 -0
  299. package/dist/esm/contracts/errors.js.map +1 -0
  300. package/dist/esm/contracts/evidence.d.ts +49 -0
  301. package/dist/esm/contracts/evidence.d.ts.map +1 -0
  302. package/dist/esm/contracts/evidence.js +11 -0
  303. package/dist/esm/contracts/evidence.js.map +1 -0
  304. package/dist/esm/contracts/index.d.ts +10 -0
  305. package/dist/esm/contracts/index.d.ts.map +1 -0
  306. package/dist/esm/contracts/index.js +10 -0
  307. package/dist/esm/contracts/index.js.map +1 -0
  308. package/dist/esm/contracts/store.d.ts +30 -0
  309. package/dist/esm/contracts/store.d.ts.map +1 -0
  310. package/dist/esm/contracts/store.js +2 -0
  311. package/dist/esm/contracts/store.js.map +1 -0
  312. package/dist/esm/core/AgentRegistry.d.ts +1 -1
  313. package/dist/esm/core/AgentRegistry.js +1 -1
  314. package/dist/esm/core/DashboardBroadcaster.d.ts +3 -3
  315. package/dist/esm/core/DashboardBroadcaster.js +2 -2
  316. package/dist/esm/core/DashboardWebSocketServer.d.ts +1 -1
  317. package/dist/esm/core/DashboardWebSocketServer.js +1 -1
  318. package/dist/esm/core/GhostAlchemist.js +1 -1
  319. package/dist/esm/core/GhostListener.js +2 -2
  320. package/dist/esm/core/OrchestrationEngine.d.ts +3 -3
  321. package/dist/esm/core/OrchestrationEngine.js +2 -2
  322. package/dist/esm/core/SubconsciousEngine.d.ts +1 -1
  323. package/dist/esm/core/SubconsciousEngine.js +2 -2
  324. package/dist/esm/core/WebSocketServer.d.ts +2 -2
  325. package/dist/esm/core/WebSocketServer.js +1 -1
  326. package/dist/esm/core/index.d.ts +6 -6
  327. package/dist/esm/core/index.js +6 -6
  328. package/dist/esm/core/router.d.ts +3 -3
  329. package/dist/esm/core/router.js +1 -1
  330. package/dist/esm/db/database.js +1 -1
  331. package/dist/esm/embed.d.ts +2 -2
  332. package/dist/esm/embed.js +2 -2
  333. package/dist/esm/examples/basic-usage.js +1 -1
  334. package/dist/esm/index.d.ts +14 -14
  335. package/dist/esm/index.js +14 -14
  336. package/dist/esm/infra/analyzers/DriftDetector.d.ts +1 -1
  337. package/dist/esm/infra/analyzers/InfraAnalyzer.d.ts +1 -1
  338. package/dist/esm/infra/analyzers/MonolithAnalyzer.d.ts +1 -1
  339. package/dist/esm/infra/analyzers/index.d.ts +3 -3
  340. package/dist/esm/infra/analyzers/index.js +3 -3
  341. package/dist/esm/infra/cli.js +2 -2
  342. package/dist/esm/infra/config.d.ts +1 -1
  343. package/dist/esm/infra/index.d.ts +5 -5
  344. package/dist/esm/infra/index.js +5 -5
  345. package/dist/esm/infra/mcp-tools.js +5 -5
  346. package/dist/esm/infra/providers/InfraProvider.d.ts +1 -1
  347. package/dist/esm/infra/providers/JenkinsProvider.d.ts +2 -2
  348. package/dist/esm/infra/providers/OKDProvider.d.ts +2 -2
  349. package/dist/esm/infra/providers/TerraformProvider.d.ts +2 -2
  350. package/dist/esm/infra/providers/index.d.ts +5 -5
  351. package/dist/esm/infra/providers/index.js +3 -3
  352. package/dist/esm/mcp/index.js +5 -5
  353. package/dist/esm/mcp/prompts.js +1 -1
  354. package/dist/esm/mcp/resources.js +2 -2
  355. package/dist/esm/mcp/tasks.js +1 -1
  356. package/dist/esm/mcp/tool-profiles.d.ts.map +1 -1
  357. package/dist/esm/mcp/tool-profiles.js +47 -2
  358. package/dist/esm/mcp/tool-profiles.js.map +1 -1
  359. package/dist/esm/mcp/tools.d.ts +2 -0
  360. package/dist/esm/mcp/tools.d.ts.map +1 -1
  361. package/dist/esm/mcp/tools.js +366 -78
  362. package/dist/esm/mcp/tools.js.map +1 -1
  363. package/dist/esm/observability/IdeContextSync.d.ts +1 -1
  364. package/dist/esm/observability/IdeContextSync.js +5 -5
  365. package/dist/esm/pr-review/PRReviewEngine.d.ts +1 -1
  366. package/dist/esm/pr-review/PRReviewEngine.js +4 -4
  367. package/dist/esm/pr-review/ReviewStore.d.ts +1 -1
  368. package/dist/esm/pr-review/adapters/AzureDevOpsAdapter.d.ts +2 -2
  369. package/dist/esm/pr-review/adapters/AzureDevOpsAdapter.js +1 -1
  370. package/dist/esm/pr-review/adapters/GitHubAdapter.d.ts +2 -2
  371. package/dist/esm/pr-review/adapters/GitHubAdapter.js +1 -1
  372. package/dist/esm/pr-review/adapters/GitLabAdapter.d.ts +2 -2
  373. package/dist/esm/pr-review/adapters/GitLabAdapter.js +1 -1
  374. package/dist/esm/pr-review/adapters/GitPlatformAdapter.d.ts +1 -1
  375. package/dist/esm/pr-review/adapters/index.d.ts +4 -4
  376. package/dist/esm/pr-review/adapters/index.js +3 -3
  377. package/dist/esm/pr-review/analyzers/QualityGrader.d.ts +1 -1
  378. package/dist/esm/pr-review/analyzers/RegressionDetector.d.ts +1 -1
  379. package/dist/esm/pr-review/analyzers/SecurityScanner.d.ts +1 -1
  380. package/dist/esm/pr-review/analyzers/StaticAnalyzer.d.ts +1 -1
  381. package/dist/esm/pr-review/analyzers/index.d.ts +8 -8
  382. package/dist/esm/pr-review/analyzers/index.js +4 -4
  383. package/dist/esm/pr-review/bridge/BrainBridge.d.ts +1 -1
  384. package/dist/esm/pr-review/bridge/BrainBridge.js +2 -2
  385. package/dist/esm/pr-review/bridge/BrainBridge.js.map +1 -1
  386. package/dist/esm/pr-review/bridge/index.d.ts +1 -1
  387. package/dist/esm/pr-review/bridge/index.js +1 -1
  388. package/dist/esm/pr-review/index.d.ts +4 -4
  389. package/dist/esm/pr-review/index.js +2 -2
  390. package/dist/esm/pr-review/reviewRunner.d.ts +2 -2
  391. package/dist/esm/pr-review/reviewRunner.js +6 -6
  392. package/dist/esm/pr-review/webhook/WebhookServer.js +1 -1
  393. package/dist/esm/pr-review/webhook/index.d.ts +1 -1
  394. package/dist/esm/pr-review/webhook/index.js +1 -1
  395. package/dist/esm/protocol/flows.d.ts +1 -1
  396. package/dist/esm/protocol/flows.js +1 -1
  397. package/dist/esm/protocol/index.d.ts +4 -4
  398. package/dist/esm/protocol/index.js +4 -4
  399. package/dist/esm/protocol/utils.d.ts +1 -1
  400. package/dist/esm/protocol/utils.js +2 -2
  401. package/dist/esm/protocol/validators.d.ts +1 -1
  402. package/dist/esm/protocol/validators.js +1 -1
  403. package/dist/esm/proxy/ContextInjector.d.ts +1 -1
  404. package/dist/esm/proxy/Gatekeeper.d.ts +1 -1
  405. package/dist/esm/security/SecurityMiddleware.d.ts +1 -1
  406. package/dist/esm/security/SecurityMiddleware.js +3 -3
  407. package/dist/esm/security/index.d.ts +4 -4
  408. package/dist/esm/security/index.js +4 -4
  409. package/dist/esm/speculative/SpeculativeCache.d.ts +2 -2
  410. package/dist/esm/speculative/SpeculativeEngine.d.ts +2 -2
  411. package/dist/esm/speculative/SpeculativeEngine.js +3 -3
  412. package/dist/esm/speculative/WorkerPool.d.ts +1 -1
  413. package/dist/esm/speculative/index.d.ts +4 -4
  414. package/dist/esm/speculative/index.js +4 -4
  415. package/dist/esm/subconscious/BrainEmbeddings.d.ts +59 -0
  416. package/dist/esm/subconscious/BrainEmbeddings.d.ts.map +1 -0
  417. package/dist/esm/subconscious/BrainEmbeddings.js +211 -0
  418. package/dist/esm/subconscious/BrainEmbeddings.js.map +1 -0
  419. package/dist/esm/subconscious/GitIngest.d.ts +1 -1
  420. package/dist/esm/subconscious/GitIngest.js +3 -3
  421. package/dist/esm/subconscious/GitIngest.js.map +1 -1
  422. package/dist/esm/subconscious/SemanticCache.d.ts +2 -2
  423. package/dist/esm/subconscious/SemanticCache.js +2 -2
  424. package/dist/esm/subconscious/SubconsciousEngine.d.ts +1 -1
  425. package/dist/esm/subconscious/SubconsciousEngine.js +3 -3
  426. package/dist/esm/subconscious/TheBrainV2.d.ts +327 -9
  427. package/dist/esm/subconscious/TheBrainV2.d.ts.map +1 -1
  428. package/dist/esm/subconscious/TheBrainV2.js +947 -98
  429. package/dist/esm/subconscious/TheBrainV2.js.map +1 -1
  430. package/dist/esm/subconscious/freshness/LocalFsResolver.d.ts +16 -0
  431. package/dist/esm/subconscious/freshness/LocalFsResolver.d.ts.map +1 -0
  432. package/dist/esm/subconscious/freshness/LocalFsResolver.js +67 -0
  433. package/dist/esm/subconscious/freshness/LocalFsResolver.js.map +1 -0
  434. package/dist/esm/subconscious/freshness/SuppliedEvidenceResolver.d.ts +23 -0
  435. package/dist/esm/subconscious/freshness/SuppliedEvidenceResolver.d.ts.map +1 -0
  436. package/dist/esm/subconscious/freshness/SuppliedEvidenceResolver.js +20 -0
  437. package/dist/esm/subconscious/freshness/SuppliedEvidenceResolver.js.map +1 -0
  438. package/dist/esm/subconscious/freshness/index.d.ts +10 -0
  439. package/dist/esm/subconscious/freshness/index.d.ts.map +1 -0
  440. package/dist/esm/subconscious/freshness/index.js +10 -0
  441. package/dist/esm/subconscious/freshness/index.js.map +1 -0
  442. package/dist/esm/subconscious/index.d.ts +4 -4
  443. package/dist/esm/subconscious/index.js +4 -4
  444. package/dist/esm/utils/AffectedTests.js +1 -1
  445. package/dist/esm/utils/AutoContextBundle.d.ts +1 -1
  446. package/dist/esm/utils/AutoContextBundle.js +4 -4
  447. package/dist/esm/utils/BulkFileDigest.js +2 -2
  448. package/dist/esm/utils/ClipboardWatcher.js +2 -2
  449. package/dist/esm/utils/ContextCollapser.js +1 -1
  450. package/dist/esm/utils/ConversationCheckpoint.js +2 -2
  451. package/dist/esm/utils/ConversationCheckpoint.js.map +1 -1
  452. package/dist/esm/utils/ExecutiveReport.js +1 -1
  453. package/dist/esm/utils/OutputLedger.js +2 -2
  454. package/dist/esm/utils/ProjectIdentity.d.ts +12 -0
  455. package/dist/esm/utils/ProjectIdentity.d.ts.map +1 -0
  456. package/dist/esm/utils/ProjectIdentity.js +37 -0
  457. package/dist/esm/utils/ProjectIdentity.js.map +1 -0
  458. package/dist/esm/utils/PromptPatternCache.d.ts.map +1 -1
  459. package/dist/esm/utils/PromptPatternCache.js +12 -2
  460. package/dist/esm/utils/PromptPatternCache.js.map +1 -1
  461. package/dist/esm/utils/ReadWorkspaceCache.js +1 -1
  462. package/dist/esm/utils/RepeatGuard.d.ts.map +1 -1
  463. package/dist/esm/utils/RepeatGuard.js +10 -2
  464. package/dist/esm/utils/RepeatGuard.js.map +1 -1
  465. package/dist/esm/utils/SpeculativeWarmer.d.ts +1 -1
  466. package/dist/esm/utils/SpeculativeWarmer.js +2 -2
  467. package/dist/esm/utils/StateHashCache.d.ts +5 -0
  468. package/dist/esm/utils/StateHashCache.d.ts.map +1 -1
  469. package/dist/esm/utils/StateHashCache.js +40 -16
  470. package/dist/esm/utils/StateHashCache.js.map +1 -1
  471. package/dist/esm/utils/StructuralSearch.d.ts +1 -1
  472. package/dist/esm/utils/SurgicalASTInsert.js +1 -1
  473. package/dist/esm/utils/SymbolSurgicalContext.js +1 -1
  474. package/dist/esm/utils/TestAutofixInterceptor.js +1 -1
  475. package/dist/esm/utils/WorkspaceSearch.js +0 -0
  476. package/dist/esm/utils/logger.js +1 -1
  477. package/dist/esm/utils/reportSavings.js +1 -1
  478. package/package.json +1 -1
  479. package/sdks/crewai/README.md +25 -0
  480. package/dist/cjs/package.json +0 -3
  481. package/dist/esm/package.json +0 -3
  482. package/sdks/crewai/dist/index.d.ts +0 -130
  483. package/sdks/crewai/dist/index.js +0 -308
@@ -0,0 +1,32 @@
1
+ import type { IdentityStore, NewKeyInput } from './identityStore';
2
+ export type KeyPrefix = 'lk_live_' | 'lk_test_';
3
+ export declare const KEY_PREFIX_LIVE: KeyPrefix;
4
+ export declare const KEY_PREFIX_TEST: KeyPrefix;
5
+ export declare const KEY_SHAPE: RegExp;
6
+ export interface GeneratedApiKey {
7
+ /** Stable, NON-secret record id (`key_<hex>`). Safe for dashboards and logs. */
8
+ id: string;
9
+ /** PLAINTEXT key value. Returned exactly once, never stored, never logged. */
10
+ key: string;
11
+ /** sha256 of the full key value — the only thing the DB ever sees. */
12
+ hash: string;
13
+ prefix: KeyPrefix;
14
+ }
15
+ /** sha256 of the full bearer value, hex-encoded. Deterministic, one-way. */
16
+ export declare function hashApiKey(key: string): string;
17
+ /** Cheap shape check before hashing — rejects obvious junk without a store hit. */
18
+ export declare function isWellFormedKey(token: string): boolean;
19
+ /**
20
+ * Generate a fresh key. The plaintext `key` lives only in the returned object
21
+ * (and, transitively, in the HTTP response of the creation call).
22
+ */
23
+ export declare function generateApiKey(prefix?: KeyPrefix): GeneratedApiKey;
24
+ /**
25
+ * Issue a key end-to-end: generate the plaintext, persist ONLY its hash, return
26
+ * the plaintext to the caller a single time. The returned value must be sent to
27
+ * the client and discarded — it exists in no store.
28
+ */
29
+ export declare function issueApiKey(store: IdentityStore, input: Omit<NewKeyInput, 'prefix' | 'hash'> & {
30
+ prefix?: KeyPrefix;
31
+ }): Promise<GeneratedApiKey>;
32
+ //# sourceMappingURL=ApiKey.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiKey.d.ts","sourceRoot":"","sources":["../../../../src/cloud/identity/ApiKey.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAGlE,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;AAEhD,eAAO,MAAM,eAAe,EAAE,SAAsB,CAAC;AACrD,eAAO,MAAM,eAAe,EAAE,SAAsB,CAAC;AACrD,eAAO,MAAM,SAAS,QAAqC,CAAC;AAE5D,MAAM,WAAW,eAAe;IAC9B,gFAAgF;IAChF,EAAE,EAAE,MAAM,CAAC;IACX,8EAA8E;IAC9E,GAAG,EAAE,MAAM,CAAC;IACZ,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,CAAC;CACnB;AAED,4EAA4E;AAC5E,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,GAAE,SAA2B,GAAG,eAAe,CAInF;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,aAAa,EACpB,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,MAAM,CAAC,GAAG;IAAE,MAAM,CAAC,EAAE,SAAS,CAAA;CAAE,GACnE,OAAO,CAAC,eAAe,CAAC,CAW1B"}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.KEY_SHAPE = exports.KEY_PREFIX_TEST = exports.KEY_PREFIX_LIVE = void 0;
7
+ exports.hashApiKey = hashApiKey;
8
+ exports.isWellFormedKey = isWellFormedKey;
9
+ exports.generateApiKey = generateApiKey;
10
+ exports.issueApiKey = issueApiKey;
11
+ /**
12
+ * Lemma API v2 — API key generation & hashing (Lane D)
13
+ *
14
+ * SECURITY CONTRACT:
15
+ * - The plaintext key value is produced EXACTLY ONCE, inside `generateApiKey`,
16
+ * and returned to the caller of `issueApiKey`. It is never persisted and
17
+ * never logged: the only derivation that survives is the SHA-256 hash.
18
+ * - `identityStore.createKey()` receives only `{ hash }` — the plaintext never
19
+ * enters the persistence layer, by construction, not by discipline.
20
+ */
21
+ const crypto_1 = __importDefault(require("crypto"));
22
+ exports.KEY_PREFIX_LIVE = 'lk_live_';
23
+ exports.KEY_PREFIX_TEST = 'lk_test_';
24
+ exports.KEY_SHAPE = /^lk_(live|test)_[0-9a-f]{32,64}$/;
25
+ /** sha256 of the full bearer value, hex-encoded. Deterministic, one-way. */
26
+ function hashApiKey(key) {
27
+ return crypto_1.default.createHash('sha256').update(key, 'utf8').digest('hex');
28
+ }
29
+ /** Cheap shape check before hashing — rejects obvious junk without a store hit. */
30
+ function isWellFormedKey(token) {
31
+ return exports.KEY_SHAPE.test(token);
32
+ }
33
+ /**
34
+ * Generate a fresh key. The plaintext `key` lives only in the returned object
35
+ * (and, transitively, in the HTTP response of the creation call).
36
+ */
37
+ function generateApiKey(prefix = exports.KEY_PREFIX_LIVE) {
38
+ const randomHex = crypto_1.default.randomBytes(16).toString('hex');
39
+ const key = `${prefix}${randomHex}`;
40
+ return { id: `key_${randomHex.slice(0, 12)}`, key, hash: hashApiKey(key), prefix };
41
+ }
42
+ /**
43
+ * Issue a key end-to-end: generate the plaintext, persist ONLY its hash, return
44
+ * the plaintext to the caller a single time. The returned value must be sent to
45
+ * the client and discarded — it exists in no store.
46
+ */
47
+ async function issueApiKey(store, input) {
48
+ const prefix = input.prefix ?? exports.KEY_PREFIX_LIVE;
49
+ const generated = generateApiKey(prefix);
50
+ await store.createKey({
51
+ tenantId: input.tenantId,
52
+ name: input.name,
53
+ plan: input.plan,
54
+ prefix,
55
+ hash: generated.hash,
56
+ });
57
+ return generated;
58
+ }
59
+ //# sourceMappingURL=ApiKey.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiKey.js","sourceRoot":"","sources":["../../../../src/cloud/identity/ApiKey.ts"],"names":[],"mappings":";;;;;;AA+BA,gCAEC;AAGD,0CAEC;AAMD,wCAIC;AAOD,kCAcC;AArED;;;;;;;;;GASG;AACH,oDAA4B;AAMf,QAAA,eAAe,GAAc,UAAU,CAAC;AACxC,QAAA,eAAe,GAAc,UAAU,CAAC;AACxC,QAAA,SAAS,GAAG,kCAAkC,CAAC;AAY5D,4EAA4E;AAC5E,SAAgB,UAAU,CAAC,GAAW;IACpC,OAAO,gBAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACvE,CAAC;AAED,mFAAmF;AACnF,SAAgB,eAAe,CAAC,KAAa;IAC3C,OAAO,iBAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED;;;GAGG;AACH,SAAgB,cAAc,CAAC,SAAoB,uBAAe;IAChE,MAAM,SAAS,GAAG,gBAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACzD,MAAM,GAAG,GAAG,GAAG,MAAM,GAAG,SAAS,EAAE,CAAC;IACpC,OAAO,EAAE,EAAE,EAAE,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;AACrF,CAAC;AAED;;;;GAIG;AACI,KAAK,UAAU,WAAW,CAC/B,KAAoB,EACpB,KAAoE;IAEpE,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,uBAAe,CAAC;IAC/C,MAAM,SAAS,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,KAAK,CAAC,SAAS,CAAC;QACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAc;QAC1B,MAAM;QACN,IAAI,EAAE,SAAS,CAAC,IAAI;KACrB,CAAC,CAAC;IACH,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Lemma API v2 — PlanPolicy (Lane D)
3
+ *
4
+ * Replaces `src/cloud/types.ts` PLAN_LIMITS. Quota is measured by ACTIVE-VERIFIED
5
+ * memories and by SEAT, not only by request count, and `Infinity` is gone —
6
+ * every plan has an explicit, positive ceiling. Exceeding a cap yields a 429
7
+ * with an actionable body: limit, current use, reset time and upgrade link.
8
+ *
9
+ * This module owns the plan table. The DB migration only stores tenancy; keeping
10
+ * a second copy of the limits in SQL would guarantee drift.
11
+ */
12
+ export type PlanId = 'free' | 'pro' | 'scale';
13
+ export interface PlanLimits {
14
+ /** Active AND verified memories the tenant may keep. */
15
+ activeMemories: number;
16
+ /** Concurrent seats (API keys / members) the tenant may hold. */
17
+ seats: number;
18
+ /** Requests allowed per rate-limit window. */
19
+ dailyRequests: number;
20
+ /** Requests allowed per calendar month. */
21
+ monthlyRequests: number;
22
+ /** Length of the rate-limit window (24h = UTC-day buckets). */
23
+ rateLimitWindowMs: number;
24
+ /** Where the client is pointed when a cap is hit. */
25
+ upgradeUrl: string;
26
+ }
27
+ export declare const RATE_LIMIT_WINDOW_MS: number;
28
+ export declare const PLAN_UPGRADE_URL: Readonly<Record<PlanId, string>>;
29
+ /** Single source of truth for plan ceilings. Every value finite and > 0. */
30
+ export declare const PLAN_LIMITS: Readonly<Record<PlanId, PlanLimits>>;
31
+ export declare const DEFAULT_PLAN: PlanId;
32
+ /**
33
+ * The `Infinity` elimination check, exported so tests can prove it (and the
34
+ * policy constructor refuses any non-finite/zero ceiling at startup).
35
+ */
36
+ export declare function validatePlanLimits(limits: Record<string, PlanLimits>): string[];
37
+ export type QuotaKind = 'memories' | 'seats';
38
+ export interface QuotaViolation {
39
+ kind: QuotaKind;
40
+ plan: PlanId;
41
+ limit: number;
42
+ current: number;
43
+ upgradeUrl: string;
44
+ message: string;
45
+ }
46
+ export type QuotaCheck = {
47
+ allowed: true;
48
+ } | {
49
+ allowed: false;
50
+ violation: QuotaViolation;
51
+ };
52
+ /** The actionable 429 body for quota_exceeded (additive to the LemmaApiError envelope). */
53
+ export interface QuotaErrorBody {
54
+ error: {
55
+ code: 'quota_exceeded';
56
+ status: 429;
57
+ message: string;
58
+ plan: PlanId;
59
+ kind: QuotaKind;
60
+ limit: number;
61
+ current: number;
62
+ /** When the counter resets, or null when there is no scheduled reset (memory quotas). */
63
+ resetsAt: number | null;
64
+ upgradeUrl: string;
65
+ };
66
+ }
67
+ export declare function quotaErrorBody(violation: QuotaViolation, resetsAt?: number | null): QuotaErrorBody;
68
+ export declare class PlanPolicy {
69
+ private readonly limits;
70
+ constructor(limits?: Record<string, PlanLimits>);
71
+ /** Limits for a plan; unknown plans conservatively fall back to `free`. */
72
+ limitsFor(plan: string): PlanLimits;
73
+ /** Memory quota: number of ACTIVE-VERIFIED memories the plan allows. */
74
+ checkMemoryQuota(planId: string, activeVerifiedMemories: number): QuotaCheck;
75
+ /** Seat quota: number of seats (members/keys) the plan allows. */
76
+ checkSeatQuota(planId: string, seats: number): QuotaCheck;
77
+ private checkStatic;
78
+ }
79
+ //# sourceMappingURL=PlanPolicy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlanPolicy.d.ts","sourceRoot":"","sources":["../../../../src/cloud/identity/PlanPolicy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC;AAE9C,MAAM,WAAW,UAAU;IACzB,wDAAwD;IACxD,cAAc,EAAE,MAAM,CAAC;IACvB,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,aAAa,EAAE,MAAM,CAAC;IACtB,2CAA2C;IAC3C,eAAe,EAAE,MAAM,CAAC;IACxB,+DAA+D;IAC/D,iBAAiB,EAAE,MAAM,CAAC;IAC1B,qDAAqD;IACrD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,oBAAoB,QAAsB,CAAC;AAExD,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAI5D,CAAC;AAEH,4EAA4E;AAC5E,eAAO,MAAM,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAyB3D,CAAC;AAEH,eAAO,MAAM,YAAY,EAAE,MAAe,CAAC;AAU3C;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,MAAM,EAAE,CAY/E;AAED,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;AAE7C,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,UAAU,GAAG;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,SAAS,EAAE,cAAc,CAAA;CAAE,CAAC;AAE3F,2FAA2F;AAC3F,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE;QACL,IAAI,EAAE,gBAAgB,CAAC;QACvB,MAAM,EAAE,GAAG,CAAC;QACZ,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,SAAS,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,yFAAyF;QACzF,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,cAAc,EAAE,QAAQ,GAAE,MAAM,GAAG,IAAW,GAAG,cAAc,CAcxG;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;gBAExC,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAA6C;IAQ1F,2EAA2E;IAC3E,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU;IAInC,wEAAwE;IACxE,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,sBAAsB,EAAE,MAAM,GAAG,UAAU;IAiB5E,kEAAkE;IAClE,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU;IAgBzD,OAAO,CAAC,WAAW;CAcpB"}
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PlanPolicy = exports.DEFAULT_PLAN = exports.PLAN_LIMITS = exports.PLAN_UPGRADE_URL = exports.RATE_LIMIT_WINDOW_MS = void 0;
4
+ exports.validatePlanLimits = validatePlanLimits;
5
+ exports.quotaErrorBody = quotaErrorBody;
6
+ exports.RATE_LIMIT_WINDOW_MS = 24 * 60 * 60 * 1000;
7
+ exports.PLAN_UPGRADE_URL = Object.freeze({
8
+ free: 'https://lemma.dev/pricing',
9
+ pro: 'https://lemma.dev/pricing',
10
+ scale: 'https://lemma.dev/contact',
11
+ });
12
+ /** Single source of truth for plan ceilings. Every value finite and > 0. */
13
+ exports.PLAN_LIMITS = Object.freeze({
14
+ free: Object.freeze({
15
+ activeMemories: 1000,
16
+ seats: 1,
17
+ dailyRequests: 1000,
18
+ monthlyRequests: 10000,
19
+ rateLimitWindowMs: exports.RATE_LIMIT_WINDOW_MS,
20
+ upgradeUrl: exports.PLAN_UPGRADE_URL.free,
21
+ }),
22
+ pro: Object.freeze({
23
+ activeMemories: 10000,
24
+ seats: 10,
25
+ dailyRequests: 5000,
26
+ monthlyRequests: 60000,
27
+ rateLimitWindowMs: exports.RATE_LIMIT_WINDOW_MS,
28
+ upgradeUrl: exports.PLAN_UPGRADE_URL.pro,
29
+ }),
30
+ scale: Object.freeze({
31
+ activeMemories: 100000,
32
+ seats: 50,
33
+ dailyRequests: 20000,
34
+ monthlyRequests: 250000,
35
+ rateLimitWindowMs: exports.RATE_LIMIT_WINDOW_MS,
36
+ upgradeUrl: exports.PLAN_UPGRADE_URL.scale,
37
+ }),
38
+ });
39
+ exports.DEFAULT_PLAN = 'free';
40
+ const NUMERIC_LIMIT_KEYS = [
41
+ 'activeMemories',
42
+ 'seats',
43
+ 'dailyRequests',
44
+ 'monthlyRequests',
45
+ 'rateLimitWindowMs',
46
+ ];
47
+ /**
48
+ * The `Infinity` elimination check, exported so tests can prove it (and the
49
+ * policy constructor refuses any non-finite/zero ceiling at startup).
50
+ */
51
+ function validatePlanLimits(limits) {
52
+ const problems = [];
53
+ for (const [plan, l] of Object.entries(limits)) {
54
+ for (const key of NUMERIC_LIMIT_KEYS) {
55
+ const value = l[key];
56
+ if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {
57
+ problems.push(`${plan}.${key} = ${value}`);
58
+ }
59
+ }
60
+ if (!l.upgradeUrl)
61
+ problems.push(`${plan}.upgradeUrl missing`);
62
+ }
63
+ return problems;
64
+ }
65
+ function quotaErrorBody(violation, resetsAt = null) {
66
+ return {
67
+ error: {
68
+ code: 'quota_exceeded',
69
+ status: 429,
70
+ message: violation.message,
71
+ plan: violation.plan,
72
+ kind: violation.kind,
73
+ limit: violation.limit,
74
+ current: violation.current,
75
+ resetsAt,
76
+ upgradeUrl: violation.upgradeUrl,
77
+ },
78
+ };
79
+ }
80
+ class PlanPolicy {
81
+ constructor(limits = exports.PLAN_LIMITS) {
82
+ const problems = validatePlanLimits(limits);
83
+ if (problems.length > 0) {
84
+ throw new Error(`PlanPolicy: invalid plan limits (${problems.join(', ')})`);
85
+ }
86
+ this.limits = limits;
87
+ }
88
+ /** Limits for a plan; unknown plans conservatively fall back to `free`. */
89
+ limitsFor(plan) {
90
+ return this.limits[plan] ?? this.limits[exports.DEFAULT_PLAN];
91
+ }
92
+ /** Memory quota: number of ACTIVE-VERIFIED memories the plan allows. */
93
+ checkMemoryQuota(planId, activeVerifiedMemories) {
94
+ return this.checkStatic(planId, 'memories', activeVerifiedMemories, (limit, plan) => ({
95
+ allowed: false,
96
+ violation: {
97
+ kind: 'memories',
98
+ plan,
99
+ limit,
100
+ current: activeVerifiedMemories,
101
+ upgradeUrl: this.limitsFor(planId).upgradeUrl,
102
+ message: `${plan} plan allows ${limit} active verified memories; ` +
103
+ `you currently have ${activeVerifiedMemories}. ` +
104
+ `Upgrade at ${this.limitsFor(planId).upgradeUrl}`,
105
+ },
106
+ }));
107
+ }
108
+ /** Seat quota: number of seats (members/keys) the plan allows. */
109
+ checkSeatQuota(planId, seats) {
110
+ return this.checkStatic(planId, 'seats', seats, (limit, plan) => ({
111
+ allowed: false,
112
+ violation: {
113
+ kind: 'seats',
114
+ plan,
115
+ limit,
116
+ current: seats,
117
+ upgradeUrl: this.limitsFor(planId).upgradeUrl,
118
+ message: `${plan} plan allows ${limit} seat(s); you currently have ${seats}. ` +
119
+ `Upgrade at ${this.limitsFor(planId).upgradeUrl}`,
120
+ },
121
+ }));
122
+ }
123
+ checkStatic(planId, kind, current, makeViolation) {
124
+ const plan = (planId in this.limits ? planId : exports.DEFAULT_PLAN);
125
+ const limitKey = kind === 'memories' ? 'activeMemories' : 'seats';
126
+ const limit = this.limitsFor(planId)[limitKey];
127
+ // El tope es exclusivo: en el límite (free con 1000 activas) la siguiente
128
+ // escritura ya está negada — "intenta crear la 1001 ⇒ 429".
129
+ if (current >= limit)
130
+ return makeViolation(limit, plan);
131
+ return { allowed: true };
132
+ }
133
+ }
134
+ exports.PlanPolicy = PlanPolicy;
135
+ //# sourceMappingURL=PlanPolicy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlanPolicy.js","sourceRoot":"","sources":["../../../../src/cloud/identity/PlanPolicy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Lemma API v2 — per-tenant rate limiter (Lane D)
3
+ *
4
+ * Fixed-window counter keyed by `tenantId + windowBucket`. Exceeding the window
5
+ * limit yields a 429 with `Retry-After` (backoff until the bucket ends). The
6
+ * window is derived from `windowMs` and an injectable clock so tests are
7
+ * deterministic. Fixed window (not sliding) is a deliberate trade: it allows a
8
+ * brief 2x burst at the boundary in exchange for a cheap, exactly-computable
9
+ * `Retry-After` (until the next bucket start).
10
+ */
11
+ import type { Pool } from 'pg';
12
+ export interface RateLimitDecision {
13
+ allowed: boolean;
14
+ used: number;
15
+ limit: number;
16
+ remaining: number;
17
+ /** Epoch ms when the current window ends and the counter resets. */
18
+ resetAt: number;
19
+ }
20
+ export interface RateLimiter {
21
+ consume(tenantId: string, limit: number, windowMs: number, now?: number): Promise<RateLimitDecision>;
22
+ }
23
+ /** The 429 body for rate_limited (additive to the LemmaApiError envelope). */
24
+ export interface RateLimitErrorBody {
25
+ error: {
26
+ code: 'rate_limited';
27
+ status: 429;
28
+ message: string;
29
+ limit: number;
30
+ used: number;
31
+ remaining: number;
32
+ retryAfter: number;
33
+ resetsAt: number;
34
+ upgradeUrl: string;
35
+ };
36
+ }
37
+ export declare function rateLimitErrorBody(decision: RateLimitDecision, retryAfterSeconds: number, upgradeUrl: string): RateLimitErrorBody;
38
+ /** In-process fixed-window limiter. Suitable for single-instance dev and tests. */
39
+ export declare class InMemoryRateLimiter implements RateLimiter {
40
+ private readonly buckets;
41
+ consume(tenantId: string, limit: number, windowMs: number, now?: number): Promise<RateLimitDecision>;
42
+ }
43
+ /** Postgres-backed fixed-window limiter, atomic via a single upsert. */
44
+ export declare class PostgresRateLimiter implements RateLimiter {
45
+ private readonly pool;
46
+ constructor(pool: Pool);
47
+ consume(tenantId: string, limit: number, windowMs: number, now?: number): Promise<RateLimitDecision>;
48
+ }
49
+ //# sourceMappingURL=RateLimiter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RateLimiter.d.ts","sourceRoot":"","sources":["../../../../src/cloud/identity/RateLimiter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAE/B,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACtG;AAED,8EAA8E;AAC9E,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE;QACL,IAAI,EAAE,cAAc,CAAC;QACrB,MAAM,EAAE,GAAG,CAAC;QACZ,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,kBAAkB,CAgBjI;AAED,mFAAmF;AACnF,qBAAa,mBAAoB,YAAW,WAAW;IACrD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwD;IAE1E,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAyBvH;AAED,wEAAwE;AACxE,qBAAa,mBAAoB,YAAW,WAAW;IACzC,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,IAAI;IAEjC,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAoBvH"}
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PostgresRateLimiter = exports.InMemoryRateLimiter = void 0;
4
+ exports.rateLimitErrorBody = rateLimitErrorBody;
5
+ function rateLimitErrorBody(decision, retryAfterSeconds, upgradeUrl) {
6
+ return {
7
+ error: {
8
+ code: 'rate_limited',
9
+ status: 429,
10
+ message: `rate limit exceeded: ${decision.used}/${decision.limit} requests in the current window. ` +
11
+ `Back off and retry after ${retryAfterSeconds}s, or upgrade at ${upgradeUrl}.`,
12
+ limit: decision.limit,
13
+ used: decision.used,
14
+ remaining: decision.remaining,
15
+ retryAfter: retryAfterSeconds,
16
+ resetsAt: decision.resetAt,
17
+ upgradeUrl,
18
+ },
19
+ };
20
+ }
21
+ /** In-process fixed-window limiter. Suitable for single-instance dev and tests. */
22
+ class InMemoryRateLimiter {
23
+ constructor() {
24
+ this.buckets = new Map();
25
+ }
26
+ async consume(tenantId, limit, windowMs, now = Date.now()) {
27
+ const bucket = Math.floor(now / windowMs);
28
+ const key = `${tenantId}:${bucket}`;
29
+ // Prune expired windows (on this call path only — no background timers).
30
+ for (const [k, entry] of this.buckets) {
31
+ if (entry.bucket < bucket)
32
+ this.buckets.delete(k);
33
+ }
34
+ let entry = this.buckets.get(key);
35
+ if (!entry) {
36
+ entry = { bucket, count: 0 };
37
+ this.buckets.set(key, entry);
38
+ }
39
+ entry.count += 1;
40
+ const resetAt = (bucket + 1) * windowMs;
41
+ return {
42
+ allowed: entry.count <= limit,
43
+ used: entry.count,
44
+ limit,
45
+ remaining: Math.max(0, limit - entry.count),
46
+ resetAt,
47
+ };
48
+ }
49
+ }
50
+ exports.InMemoryRateLimiter = InMemoryRateLimiter;
51
+ /** Postgres-backed fixed-window limiter, atomic via a single upsert. */
52
+ class PostgresRateLimiter {
53
+ constructor(pool) {
54
+ this.pool = pool;
55
+ }
56
+ async consume(tenantId, limit, windowMs, now = Date.now()) {
57
+ const bucket = Math.floor(now / windowMs);
58
+ const { rows } = await this.pool.query(`INSERT INTO tenant_rate_limits (tenant_id, bucket, request_count)
59
+ VALUES ($1, $2, 1)
60
+ ON CONFLICT (tenant_id, bucket) DO UPDATE
61
+ SET request_count = tenant_rate_limits.request_count + 1,
62
+ updated_at = CURRENT_TIMESTAMP
63
+ RETURNING request_count`, [tenantId, String(bucket)]);
64
+ const used = Number(rows[0]?.request_count ?? 1);
65
+ return {
66
+ allowed: used <= limit,
67
+ used,
68
+ limit,
69
+ remaining: Math.max(0, limit - used),
70
+ resetAt: (bucket + 1) * windowMs,
71
+ };
72
+ }
73
+ }
74
+ exports.PostgresRateLimiter = PostgresRateLimiter;
75
+ //# sourceMappingURL=RateLimiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RateLimiter.js","sourceRoot":"","sources":["../../../../src/cloud/identity/RateLimiter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { IdentityStore } from './identityStore';
2
+ export interface Tenant {
3
+ id: string;
4
+ plan: 'free' | 'pro' | 'scale';
5
+ keyId: string;
6
+ }
7
+ export declare class TenantResolver {
8
+ private readonly store;
9
+ readonly lane = "D";
10
+ constructor(store: IdentityStore);
11
+ /**
12
+ * Resolve a bearer token to a tenant. Returns `null` for malformed, unknown,
13
+ * revoked or expired keys. The store is queried on EVERY call; revocation is
14
+ * observed on the next request, never after a cached delay.
15
+ */
16
+ resolve(bearerToken: string): Promise<Tenant | null>;
17
+ }
18
+ export default TenantResolver;
19
+ //# sourceMappingURL=TenantResolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TenantResolver.d.ts","sourceRoot":"","sources":["../../../../src/cloud/identity/TenantResolver.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,cAAc;IAGb,OAAO,CAAC,QAAQ,CAAC,KAAK;IAFlC,QAAQ,CAAC,IAAI,OAAO;gBAES,KAAK,EAAE,aAAa;IAEjD;;;;OAIG;IACG,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAY3D;AAED,eAAe,cAAc,CAAC"}
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TenantResolver = void 0;
4
+ /**
5
+ * Lemma API v2 — TenantResolver (Lane D)
6
+ *
7
+ * Resolves `Authorization: Bearer lk_live_...` → the owning tenant. Keys are
8
+ * stored as SHA-256 hashes; the plaintext is only ever returned once, at
9
+ * creation, and never logged. Resolution is deliberately cache-free: every
10
+ * request hashes the presented token and hits the store, so a revoked key fails
11
+ * on the very next request — there is no 24h (or any) positive cache.
12
+ */
13
+ const ApiKey_1 = require("./ApiKey");
14
+ class TenantResolver {
15
+ constructor(store) {
16
+ this.store = store;
17
+ this.lane = 'D';
18
+ }
19
+ /**
20
+ * Resolve a bearer token to a tenant. Returns `null` for malformed, unknown,
21
+ * revoked or expired keys. The store is queried on EVERY call; revocation is
22
+ * observed on the next request, never after a cached delay.
23
+ */
24
+ async resolve(bearerToken) {
25
+ if (!(0, ApiKey_1.isWellFormedKey)(bearerToken))
26
+ return null;
27
+ const hash = (0, ApiKey_1.hashApiKey)(bearerToken);
28
+ const record = await this.store.findKeyByHash(hash);
29
+ if (!record)
30
+ return null;
31
+ if (!record.active)
32
+ return null;
33
+ if (record.expiresAt !== null && Date.now() > record.expiresAt)
34
+ return null;
35
+ return { id: record.tenantId, plan: record.plan, keyId: record.id };
36
+ }
37
+ }
38
+ exports.TenantResolver = TenantResolver;
39
+ exports.default = TenantResolver;
40
+ //# sourceMappingURL=TenantResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TenantResolver.js","sourceRoot":"","sources":["../../../../src/cloud/identity/TenantResolver.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;GAQG;AACH,qCAAuD;AASvD,MAAa,cAAc;IAGzB,YAA6B,KAAoB;QAApB,UAAK,GAAL,KAAK,CAAe;QAFxC,SAAI,GAAG,GAAG,CAAC;IAEgC,CAAC;IAErD;;;;OAIG;IACH,KAAK,CAAC,OAAO,CAAC,WAAmB;QAC/B,IAAI,CAAC,IAAA,wBAAe,EAAC,WAAW,CAAC;YAAE,OAAO,IAAI,CAAC;QAE/C,MAAM,IAAI,GAAG,IAAA,mBAAU,EAAC,WAAW,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAEpD,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QACzB,IAAI,CAAC,MAAM,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAChC,IAAI,MAAM,CAAC,SAAS,KAAK,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS;YAAE,OAAO,IAAI,CAAC;QAE5E,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;IACtE,CAAC;CACF;AAtBD,wCAsBC;AAED,kBAAe,cAAc,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Lemma API v2 — authenticateV2 middleware (Lane D)
3
+ *
4
+ * Express factory. Usage:
5
+ *
6
+ * import { authenticateV2 } from './cloud/identity';
7
+ * app.use(authenticateV2({ resolver, rateLimiter, policy }));
8
+ *
9
+ * On success it attaches `req.tenant = { id, plan, keyId }` and calls `next()`.
10
+ * Missing or invalid keys → 401 `unauthenticated` (identical body for unknown
11
+ * vs. revoked, so the endpoint never leaks key state). Rate limiting is applied
12
+ * per tenant before the handler runs; exceeding it → 429 `rate_limited` with a
13
+ * `Retry-After` header and an actionable body.
14
+ */
15
+ import type { Request, RequestHandler } from 'express';
16
+ import { PlanPolicy, RATE_LIMIT_WINDOW_MS } from './PlanPolicy';
17
+ import type { RateLimiter } from './RateLimiter';
18
+ import type { Tenant, TenantResolver } from './TenantResolver';
19
+ declare global {
20
+ namespace Express {
21
+ interface Request {
22
+ /** Set by authenticateV2 when a valid API key was presented. */
23
+ tenant?: Tenant;
24
+ }
25
+ }
26
+ }
27
+ export interface AuthenticateV2Deps {
28
+ resolver: Pick<TenantResolver, 'resolve'>;
29
+ policy?: PlanPolicy;
30
+ rateLimiter?: RateLimiter;
31
+ /** Length of the per-tenant rate-limit window; defaults to 24h (UTC-day buckets). */
32
+ rateLimitWindowMs?: number;
33
+ /** Clock override for deterministic tests. */
34
+ now?: () => number;
35
+ }
36
+ /** Convenience type for handlers that run behind authenticateV2. */
37
+ export type AuthenticatedRequest = Request & {
38
+ tenant: Tenant;
39
+ };
40
+ /**
41
+ * Build the auth middleware. `deps.rateLimiter` is optional: when provided, each
42
+ * request consumes one slot from the tenant's window (limit from the tenant's
43
+ * plan); when the window is exhausted the middleware answers 429 with Retry-After.
44
+ */
45
+ export declare function authenticateV2(deps: AuthenticateV2Deps): RequestHandler;
46
+ export { RATE_LIMIT_WINDOW_MS };
47
+ export default authenticateV2;
48
+ //# sourceMappingURL=authenticateV2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authenticateV2.d.ts","sourceRoot":"","sources":["../../../../src/cloud/identity/authenticateV2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEvD,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAE/D,OAAO,CAAC,MAAM,CAAC;IAEb,UAAU,OAAO,CAAC;QAChB,UAAU,OAAO;YACf,gEAAgE;YAChE,MAAM,CAAC,EAAE,MAAM,CAAC;SACjB;KACF;CACF;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;IAC1C,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,qFAAqF;IACrF,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,8CAA8C;IAC9C,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,oEAAoE;AACpE,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAgBhE;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,cAAc,CA0CvE;AAED,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAChC,eAAe,cAAc,CAAC"}
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RATE_LIMIT_WINDOW_MS = void 0;
4
+ exports.authenticateV2 = authenticateV2;
5
+ const errors_1 = require("../../contracts/errors");
6
+ const PlanPolicy_1 = require("./PlanPolicy");
7
+ Object.defineProperty(exports, "RATE_LIMIT_WINDOW_MS", { enumerable: true, get: function () { return PlanPolicy_1.RATE_LIMIT_WINDOW_MS; } });
8
+ const RateLimiter_1 = require("./RateLimiter");
9
+ function parseBearer(header) {
10
+ if (!header)
11
+ return null;
12
+ const match = /^Bearer\s+(.+)$/i.exec(header.trim());
13
+ return match ? match[1].trim() : null;
14
+ }
15
+ function unauthenticatedError() {
16
+ return new errors_1.LemmaApiError({
17
+ code: 'unauthenticated',
18
+ status: 401,
19
+ message: 'missing or invalid API key',
20
+ });
21
+ }
22
+ /**
23
+ * Build the auth middleware. `deps.rateLimiter` is optional: when provided, each
24
+ * request consumes one slot from the tenant's window (limit from the tenant's
25
+ * plan); when the window is exhausted the middleware answers 429 with Retry-After.
26
+ */
27
+ function authenticateV2(deps) {
28
+ const policy = deps.policy ?? new PlanPolicy_1.PlanPolicy();
29
+ const windowMs = deps.rateLimitWindowMs ?? PlanPolicy_1.RATE_LIMIT_WINDOW_MS;
30
+ const now = deps.now ?? Date.now;
31
+ return async (req, res, next) => {
32
+ try {
33
+ const token = parseBearer(req.headers.authorization);
34
+ if (!token) {
35
+ res.status(401).set('WWW-Authenticate', 'Bearer').json(unauthenticatedError().toJSON());
36
+ return;
37
+ }
38
+ const tenant = await deps.resolver.resolve(token);
39
+ if (!tenant) {
40
+ res.status(401).set('WWW-Authenticate', 'Bearer').json(unauthenticatedError().toJSON());
41
+ return;
42
+ }
43
+ if (deps.rateLimiter) {
44
+ const limit = policy.limitsFor(tenant.plan).dailyRequests;
45
+ const decision = await deps.rateLimiter.consume(tenant.id, limit, windowMs, now());
46
+ if (!decision.allowed) {
47
+ const retryAfter = Math.max(1, Math.ceil((decision.resetAt - now()) / 1000));
48
+ const upgradeUrl = policy.limitsFor(tenant.plan).upgradeUrl;
49
+ res
50
+ .status(429)
51
+ .set('Retry-After', String(retryAfter))
52
+ .set('WWW-Authenticate', 'Bearer')
53
+ .json((0, RateLimiter_1.rateLimitErrorBody)(decision, retryAfter, upgradeUrl));
54
+ return;
55
+ }
56
+ }
57
+ req.tenant = tenant;
58
+ next();
59
+ }
60
+ catch (err) {
61
+ next(err);
62
+ }
63
+ };
64
+ }
65
+ exports.default = authenticateV2;
66
+ //# sourceMappingURL=authenticateV2.js.map