@nxuss/lemma 1.43.0 → 1.45.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 (388) hide show
  1. package/README.md +26 -8
  2. package/bin/brain-ingest.js +48 -13
  3. package/bin/cloud.js +228 -0
  4. package/dist/cjs/cli/hostHooks.d.ts +44 -7
  5. package/dist/cjs/cli/hostHooks.d.ts.map +1 -1
  6. package/dist/cjs/cli/hostHooks.js +201 -11
  7. package/dist/cjs/cli/hostHooks.js.map +1 -1
  8. package/dist/cjs/cli/lemma-proxy.d.ts.map +1 -1
  9. package/dist/cjs/cli/lemma-proxy.js +13 -16
  10. package/dist/cjs/cli/lemma-proxy.js.map +1 -1
  11. package/dist/cjs/cloud/CloudBrainClient.d.ts +52 -0
  12. package/dist/cjs/cloud/CloudBrainClient.d.ts.map +1 -0
  13. package/dist/cjs/cloud/CloudBrainClient.js +161 -0
  14. package/dist/cjs/cloud/CloudBrainClient.js.map +1 -0
  15. package/dist/cjs/cloud/CloudConfig.d.ts +41 -0
  16. package/dist/cjs/cloud/CloudConfig.d.ts.map +1 -0
  17. package/dist/cjs/cloud/CloudConfig.js +133 -0
  18. package/dist/cjs/cloud/CloudConfig.js.map +1 -0
  19. package/dist/cjs/cloud/CloudEntitlement.d.ts +55 -0
  20. package/dist/cjs/cloud/CloudEntitlement.d.ts.map +1 -0
  21. package/dist/cjs/cloud/CloudEntitlement.js +174 -0
  22. package/dist/cjs/cloud/CloudEntitlement.js.map +1 -0
  23. package/dist/cjs/cloud/billing/stripeApi.d.ts +43 -0
  24. package/dist/cjs/cloud/billing/stripeApi.d.ts.map +1 -0
  25. package/dist/cjs/cloud/billing/stripeApi.js +116 -0
  26. package/dist/cjs/cloud/billing/stripeApi.js.map +1 -0
  27. package/dist/cjs/cloud/billing/stripeWebhook.d.ts +35 -0
  28. package/dist/cjs/cloud/billing/stripeWebhook.d.ts.map +1 -0
  29. package/dist/cjs/cloud/billing/stripeWebhook.js +190 -0
  30. package/dist/cjs/cloud/billing/stripeWebhook.js.map +1 -0
  31. package/dist/cjs/cloud/console/ConsoleStore.d.ts +111 -0
  32. package/dist/cjs/cloud/console/ConsoleStore.d.ts.map +1 -0
  33. package/dist/cjs/cloud/console/ConsoleStore.js +172 -0
  34. package/dist/cjs/cloud/console/ConsoleStore.js.map +1 -0
  35. package/dist/cjs/cloud/console/consoleRouter.d.ts +68 -0
  36. package/dist/cjs/cloud/console/consoleRouter.d.ts.map +1 -0
  37. package/dist/cjs/cloud/console/consoleRouter.js +301 -0
  38. package/dist/cjs/cloud/console/consoleRouter.js.map +1 -0
  39. package/dist/cjs/cloud/console/mailer.d.ts +22 -0
  40. package/dist/cjs/cloud/console/mailer.d.ts.map +1 -0
  41. package/dist/cjs/cloud/console/mailer.js +35 -0
  42. package/dist/cjs/cloud/console/mailer.js.map +1 -0
  43. package/dist/cjs/cloud/identity/PlanPolicy.d.ts +42 -6
  44. package/dist/cjs/cloud/identity/PlanPolicy.d.ts.map +1 -1
  45. package/dist/cjs/cloud/identity/PlanPolicy.js +102 -22
  46. package/dist/cjs/cloud/identity/PlanPolicy.js.map +1 -1
  47. package/dist/cjs/cloud/identity/RateLimiter.d.ts +21 -1
  48. package/dist/cjs/cloud/identity/RateLimiter.d.ts.map +1 -1
  49. package/dist/cjs/cloud/identity/RateLimiter.js +59 -2
  50. package/dist/cjs/cloud/identity/RateLimiter.js.map +1 -1
  51. package/dist/cjs/cloud/identity/TenantResolver.d.ts +6 -1
  52. package/dist/cjs/cloud/identity/TenantResolver.d.ts.map +1 -1
  53. package/dist/cjs/cloud/identity/TenantResolver.js +1 -1
  54. package/dist/cjs/cloud/identity/TenantResolver.js.map +1 -1
  55. package/dist/cjs/cloud/identity/authenticateV2.d.ts.map +1 -1
  56. package/dist/cjs/cloud/identity/authenticateV2.js +7 -4
  57. package/dist/cjs/cloud/identity/authenticateV2.js.map +1 -1
  58. package/dist/cjs/cloud/identity/identityStore.d.ts +96 -10
  59. package/dist/cjs/cloud/identity/identityStore.d.ts.map +1 -1
  60. package/dist/cjs/cloud/identity/identityStore.js +203 -4
  61. package/dist/cjs/cloud/identity/identityStore.js.map +1 -1
  62. package/dist/cjs/cloud/metering/PostgresLedgerStore.d.ts +18 -0
  63. package/dist/cjs/cloud/metering/PostgresLedgerStore.d.ts.map +1 -0
  64. package/dist/cjs/cloud/metering/PostgresLedgerStore.js +56 -0
  65. package/dist/cjs/cloud/metering/PostgresLedgerStore.js.map +1 -0
  66. package/dist/cjs/cloud/metering/UsageLedger.d.ts +74 -0
  67. package/dist/cjs/cloud/metering/UsageLedger.d.ts.map +1 -1
  68. package/dist/cjs/cloud/metering/UsageLedger.js +122 -17
  69. package/dist/cjs/cloud/metering/UsageLedger.js.map +1 -1
  70. package/dist/cjs/cloud/metering/index.d.ts +1 -0
  71. package/dist/cjs/cloud/metering/index.d.ts.map +1 -1
  72. package/dist/cjs/cloud/metering/index.js +1 -0
  73. package/dist/cjs/cloud/metering/index.js.map +1 -1
  74. package/dist/cjs/cloud/store/FileBrainStore.d.ts +6 -1
  75. package/dist/cjs/cloud/store/FileBrainStore.d.ts.map +1 -1
  76. package/dist/cjs/cloud/store/FileBrainStore.js +8 -0
  77. package/dist/cjs/cloud/store/FileBrainStore.js.map +1 -1
  78. package/dist/cjs/cloud/store/PostgresBrainStore.d.ts +11 -1
  79. package/dist/cjs/cloud/store/PostgresBrainStore.d.ts.map +1 -1
  80. package/dist/cjs/cloud/store/PostgresBrainStore.js +32 -0
  81. package/dist/cjs/cloud/store/PostgresBrainStore.js.map +1 -1
  82. package/dist/cjs/cloud/store/memorySummary.d.ts +29 -0
  83. package/dist/cjs/cloud/store/memorySummary.d.ts.map +1 -0
  84. package/dist/cjs/cloud/store/memorySummary.js +66 -0
  85. package/dist/cjs/cloud/store/memorySummary.js.map +1 -0
  86. package/dist/cjs/cloud/v2/app.d.ts.map +1 -1
  87. package/dist/cjs/cloud/v2/app.js +6 -0
  88. package/dist/cjs/cloud/v2/app.js.map +1 -1
  89. package/dist/cjs/cloud/v2/inputGuard.d.ts +23 -0
  90. package/dist/cjs/cloud/v2/inputGuard.d.ts.map +1 -0
  91. package/dist/cjs/cloud/v2/inputGuard.js +71 -0
  92. package/dist/cjs/cloud/v2/inputGuard.js.map +1 -0
  93. package/dist/cjs/cloud/v2/routes/admin.d.ts +24 -0
  94. package/dist/cjs/cloud/v2/routes/admin.d.ts.map +1 -0
  95. package/dist/cjs/cloud/v2/routes/admin.js +344 -0
  96. package/dist/cjs/cloud/v2/routes/admin.js.map +1 -0
  97. package/dist/cjs/cloud/v2/routes/entitlement.d.ts +13 -0
  98. package/dist/cjs/cloud/v2/routes/entitlement.d.ts.map +1 -0
  99. package/dist/cjs/cloud/v2/routes/entitlement.js +24 -0
  100. package/dist/cjs/cloud/v2/routes/entitlement.js.map +1 -0
  101. package/dist/cjs/cloud/v2/routes/index.d.ts +14 -1
  102. package/dist/cjs/cloud/v2/routes/index.d.ts.map +1 -1
  103. package/dist/cjs/cloud/v2/routes/index.js +36 -0
  104. package/dist/cjs/cloud/v2/routes/index.js.map +1 -1
  105. package/dist/cjs/cloud/v2/routes/memories.d.ts +21 -2
  106. package/dist/cjs/cloud/v2/routes/memories.d.ts.map +1 -1
  107. package/dist/cjs/cloud/v2/routes/memories.js +77 -0
  108. package/dist/cjs/cloud/v2/routes/memories.js.map +1 -1
  109. package/dist/cjs/cloud/v2/routes/recall.d.ts +1 -0
  110. package/dist/cjs/cloud/v2/routes/recall.d.ts.map +1 -1
  111. package/dist/cjs/cloud/v2/routes/recall.js +4 -0
  112. package/dist/cjs/cloud/v2/routes/recall.js.map +1 -1
  113. package/dist/cjs/cloud/v2/routes/tenant.d.ts +36 -0
  114. package/dist/cjs/cloud/v2/routes/tenant.d.ts.map +1 -0
  115. package/dist/cjs/cloud/v2/routes/tenant.js +65 -0
  116. package/dist/cjs/cloud/v2/routes/tenant.js.map +1 -0
  117. package/dist/cjs/cloud/v2/routes/usage.d.ts +1 -1
  118. package/dist/cjs/cloud/v2/routes/usage.d.ts.map +1 -1
  119. package/dist/cjs/cloud/v2/routes/verify.d.ts +1 -0
  120. package/dist/cjs/cloud/v2/routes/verify.d.ts.map +1 -1
  121. package/dist/cjs/cloud/v2/routes/verify.js +4 -0
  122. package/dist/cjs/cloud/v2/routes/verify.js.map +1 -1
  123. package/dist/cjs/cloud/v2/server.d.ts +9 -3
  124. package/dist/cjs/cloud/v2/server.d.ts.map +1 -1
  125. package/dist/cjs/cloud/v2/server.js +36 -2
  126. package/dist/cjs/cloud/v2/server.js.map +1 -1
  127. package/dist/cjs/cloud/v2/usageRecorder.d.ts +19 -0
  128. package/dist/cjs/cloud/v2/usageRecorder.d.ts.map +1 -0
  129. package/dist/cjs/cloud/v2/usageRecorder.js +42 -0
  130. package/dist/cjs/cloud/v2/usageRecorder.js.map +1 -0
  131. package/dist/cjs/contracts/api-v2.types.d.ts +92 -2
  132. package/dist/cjs/contracts/api-v2.types.d.ts.map +1 -1
  133. package/dist/cjs/contracts/store.d.ts +37 -0
  134. package/dist/cjs/contracts/store.d.ts.map +1 -1
  135. package/dist/cjs/mcp/index.js +7 -1
  136. package/dist/cjs/mcp/index.js.map +1 -1
  137. package/dist/cjs/mcp/tools/memory.d.ts.map +1 -1
  138. package/dist/cjs/mcp/tools/memory.js +74 -4
  139. package/dist/cjs/mcp/tools/memory.js.map +1 -1
  140. package/dist/cjs/mcp/tools/misc.d.ts.map +1 -1
  141. package/dist/cjs/mcp/tools/misc.js +2 -1
  142. package/dist/cjs/mcp/tools/misc.js.map +1 -1
  143. package/dist/cjs/mcp/tools/workspace.d.ts.map +1 -1
  144. package/dist/cjs/mcp/tools/workspace.js +4 -1
  145. package/dist/cjs/mcp/tools/workspace.js.map +1 -1
  146. package/dist/cjs/mcp/tools.d.ts +10 -0
  147. package/dist/cjs/mcp/tools.d.ts.map +1 -1
  148. package/dist/cjs/mcp/tools.js +47 -12
  149. package/dist/cjs/mcp/tools.js.map +1 -1
  150. package/dist/cjs/proxy/KeyManager.d.ts.map +1 -1
  151. package/dist/cjs/proxy/KeyManager.js +5 -0
  152. package/dist/cjs/proxy/KeyManager.js.map +1 -1
  153. package/dist/cjs/subconscious/CloudBrain.d.ts +77 -0
  154. package/dist/cjs/subconscious/CloudBrain.d.ts.map +1 -0
  155. package/dist/cjs/subconscious/CloudBrain.js +347 -0
  156. package/dist/cjs/subconscious/CloudBrain.js.map +1 -0
  157. package/dist/cjs/subconscious/HostRecall.d.ts.map +1 -1
  158. package/dist/cjs/subconscious/HostRecall.js +11 -4
  159. package/dist/cjs/subconscious/HostRecall.js.map +1 -1
  160. package/dist/cjs/subconscious/ProjectIdentity.d.ts +9 -0
  161. package/dist/cjs/subconscious/ProjectIdentity.d.ts.map +1 -0
  162. package/dist/cjs/subconscious/ProjectIdentity.js +63 -0
  163. package/dist/cjs/subconscious/ProjectIdentity.js.map +1 -0
  164. package/dist/cjs/subconscious/TeamBrain.d.ts +9 -3
  165. package/dist/cjs/subconscious/TeamBrain.d.ts.map +1 -1
  166. package/dist/cjs/subconscious/TeamBrain.js +39 -5
  167. package/dist/cjs/subconscious/TeamBrain.js.map +1 -1
  168. package/dist/cjs/utils/FixCapture.d.ts +7 -5
  169. package/dist/cjs/utils/FixCapture.d.ts.map +1 -1
  170. package/dist/cjs/utils/FixCapture.js +64 -32
  171. package/dist/cjs/utils/FixCapture.js.map +1 -1
  172. package/dist/cjs/utils/NoTerminal.d.ts +27 -0
  173. package/dist/cjs/utils/NoTerminal.d.ts.map +1 -0
  174. package/dist/cjs/utils/NoTerminal.js +37 -0
  175. package/dist/cjs/utils/NoTerminal.js.map +1 -0
  176. package/dist/cjs/utils/OpenCodeSession.d.ts +70 -0
  177. package/dist/cjs/utils/OpenCodeSession.d.ts.map +1 -0
  178. package/dist/cjs/utils/OpenCodeSession.js +154 -0
  179. package/dist/cjs/utils/OpenCodeSession.js.map +1 -0
  180. package/dist/cjs/utils/ProLicense.d.ts.map +1 -1
  181. package/dist/cjs/utils/ProLicense.js +11 -3
  182. package/dist/cjs/utils/ProLicense.js.map +1 -1
  183. package/dist/cjs/utils/SessionCapture.d.ts +31 -7
  184. package/dist/cjs/utils/SessionCapture.d.ts.map +1 -1
  185. package/dist/cjs/utils/SessionCapture.js +185 -32
  186. package/dist/cjs/utils/SessionCapture.js.map +1 -1
  187. package/dist/cjs/utils/StopNudge.d.ts +8 -0
  188. package/dist/cjs/utils/StopNudge.d.ts.map +1 -0
  189. package/dist/cjs/utils/StopNudge.js +93 -0
  190. package/dist/cjs/utils/StopNudge.js.map +1 -0
  191. package/dist/cjs/utils/TestAutofixInterceptor.d.ts.map +1 -1
  192. package/dist/cjs/utils/TestAutofixInterceptor.js +2 -0
  193. package/dist/cjs/utils/TestAutofixInterceptor.js.map +1 -1
  194. package/dist/esm/cli/hostHooks.d.ts +44 -7
  195. package/dist/esm/cli/hostHooks.d.ts.map +1 -1
  196. package/dist/esm/cli/hostHooks.js +199 -10
  197. package/dist/esm/cli/hostHooks.js.map +1 -1
  198. package/dist/esm/cli/lemma-proxy.d.ts.map +1 -1
  199. package/dist/esm/cli/lemma-proxy.js +14 -17
  200. package/dist/esm/cli/lemma-proxy.js.map +1 -1
  201. package/dist/esm/cloud/CloudBrainClient.d.ts +52 -0
  202. package/dist/esm/cloud/CloudBrainClient.d.ts.map +1 -0
  203. package/dist/esm/cloud/CloudBrainClient.js +153 -0
  204. package/dist/esm/cloud/CloudBrainClient.js.map +1 -0
  205. package/dist/esm/cloud/CloudConfig.d.ts +41 -0
  206. package/dist/esm/cloud/CloudConfig.d.ts.map +1 -0
  207. package/dist/esm/cloud/CloudConfig.js +118 -0
  208. package/dist/esm/cloud/CloudConfig.js.map +1 -0
  209. package/dist/esm/cloud/CloudEntitlement.d.ts +55 -0
  210. package/dist/esm/cloud/CloudEntitlement.d.ts.map +1 -0
  211. package/dist/esm/cloud/CloudEntitlement.js +159 -0
  212. package/dist/esm/cloud/CloudEntitlement.js.map +1 -0
  213. package/dist/esm/cloud/billing/stripeApi.d.ts +43 -0
  214. package/dist/esm/cloud/billing/stripeApi.d.ts.map +1 -0
  215. package/dist/esm/cloud/billing/stripeApi.js +108 -0
  216. package/dist/esm/cloud/billing/stripeApi.js.map +1 -0
  217. package/dist/esm/cloud/billing/stripeWebhook.d.ts +35 -0
  218. package/dist/esm/cloud/billing/stripeWebhook.d.ts.map +1 -0
  219. package/dist/esm/cloud/billing/stripeWebhook.js +181 -0
  220. package/dist/esm/cloud/billing/stripeWebhook.js.map +1 -0
  221. package/dist/esm/cloud/console/ConsoleStore.d.ts +111 -0
  222. package/dist/esm/cloud/console/ConsoleStore.d.ts.map +1 -0
  223. package/dist/esm/cloud/console/ConsoleStore.js +161 -0
  224. package/dist/esm/cloud/console/ConsoleStore.js.map +1 -0
  225. package/dist/esm/cloud/console/consoleRouter.d.ts +68 -0
  226. package/dist/esm/cloud/console/consoleRouter.d.ts.map +1 -0
  227. package/dist/esm/cloud/console/consoleRouter.js +290 -0
  228. package/dist/esm/cloud/console/consoleRouter.js.map +1 -0
  229. package/dist/esm/cloud/console/mailer.d.ts +22 -0
  230. package/dist/esm/cloud/console/mailer.d.ts.map +1 -0
  231. package/dist/esm/cloud/console/mailer.js +30 -0
  232. package/dist/esm/cloud/console/mailer.js.map +1 -0
  233. package/dist/esm/cloud/identity/PlanPolicy.d.ts +42 -6
  234. package/dist/esm/cloud/identity/PlanPolicy.d.ts.map +1 -1
  235. package/dist/esm/cloud/identity/PlanPolicy.js +100 -21
  236. package/dist/esm/cloud/identity/PlanPolicy.js.map +1 -1
  237. package/dist/esm/cloud/identity/RateLimiter.d.ts +21 -1
  238. package/dist/esm/cloud/identity/RateLimiter.d.ts.map +1 -1
  239. package/dist/esm/cloud/identity/RateLimiter.js +57 -2
  240. package/dist/esm/cloud/identity/RateLimiter.js.map +1 -1
  241. package/dist/esm/cloud/identity/TenantResolver.d.ts +6 -1
  242. package/dist/esm/cloud/identity/TenantResolver.d.ts.map +1 -1
  243. package/dist/esm/cloud/identity/TenantResolver.js +1 -1
  244. package/dist/esm/cloud/identity/TenantResolver.js.map +1 -1
  245. package/dist/esm/cloud/identity/authenticateV2.d.ts.map +1 -1
  246. package/dist/esm/cloud/identity/authenticateV2.js +7 -4
  247. package/dist/esm/cloud/identity/authenticateV2.js.map +1 -1
  248. package/dist/esm/cloud/identity/identityStore.d.ts +96 -10
  249. package/dist/esm/cloud/identity/identityStore.d.ts.map +1 -1
  250. package/dist/esm/cloud/identity/identityStore.js +199 -3
  251. package/dist/esm/cloud/identity/identityStore.js.map +1 -1
  252. package/dist/esm/cloud/metering/PostgresLedgerStore.d.ts +18 -0
  253. package/dist/esm/cloud/metering/PostgresLedgerStore.d.ts.map +1 -0
  254. package/dist/esm/cloud/metering/PostgresLedgerStore.js +52 -0
  255. package/dist/esm/cloud/metering/PostgresLedgerStore.js.map +1 -0
  256. package/dist/esm/cloud/metering/UsageLedger.d.ts +74 -0
  257. package/dist/esm/cloud/metering/UsageLedger.d.ts.map +1 -1
  258. package/dist/esm/cloud/metering/UsageLedger.js +119 -16
  259. package/dist/esm/cloud/metering/UsageLedger.js.map +1 -1
  260. package/dist/esm/cloud/metering/index.d.ts +1 -0
  261. package/dist/esm/cloud/metering/index.d.ts.map +1 -1
  262. package/dist/esm/cloud/metering/index.js +1 -0
  263. package/dist/esm/cloud/metering/index.js.map +1 -1
  264. package/dist/esm/cloud/store/FileBrainStore.d.ts +6 -1
  265. package/dist/esm/cloud/store/FileBrainStore.d.ts.map +1 -1
  266. package/dist/esm/cloud/store/FileBrainStore.js +8 -0
  267. package/dist/esm/cloud/store/FileBrainStore.js.map +1 -1
  268. package/dist/esm/cloud/store/PostgresBrainStore.d.ts +11 -1
  269. package/dist/esm/cloud/store/PostgresBrainStore.d.ts.map +1 -1
  270. package/dist/esm/cloud/store/PostgresBrainStore.js +32 -0
  271. package/dist/esm/cloud/store/PostgresBrainStore.js.map +1 -1
  272. package/dist/esm/cloud/store/memorySummary.d.ts +29 -0
  273. package/dist/esm/cloud/store/memorySummary.d.ts.map +1 -0
  274. package/dist/esm/cloud/store/memorySummary.js +60 -0
  275. package/dist/esm/cloud/store/memorySummary.js.map +1 -0
  276. package/dist/esm/cloud/v2/app.d.ts.map +1 -1
  277. package/dist/esm/cloud/v2/app.js +6 -0
  278. package/dist/esm/cloud/v2/app.js.map +1 -1
  279. package/dist/esm/cloud/v2/inputGuard.d.ts +23 -0
  280. package/dist/esm/cloud/v2/inputGuard.d.ts.map +1 -0
  281. package/dist/esm/cloud/v2/inputGuard.js +63 -0
  282. package/dist/esm/cloud/v2/inputGuard.js.map +1 -0
  283. package/dist/esm/cloud/v2/routes/admin.d.ts +24 -0
  284. package/dist/esm/cloud/v2/routes/admin.d.ts.map +1 -0
  285. package/dist/esm/cloud/v2/routes/admin.js +337 -0
  286. package/dist/esm/cloud/v2/routes/admin.js.map +1 -0
  287. package/dist/esm/cloud/v2/routes/entitlement.d.ts +13 -0
  288. package/dist/esm/cloud/v2/routes/entitlement.d.ts.map +1 -0
  289. package/dist/esm/cloud/v2/routes/entitlement.js +21 -0
  290. package/dist/esm/cloud/v2/routes/entitlement.js.map +1 -0
  291. package/dist/esm/cloud/v2/routes/index.d.ts +14 -1
  292. package/dist/esm/cloud/v2/routes/index.d.ts.map +1 -1
  293. package/dist/esm/cloud/v2/routes/index.js +37 -1
  294. package/dist/esm/cloud/v2/routes/index.js.map +1 -1
  295. package/dist/esm/cloud/v2/routes/memories.d.ts +21 -2
  296. package/dist/esm/cloud/v2/routes/memories.d.ts.map +1 -1
  297. package/dist/esm/cloud/v2/routes/memories.js +75 -0
  298. package/dist/esm/cloud/v2/routes/memories.js.map +1 -1
  299. package/dist/esm/cloud/v2/routes/recall.d.ts +1 -0
  300. package/dist/esm/cloud/v2/routes/recall.d.ts.map +1 -1
  301. package/dist/esm/cloud/v2/routes/recall.js +5 -1
  302. package/dist/esm/cloud/v2/routes/recall.js.map +1 -1
  303. package/dist/esm/cloud/v2/routes/tenant.d.ts +36 -0
  304. package/dist/esm/cloud/v2/routes/tenant.d.ts.map +1 -0
  305. package/dist/esm/cloud/v2/routes/tenant.js +61 -0
  306. package/dist/esm/cloud/v2/routes/tenant.js.map +1 -0
  307. package/dist/esm/cloud/v2/routes/usage.d.ts +1 -1
  308. package/dist/esm/cloud/v2/routes/usage.d.ts.map +1 -1
  309. package/dist/esm/cloud/v2/routes/verify.d.ts +1 -0
  310. package/dist/esm/cloud/v2/routes/verify.d.ts.map +1 -1
  311. package/dist/esm/cloud/v2/routes/verify.js +5 -1
  312. package/dist/esm/cloud/v2/routes/verify.js.map +1 -1
  313. package/dist/esm/cloud/v2/server.d.ts +9 -3
  314. package/dist/esm/cloud/v2/server.d.ts.map +1 -1
  315. package/dist/esm/cloud/v2/server.js +36 -3
  316. package/dist/esm/cloud/v2/server.js.map +1 -1
  317. package/dist/esm/cloud/v2/usageRecorder.d.ts +19 -0
  318. package/dist/esm/cloud/v2/usageRecorder.d.ts.map +1 -0
  319. package/dist/esm/cloud/v2/usageRecorder.js +37 -0
  320. package/dist/esm/cloud/v2/usageRecorder.js.map +1 -0
  321. package/dist/esm/contracts/api-v2.types.d.ts +92 -2
  322. package/dist/esm/contracts/api-v2.types.d.ts.map +1 -1
  323. package/dist/esm/contracts/store.d.ts +37 -0
  324. package/dist/esm/contracts/store.d.ts.map +1 -1
  325. package/dist/esm/mcp/index.js +8 -2
  326. package/dist/esm/mcp/index.js.map +1 -1
  327. package/dist/esm/mcp/tools/memory.d.ts.map +1 -1
  328. package/dist/esm/mcp/tools/memory.js +74 -4
  329. package/dist/esm/mcp/tools/memory.js.map +1 -1
  330. package/dist/esm/mcp/tools/misc.d.ts.map +1 -1
  331. package/dist/esm/mcp/tools/misc.js +2 -1
  332. package/dist/esm/mcp/tools/misc.js.map +1 -1
  333. package/dist/esm/mcp/tools/workspace.d.ts.map +1 -1
  334. package/dist/esm/mcp/tools/workspace.js +4 -1
  335. package/dist/esm/mcp/tools/workspace.js.map +1 -1
  336. package/dist/esm/mcp/tools.d.ts +10 -0
  337. package/dist/esm/mcp/tools.d.ts.map +1 -1
  338. package/dist/esm/mcp/tools.js +46 -12
  339. package/dist/esm/mcp/tools.js.map +1 -1
  340. package/dist/esm/proxy/KeyManager.d.ts.map +1 -1
  341. package/dist/esm/proxy/KeyManager.js +5 -0
  342. package/dist/esm/proxy/KeyManager.js.map +1 -1
  343. package/dist/esm/subconscious/CloudBrain.d.ts +77 -0
  344. package/dist/esm/subconscious/CloudBrain.d.ts.map +1 -0
  345. package/dist/esm/subconscious/CloudBrain.js +330 -0
  346. package/dist/esm/subconscious/CloudBrain.js.map +1 -0
  347. package/dist/esm/subconscious/HostRecall.d.ts.map +1 -1
  348. package/dist/esm/subconscious/HostRecall.js +11 -4
  349. package/dist/esm/subconscious/HostRecall.js.map +1 -1
  350. package/dist/esm/subconscious/ProjectIdentity.d.ts +9 -0
  351. package/dist/esm/subconscious/ProjectIdentity.d.ts.map +1 -0
  352. package/dist/esm/subconscious/ProjectIdentity.js +56 -0
  353. package/dist/esm/subconscious/ProjectIdentity.js.map +1 -0
  354. package/dist/esm/subconscious/TeamBrain.d.ts +9 -3
  355. package/dist/esm/subconscious/TeamBrain.d.ts.map +1 -1
  356. package/dist/esm/subconscious/TeamBrain.js +39 -7
  357. package/dist/esm/subconscious/TeamBrain.js.map +1 -1
  358. package/dist/esm/utils/FixCapture.d.ts +7 -5
  359. package/dist/esm/utils/FixCapture.d.ts.map +1 -1
  360. package/dist/esm/utils/FixCapture.js +64 -33
  361. package/dist/esm/utils/FixCapture.js.map +1 -1
  362. package/dist/esm/utils/NoTerminal.d.ts +27 -0
  363. package/dist/esm/utils/NoTerminal.d.ts.map +1 -0
  364. package/dist/esm/utils/NoTerminal.js +33 -0
  365. package/dist/esm/utils/NoTerminal.js.map +1 -0
  366. package/dist/esm/utils/OpenCodeSession.d.ts +70 -0
  367. package/dist/esm/utils/OpenCodeSession.d.ts.map +1 -0
  368. package/dist/esm/utils/OpenCodeSession.js +146 -0
  369. package/dist/esm/utils/OpenCodeSession.js.map +1 -0
  370. package/dist/esm/utils/ProLicense.d.ts.map +1 -1
  371. package/dist/esm/utils/ProLicense.js +11 -3
  372. package/dist/esm/utils/ProLicense.js.map +1 -1
  373. package/dist/esm/utils/SessionCapture.d.ts +31 -7
  374. package/dist/esm/utils/SessionCapture.d.ts.map +1 -1
  375. package/dist/esm/utils/SessionCapture.js +185 -32
  376. package/dist/esm/utils/SessionCapture.js.map +1 -1
  377. package/dist/esm/utils/StopNudge.d.ts +8 -0
  378. package/dist/esm/utils/StopNudge.d.ts.map +1 -0
  379. package/dist/esm/utils/StopNudge.js +86 -0
  380. package/dist/esm/utils/StopNudge.js.map +1 -0
  381. package/dist/esm/utils/TestAutofixInterceptor.d.ts.map +1 -1
  382. package/dist/esm/utils/TestAutofixInterceptor.js +2 -0
  383. package/dist/esm/utils/TestAutofixInterceptor.js.map +1 -1
  384. package/lemma-proxy.cjs +5 -0
  385. package/package.json +2 -1
  386. package/sdks/crewai/dist/ts/src/client.d.ts +5 -1
  387. package/sdks/crewai/dist/ts/src/client.js +8 -0
  388. package/sdks/crewai/dist/ts/src/types.d.ts +32 -1
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ResendMailer = void 0;
4
+ exports.resendMailerFromEnv = resendMailerFromEnv;
5
+ function resendMailerFromEnv(env = process.env) {
6
+ const apiKey = env.RESEND_API_KEY;
7
+ if (!apiKey)
8
+ return undefined;
9
+ return new ResendMailer({ apiKey, from: env.CONSOLE_MAIL_FROM || 'Lemma <hello@nxus.studio>' });
10
+ }
11
+ class ResendMailer {
12
+ constructor(config) {
13
+ this.config = config;
14
+ this.fetchImpl = config.fetchImpl ?? fetch;
15
+ }
16
+ async sendLoginLink(to, link, minutes) {
17
+ const res = await this.fetchImpl('https://api.resend.com/emails', {
18
+ method: 'POST',
19
+ headers: { Authorization: `Bearer ${this.config.apiKey}`, 'Content-Type': 'application/json' },
20
+ body: JSON.stringify({
21
+ from: this.config.from,
22
+ to: [to],
23
+ subject: 'Your Lemma Cloud sign-in link / Tu enlace de acceso a Lemma Cloud',
24
+ text: `Sign in to Lemma Cloud (valid ${minutes} minutes, works once):\n${link}\n\n` +
25
+ `Entra a Lemma Cloud (válido ${minutes} minutos, funciona una vez):\n${link}\n\n` +
26
+ `If you did not ask for this, ignore this email. / Si no lo pediste, ignora este correo.`,
27
+ }),
28
+ });
29
+ // The status only: the response body and the request (which holds the link) stay out of any log.
30
+ if (!res.ok)
31
+ throw new Error(`mail provider answered ${res.status}`);
32
+ }
33
+ }
34
+ exports.ResendMailer = ResendMailer;
35
+ //# sourceMappingURL=mailer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mailer.js","sourceRoot":"","sources":["../../../../src/cloud/console/mailer.ts"],"names":[],"mappings":";;;AAgBA,kDAIC;AAJD,SAAgB,mBAAmB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACtE,MAAM,MAAM,GAAG,GAAG,CAAC,cAAc,CAAC;IAClC,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,OAAO,IAAI,YAAY,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,iBAAiB,IAAI,2BAA2B,EAAE,CAAC,CAAC;AAClG,CAAC;AAED,MAAa,YAAY;IAEvB,YAA6B,MAAoB;QAApB,WAAM,GAAN,MAAM,CAAc;QAC/C,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,KAAK,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,EAAU,EAAE,IAAY,EAAE,OAAe;QAC3D,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,+BAA+B,EAAE;YAChE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC9F,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI;gBACtB,EAAE,EAAE,CAAC,EAAE,CAAC;gBACR,OAAO,EAAE,mEAAmE;gBAC5E,IAAI,EACF,iCAAiC,OAAO,2BAA2B,IAAI,MAAM;oBAC7E,+BAA+B,OAAO,iCAAiC,IAAI,MAAM;oBACjF,yFAAyF;aAC5F,CAAC;SACH,CAAC,CAAC;QACH,iGAAiG;QACjG,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IACvE,CAAC;CACF;AAvBD,oCAuBC"}
@@ -9,7 +9,16 @@
9
9
  * This module owns the plan table. The DB migration only stores tenancy; keeping
10
10
  * a second copy of the limits in SQL would guarantee drift.
11
11
  */
12
- export type PlanId = 'free' | 'pro' | 'scale';
12
+ /**
13
+ * Cloud plans. `vinel` is the team tier (every seat also unlocks the local Pro tools) and `regnum`
14
+ * is the large-organisation tier. They used to be `pro` and `scale`; `pro` now means only the local
15
+ * Pro license, so the two are never confused. `internal` is not sold: it is for the maintainers' own
16
+ * accounts (huge but finite ceilings, because Infinity is banned), assigned only through the admin API,
17
+ * and the Stripe webhook never touches a tenant on it. Add a plan here and the type, the admin API validation
18
+ * and the SQL CHECK (a new migration) follow from this list.
19
+ */
20
+ export declare const PLAN_IDS: readonly ["free", "vinel", "regnum", "internal"];
21
+ export type PlanId = (typeof PLAN_IDS)[number];
13
22
  export interface PlanLimits {
14
23
  /** Active AND verified memories the tenant may keep. */
15
24
  activeMemories: number;
@@ -28,12 +37,35 @@ export declare const RATE_LIMIT_WINDOW_MS: number;
28
37
  export declare const PLAN_UPGRADE_URL: Readonly<Record<PlanId, string>>;
29
38
  /** Single source of truth for plan ceilings. Every value finite and > 0. */
30
39
  export declare const PLAN_LIMITS: Readonly<Record<PlanId, PlanLimits>>;
40
+ /**
41
+ * Whether a seat on the plan also unlocks the local Pro tools. A Record over PlanId, so adding a plan
42
+ * to PLAN_IDS without deciding this does not compile. The client never decides it: it asks the server
43
+ * (GET /v2/entitlement), so changing a plan here changes what every connected dev gets.
44
+ */
45
+ export declare const PLAN_INCLUDES_PRO: Readonly<Record<PlanId, boolean>>;
31
46
  export declare const DEFAULT_PLAN: PlanId;
47
+ /** The ceilings a founder's plan can raise. Seats are what a plan is sold by, so they are the plan's own. */
48
+ export type FounderLimits = Partial<Pick<PlanLimits, 'activeMemories' | 'dailyRequests' | 'monthlyRequests'>>;
49
+ /**
50
+ * What the founders (the first teams, who signed up before Cloud opened to everyone) keep. A founder gets,
51
+ * limit by limit, the HIGHER of this and the public plan: lowering a public plan later never reaches a
52
+ * founder, and raising one above these never leaves a founder behind. Only the paid plans have founder
53
+ * limits; a founder whose subscription ends is on `free` like anyone else (the flag stays, and comes back
54
+ * into force if they subscribe again). Like PLAN_LIMITS these numbers are not published: the landing only
55
+ * promises that founders keep better limits.
56
+ */
57
+ export declare const FOUNDER_LIMITS: Readonly<Partial<Record<PlanId, FounderLimits>>>;
58
+ /** What, besides the plan, decides a tenant's limits. */
59
+ export interface LimitsContext {
60
+ founder?: boolean;
61
+ }
32
62
  /**
33
63
  * The `Infinity` elimination check, exported so tests can prove it (and the
34
64
  * policy constructor refuses any non-finite/zero ceiling at startup).
35
65
  */
36
66
  export declare function validatePlanLimits(limits: Record<string, PlanLimits>): string[];
67
+ /** Founder ceilings must be finite and positive too, and only for plans that exist. */
68
+ export declare function validateFounderLimits(founder: Partial<Record<string, FounderLimits>>): string[];
37
69
  export type QuotaKind = 'memories' | 'seats';
38
70
  export interface QuotaViolation {
39
71
  kind: QuotaKind;
@@ -67,13 +99,17 @@ export interface QuotaErrorBody {
67
99
  export declare function quotaErrorBody(violation: QuotaViolation, resetsAt?: number | null): QuotaErrorBody;
68
100
  export declare class PlanPolicy {
69
101
  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;
102
+ private readonly founder;
103
+ constructor(limits?: Record<string, PlanLimits>, founder?: Partial<Record<string, FounderLimits>>);
104
+ /**
105
+ * Limits for a plan; unknown plans conservatively fall back to `free`. With `founder`, each ceiling the
106
+ * founder table names is the higher of the two (see FOUNDER_LIMITS).
107
+ */
108
+ limitsFor(plan: string, ctx?: LimitsContext): PlanLimits;
73
109
  /** Memory quota: number of ACTIVE-VERIFIED memories the plan allows. */
74
- checkMemoryQuota(planId: string, activeVerifiedMemories: number): QuotaCheck;
110
+ checkMemoryQuota(planId: string, activeVerifiedMemories: number, ctx?: LimitsContext): QuotaCheck;
75
111
  /** Seat quota: number of seats (members/keys) the plan allows. */
76
- checkSeatQuota(planId: string, seats: number): QuotaCheck;
112
+ checkSeatQuota(planId: string, seats: number, ctx?: LimitsContext): QuotaCheck;
77
113
  private checkStatic;
78
114
  }
79
115
  //# sourceMappingURL=PlanPolicy.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"PlanPolicy.d.ts","sourceRoot":"","sources":["../../../../src/cloud/identity/PlanPolicy.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,35 @@
1
1
  "use strict";
2
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;
3
+ exports.PlanPolicy = exports.FOUNDER_LIMITS = exports.DEFAULT_PLAN = exports.PLAN_INCLUDES_PRO = exports.PLAN_LIMITS = exports.PLAN_UPGRADE_URL = exports.RATE_LIMIT_WINDOW_MS = exports.PLAN_IDS = void 0;
4
4
  exports.validatePlanLimits = validatePlanLimits;
5
+ exports.validateFounderLimits = validateFounderLimits;
5
6
  exports.quotaErrorBody = quotaErrorBody;
7
+ /**
8
+ * Lemma API v2 — PlanPolicy (Lane D)
9
+ *
10
+ * Replaces `src/cloud/types.ts` PLAN_LIMITS. Quota is measured by ACTIVE-VERIFIED
11
+ * memories and by SEAT, not only by request count, and `Infinity` is gone —
12
+ * every plan has an explicit, positive ceiling. Exceeding a cap yields a 429
13
+ * with an actionable body: limit, current use, reset time and upgrade link.
14
+ *
15
+ * This module owns the plan table. The DB migration only stores tenancy; keeping
16
+ * a second copy of the limits in SQL would guarantee drift.
17
+ */
18
+ /**
19
+ * Cloud plans. `vinel` is the team tier (every seat also unlocks the local Pro tools) and `regnum`
20
+ * is the large-organisation tier. They used to be `pro` and `scale`; `pro` now means only the local
21
+ * Pro license, so the two are never confused. `internal` is not sold: it is for the maintainers' own
22
+ * accounts (huge but finite ceilings, because Infinity is banned), assigned only through the admin API,
23
+ * and the Stripe webhook never touches a tenant on it. Add a plan here and the type, the admin API validation
24
+ * and the SQL CHECK (a new migration) follow from this list.
25
+ */
26
+ exports.PLAN_IDS = ['free', 'vinel', 'regnum', 'internal'];
6
27
  exports.RATE_LIMIT_WINDOW_MS = 24 * 60 * 60 * 1000;
7
28
  exports.PLAN_UPGRADE_URL = Object.freeze({
8
29
  free: 'https://lemma.dev/pricing',
9
- pro: 'https://lemma.dev/pricing',
10
- scale: 'https://lemma.dev/contact',
30
+ vinel: 'https://lemma.dev/pricing',
31
+ regnum: 'https://lemma.dev/contact',
32
+ internal: 'https://lemma.dev/contact',
11
33
  });
12
34
  /** Single source of truth for plan ceilings. Every value finite and > 0. */
13
35
  exports.PLAN_LIMITS = Object.freeze({
@@ -19,24 +41,55 @@ exports.PLAN_LIMITS = Object.freeze({
19
41
  rateLimitWindowMs: exports.RATE_LIMIT_WINDOW_MS,
20
42
  upgradeUrl: exports.PLAN_UPGRADE_URL.free,
21
43
  }),
22
- pro: Object.freeze({
44
+ vinel: Object.freeze({
23
45
  activeMemories: 10000,
24
46
  seats: 10,
25
47
  dailyRequests: 5000,
26
48
  monthlyRequests: 60000,
27
49
  rateLimitWindowMs: exports.RATE_LIMIT_WINDOW_MS,
28
- upgradeUrl: exports.PLAN_UPGRADE_URL.pro,
50
+ upgradeUrl: exports.PLAN_UPGRADE_URL.vinel,
29
51
  }),
30
- scale: Object.freeze({
52
+ regnum: Object.freeze({
31
53
  activeMemories: 100000,
32
54
  seats: 50,
33
55
  dailyRequests: 20000,
34
56
  monthlyRequests: 250000,
35
57
  rateLimitWindowMs: exports.RATE_LIMIT_WINDOW_MS,
36
- upgradeUrl: exports.PLAN_UPGRADE_URL.scale,
58
+ upgradeUrl: exports.PLAN_UPGRADE_URL.regnum,
37
59
  }),
60
+ internal: Object.freeze({
61
+ activeMemories: 10000000,
62
+ seats: 25,
63
+ dailyRequests: 1000000,
64
+ monthlyRequests: 30000000,
65
+ rateLimitWindowMs: exports.RATE_LIMIT_WINDOW_MS,
66
+ upgradeUrl: exports.PLAN_UPGRADE_URL.internal,
67
+ }),
68
+ });
69
+ /**
70
+ * Whether a seat on the plan also unlocks the local Pro tools. A Record over PlanId, so adding a plan
71
+ * to PLAN_IDS without deciding this does not compile. The client never decides it: it asks the server
72
+ * (GET /v2/entitlement), so changing a plan here changes what every connected dev gets.
73
+ */
74
+ exports.PLAN_INCLUDES_PRO = Object.freeze({
75
+ free: false,
76
+ vinel: true,
77
+ regnum: true,
78
+ internal: true,
38
79
  });
39
80
  exports.DEFAULT_PLAN = 'free';
81
+ /**
82
+ * What the founders (the first teams, who signed up before Cloud opened to everyone) keep. A founder gets,
83
+ * limit by limit, the HIGHER of this and the public plan: lowering a public plan later never reaches a
84
+ * founder, and raising one above these never leaves a founder behind. Only the paid plans have founder
85
+ * limits; a founder whose subscription ends is on `free` like anyone else (the flag stays, and comes back
86
+ * into force if they subscribe again). Like PLAN_LIMITS these numbers are not published: the landing only
87
+ * promises that founders keep better limits.
88
+ */
89
+ exports.FOUNDER_LIMITS = Object.freeze({
90
+ vinel: Object.freeze({ activeMemories: 25000, dailyRequests: 10000, monthlyRequests: 150000 }),
91
+ regnum: Object.freeze({ activeMemories: 250000, dailyRequests: 40000, monthlyRequests: 600000 }),
92
+ });
40
93
  const NUMERIC_LIMIT_KEYS = [
41
94
  'activeMemories',
42
95
  'seats',
@@ -62,6 +115,19 @@ function validatePlanLimits(limits) {
62
115
  }
63
116
  return problems;
64
117
  }
118
+ /** Founder ceilings must be finite and positive too, and only for plans that exist. */
119
+ function validateFounderLimits(founder) {
120
+ const problems = [];
121
+ for (const [plan, l] of Object.entries(founder)) {
122
+ if (!exports.PLAN_IDS.includes(plan))
123
+ problems.push(`founder.${plan}: unknown plan`);
124
+ for (const [key, value] of Object.entries(l ?? {})) {
125
+ if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0)
126
+ problems.push(`founder.${plan}.${key} = ${value}`);
127
+ }
128
+ }
129
+ return problems;
130
+ }
65
131
  function quotaErrorBody(violation, resetsAt = null) {
66
132
  return {
67
133
  error: {
@@ -78,52 +144,66 @@ function quotaErrorBody(violation, resetsAt = null) {
78
144
  };
79
145
  }
80
146
  class PlanPolicy {
81
- constructor(limits = exports.PLAN_LIMITS) {
82
- const problems = validatePlanLimits(limits);
147
+ constructor(limits = exports.PLAN_LIMITS, founder = exports.FOUNDER_LIMITS) {
148
+ const problems = [...validatePlanLimits(limits), ...validateFounderLimits(founder)];
83
149
  if (problems.length > 0) {
84
150
  throw new Error(`PlanPolicy: invalid plan limits (${problems.join(', ')})`);
85
151
  }
86
152
  this.limits = limits;
153
+ this.founder = founder;
87
154
  }
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];
155
+ /**
156
+ * Limits for a plan; unknown plans conservatively fall back to `free`. With `founder`, each ceiling the
157
+ * founder table names is the higher of the two (see FOUNDER_LIMITS).
158
+ */
159
+ limitsFor(plan, ctx = {}) {
160
+ const base = this.limits[plan] ?? this.limits[exports.DEFAULT_PLAN];
161
+ const raise = ctx.founder ? this.founder[plan in this.limits ? plan : exports.DEFAULT_PLAN] : undefined;
162
+ if (!raise)
163
+ return base;
164
+ const out = { ...base };
165
+ for (const key of Object.keys(raise)) {
166
+ const v = raise[key];
167
+ if (typeof v === 'number')
168
+ out[key] = Math.max(base[key], v);
169
+ }
170
+ return out;
91
171
  }
92
172
  /** Memory quota: number of ACTIVE-VERIFIED memories the plan allows. */
93
- checkMemoryQuota(planId, activeVerifiedMemories) {
94
- return this.checkStatic(planId, 'memories', activeVerifiedMemories, (limit, plan) => ({
173
+ checkMemoryQuota(planId, activeVerifiedMemories, ctx = {}) {
174
+ return this.checkStatic(planId, 'memories', activeVerifiedMemories, ctx, (limit, plan) => ({
95
175
  allowed: false,
96
176
  violation: {
97
177
  kind: 'memories',
98
178
  plan,
99
179
  limit,
100
180
  current: activeVerifiedMemories,
101
- upgradeUrl: this.limitsFor(planId).upgradeUrl,
181
+ upgradeUrl: this.limitsFor(planId, ctx).upgradeUrl,
102
182
  message: `${plan} plan allows ${limit} active verified memories; ` +
103
183
  `you currently have ${activeVerifiedMemories}. ` +
104
- `Upgrade at ${this.limitsFor(planId).upgradeUrl}`,
184
+ `Upgrade at ${this.limitsFor(planId, ctx).upgradeUrl}`,
105
185
  },
106
186
  }));
107
187
  }
108
188
  /** Seat quota: number of seats (members/keys) the plan allows. */
109
- checkSeatQuota(planId, seats) {
110
- return this.checkStatic(planId, 'seats', seats, (limit, plan) => ({
189
+ checkSeatQuota(planId, seats, ctx = {}) {
190
+ return this.checkStatic(planId, 'seats', seats, ctx, (limit, plan) => ({
111
191
  allowed: false,
112
192
  violation: {
113
193
  kind: 'seats',
114
194
  plan,
115
195
  limit,
116
196
  current: seats,
117
- upgradeUrl: this.limitsFor(planId).upgradeUrl,
197
+ upgradeUrl: this.limitsFor(planId, ctx).upgradeUrl,
118
198
  message: `${plan} plan allows ${limit} seat(s); you currently have ${seats}. ` +
119
- `Upgrade at ${this.limitsFor(planId).upgradeUrl}`,
199
+ `Upgrade at ${this.limitsFor(planId, ctx).upgradeUrl}`,
120
200
  },
121
201
  }));
122
202
  }
123
- checkStatic(planId, kind, current, makeViolation) {
203
+ checkStatic(planId, kind, current, ctx, makeViolation) {
124
204
  const plan = (planId in this.limits ? planId : exports.DEFAULT_PLAN);
125
205
  const limitKey = kind === 'memories' ? 'activeMemories' : 'seats';
126
- const limit = this.limitsFor(planId)[limitKey];
206
+ const limit = this.limitsFor(planId, ctx)[limitKey];
127
207
  // El tope es exclusivo: en el límite (free con 1000 activas) la siguiente
128
208
  // escritura ya está negada — "intenta crear la 1001 ⇒ 429".
129
209
  if (current >= limit)
@@ -1 +1 @@
1
- {"version":3,"file":"PlanPolicy.js","sourceRoot":"","sources":["../../../../src/cloud/identity/PlanPolicy.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PlanPolicy.js","sourceRoot":"","sources":["../../../../src/cloud/identity/PlanPolicy.ts"],"names":[],"mappings":"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"}
@@ -19,13 +19,22 @@ export interface RateLimitDecision {
19
19
  }
20
20
  export interface RateLimiter {
21
21
  consume(tenantId: string, limit: number, windowMs: number, now?: number): Promise<RateLimitDecision>;
22
+ /** Requests counted in the current window, WITHOUT counting this call. For reporting, never for enforcing. */
23
+ peek?(tenantId: string, windowMs: number, now?: number): Promise<number>;
24
+ /** One request against the tenant's calendar-month (UTC) allowance; resetAt is the first instant of the next month. */
25
+ consumeMonthly?(tenantId: string, limit: number, now?: number): Promise<RateLimitDecision>;
26
+ /** Requests counted this calendar month, WITHOUT counting this call. For reporting, never for enforcing. */
27
+ peekMonthly?(tenantId: string, now?: number): Promise<number>;
22
28
  }
29
+ /** Which allowance a 429 came from. */
30
+ export type RateLimitWindow = 'day' | 'month';
23
31
  /** The 429 body for rate_limited (additive to the LemmaApiError envelope). */
24
32
  export interface RateLimitErrorBody {
25
33
  error: {
26
34
  code: 'rate_limited';
27
35
  status: 429;
28
36
  message: string;
37
+ window: RateLimitWindow;
29
38
  limit: number;
30
39
  used: number;
31
40
  remaining: number;
@@ -34,16 +43,27 @@ export interface RateLimitErrorBody {
34
43
  upgradeUrl: string;
35
44
  };
36
45
  }
37
- export declare function rateLimitErrorBody(decision: RateLimitDecision, retryAfterSeconds: number, upgradeUrl: string): RateLimitErrorBody;
46
+ export declare function rateLimitErrorBody(decision: RateLimitDecision, retryAfterSeconds: number, upgradeUrl: string, window?: RateLimitWindow): RateLimitErrorBody;
47
+ /** Bucket id of the calendar month (UTC) that contains `now`, e.g. `m:2026-10`. Text, so it shares the daily buckets' table without clashing. */
48
+ export declare function monthBucket(now: number): string;
49
+ /** First instant (epoch ms) of the UTC month after the one containing `now`. */
50
+ export declare function nextMonthStart(now: number): number;
38
51
  /** In-process fixed-window limiter. Suitable for single-instance dev and tests. */
39
52
  export declare class InMemoryRateLimiter implements RateLimiter {
40
53
  private readonly buckets;
41
54
  consume(tenantId: string, limit: number, windowMs: number, now?: number): Promise<RateLimitDecision>;
55
+ peek(tenantId: string, windowMs: number, now?: number): Promise<number>;
56
+ private readonly months;
57
+ consumeMonthly(tenantId: string, limit: number, now?: number): Promise<RateLimitDecision>;
58
+ peekMonthly(tenantId: string, now?: number): Promise<number>;
42
59
  }
43
60
  /** Postgres-backed fixed-window limiter, atomic via a single upsert. */
44
61
  export declare class PostgresRateLimiter implements RateLimiter {
45
62
  private readonly pool;
46
63
  constructor(pool: Pool);
47
64
  consume(tenantId: string, limit: number, windowMs: number, now?: number): Promise<RateLimitDecision>;
65
+ peek(tenantId: string, windowMs: number, now?: number): Promise<number>;
66
+ consumeMonthly(tenantId: string, limit: number, now?: number): Promise<RateLimitDecision>;
67
+ peekMonthly(tenantId: string, now?: number): Promise<number>;
48
68
  }
49
69
  //# sourceMappingURL=RateLimiter.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"RateLimiter.d.ts","sourceRoot":"","sources":["../../../../src/cloud/identity/RateLimiter.ts"],"names":[],"mappings":"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"}
@@ -2,13 +2,17 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PostgresRateLimiter = exports.InMemoryRateLimiter = void 0;
4
4
  exports.rateLimitErrorBody = rateLimitErrorBody;
5
- function rateLimitErrorBody(decision, retryAfterSeconds, upgradeUrl) {
5
+ exports.monthBucket = monthBucket;
6
+ exports.nextMonthStart = nextMonthStart;
7
+ function rateLimitErrorBody(decision, retryAfterSeconds, upgradeUrl, window = 'day') {
8
+ const scope = window === 'month' ? 'requests this month' : 'requests in the current window';
6
9
  return {
7
10
  error: {
8
11
  code: 'rate_limited',
9
12
  status: 429,
10
- message: `rate limit exceeded: ${decision.used}/${decision.limit} requests in the current window. ` +
13
+ message: `rate limit exceeded: ${decision.used}/${decision.limit} ${scope}. ` +
11
14
  `Back off and retry after ${retryAfterSeconds}s, or upgrade at ${upgradeUrl}.`,
15
+ window,
12
16
  limit: decision.limit,
13
17
  used: decision.used,
14
18
  remaining: decision.remaining,
@@ -18,10 +22,21 @@ function rateLimitErrorBody(decision, retryAfterSeconds, upgradeUrl) {
18
22
  },
19
23
  };
20
24
  }
25
+ /** Bucket id of the calendar month (UTC) that contains `now`, e.g. `m:2026-10`. Text, so it shares the daily buckets' table without clashing. */
26
+ function monthBucket(now) {
27
+ const d = new Date(now);
28
+ return `m:${d.getUTCFullYear()}-${String(d.getUTCMonth() + 1).padStart(2, '0')}`;
29
+ }
30
+ /** First instant (epoch ms) of the UTC month after the one containing `now`. */
31
+ function nextMonthStart(now) {
32
+ const d = new Date(now);
33
+ return Date.UTC(d.getUTCFullYear(), d.getUTCMonth() + 1, 1);
34
+ }
21
35
  /** In-process fixed-window limiter. Suitable for single-instance dev and tests. */
22
36
  class InMemoryRateLimiter {
23
37
  constructor() {
24
38
  this.buckets = new Map();
39
+ this.months = new Map();
25
40
  }
26
41
  async consume(tenantId, limit, windowMs, now = Date.now()) {
27
42
  const bucket = Math.floor(now / windowMs);
@@ -46,6 +61,24 @@ class InMemoryRateLimiter {
46
61
  resetAt,
47
62
  };
48
63
  }
64
+ async peek(tenantId, windowMs, now = Date.now()) {
65
+ return this.buckets.get(`${tenantId}:${Math.floor(now / windowMs)}`)?.count ?? 0;
66
+ }
67
+ async consumeMonthly(tenantId, limit, now = Date.now()) {
68
+ const bucket = monthBucket(now);
69
+ // Keep only the current month, as the daily map does: no background timers.
70
+ for (const k of this.months.keys()) {
71
+ if (!k.endsWith(`:${bucket}`))
72
+ this.months.delete(k);
73
+ }
74
+ const key = `${tenantId}:${bucket}`;
75
+ const used = (this.months.get(key) ?? 0) + 1;
76
+ this.months.set(key, used);
77
+ return { allowed: used <= limit, used, limit, remaining: Math.max(0, limit - used), resetAt: nextMonthStart(now) };
78
+ }
79
+ async peekMonthly(tenantId, now = Date.now()) {
80
+ return this.months.get(`${tenantId}:${monthBucket(now)}`) ?? 0;
81
+ }
49
82
  }
50
83
  exports.InMemoryRateLimiter = InMemoryRateLimiter;
51
84
  /** Postgres-backed fixed-window limiter, atomic via a single upsert. */
@@ -70,6 +103,30 @@ class PostgresRateLimiter {
70
103
  resetAt: (bucket + 1) * windowMs,
71
104
  };
72
105
  }
106
+ async peek(tenantId, windowMs, now = Date.now()) {
107
+ const { rows } = await this.pool.query('SELECT request_count FROM tenant_rate_limits WHERE tenant_id = $1 AND bucket = $2', [
108
+ tenantId,
109
+ String(Math.floor(now / windowMs)),
110
+ ]);
111
+ return Number(rows[0]?.request_count ?? 0);
112
+ }
113
+ async consumeMonthly(tenantId, limit, now = Date.now()) {
114
+ const { rows } = await this.pool.query(`INSERT INTO tenant_rate_limits (tenant_id, bucket, request_count)
115
+ VALUES ($1, $2, 1)
116
+ ON CONFLICT (tenant_id, bucket) DO UPDATE
117
+ SET request_count = tenant_rate_limits.request_count + 1,
118
+ updated_at = CURRENT_TIMESTAMP
119
+ RETURNING request_count`, [tenantId, monthBucket(now)]);
120
+ const used = Number(rows[0]?.request_count ?? 1);
121
+ return { allowed: used <= limit, used, limit, remaining: Math.max(0, limit - used), resetAt: nextMonthStart(now) };
122
+ }
123
+ async peekMonthly(tenantId, now = Date.now()) {
124
+ const { rows } = await this.pool.query('SELECT request_count FROM tenant_rate_limits WHERE tenant_id = $1 AND bucket = $2', [
125
+ tenantId,
126
+ monthBucket(now),
127
+ ]);
128
+ return Number(rows[0]?.request_count ?? 0);
129
+ }
73
130
  }
74
131
  exports.PostgresRateLimiter = PostgresRateLimiter;
75
132
  //# sourceMappingURL=RateLimiter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"RateLimiter.js","sourceRoot":"","sources":["../../../../src/cloud/identity/RateLimiter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"RateLimiter.js","sourceRoot":"","sources":["../../../../src/cloud/identity/RateLimiter.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,13 @@
1
1
  import type { IdentityStore } from './identityStore';
2
+ import type { PlanId } from './PlanPolicy';
2
3
  export interface Tenant {
3
4
  id: string;
4
- plan: 'free' | 'pro' | 'scale';
5
+ plan: PlanId;
5
6
  keyId: string;
7
+ /** Human label of the presented key (e.g. "dev-a"); recorded as the memory's author. */
8
+ keyName?: string;
9
+ /** The tenant signed up as a founder: PlanPolicy applies the founder limits. */
10
+ founder?: boolean;
6
11
  }
7
12
  export declare class TenantResolver {
8
13
  private readonly store;
@@ -1 +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"}
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;AACrD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,wFAAwF;IACxF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;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"}
@@ -32,7 +32,7 @@ class TenantResolver {
32
32
  return null;
33
33
  if (record.expiresAt !== null && Date.now() > record.expiresAt)
34
34
  return null;
35
- return { id: record.tenantId, plan: record.plan, keyId: record.id };
35
+ return { id: record.tenantId, plan: record.plan, keyId: record.id, keyName: record.name, ...(record.founder ? { founder: true } : {}) };
36
36
  }
37
37
  }
38
38
  exports.TenantResolver = TenantResolver;
@@ -1 +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"}
1
+ {"version":3,"file":"TenantResolver.js","sourceRoot":"","sources":["../../../../src/cloud/identity/TenantResolver.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;GAQG;AACH,qCAAuD;AAcvD,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,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IAC1I,CAAC;CACF;AAtBD,wCAsBC;AAED,kBAAe,cAAc,CAAC"}
@@ -1 +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"}
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,CA6CvE;AAED,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAChC,eAAe,cAAc,CAAC"}
@@ -41,16 +41,19 @@ function authenticateV2(deps) {
41
41
  return;
42
42
  }
43
43
  if (deps.rateLimiter) {
44
- const limit = policy.limitsFor(tenant.plan).dailyRequests;
45
- const decision = await deps.rateLimiter.consume(tenant.id, limit, windowMs, now());
44
+ const limits = policy.limitsFor(tenant.plan, { founder: tenant.founder === true });
45
+ const daily = await deps.rateLimiter.consume(tenant.id, limits.dailyRequests, windowMs, now());
46
+ // A request the day already refused does not eat the month's allowance.
47
+ const decision = !daily.allowed || !deps.rateLimiter.consumeMonthly
48
+ ? daily
49
+ : await deps.rateLimiter.consumeMonthly(tenant.id, limits.monthlyRequests, now());
46
50
  if (!decision.allowed) {
47
51
  const retryAfter = Math.max(1, Math.ceil((decision.resetAt - now()) / 1000));
48
- const upgradeUrl = policy.limitsFor(tenant.plan).upgradeUrl;
49
52
  res
50
53
  .status(429)
51
54
  .set('Retry-After', String(retryAfter))
52
55
  .set('WWW-Authenticate', 'Bearer')
53
- .json((0, RateLimiter_1.rateLimitErrorBody)(decision, retryAfter, upgradeUrl));
56
+ .json((0, RateLimiter_1.rateLimitErrorBody)(decision, retryAfter, limits.upgradeUrl, decision === daily ? 'day' : 'month'));
54
57
  return;
55
58
  }
56
59
  }