@lenne.tech/nest-server 12.0.0 → 12.1.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 (693) hide show
  1. package/.claude/rules/architecture.md +6 -1
  2. package/.claude/rules/better-auth.md +46 -0
  3. package/.claude/rules/configurable-features.md +3 -2
  4. package/.claude/rules/package-management.md +24 -2
  5. package/.claude/rules/persistence.md +100 -0
  6. package/.claude/rules/role-system.md +9 -0
  7. package/.claude/rules/testing.md +116 -18
  8. package/CLAUDE.md +21 -2
  9. package/FRAMEWORK-API.md +6 -4
  10. package/README.md +106 -34
  11. package/dist/core/common/decorators/unified-field.decorator.d.ts +2 -1
  12. package/dist/core/common/decorators/unified-field.decorator.js +4 -1
  13. package/dist/core/common/decorators/unified-field.decorator.js.map +1 -1
  14. package/dist/core/common/filters/mongoose-cast-error.filter.d.ts +7 -5
  15. package/dist/core/common/filters/mongoose-cast-error.filter.js +3 -2
  16. package/dist/core/common/filters/mongoose-cast-error.filter.js.map +1 -1
  17. package/dist/core/common/helpers/db.helper.d.ts +2 -1
  18. package/dist/core/common/helpers/db.helper.js +32 -26
  19. package/dist/core/common/helpers/db.helper.js.map +1 -1
  20. package/dist/core/common/helpers/decorator.helper.d.ts +1 -1
  21. package/dist/core/common/helpers/filter.helper.d.ts +2 -1
  22. package/dist/core/common/helpers/filter.helper.js.map +1 -1
  23. package/dist/core/common/helpers/gridfs.helper.d.ts +4 -4
  24. package/dist/core/common/helpers/gridfs.helper.js +14 -6
  25. package/dist/core/common/helpers/gridfs.helper.js.map +1 -1
  26. package/dist/core/common/helpers/id.helper.d.ts +4 -1
  27. package/dist/core/common/helpers/id.helper.js +10 -4
  28. package/dist/core/common/helpers/id.helper.js.map +1 -1
  29. package/dist/core/common/helpers/model.helper.js +5 -5
  30. package/dist/core/common/helpers/model.helper.js.map +1 -1
  31. package/dist/core/common/helpers/service.helper.js +3 -3
  32. package/dist/core/common/helpers/service.helper.js.map +1 -1
  33. package/dist/core/common/interfaces/server-options.interface.d.ts +18 -2
  34. package/dist/core/common/interfaces/service-options.interface.d.ts +2 -2
  35. package/dist/core/common/models/core-persistence.model.d.ts +1 -2
  36. package/dist/core/common/models/core-persistence.model.js +3 -3
  37. package/dist/core/common/models/core-persistence.model.js.map +1 -1
  38. package/dist/core/common/persistence/core-persistence.lifecycle.d.ts +9 -0
  39. package/dist/core/common/persistence/core-persistence.lifecycle.js +38 -0
  40. package/dist/core/common/persistence/core-persistence.lifecycle.js.map +1 -0
  41. package/dist/core/common/persistence/core-persistence.module.d.ts +9 -0
  42. package/dist/core/common/persistence/core-persistence.module.js +76 -0
  43. package/dist/core/common/persistence/core-persistence.module.js.map +1 -0
  44. package/dist/core/common/persistence/data-source.config.d.ts +33 -0
  45. package/dist/core/common/persistence/data-source.config.js +151 -0
  46. package/dist/core/common/persistence/data-source.config.js.map +1 -0
  47. package/dist/core/common/persistence/data-source.runtime.d.ts +45 -0
  48. package/dist/core/common/persistence/data-source.runtime.js +278 -0
  49. package/dist/core/common/persistence/data-source.runtime.js.map +1 -0
  50. package/dist/core/common/persistence/data-store.interface.d.ts +73 -0
  51. package/dist/core/common/persistence/data-store.interface.js +2 -0
  52. package/dist/core/common/persistence/data-store.interface.js.map +1 -0
  53. package/dist/core/common/persistence/expiry-sweep.d.ts +12 -0
  54. package/dist/core/common/persistence/expiry-sweep.js +55 -0
  55. package/dist/core/common/persistence/expiry-sweep.js.map +1 -0
  56. package/dist/core/common/persistence/id-format.d.ts +3 -0
  57. package/dist/core/common/persistence/id-format.js +21 -0
  58. package/dist/core/common/persistence/id-format.js.map +1 -0
  59. package/dist/core/common/persistence/infrastructure-locks.d.ts +13 -0
  60. package/dist/core/common/persistence/infrastructure-locks.js +35 -0
  61. package/dist/core/common/persistence/infrastructure-locks.js.map +1 -0
  62. package/dist/core/common/persistence/inject-store.decorator.d.ts +1 -0
  63. package/dist/core/common/persistence/inject-store.decorator.js +6 -0
  64. package/dist/core/common/persistence/inject-store.decorator.js.map +1 -0
  65. package/dist/core/common/persistence/lock-store.interface.d.ts +5 -0
  66. package/dist/core/common/persistence/lock-store.interface.js +2 -0
  67. package/dist/core/common/persistence/lock-store.interface.js.map +1 -0
  68. package/dist/core/common/persistence/model-descriptor.interface.d.ts +36 -0
  69. package/dist/core/common/persistence/model-descriptor.interface.js +2 -0
  70. package/dist/core/common/persistence/model-descriptor.interface.js.map +1 -0
  71. package/dist/core/common/persistence/model-metadata.registry.d.ts +14 -0
  72. package/dist/core/common/persistence/model-metadata.registry.js +194 -0
  73. package/dist/core/common/persistence/model-metadata.registry.js.map +1 -0
  74. package/dist/core/common/persistence/mongo/collection-name.d.ts +2 -0
  75. package/dist/core/common/persistence/mongo/collection-name.js +73 -0
  76. package/dist/core/common/persistence/mongo/collection-name.js.map +1 -0
  77. package/dist/core/common/persistence/mongo/declared-schema.view.d.ts +11 -0
  78. package/dist/core/common/persistence/mongo/declared-schema.view.js +292 -0
  79. package/dist/core/common/persistence/mongo/declared-schema.view.js.map +1 -0
  80. package/dist/core/common/persistence/mongo/hex-object-id.d.ts +13 -0
  81. package/dist/core/common/persistence/mongo/hex-object-id.js +54 -0
  82. package/dist/core/common/persistence/mongo/hex-object-id.js.map +1 -0
  83. package/dist/core/common/persistence/mongo/model-declarations.d.ts +35 -0
  84. package/dist/core/common/persistence/mongo/model-declarations.js +80 -0
  85. package/dist/core/common/persistence/mongo/model-declarations.js.map +1 -0
  86. package/dist/core/common/persistence/mongo/mongo-packages.d.ts +15 -0
  87. package/dist/core/common/persistence/mongo/mongo-packages.js +66 -0
  88. package/dist/core/common/persistence/mongo/mongo-packages.js.map +1 -0
  89. package/dist/core/common/persistence/mongo/mongoose-compat.d.ts +22 -0
  90. package/dist/core/common/persistence/mongo/mongoose-compat.js +65 -0
  91. package/dist/core/common/persistence/mongo/mongoose-compat.js.map +1 -0
  92. package/dist/core/common/persistence/mongo/no-mongo-connection.module.d.ts +2 -0
  93. package/dist/core/common/persistence/mongo/no-mongo-connection.module.js +19 -0
  94. package/dist/core/common/persistence/mongo/no-mongo-connection.module.js.map +1 -0
  95. package/dist/core/common/persistence/mongo-lock-store.d.ts +21 -0
  96. package/dist/core/common/persistence/mongo-lock-store.js +72 -0
  97. package/dist/core/common/persistence/mongo-lock-store.js.map +1 -0
  98. package/dist/core/common/persistence/mongoose-data-store.d.ts +33 -0
  99. package/dist/core/common/persistence/mongoose-data-store.js +187 -0
  100. package/dist/core/common/persistence/mongoose-data-store.js.map +1 -0
  101. package/dist/core/common/persistence/neutral-populate.d.ts +6 -0
  102. package/dist/core/common/persistence/neutral-populate.js +72 -0
  103. package/dist/core/common/persistence/neutral-populate.js.map +1 -0
  104. package/dist/core/common/persistence/persisted-model.decorator.d.ts +6 -0
  105. package/dist/core/common/persistence/persisted-model.decorator.js +24 -0
  106. package/dist/core/common/persistence/persisted-model.decorator.js.map +1 -0
  107. package/dist/core/common/persistence/persistence-runtime.registry.d.ts +61 -0
  108. package/dist/core/common/persistence/persistence-runtime.registry.js +47 -0
  109. package/dist/core/common/persistence/persistence-runtime.registry.js.map +1 -0
  110. package/dist/core/common/persistence/persistence.tokens.d.ts +1 -0
  111. package/dist/core/common/persistence/persistence.tokens.js +4 -0
  112. package/dist/core/common/persistence/persistence.tokens.js.map +1 -0
  113. package/dist/core/common/persistence/policies/audit.policy.d.ts +8 -0
  114. package/dist/core/common/persistence/policies/audit.policy.js +37 -0
  115. package/dist/core/common/persistence/policies/audit.policy.js.map +1 -0
  116. package/dist/core/common/persistence/policies/password.policy.d.ts +3 -0
  117. package/dist/core/common/persistence/policies/password.policy.js +46 -0
  118. package/dist/core/common/persistence/policies/password.policy.js.map +1 -0
  119. package/dist/core/common/persistence/policies/role-guard.policy.d.ts +3 -0
  120. package/dist/core/common/persistence/policies/role-guard.policy.js +46 -0
  121. package/dist/core/common/persistence/policies/role-guard.policy.js.map +1 -0
  122. package/dist/core/common/persistence/policies/system-role.policy.d.ts +5 -0
  123. package/dist/core/common/persistence/policies/system-role.policy.js +46 -0
  124. package/dist/core/common/persistence/policies/system-role.policy.js.map +1 -0
  125. package/dist/core/common/persistence/policies/tenant.policy.d.ts +19 -0
  126. package/dist/core/common/persistence/policies/tenant.policy.js +120 -0
  127. package/dist/core/common/persistence/policies/tenant.policy.js.map +1 -0
  128. package/dist/core/common/persistence/routed-model.guard.d.ts +4 -0
  129. package/dist/core/common/persistence/routed-model.guard.js +73 -0
  130. package/dist/core/common/persistence/routed-model.guard.js.map +1 -0
  131. package/dist/core/common/persistence/sql/mysql/mysql-data-store.d.ts +46 -0
  132. package/dist/core/common/persistence/sql/mysql/mysql-data-store.js +350 -0
  133. package/dist/core/common/persistence/sql/mysql/mysql-data-store.js.map +1 -0
  134. package/dist/core/common/persistence/sql/mysql/mysql-executor.d.ts +13 -0
  135. package/dist/core/common/persistence/sql/mysql/mysql-executor.js +194 -0
  136. package/dist/core/common/persistence/sql/mysql/mysql-executor.js.map +1 -0
  137. package/dist/core/common/persistence/sql/mysql/mysql-lock-store.d.ts +11 -0
  138. package/dist/core/common/persistence/sql/mysql/mysql-lock-store.js +55 -0
  139. package/dist/core/common/persistence/sql/mysql/mysql-lock-store.js.map +1 -0
  140. package/dist/core/common/persistence/sql/mysql/mysql-schema.compiler.d.ts +36 -0
  141. package/dist/core/common/persistence/sql/mysql/mysql-schema.compiler.js +288 -0
  142. package/dist/core/common/persistence/sql/mysql/mysql-schema.compiler.js.map +1 -0
  143. package/dist/core/common/persistence/sql/mysql/mysql-schema.migrator.d.ts +19 -0
  144. package/dist/core/common/persistence/sql/mysql/mysql-schema.migrator.js +328 -0
  145. package/dist/core/common/persistence/sql/mysql/mysql-schema.migrator.js.map +1 -0
  146. package/dist/core/common/persistence/sql/mysql/mysql-session.d.ts +13 -0
  147. package/dist/core/common/persistence/sql/mysql/mysql-session.js +85 -0
  148. package/dist/core/common/persistence/sql/mysql/mysql-session.js.map +1 -0
  149. package/dist/core/common/persistence/sql/mysql/mysql-update.compiler.d.ts +9 -0
  150. package/dist/core/common/persistence/sql/mysql/mysql-update.compiler.js +264 -0
  151. package/dist/core/common/persistence/sql/mysql/mysql-update.compiler.js.map +1 -0
  152. package/dist/core/common/persistence/sql/mysql/mysql-where.compiler.d.ts +20 -0
  153. package/dist/core/common/persistence/sql/mysql/mysql-where.compiler.js +519 -0
  154. package/dist/core/common/persistence/sql/mysql/mysql-where.compiler.js.map +1 -0
  155. package/dist/core/common/persistence/sql/postgres/postgres-lock-store.d.ts +11 -0
  156. package/dist/core/common/persistence/sql/postgres/postgres-lock-store.js +44 -0
  157. package/dist/core/common/persistence/sql/postgres/postgres-lock-store.js.map +1 -0
  158. package/dist/core/common/persistence/sql/postgres/postgres-schema.compiler.d.ts +42 -0
  159. package/dist/core/common/persistence/sql/postgres/postgres-schema.compiler.js +220 -0
  160. package/dist/core/common/persistence/sql/postgres/postgres-schema.compiler.js.map +1 -0
  161. package/dist/core/common/persistence/sql/postgres/postgres-schema.migrator.d.ts +12 -0
  162. package/dist/core/common/persistence/sql/postgres/postgres-schema.migrator.js +315 -0
  163. package/dist/core/common/persistence/sql/postgres/postgres-schema.migrator.js.map +1 -0
  164. package/dist/core/common/persistence/sql/postgres/postgres-update.compiler.d.ts +5 -0
  165. package/dist/core/common/persistence/sql/postgres/postgres-update.compiler.js +225 -0
  166. package/dist/core/common/persistence/sql/postgres/postgres-update.compiler.js.map +1 -0
  167. package/dist/core/common/persistence/sql/postgres/postgres-where.compiler.d.ts +13 -0
  168. package/dist/core/common/persistence/sql/postgres/postgres-where.compiler.js +484 -0
  169. package/dist/core/common/persistence/sql/postgres/postgres-where.compiler.js.map +1 -0
  170. package/dist/core/common/persistence/sql/sql-cast.d.ts +2 -0
  171. package/dist/core/common/persistence/sql/sql-cast.js +194 -0
  172. package/dist/core/common/persistence/sql/sql-cast.js.map +1 -0
  173. package/dist/core/common/persistence/sql/sql-data-store.d.ts +79 -0
  174. package/dist/core/common/persistence/sql/sql-data-store.js +592 -0
  175. package/dist/core/common/persistence/sql/sql-data-store.js.map +1 -0
  176. package/dist/core/common/persistence/sql/sql-dialect.d.ts +20 -0
  177. package/dist/core/common/persistence/sql/sql-dialect.js +38 -0
  178. package/dist/core/common/persistence/sql/sql-dialect.js.map +1 -0
  179. package/dist/core/common/persistence/sql/sql-errors.d.ts +17 -0
  180. package/dist/core/common/persistence/sql/sql-errors.js +25 -0
  181. package/dist/core/common/persistence/sql/sql-errors.js.map +1 -0
  182. package/dist/core/common/persistence/sql/sql-executor.factory.d.ts +11 -0
  183. package/dist/core/common/persistence/sql/sql-executor.factory.js +199 -0
  184. package/dist/core/common/persistence/sql/sql-executor.factory.js.map +1 -0
  185. package/dist/core/common/persistence/sql/sql-executor.interface.d.ts +32 -0
  186. package/dist/core/common/persistence/sql/sql-executor.interface.js +2 -0
  187. package/dist/core/common/persistence/sql/sql-executor.interface.js.map +1 -0
  188. package/dist/core/common/persistence/sql/sql-naming.d.ts +15 -0
  189. package/dist/core/common/persistence/sql/sql-naming.js +90 -0
  190. package/dist/core/common/persistence/sql/sql-naming.js.map +1 -0
  191. package/dist/core/common/persistence/sql/sql-schema.shared.d.ts +25 -0
  192. package/dist/core/common/persistence/sql/sql-schema.shared.js +69 -0
  193. package/dist/core/common/persistence/sql/sql-schema.shared.js.map +1 -0
  194. package/dist/core/common/persistence/sql/sql-session.d.ts +6 -0
  195. package/dist/core/common/persistence/sql/sql-session.js +78 -0
  196. package/dist/core/common/persistence/sql/sql-session.js.map +1 -0
  197. package/dist/core/common/persistence/sql/where-shared.d.ts +18 -0
  198. package/dist/core/common/persistence/sql/where-shared.js +93 -0
  199. package/dist/core/common/persistence/sql/where-shared.js.map +1 -0
  200. package/dist/core/common/persistence/store-guards.d.ts +10 -0
  201. package/dist/core/common/persistence/store-guards.js +49 -0
  202. package/dist/core/common/persistence/store-guards.js.map +1 -0
  203. package/dist/core/common/persistence/store-upsert.d.ts +2 -0
  204. package/dist/core/common/persistence/store-upsert.js +20 -0
  205. package/dist/core/common/persistence/store-upsert.js.map +1 -0
  206. package/dist/core/common/persistence/unavailable-store.d.ts +2 -0
  207. package/dist/core/common/persistence/unavailable-store.js +53 -0
  208. package/dist/core/common/persistence/unavailable-store.js.map +1 -0
  209. package/dist/core/common/persistence/unsupported-capability.error.d.ts +3 -0
  210. package/dist/core/common/persistence/unsupported-capability.error.js +4 -0
  211. package/dist/core/common/persistence/unsupported-capability.error.js.map +1 -0
  212. package/dist/core/common/plugins/mongoose-audit-fields.plugin.js +24 -68
  213. package/dist/core/common/plugins/mongoose-audit-fields.plugin.js.map +1 -1
  214. package/dist/core/common/plugins/mongoose-id.plugin.js +3 -0
  215. package/dist/core/common/plugins/mongoose-id.plugin.js.map +1 -1
  216. package/dist/core/common/plugins/mongoose-password.plugin.d.ts +1 -3
  217. package/dist/core/common/plugins/mongoose-password.plugin.js +2 -45
  218. package/dist/core/common/plugins/mongoose-password.plugin.js.map +1 -1
  219. package/dist/core/common/plugins/mongoose-role-guard.plugin.js +5 -46
  220. package/dist/core/common/plugins/mongoose-role-guard.plugin.js.map +1 -1
  221. package/dist/core/common/plugins/mongoose-system-role.plugin.js +2 -43
  222. package/dist/core/common/plugins/mongoose-system-role.plugin.js.map +1 -1
  223. package/dist/core/common/plugins/mongoose-tenant.plugin.js +10 -70
  224. package/dist/core/common/plugins/mongoose-tenant.plugin.js.map +1 -1
  225. package/dist/core/common/scalars/upload.scalar.js +1 -1
  226. package/dist/core/common/scalars/upload.scalar.js.map +1 -1
  227. package/dist/core/common/services/core-cron-jobs.initializer.js +1 -1
  228. package/dist/core/common/services/core-cron-jobs.initializer.js.map +1 -1
  229. package/dist/core/common/services/core-cron-jobs.service.d.ts +1 -0
  230. package/dist/core/common/services/core-cron-jobs.service.js +23 -14
  231. package/dist/core/common/services/core-cron-jobs.service.js.map +1 -1
  232. package/dist/core/common/services/crud.service.d.ts +4 -1
  233. package/dist/core/common/services/crud.service.js +132 -23
  234. package/dist/core/common/services/crud.service.js.map +1 -1
  235. package/dist/core/common/services/model-doc.service.js +1 -1
  236. package/dist/core/common/services/model-doc.service.js.map +1 -1
  237. package/dist/core/common/services/module.service.d.ts +9 -2
  238. package/dist/core/common/services/module.service.js +51 -6
  239. package/dist/core/common/services/module.service.js.map +1 -1
  240. package/dist/core/common/types/field-selection.type.d.ts +1 -1
  241. package/dist/core/common/types/id.type.d.ts +4 -4
  242. package/dist/core/common/types/object-id-like.type.d.ts +3 -0
  243. package/dist/core/common/types/object-id-like.type.js +2 -0
  244. package/dist/core/common/types/object-id-like.type.js.map +1 -0
  245. package/dist/core/common/types/populate-config.type.d.ts +1 -1
  246. package/dist/core/common/types/string-or-object-id.type.d.ts +2 -2
  247. package/dist/core/modules/ai/core-ai.constants.d.ts +4 -0
  248. package/dist/core/modules/ai/core-ai.constants.js +4 -0
  249. package/dist/core/modules/ai/core-ai.constants.js.map +1 -1
  250. package/dist/core/modules/ai/core-ai.module.js +21 -17
  251. package/dist/core/modules/ai/core-ai.module.js.map +1 -1
  252. package/dist/core/modules/ai/models/core-ai-budget-limit.model.d.ts +2 -92
  253. package/dist/core/modules/ai/models/core-ai-budget-limit.model.js +1 -1
  254. package/dist/core/modules/ai/models/core-ai-budget-limit.model.js.map +1 -1
  255. package/dist/core/modules/ai/models/core-ai-connection-preference.model.d.ts +2 -87
  256. package/dist/core/modules/ai/models/core-ai-connection-preference.model.js +1 -1
  257. package/dist/core/modules/ai/models/core-ai-connection-preference.model.js.map +1 -1
  258. package/dist/core/modules/ai/models/core-ai-connection.model.d.ts +2 -177
  259. package/dist/core/modules/ai/models/core-ai-connection.model.js +1 -1
  260. package/dist/core/modules/ai/models/core-ai-connection.model.js.map +1 -1
  261. package/dist/core/modules/ai/models/core-ai-conversation.model.d.ts +2 -92
  262. package/dist/core/modules/ai/models/core-ai-conversation.model.js +3 -4
  263. package/dist/core/modules/ai/models/core-ai-conversation.model.js.map +1 -1
  264. package/dist/core/modules/ai/models/core-ai-interaction.model.d.ts +2 -120
  265. package/dist/core/modules/ai/models/core-ai-interaction.model.js +2 -3
  266. package/dist/core/modules/ai/models/core-ai-interaction.model.js.map +1 -1
  267. package/dist/core/modules/ai/models/core-ai-mcp-oauth.models.d.ts +3 -0
  268. package/dist/core/modules/ai/models/core-ai-mcp-oauth.models.js +21 -0
  269. package/dist/core/modules/ai/models/core-ai-mcp-oauth.models.js.map +1 -0
  270. package/dist/core/modules/ai/models/core-ai-mode.model.d.ts +2 -102
  271. package/dist/core/modules/ai/models/core-ai-mode.model.js +1 -1
  272. package/dist/core/modules/ai/models/core-ai-mode.model.js.map +1 -1
  273. package/dist/core/modules/ai/models/core-ai-prompt-hint.model.d.ts +2 -97
  274. package/dist/core/modules/ai/models/core-ai-prompt-hint.model.js +1 -1
  275. package/dist/core/modules/ai/models/core-ai-prompt-hint.model.js.map +1 -1
  276. package/dist/core/modules/ai/models/core-ai-prompt.model.d.ts +2 -112
  277. package/dist/core/modules/ai/models/core-ai-prompt.model.js +1 -1
  278. package/dist/core/modules/ai/models/core-ai-prompt.model.js.map +1 -1
  279. package/dist/core/modules/ai/models/core-ai-slot.model.d.ts +2 -112
  280. package/dist/core/modules/ai/models/core-ai-slot.model.js +1 -1
  281. package/dist/core/modules/ai/models/core-ai-slot.model.js.map +1 -1
  282. package/dist/core/modules/ai/models/core-ai-tool-grant.model.d.ts +2 -97
  283. package/dist/core/modules/ai/models/core-ai-tool-grant.model.js +1 -1
  284. package/dist/core/modules/ai/models/core-ai-tool-grant.model.js.map +1 -1
  285. package/dist/core/modules/ai/models/core-ai-tool-policy.model.d.ts +2 -103
  286. package/dist/core/modules/ai/models/core-ai-tool-policy.model.js +1 -1
  287. package/dist/core/modules/ai/models/core-ai-tool-policy.model.js.map +1 -1
  288. package/dist/core/modules/ai/services/core-ai-budget.service.d.ts +3 -1
  289. package/dist/core/modules/ai/services/core-ai-budget.service.js +15 -5
  290. package/dist/core/modules/ai/services/core-ai-budget.service.js.map +1 -1
  291. package/dist/core/modules/ai/services/core-ai-connection-preference.service.d.ts +1 -1
  292. package/dist/core/modules/ai/services/core-ai-connection-preference.service.js +6 -10
  293. package/dist/core/modules/ai/services/core-ai-connection-preference.service.js.map +1 -1
  294. package/dist/core/modules/ai/services/core-ai-connection.service.d.ts +1 -1
  295. package/dist/core/modules/ai/services/core-ai-connection.service.js +20 -42
  296. package/dist/core/modules/ai/services/core-ai-connection.service.js.map +1 -1
  297. package/dist/core/modules/ai/services/core-ai-conversation.service.d.ts +1 -1
  298. package/dist/core/modules/ai/services/core-ai-conversation.service.js +28 -29
  299. package/dist/core/modules/ai/services/core-ai-conversation.service.js.map +1 -1
  300. package/dist/core/modules/ai/services/core-ai-interaction.service.d.ts +1 -1
  301. package/dist/core/modules/ai/services/core-ai-interaction.service.js +3 -4
  302. package/dist/core/modules/ai/services/core-ai-interaction.service.js.map +1 -1
  303. package/dist/core/modules/ai/services/core-ai-mcp-oauth.service.d.ts +8 -0
  304. package/dist/core/modules/ai/services/core-ai-mcp-oauth.service.js +70 -18
  305. package/dist/core/modules/ai/services/core-ai-mcp-oauth.service.js.map +1 -1
  306. package/dist/core/modules/ai/services/core-ai-mode.service.d.ts +1 -1
  307. package/dist/core/modules/ai/services/core-ai-mode.service.js +3 -7
  308. package/dist/core/modules/ai/services/core-ai-mode.service.js.map +1 -1
  309. package/dist/core/modules/ai/services/core-ai-prompt-hint.service.d.ts +8 -1
  310. package/dist/core/modules/ai/services/core-ai-prompt-hint.service.js +32 -26
  311. package/dist/core/modules/ai/services/core-ai-prompt-hint.service.js.map +1 -1
  312. package/dist/core/modules/ai/services/core-ai-prompt.service.d.ts +1 -1
  313. package/dist/core/modules/ai/services/core-ai-prompt.service.js +10 -13
  314. package/dist/core/modules/ai/services/core-ai-prompt.service.js.map +1 -1
  315. package/dist/core/modules/ai/services/core-ai-slot.service.d.ts +1 -1
  316. package/dist/core/modules/ai/services/core-ai-slot.service.js +14 -25
  317. package/dist/core/modules/ai/services/core-ai-slot.service.js.map +1 -1
  318. package/dist/core/modules/ai/services/core-ai-tool-grant.service.d.ts +1 -1
  319. package/dist/core/modules/ai/services/core-ai-tool-grant.service.js +6 -18
  320. package/dist/core/modules/ai/services/core-ai-tool-grant.service.js.map +1 -1
  321. package/dist/core/modules/ai/services/core-ai-tool-policy.service.d.ts +1 -1
  322. package/dist/core/modules/ai/services/core-ai-tool-policy.service.js +4 -8
  323. package/dist/core/modules/ai/services/core-ai-tool-policy.service.js.map +1 -1
  324. package/dist/core/modules/api-token/core-api-token.model.js +1 -1
  325. package/dist/core/modules/api-token/core-api-token.model.js.map +1 -1
  326. package/dist/core/modules/api-token/core-api-token.module.js +3 -2
  327. package/dist/core/modules/api-token/core-api-token.module.js.map +1 -1
  328. package/dist/core/modules/api-token/core-api-token.service.d.ts +8 -2
  329. package/dist/core/modules/api-token/core-api-token.service.js +106 -39
  330. package/dist/core/modules/api-token/core-api-token.service.js.map +1 -1
  331. package/dist/core/modules/auth/core-auth.module.js +2 -0
  332. package/dist/core/modules/auth/core-auth.module.js.map +1 -1
  333. package/dist/core/modules/auth/guards/legacy-auth-rate-limit.guard.js +1 -2
  334. package/dist/core/modules/auth/guards/legacy-auth-rate-limit.guard.js.map +1 -1
  335. package/dist/core/modules/auth/guards/role-guard.token.d.ts +1 -0
  336. package/dist/core/modules/auth/guards/role-guard.token.js +2 -0
  337. package/dist/core/modules/auth/guards/role-guard.token.js.map +1 -0
  338. package/dist/core/modules/auth/services/core-auth.service.js +4 -2
  339. package/dist/core/modules/auth/services/core-auth.service.js.map +1 -1
  340. package/dist/core/modules/better-auth/better-auth-sql.helper.d.ts +6 -0
  341. package/dist/core/modules/better-auth/better-auth-sql.helper.js +113 -0
  342. package/dist/core/modules/better-auth/better-auth-sql.helper.js.map +1 -0
  343. package/dist/core/modules/better-auth/better-auth-token.service.d.ts +3 -1
  344. package/dist/core/modules/better-auth/better-auth-token.service.js +15 -24
  345. package/dist/core/modules/better-auth/better-auth-token.service.js.map +1 -1
  346. package/dist/core/modules/better-auth/better-auth.config.d.ts +7 -0
  347. package/dist/core/modules/better-auth/better-auth.config.js +16 -5
  348. package/dist/core/modules/better-auth/better-auth.config.js.map +1 -1
  349. package/dist/core/modules/better-auth/better-auth.types.d.ts +1 -1
  350. package/dist/core/modules/better-auth/core-better-auth-api.middleware.d.ts +1 -0
  351. package/dist/core/modules/better-auth/core-better-auth-api.middleware.js +6 -1
  352. package/dist/core/modules/better-auth/core-better-auth-api.middleware.js.map +1 -1
  353. package/dist/core/modules/better-auth/core-better-auth-challenge.service.js +30 -15
  354. package/dist/core/modules/better-auth/core-better-auth-challenge.service.js.map +1 -1
  355. package/dist/core/modules/better-auth/core-better-auth-mongo.users.d.ts +10 -0
  356. package/dist/core/modules/better-auth/core-better-auth-mongo.users.js +24 -0
  357. package/dist/core/modules/better-auth/core-better-auth-mongo.users.js.map +1 -0
  358. package/dist/core/modules/better-auth/core-better-auth-sql.registry.d.ts +3 -0
  359. package/dist/core/modules/better-auth/core-better-auth-sql.registry.js +8 -0
  360. package/dist/core/modules/better-auth/core-better-auth-sql.registry.js.map +1 -0
  361. package/dist/core/modules/better-auth/core-better-auth-sql.store.d.ts +71 -0
  362. package/dist/core/modules/better-auth/core-better-auth-sql.store.js +190 -0
  363. package/dist/core/modules/better-auth/core-better-auth-sql.store.js.map +1 -0
  364. package/dist/core/modules/better-auth/core-better-auth-user.mapper.d.ts +24 -1
  365. package/dist/core/modules/better-auth/core-better-auth-user.mapper.js +308 -32
  366. package/dist/core/modules/better-auth/core-better-auth-user.mapper.js.map +1 -1
  367. package/dist/core/modules/better-auth/core-better-auth.module.d.ts +2 -0
  368. package/dist/core/modules/better-auth/core-better-auth.module.js +54 -32
  369. package/dist/core/modules/better-auth/core-better-auth.module.js.map +1 -1
  370. package/dist/core/modules/better-auth/core-better-auth.service.d.ts +7 -2
  371. package/dist/core/modules/better-auth/core-better-auth.service.js +61 -9
  372. package/dist/core/modules/better-auth/core-better-auth.service.js.map +1 -1
  373. package/dist/core/modules/file/core-file-info.model.d.ts +1 -2
  374. package/dist/core/modules/file/core-file-info.model.js +2 -2
  375. package/dist/core/modules/file/core-file-info.model.js.map +1 -1
  376. package/dist/core/modules/file/core-file.service.d.ts +5 -3
  377. package/dist/core/modules/file/core-file.service.js +16 -9
  378. package/dist/core/modules/file/core-file.service.js.map +1 -1
  379. package/dist/core/modules/file/file-metadata.helper.d.ts +1 -1
  380. package/dist/core/modules/file/file-metadata.helper.js +2 -2
  381. package/dist/core/modules/file/file-metadata.helper.js.map +1 -1
  382. package/dist/core/modules/file/file-metadata.models.d.ts +35 -0
  383. package/dist/core/modules/file/file-metadata.models.js +20 -0
  384. package/dist/core/modules/file/file-metadata.models.js.map +1 -0
  385. package/dist/core/modules/file/file-metadata.store.d.ts +6 -0
  386. package/dist/core/modules/file/file-metadata.store.js +77 -0
  387. package/dist/core/modules/file/file-metadata.store.js.map +1 -0
  388. package/dist/core/modules/file/file-storage.helper.d.ts +1 -0
  389. package/dist/core/modules/file/file-storage.helper.js +34 -0
  390. package/dist/core/modules/file/file-storage.helper.js.map +1 -1
  391. package/dist/core/modules/file/filesystem-file.helper.d.ts +1 -1
  392. package/dist/core/modules/file/filesystem-file.helper.js +4 -4
  393. package/dist/core/modules/file/filesystem-file.helper.js.map +1 -1
  394. package/dist/core/modules/file/s3-file.helper.d.ts +1 -1
  395. package/dist/core/modules/file/s3-file.helper.js +5 -5
  396. package/dist/core/modules/file/s3-file.helper.js.map +1 -1
  397. package/dist/core/modules/health-check/core-health-check.module.js +12 -2
  398. package/dist/core/modules/health-check/core-health-check.module.js.map +1 -1
  399. package/dist/core/modules/health-check/core-health-check.service.d.ts +4 -3
  400. package/dist/core/modules/health-check/core-health-check.service.js +26 -5
  401. package/dist/core/modules/health-check/core-health-check.service.js.map +1 -1
  402. package/dist/core/modules/hub/core-hub.controller.d.ts +1 -0
  403. package/dist/core/modules/hub/core-hub.controller.js +10 -0
  404. package/dist/core/modules/hub/core-hub.controller.js.map +1 -1
  405. package/dist/core/modules/hub/core-hub.service.js +1 -1
  406. package/dist/core/modules/hub/core-hub.service.js.map +1 -1
  407. package/dist/core/modules/hub/helpers/hub-client-js.helper.js +23 -0
  408. package/dist/core/modules/hub/helpers/hub-client-js.helper.js.map +1 -1
  409. package/dist/core/modules/hub/hub-action-messages.d.ts +2 -0
  410. package/dist/core/modules/hub/hub-action-messages.js +2 -0
  411. package/dist/core/modules/hub/hub-action-messages.js.map +1 -1
  412. package/dist/core/modules/hub/hub-nav.js +1 -0
  413. package/dist/core/modules/hub/hub-nav.js.map +1 -1
  414. package/dist/core/modules/hub/interfaces/hub-panels.interface.d.ts +17 -1
  415. package/dist/core/modules/hub/services/core-hub-db.service.d.ts +6 -1
  416. package/dist/core/modules/hub/services/core-hub-db.service.js +16 -14
  417. package/dist/core/modules/hub/services/core-hub-db.service.js.map +1 -1
  418. package/dist/core/modules/hub/services/core-hub-migrations.service.d.ts +5 -0
  419. package/dist/core/modules/hub/services/core-hub-migrations.service.js +74 -1
  420. package/dist/core/modules/hub/services/core-hub-migrations.service.js.map +1 -1
  421. package/dist/core/modules/hub/services/core-hub-sources.service.d.ts +2 -1
  422. package/dist/core/modules/hub/services/core-hub-sources.service.js +32 -0
  423. package/dist/core/modules/hub/services/core-hub-sources.service.js.map +1 -1
  424. package/dist/core/modules/hub/services/hub-query-profiler.service.js +1 -1
  425. package/dist/core/modules/hub/services/hub-query-profiler.service.js.map +1 -1
  426. package/dist/core/modules/migrate/cli/migrate-cli.d.ts +2 -0
  427. package/dist/core/modules/migrate/cli/migrate-cli.js +35 -1
  428. package/dist/core/modules/migrate/cli/migrate-cli.js.map +1 -1
  429. package/dist/core/modules/migrate/index.d.ts +3 -0
  430. package/dist/core/modules/migrate/index.js +3 -0
  431. package/dist/core/modules/migrate/index.js.map +1 -1
  432. package/dist/core/modules/migrate/migration-runner.d.ts +2 -2
  433. package/dist/core/modules/migrate/migration-runner.js.map +1 -1
  434. package/dist/core/modules/migrate/migration-state-store.interface.d.ts +16 -0
  435. package/dist/core/modules/migrate/migration-state-store.interface.js +2 -0
  436. package/dist/core/modules/migrate/migration-state-store.interface.js.map +1 -0
  437. package/dist/core/modules/migrate/migration.helper.d.ts +3 -2
  438. package/dist/core/modules/migrate/migration.helper.js +21 -6
  439. package/dist/core/modules/migrate/migration.helper.js.map +1 -1
  440. package/dist/core/modules/migrate/mongo-state-store.d.ts +5 -12
  441. package/dist/core/modules/migrate/mongo-state-store.js +30 -24
  442. package/dist/core/modules/migrate/mongo-state-store.js.map +1 -1
  443. package/dist/core/modules/migrate/sql-migration.helper.d.ts +4 -0
  444. package/dist/core/modules/migrate/sql-migration.helper.js +34 -0
  445. package/dist/core/modules/migrate/sql-migration.helper.js.map +1 -0
  446. package/dist/core/modules/migrate/sql-state-store.d.ts +24 -0
  447. package/dist/core/modules/migrate/sql-state-store.js +129 -0
  448. package/dist/core/modules/migrate/sql-state-store.js.map +1 -0
  449. package/dist/core/modules/system-setup/core-system-setup.service.d.ts +8 -0
  450. package/dist/core/modules/system-setup/core-system-setup.service.js +41 -25
  451. package/dist/core/modules/system-setup/core-system-setup.service.js.map +1 -1
  452. package/dist/core/modules/tenant/core-tenant-member.model.js +1 -1
  453. package/dist/core/modules/tenant/core-tenant-member.model.js.map +1 -1
  454. package/dist/core/modules/tenant/core-tenant-member.store.d.ts +2 -0
  455. package/dist/core/modules/tenant/core-tenant-member.store.js +6 -0
  456. package/dist/core/modules/tenant/core-tenant-member.store.js.map +1 -0
  457. package/dist/core/modules/tenant/core-tenant.guard.d.ts +8 -3
  458. package/dist/core/modules/tenant/core-tenant.guard.js +57 -28
  459. package/dist/core/modules/tenant/core-tenant.guard.js.map +1 -1
  460. package/dist/core/modules/tenant/core-tenant.module.js +3 -2
  461. package/dist/core/modules/tenant/core-tenant.module.js.map +1 -1
  462. package/dist/core/modules/tenant/core-tenant.service.d.ts +3 -1
  463. package/dist/core/modules/tenant/core-tenant.service.js +48 -28
  464. package/dist/core/modules/tenant/core-tenant.service.js.map +1 -1
  465. package/dist/core/modules/tus/core-tus.service.d.ts +1 -1
  466. package/dist/core/modules/tus/core-tus.service.js +8 -7
  467. package/dist/core/modules/tus/core-tus.service.js.map +1 -1
  468. package/dist/core/modules/tus/tus.module.js +1 -1
  469. package/dist/core/modules/tus/tus.module.js.map +1 -1
  470. package/dist/core/modules/user/core-user.model.d.ts +1 -1
  471. package/dist/core/modules/user/core-user.model.js +1 -1
  472. package/dist/core/modules/user/core-user.model.js.map +1 -1
  473. package/dist/core/modules/user/core-user.service.d.ts +3 -1
  474. package/dist/core/modules/user/core-user.service.js +71 -16
  475. package/dist/core/modules/user/core-user.service.js.map +1 -1
  476. package/dist/core.module.js +39 -5
  477. package/dist/core.module.js.map +1 -1
  478. package/dist/index.d.ts +26 -0
  479. package/dist/index.js +26 -0
  480. package/dist/index.js.map +1 -1
  481. package/dist/server/common/models/persistence.model.d.ts +1 -1
  482. package/dist/server/common/models/persistence.model.js +3 -3
  483. package/dist/server/common/models/persistence.model.js.map +1 -1
  484. package/dist/server/modules/file/file-info.model.d.ts +1 -77
  485. package/dist/server/modules/file/file-info.model.js +1 -1
  486. package/dist/server/modules/file/file-info.model.js.map +1 -1
  487. package/dist/server/modules/file/file.service.js +1 -1
  488. package/dist/server/modules/file/file.service.js.map +1 -1
  489. package/dist/server/modules/user/user.model.d.ts +2 -186
  490. package/dist/server/modules/user/user.model.js +4 -5
  491. package/dist/server/modules/user/user.model.js.map +1 -1
  492. package/dist/server/modules/user/user.module.js +4 -3
  493. package/dist/server/modules/user/user.module.js.map +1 -1
  494. package/dist/server/modules/user/user.service.d.ts +1 -1
  495. package/dist/server/modules/user/user.service.js +5 -8
  496. package/dist/server/modules/user/user.service.js.map +1 -1
  497. package/dist/test/test.helper.js +2 -2
  498. package/dist/test/test.helper.js.map +1 -1
  499. package/dist/types/graphql-upload.d.ts +10 -7
  500. package/docs/REQUEST-LIFECYCLE.md +6 -3
  501. package/docs/choosing-a-database.md +107 -0
  502. package/docs/native-driver-security.md +29 -0
  503. package/docs/security-overrides.md +15 -6
  504. package/migration-guides/12.0.x-to-12.1.x.md +255 -0
  505. package/package.json +75 -29
  506. package/src/core/common/decorators/unified-field.decorator.ts +11 -1
  507. package/src/core/common/filters/mongoose-cast-error.filter.ts +12 -6
  508. package/src/core/common/helpers/db.helper.ts +40 -25
  509. package/src/core/common/helpers/decorator.helper.ts +1 -1
  510. package/src/core/common/helpers/filter.helper.ts +2 -1
  511. package/src/core/common/helpers/gridfs.helper.ts +28 -9
  512. package/src/core/common/helpers/id.helper.ts +21 -4
  513. package/src/core/common/helpers/model.helper.ts +5 -6
  514. package/src/core/common/helpers/service.helper.ts +3 -3
  515. package/src/core/common/interfaces/server-options.interface.ts +118 -10
  516. package/src/core/common/interfaces/service-options.interface.ts +2 -2
  517. package/src/core/common/models/core-persistence.model.ts +3 -3
  518. package/src/core/common/persistence/core-persistence.lifecycle.ts +47 -0
  519. package/src/core/common/persistence/core-persistence.module.ts +109 -0
  520. package/src/core/common/persistence/data-source.config.ts +271 -0
  521. package/src/core/common/persistence/data-source.runtime.ts +351 -0
  522. package/src/core/common/persistence/data-store.interface.ts +155 -0
  523. package/src/core/common/persistence/expiry-sweep.ts +105 -0
  524. package/src/core/common/persistence/id-format.ts +43 -0
  525. package/src/core/common/persistence/infrastructure-locks.ts +66 -0
  526. package/src/core/common/persistence/inject-store.decorator.ts +16 -0
  527. package/src/core/common/persistence/lock-store.interface.ts +17 -0
  528. package/src/core/common/persistence/model-descriptor.interface.ts +90 -0
  529. package/src/core/common/persistence/model-metadata.registry.ts +285 -0
  530. package/src/core/common/persistence/mongo/collection-name.ts +87 -0
  531. package/src/core/common/persistence/mongo/declared-schema.view.ts +378 -0
  532. package/src/core/common/persistence/mongo/hex-object-id.ts +75 -0
  533. package/src/core/common/persistence/mongo/model-declarations.ts +135 -0
  534. package/src/core/common/persistence/mongo/mongo-packages.ts +130 -0
  535. package/src/core/common/persistence/mongo/mongoose-compat.ts +129 -0
  536. package/src/core/common/persistence/mongo/no-mongo-connection.module.ts +18 -0
  537. package/src/core/common/persistence/mongo-lock-store.ts +121 -0
  538. package/src/core/common/persistence/mongoose-data-store.ts +232 -0
  539. package/src/core/common/persistence/neutral-populate.ts +98 -0
  540. package/src/core/common/persistence/persisted-model.decorator.ts +61 -0
  541. package/src/core/common/persistence/persistence-runtime.registry.ts +152 -0
  542. package/src/core/common/persistence/persistence.tokens.ts +9 -0
  543. package/src/core/common/persistence/policies/audit.policy.ts +80 -0
  544. package/src/core/common/persistence/policies/password.policy.ts +69 -0
  545. package/src/core/common/persistence/policies/role-guard.policy.ts +74 -0
  546. package/src/core/common/persistence/policies/system-role.policy.ts +90 -0
  547. package/src/core/common/persistence/policies/tenant.policy.ts +245 -0
  548. package/src/core/common/persistence/routed-model.guard.ts +107 -0
  549. package/src/core/common/persistence/sql/mysql/mysql-data-store.ts +503 -0
  550. package/src/core/common/persistence/sql/mysql/mysql-executor.ts +281 -0
  551. package/src/core/common/persistence/sql/mysql/mysql-lock-store.ts +87 -0
  552. package/src/core/common/persistence/sql/mysql/mysql-schema.compiler.ts +424 -0
  553. package/src/core/common/persistence/sql/mysql/mysql-schema.migrator.ts +453 -0
  554. package/src/core/common/persistence/sql/mysql/mysql-session.ts +131 -0
  555. package/src/core/common/persistence/sql/mysql/mysql-update.compiler.ts +379 -0
  556. package/src/core/common/persistence/sql/mysql/mysql-where.compiler.ts +686 -0
  557. package/src/core/common/persistence/sql/postgres/postgres-lock-store.ts +76 -0
  558. package/src/core/common/persistence/sql/postgres/postgres-schema.compiler.ts +328 -0
  559. package/src/core/common/persistence/sql/postgres/postgres-schema.migrator.ts +448 -0
  560. package/src/core/common/persistence/sql/postgres/postgres-update.compiler.ts +310 -0
  561. package/src/core/common/persistence/sql/postgres/postgres-where.compiler.ts +638 -0
  562. package/src/core/common/persistence/sql/sql-cast.ts +227 -0
  563. package/src/core/common/persistence/sql/sql-data-store.ts +762 -0
  564. package/src/core/common/persistence/sql/sql-dialect.ts +85 -0
  565. package/src/core/common/persistence/sql/sql-errors.ts +49 -0
  566. package/src/core/common/persistence/sql/sql-executor.factory.ts +282 -0
  567. package/src/core/common/persistence/sql/sql-executor.interface.ts +57 -0
  568. package/src/core/common/persistence/sql/sql-naming.ts +133 -0
  569. package/src/core/common/persistence/sql/sql-schema.shared.ts +105 -0
  570. package/src/core/common/persistence/sql/sql-session.ts +158 -0
  571. package/src/core/common/persistence/sql/where-shared.ts +118 -0
  572. package/src/core/common/persistence/store-guards.ts +73 -0
  573. package/src/core/common/persistence/store-upsert.ts +36 -0
  574. package/src/core/common/persistence/unavailable-store.ts +63 -0
  575. package/src/core/common/persistence/unsupported-capability.error.ts +7 -0
  576. package/src/core/common/plugins/mongoose-audit-fields.plugin.ts +33 -74
  577. package/src/core/common/plugins/mongoose-id.plugin.ts +9 -0
  578. package/src/core/common/plugins/mongoose-password.plugin.ts +6 -62
  579. package/src/core/common/plugins/mongoose-role-guard.plugin.ts +11 -63
  580. package/src/core/common/plugins/mongoose-system-role.plugin.ts +7 -78
  581. package/src/core/common/plugins/mongoose-tenant.plugin.ts +23 -144
  582. package/src/core/common/scalars/upload.scalar.ts +8 -3
  583. package/src/core/common/services/core-cron-jobs.initializer.ts +1 -1
  584. package/src/core/common/services/core-cron-jobs.service.ts +33 -22
  585. package/src/core/common/services/crud.service.ts +166 -35
  586. package/src/core/common/services/model-doc.service.ts +1 -1
  587. package/src/core/common/services/module.service.ts +78 -6
  588. package/src/core/common/types/field-selection.type.ts +1 -1
  589. package/src/core/common/types/id.type.ts +2 -2
  590. package/src/core/common/types/object-id-like.type.ts +11 -0
  591. package/src/core/common/types/populate-config.type.ts +1 -1
  592. package/src/core/common/types/string-or-object-id.type.ts +2 -2
  593. package/src/core/modules/ai/README.md +15 -2
  594. package/src/core/modules/ai/core-ai.constants.ts +10 -0
  595. package/src/core/modules/ai/core-ai.module.ts +32 -17
  596. package/src/core/modules/ai/models/core-ai-budget-limit.model.ts +2 -2
  597. package/src/core/modules/ai/models/core-ai-connection-preference.model.ts +2 -2
  598. package/src/core/modules/ai/models/core-ai-connection.model.ts +2 -2
  599. package/src/core/modules/ai/models/core-ai-conversation.model.ts +8 -4
  600. package/src/core/modules/ai/models/core-ai-interaction.model.ts +3 -3
  601. package/src/core/modules/ai/models/core-ai-mcp-oauth.models.ts +46 -0
  602. package/src/core/modules/ai/models/core-ai-mode.model.ts +2 -2
  603. package/src/core/modules/ai/models/core-ai-prompt-hint.model.ts +2 -2
  604. package/src/core/modules/ai/models/core-ai-prompt.model.ts +2 -2
  605. package/src/core/modules/ai/models/core-ai-slot.model.ts +2 -2
  606. package/src/core/modules/ai/models/core-ai-tool-grant.model.ts +2 -2
  607. package/src/core/modules/ai/models/core-ai-tool-policy.model.ts +2 -2
  608. package/src/core/modules/ai/services/core-ai-budget.service.ts +22 -4
  609. package/src/core/modules/ai/services/core-ai-connection-preference.service.ts +6 -13
  610. package/src/core/modules/ai/services/core-ai-connection.service.ts +34 -44
  611. package/src/core/modules/ai/services/core-ai-conversation.service.ts +31 -29
  612. package/src/core/modules/ai/services/core-ai-interaction.service.ts +3 -3
  613. package/src/core/modules/ai/services/core-ai-mcp-oauth.service.ts +93 -20
  614. package/src/core/modules/ai/services/core-ai-mode.service.ts +3 -6
  615. package/src/core/modules/ai/services/core-ai-prompt-hint.service.ts +43 -26
  616. package/src/core/modules/ai/services/core-ai-prompt.service.ts +15 -12
  617. package/src/core/modules/ai/services/core-ai-slot.service.ts +20 -24
  618. package/src/core/modules/ai/services/core-ai-tool-grant.service.ts +17 -27
  619. package/src/core/modules/ai/services/core-ai-tool-policy.service.ts +7 -10
  620. package/src/core/modules/api-token/core-api-token.model.ts +1 -1
  621. package/src/core/modules/api-token/core-api-token.module.ts +4 -2
  622. package/src/core/modules/api-token/core-api-token.service.ts +118 -43
  623. package/src/core/modules/auth/core-auth.module.ts +2 -0
  624. package/src/core/modules/auth/guards/legacy-auth-rate-limit.guard.ts +4 -3
  625. package/src/core/modules/auth/guards/role-guard.token.ts +7 -0
  626. package/src/core/modules/auth/services/core-auth.service.ts +16 -2
  627. package/src/core/modules/better-auth/INTEGRATION-CHECKLIST.md +1 -1
  628. package/src/core/modules/better-auth/README.md +10 -1
  629. package/src/core/modules/better-auth/better-auth-sql.helper.ts +191 -0
  630. package/src/core/modules/better-auth/better-auth-token.service.ts +26 -35
  631. package/src/core/modules/better-auth/better-auth.config.ts +43 -7
  632. package/src/core/modules/better-auth/better-auth.types.ts +1 -1
  633. package/src/core/modules/better-auth/core-better-auth-api.middleware.ts +13 -1
  634. package/src/core/modules/better-auth/core-better-auth-challenge.service.ts +36 -18
  635. package/src/core/modules/better-auth/core-better-auth-mongo.users.ts +35 -0
  636. package/src/core/modules/better-auth/core-better-auth-sql.registry.ts +20 -0
  637. package/src/core/modules/better-auth/core-better-auth-sql.store.ts +309 -0
  638. package/src/core/modules/better-auth/core-better-auth-user.mapper.ts +418 -40
  639. package/src/core/modules/better-auth/core-better-auth.module.ts +71 -35
  640. package/src/core/modules/better-auth/core-better-auth.service.ts +81 -12
  641. package/src/core/modules/file/README.md +16 -3
  642. package/src/core/modules/file/core-file-info.model.ts +2 -2
  643. package/src/core/modules/file/core-file.service.ts +27 -18
  644. package/src/core/modules/file/file-metadata.helper.ts +7 -3
  645. package/src/core/modules/file/file-metadata.models.ts +44 -0
  646. package/src/core/modules/file/file-metadata.store.ts +109 -0
  647. package/src/core/modules/file/file-storage.helper.ts +47 -2
  648. package/src/core/modules/file/filesystem-file.helper.ts +11 -8
  649. package/src/core/modules/file/s3-file.helper.ts +11 -7
  650. package/src/core/modules/health-check/core-health-check.module.ts +16 -2
  651. package/src/core/modules/health-check/core-health-check.service.ts +25 -3
  652. package/src/core/modules/hub/README.md +20 -11
  653. package/src/core/modules/hub/core-hub.controller.ts +5 -0
  654. package/src/core/modules/hub/core-hub.service.ts +1 -1
  655. package/src/core/modules/hub/helpers/hub-client-js.helper.ts +23 -0
  656. package/src/core/modules/hub/hub-action-messages.ts +6 -0
  657. package/src/core/modules/hub/hub-nav.ts +1 -0
  658. package/src/core/modules/hub/interfaces/hub-panels.interface.ts +8 -1
  659. package/src/core/modules/hub/services/core-hub-db.service.ts +35 -17
  660. package/src/core/modules/hub/services/core-hub-migrations.service.ts +96 -2
  661. package/src/core/modules/hub/services/core-hub-sources.service.ts +47 -1
  662. package/src/core/modules/hub/services/hub-query-profiler.service.ts +1 -1
  663. package/src/core/modules/migrate/README.md +54 -0
  664. package/src/core/modules/migrate/cli/migrate-cli.ts +44 -3
  665. package/src/core/modules/migrate/index.ts +3 -0
  666. package/src/core/modules/migrate/migration-runner.ts +3 -2
  667. package/src/core/modules/migrate/migration-state-store.interface.ts +24 -0
  668. package/src/core/modules/migrate/migration.helper.ts +35 -10
  669. package/src/core/modules/migrate/mongo-state-store.ts +64 -65
  670. package/src/core/modules/migrate/sql-migration.helper.ts +48 -0
  671. package/src/core/modules/migrate/sql-state-store.ts +198 -0
  672. package/src/core/modules/system-setup/README.md +14 -2
  673. package/src/core/modules/system-setup/core-system-setup.service.ts +77 -45
  674. package/src/core/modules/tenant/README.md +9 -2
  675. package/src/core/modules/tenant/core-tenant-member.model.ts +1 -1
  676. package/src/core/modules/tenant/core-tenant-member.store.ts +13 -0
  677. package/src/core/modules/tenant/core-tenant.guard.ts +77 -24
  678. package/src/core/modules/tenant/core-tenant.module.ts +6 -3
  679. package/src/core/modules/tenant/core-tenant.service.ts +59 -42
  680. package/src/core/modules/tus/core-tus.service.ts +11 -12
  681. package/src/core/modules/tus/tus.module.ts +1 -1
  682. package/src/core/modules/user/core-user.model.ts +2 -2
  683. package/src/core/modules/user/core-user.service.ts +98 -20
  684. package/src/core.module.ts +60 -5
  685. package/src/index.ts +26 -0
  686. package/src/server/common/models/persistence.model.ts +4 -4
  687. package/src/server/modules/file/file-info.model.ts +1 -1
  688. package/src/server/modules/file/file.service.ts +1 -1
  689. package/src/server/modules/user/user.model.ts +10 -5
  690. package/src/server/modules/user/user.module.ts +9 -3
  691. package/src/server/modules/user/user.service.ts +9 -11
  692. package/src/test/test.helper.ts +2 -2
  693. package/src/types/graphql-upload.d.ts +10 -7
@@ -1,8 +1,10 @@
1
1
  import { Inject, Injectable } from '@nestjs/common';
2
- import { InjectConnection, InjectModel } from '@nestjs/mongoose';
3
- import { type Connection, Model, Types } from 'mongoose';
2
+ import { InjectConnection, InjectModel } from '../../../common/persistence/mongo/mongoose-compat.js';
3
+ import type { Connection, Model } from 'mongoose';
4
4
 
5
5
  import { RoleEnum } from '../../../common/enums/role.enum.js';
6
+ import { isWellFormedId } from '../../../common/persistence/id-format.js';
7
+ import { getModelStore } from '../../../common/persistence/persistence-runtime.registry.js';
6
8
  import { ServiceOptions } from '../../../common/interfaces/service-options.interface.js';
7
9
  import { CrudService } from '../../../common/services/crud.service.js';
8
10
  import type { CoreModelConstructor } from '../../../common/types/core-model-constructor.type.js';
@@ -118,25 +120,30 @@ export class CoreAiConversationService extends CrudService<
118
120
  if (!ids.length) {
119
121
  return;
120
122
  }
121
- let userModel: Model<any>;
122
- try {
123
- userModel = this.connection.model('User');
124
- } catch {
125
- // No `User` model registered on this connection (exotic setup) — skip attribution.
123
+ // Through the users' store wherever the user model is routed (a SQL source, or MongoDB); a `User` model registered
124
+ // with MongooseModule alone has no store and is read directly
125
+ const userStore = getModelStore(this.connection, 'User');
126
+ const userModel = this.connection?.models?.User as Model<any> | undefined;
127
+ let users: unknown[];
128
+ if (userStore) {
129
+ users = await userStore.find({ id: { $in: ids } }, { select: ['email', 'firstName', 'lastName', 'username'] });
130
+ } else if (userModel) {
131
+ users = await userModel
132
+ .find({ _id: { $in: ids } })
133
+ .select('email firstName lastName username')
134
+ .lean()
135
+ .exec();
136
+ } else {
137
+ // No `User` model registered (exotic setup) — skip attribution.
126
138
  return;
127
139
  }
128
- const users = await userModel
129
- .find({ _id: { $in: ids } })
130
- .select('email firstName lastName username')
131
- .lean()
132
- .exec();
133
140
  const byId = new Map(
134
141
  (users as any[]).map((user) => [
135
- String(user._id),
142
+ String(user.id ?? user._id),
136
143
  {
137
144
  email: user.email,
138
145
  firstName: user.firstName,
139
- id: String(user._id),
146
+ id: String(user.id ?? user._id),
140
147
  lastName: user.lastName,
141
148
  username: user.username,
142
149
  },
@@ -154,16 +161,9 @@ export class CoreAiConversationService extends CrudService<
154
161
  * grow unbounded.
155
162
  */
156
163
  async appendMessage(id: string, message: { content: string; createdAt?: Date; role: string }): Promise<void> {
157
- await this.mainDbModel
158
- .findByIdAndUpdate(id, {
159
- $push: {
160
- messages: {
161
- $each: [{ ...message, createdAt: message.createdAt ?? new Date() }],
162
- $slice: -this.maxRetainedMessages,
163
- },
164
- },
165
- })
166
- .exec();
164
+ await this.dataStore.pushToArray(id, 'messages', [{ ...message, createdAt: message.createdAt ?? new Date() }], {
165
+ slice: -this.maxRetainedMessages,
166
+ });
167
167
  }
168
168
 
169
169
  /**
@@ -187,16 +187,18 @@ export class CoreAiConversationService extends CrudService<
187
187
  currentUser: { id?: string; roles?: string[] } | undefined,
188
188
  limit = 20,
189
189
  ): Promise<{ content: string; role: string }[]> {
190
- if (!id || typeof id !== 'string' || !Types.ObjectId.isValid(id)) {
190
+ if (!id || typeof id !== 'string' || !isWellFormedId(id)) {
191
191
  return [];
192
192
  }
193
- const doc = await this.mainDbModel
194
- .findById(id, { createdBy: 1, messages: { $slice: -limit } })
195
- .lean()
196
- .exec();
193
+ const doc = await this.dataStore.findById(id, { select: ['createdBy', 'messages'] });
197
194
  if (!doc) {
198
195
  return [];
199
196
  }
197
+ // The last `limit` turns, cut after the read: a conversation keeps at most `maxRetainedMessages`
198
+ const messages = (doc as { messages?: unknown[] }).messages;
199
+ if (Array.isArray(messages)) {
200
+ (doc as { messages?: unknown[] }).messages = limit > 0 ? messages.slice(-limit) : [];
201
+ }
200
202
  const isOwner = currentUser?.id && String((doc as { createdBy?: unknown }).createdBy) === String(currentUser.id);
201
203
  const isAdmin = currentUser?.roles?.includes('admin');
202
204
  if (!isOwner && !isAdmin) {
@@ -1,6 +1,6 @@
1
1
  import { Inject, Injectable } from '@nestjs/common';
2
- import { InjectModel } from '@nestjs/mongoose';
3
- import { Model } from 'mongoose';
2
+ import { InjectModel } from '../../../common/persistence/mongo/mongoose-compat.js';
3
+ import type { Model } from 'mongoose';
4
4
 
5
5
  import { CrudService } from '../../../common/services/crud.service.js';
6
6
  import type { CoreModelConstructor } from '../../../common/types/core-model-constructor.type.js';
@@ -39,7 +39,7 @@ export class CoreAiInteractionService extends CrudService<CoreAiInteraction> {
39
39
  * passed through explicitly when known for robustness.
40
40
  */
41
41
  async record(rec: AiInteractionRecord): Promise<void> {
42
- await this.mainDbModel.create({
42
+ await this.dataStore.insert({
43
43
  actions: rec.actions,
44
44
  completionTokens: rec.usage?.completionTokens,
45
45
  connectionId: rec.connectionId,
@@ -1,13 +1,22 @@
1
1
  import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
2
- import { InjectConnection } from '@nestjs/mongoose';
2
+ import { InjectConnection } from '../../../common/persistence/mongo/mongoose-compat.js';
3
3
  import { AsyncLocalStorage } from 'node:async_hooks';
4
4
  import { createHash, createHmac, randomBytes, timingSafeEqual } from 'node:crypto';
5
5
  import type { Connection } from 'mongoose';
6
6
 
7
7
  import { isLocalEnv, resolveAppUrlFromConfig } from '../../../common/helpers/cookies.helper.js';
8
+ import type { DataStore } from '../../../common/persistence/data-store.interface.js';
9
+ import { getModelStore } from '../../../common/persistence/persistence-runtime.registry.js';
8
10
  import { ConfigService } from '../../../common/services/config.service.js';
9
11
  import { getApiTokenContext, hasApiTokenCredential } from '../../api-token/core-api-token.helpers.js';
12
+ import { getBetterAuthSqlStore } from '../../better-auth/core-better-auth-sql.registry.js';
10
13
  import { getBetterAuthTokenService } from '../../better-auth/core-better-auth.registry.js';
14
+ import {
15
+ AI_MCP_OAUTH_CLIENT_MODEL,
16
+ AI_MCP_OAUTH_CODE_MODEL,
17
+ AI_MCP_OAUTH_CODE_TTL_SECONDS,
18
+ AI_MCP_OAUTH_REFRESH_TOKEN_MODEL,
19
+ } from '../core-ai.constants.js';
11
20
  import {
12
21
  IMcpOAuthConsentView,
13
22
  MCP_OAUTH_CONSENT_DECISION_FIELD,
@@ -17,6 +26,7 @@ import {
17
26
  renderMcpOAuthConsentPage,
18
27
  } from '../helpers/ai-mcp-oauth-consent.helper.js';
19
28
  import { getMountedMcpOAuth } from '../helpers/ai-mcp-oauth.registry.js';
29
+ import { isValidObjectId, newObjectId } from '../../../common/persistence/mongo/mongoose-compat.js';
20
30
 
21
31
  /** One of the MCP SDK's OAuth error classes: constructed with a message (and optionally an error URI) and thrown. */
22
32
  export interface IMcpOAuthErrorClass {
@@ -167,6 +177,7 @@ export class CoreAiMcpOAuthService implements OnModuleInit {
167
177
  protected readonly refreshCollection = 'aiMcpOAuthRefreshTokens';
168
178
 
169
179
  private indexesEnsured = false;
180
+ private warnedIndexes = false;
170
181
  private warnedSecret = false;
171
182
 
172
183
  constructor(@InjectConnection() protected readonly connection: Connection) {}
@@ -304,6 +315,11 @@ export class CoreAiMcpOAuthService implements OnModuleInit {
304
315
  * Register a dynamic OAuth client.
305
316
  */
306
317
  async registerClient(client: AiMcpOAuthClient): Promise<AiMcpOAuthClient> {
318
+ const sql = this.sqlStore(AI_MCP_OAUTH_CLIENT_MODEL);
319
+ if (sql) {
320
+ await sql.insert({ client, client_id: client.client_id, createdAt: new Date() });
321
+ return client;
322
+ }
307
323
  await this.ensureIndexes();
308
324
  await this.db()
309
325
  .collection(this.clientsCollection)
@@ -321,7 +337,10 @@ export class CoreAiMcpOAuthService implements OnModuleInit {
321
337
  * the verification branch is skipped — PKCE protects the auth-code flow.
322
338
  */
323
339
  async getClient(clientId: string): Promise<AiMcpOAuthClient | null> {
324
- const doc = await this.db().collection(this.clientsCollection).findOne({ client_id: clientId });
340
+ const sql = this.sqlStore(AI_MCP_OAUTH_CLIENT_MODEL);
341
+ const doc = sql
342
+ ? (await sql.findOne({ client_id: clientId }))?.client
343
+ : await this.db().collection(this.clientsCollection).findOne({ client_id: clientId });
325
344
  if (!doc) {
326
345
  return null;
327
346
  }
@@ -336,7 +355,7 @@ export class CoreAiMcpOAuthService implements OnModuleInit {
336
355
  }
337
356
 
338
357
  /**
339
- * Persist an authorization code with its PKCE challenge (TTL 10 minutes).
358
+ * Persist an authorization code with its PKCE challenge, valid for `AI_MCP_OAUTH_CODE_TTL_SECONDS` (10 minutes).
340
359
  *
341
360
  * Issuing a code IS the authorization. While answering `/authorize` this refuses unless the
342
361
  * request is a POST — the user's approval of the consent form (see `assertCodeIssuanceAllowed`).
@@ -346,14 +365,20 @@ export class CoreAiMcpOAuthService implements OnModuleInit {
346
365
  data: { clientId: string; codeChallenge: string; userId: string },
347
366
  ): Promise<void> {
348
367
  assertCodeIssuanceAllowed();
349
- await this.ensureIndexes();
350
- await this.db().collection(this.codesCollection).insertOne({
368
+ const record = {
351
369
  clientId: data.clientId,
352
370
  code,
353
371
  codeChallenge: data.codeChallenge,
354
372
  createdAt: new Date(),
355
373
  userId: data.userId,
356
- });
374
+ };
375
+ const sql = this.sqlStore(AI_MCP_OAUTH_CODE_MODEL);
376
+ if (sql) {
377
+ await sql.insert(record);
378
+ return;
379
+ }
380
+ await this.ensureIndexes();
381
+ await this.db().collection(this.codesCollection).insertOne(record);
357
382
  }
358
383
 
359
384
  /**
@@ -362,8 +387,9 @@ export class CoreAiMcpOAuthService implements OnModuleInit {
362
387
  async getAuthorizationCode(
363
388
  code: string,
364
389
  ): Promise<{ clientId: string; codeChallenge: string; userId: string } | null> {
365
- const doc = await this.db().collection(this.codesCollection).findOne({ code });
366
- return doc ? { clientId: doc.clientId, codeChallenge: doc.codeChallenge, userId: doc.userId } : null;
390
+ const sql = this.sqlStore(AI_MCP_OAUTH_CODE_MODEL);
391
+ const doc = sql ? await sql.findOne({ code }) : await this.db().collection(this.codesCollection).findOne({ code });
392
+ return this.liveCode(doc);
367
393
  }
368
394
 
369
395
  /**
@@ -378,21 +404,44 @@ export class CoreAiMcpOAuthService implements OnModuleInit {
378
404
  clientId?: string,
379
405
  ): Promise<{ clientId: string; codeChallenge: string; userId: string } | null> {
380
406
  const filter = clientId === undefined ? { code } : { clientId, code };
381
- const doc = await this.db().collection(this.codesCollection).findOneAndDelete(filter);
407
+ const sql = this.sqlStore(AI_MCP_OAUTH_CODE_MODEL);
408
+ // Deleted whatever its age: an expired code is refused AND gone, so it can never be presented again
409
+ const doc = sql
410
+ ? await sql.deleteOne(filter)
411
+ : await this.db().collection(this.codesCollection).findOneAndDelete(filter);
382
412
  const value = (doc as any)?.value ?? doc; // driver version compatibility
383
- if (!value) {
413
+ return this.liveCode(value);
414
+ }
415
+
416
+ /**
417
+ * The code's data while it is younger than `AI_MCP_OAUTH_CODE_TTL_SECONDS`, `null` otherwise. Checked on every read:
418
+ * MongoDB's TTL index removes an expired code only eventually (its monitor runs about once a minute, later under
419
+ * load), and a SQL table has no TTL at all — the sweeper only keeps the table small.
420
+ */
421
+ protected liveCode(doc: any): { clientId: string; codeChallenge: string; userId: string } | null {
422
+ if (!doc) {
423
+ return null;
424
+ }
425
+ const createdAt = doc.createdAt ? new Date(doc.createdAt).getTime() : NaN;
426
+ if (!(Date.now() - createdAt <= AI_MCP_OAUTH_CODE_TTL_SECONDS * 1000)) {
384
427
  return null;
385
428
  }
386
- return { clientId: value.clientId, codeChallenge: value.codeChallenge, userId: value.userId };
429
+ return { clientId: doc.clientId, codeChallenge: doc.codeChallenge, userId: doc.userId };
387
430
  }
388
431
 
389
432
  /**
390
433
  * Issue a refresh token for a user + client.
391
434
  */
392
435
  async issueRefreshToken(userId: string, clientId: string): Promise<string> {
393
- await this.ensureIndexes();
394
436
  const token = this.generateId();
395
- await this.db().collection(this.refreshCollection).insertOne({ clientId, createdAt: new Date(), token, userId });
437
+ const record = { clientId, createdAt: new Date(), token, userId };
438
+ const sql = this.sqlStore(AI_MCP_OAUTH_REFRESH_TOKEN_MODEL);
439
+ if (sql) {
440
+ await sql.insert(record);
441
+ return token;
442
+ }
443
+ await this.ensureIndexes();
444
+ await this.db().collection(this.refreshCollection).insertOne(record);
396
445
  return token;
397
446
  }
398
447
 
@@ -412,7 +461,10 @@ export class CoreAiMcpOAuthService implements OnModuleInit {
412
461
  if (!token || !clientId) {
413
462
  return null;
414
463
  }
415
- const doc = await this.db().collection(this.refreshCollection).findOneAndDelete({ clientId, token });
464
+ const sql = this.sqlStore(AI_MCP_OAUTH_REFRESH_TOKEN_MODEL);
465
+ const doc = sql
466
+ ? await sql.deleteOne({ clientId, token })
467
+ : await this.db().collection(this.refreshCollection).findOneAndDelete({ clientId, token });
416
468
  const value = (doc as any)?.value ?? doc;
417
469
  if (!value) {
418
470
  return null;
@@ -427,8 +479,14 @@ export class CoreAiMcpOAuthService implements OnModuleInit {
427
479
  */
428
480
  async loadUser(userId: string): Promise<{ id: string; roles: string[] } | null> {
429
481
  try {
430
- const { ObjectId } = await import('mongodb');
431
- const query = ObjectId.isValid(userId) ? { _id: new ObjectId(userId) } : { _id: userId as any };
482
+ // With Better-Auth on SQL the subject is the row id of the `users` table there — a MongoDB `users` collection is
483
+ // empty, or a stale copy whose roles were revoked long ago
484
+ const sql = getBetterAuthSqlStore();
485
+ if (sql) {
486
+ const row = await sql.findUser({ id: userId }, ['roles']);
487
+ return row ? { id: userId, roles: Array.isArray(row.roles) ? row.roles : [] } : null;
488
+ }
489
+ const query = isValidObjectId(userId) ? { _id: newObjectId(userId) } : { _id: userId as any };
432
490
  const doc = await this.db()
433
491
  .collection('users')
434
492
  .findOne(query, { projection: { roles: 1 } });
@@ -836,15 +894,30 @@ export class CoreAiMcpOAuthService implements OnModuleInit {
836
894
  if (this.indexesEnsured) {
837
895
  return;
838
896
  }
839
- this.indexesEnsured = true;
840
897
  try {
841
898
  await this.db().collection(this.clientsCollection).createIndex({ client_id: 1 }, { unique: true });
842
- // Authorization codes expire after 10 minutes.
843
- await this.db().collection(this.codesCollection).createIndex({ createdAt: 1 }, { expireAfterSeconds: 600 });
899
+ // Removes expired codes eventually; their expiry itself is checked on every read (liveCode)
900
+ await this.db()
901
+ .collection(this.codesCollection)
902
+ .createIndex({ createdAt: 1 }, { expireAfterSeconds: AI_MCP_OAUTH_CODE_TTL_SECONDS });
844
903
  await this.db().collection(this.codesCollection).createIndex({ code: 1 }, { unique: true });
845
904
  await this.db().collection(this.refreshCollection).createIndex({ token: 1 }, { unique: true });
905
+ // Only now: a failed attempt is retried with the next write instead of never again
906
+ this.indexesEnsured = true;
846
907
  } catch (err) {
847
- this.logger.warn(`Could not ensure MCP OAuth indexes: ${(err as Error).message}`);
908
+ if (!this.warnedIndexes) {
909
+ this.warnedIndexes = true;
910
+ this.logger.warn(`Could not ensure MCP OAuth indexes: ${(err as Error).message}`);
911
+ }
848
912
  }
849
913
  }
914
+
915
+ /**
916
+ * The store of an OAuth model when it is routed to a SQL source; `undefined` keeps the native MongoDB collections.
917
+ * The models are registered by `CoreAiModule` through `CorePersistenceModule.forFeature()`.
918
+ */
919
+ protected sqlStore(modelName: string): DataStore<any> | undefined {
920
+ const store = getModelStore(this.connection, modelName);
921
+ return store && !store.capabilities.mongoosePopulate ? store : undefined;
922
+ }
850
923
  }
@@ -1,6 +1,6 @@
1
1
  import { Inject, Injectable, Logger } from '@nestjs/common';
2
- import { InjectModel } from '@nestjs/mongoose';
3
- import { Model } from 'mongoose';
2
+ import { InjectModel } from '../../../common/persistence/mongo/mongoose-compat.js';
3
+ import type { Model } from 'mongoose';
4
4
 
5
5
  import { CrudService } from '../../../common/services/crud.service.js';
6
6
  import type { CoreModelConstructor } from '../../../common/types/core-model-constructor.type.js';
@@ -36,10 +36,7 @@ export class CoreAiModeService extends CrudService<CoreAiMode, CoreAiMode, CoreA
36
36
  return null;
37
37
  }
38
38
  try {
39
- const row = await this.mainDbModel
40
- .findOne({ enabled: { $ne: false }, name })
41
- .lean<CoreAiMode>()
42
- .exec();
39
+ const row = (await this.dataStore.findOne({ enabled: { $ne: false }, name })) as CoreAiMode | null;
43
40
  return row || null;
44
41
  } catch (err) {
45
42
  this.logger.warn(`Failed to load mode "${name}": ${(err as Error).message}`);
@@ -1,6 +1,6 @@
1
1
  import { Inject, Injectable, Logger } from '@nestjs/common';
2
- import { InjectModel } from '@nestjs/mongoose';
3
- import { Model } from 'mongoose';
2
+ import { InjectModel } from '../../../common/persistence/mongo/mongoose-compat.js';
3
+ import type { Model } from 'mongoose';
4
4
 
5
5
  import { ConfigService } from '../../../common/services/config.service.js';
6
6
  import { CrudService } from '../../../common/services/crud.service.js';
@@ -72,11 +72,10 @@ export class CoreAiPromptHintService extends CrudService<
72
72
  return [];
73
73
  }
74
74
  try {
75
- const rows = await this.mainDbModel
76
- .find({ enabled: { $ne: false }, scope: { $in: [null, '', ...scopes] }, status: 'approved' })
77
- .sort({ occurrences: -1 })
78
- .lean<CoreAiPromptHint[]>()
79
- .exec();
75
+ const rows = (await this.dataStore.find(
76
+ { enabled: { $ne: false }, scope: { $in: [null, '', ...scopes] }, status: 'approved' },
77
+ { sort: { occurrences: -1 } },
78
+ )) as CoreAiPromptHint[];
80
79
  return rows.map((r) => r.content).filter((c): c is string => !!c?.trim());
81
80
  } catch {
82
81
  return [];
@@ -95,33 +94,51 @@ export class CoreAiPromptHintService extends CrudService<
95
94
  }
96
95
  const scope = signal.scope || '';
97
96
  try {
98
- const existing = await this.mainDbModel
99
- .findOne({ scope, trigger: signal.trigger })
100
- .lean<CoreAiPromptHint>()
101
- .exec();
102
- if (existing) {
103
- const occurrences = (existing.occurrences ?? 1) + 1;
104
- const update: Record<string, unknown> = { occurrences };
105
- // Auto-approve once the threshold is reached (config) and not already decided.
106
- if (config.autoApply && existing.status === 'suggested' && occurrences >= config.minOccurrences) {
107
- update.status = 'approved';
108
- }
109
- await this.mainDbModel.updateOne({ _id: (existing as any)._id }, { $set: update }).exec();
97
+ // Counted atomically: concurrent signals of one trigger each add one
98
+ const counted = (await this.incrementOccurrences(scope, signal.trigger)) as CoreAiPromptHint | null;
99
+ if (counted) {
100
+ await this.approveWhenDue(counted, config);
110
101
  return;
111
102
  }
112
103
  const status = config.autoApply && config.minOccurrences <= 1 ? 'approved' : 'suggested';
113
- await this.mainDbModel.create({
114
- content: signal.content,
115
- occurrences: 1,
116
- scope,
117
- status,
118
- trigger: signal.trigger,
119
- });
104
+ try {
105
+ await this.dataStore.insert({
106
+ content: signal.content,
107
+ occurrences: 1,
108
+ scope,
109
+ status,
110
+ trigger: signal.trigger,
111
+ });
112
+ } catch (err) {
113
+ if ((err as { code?: unknown })?.code !== 11000) {
114
+ throw err;
115
+ }
116
+ // Another signal created the hint between the two steps: count this one too
117
+ const recounted = (await this.incrementOccurrences(scope, signal.trigger)) as CoreAiPromptHint | null;
118
+ if (recounted) {
119
+ await this.approveWhenDue(recounted, config);
120
+ }
121
+ }
120
122
  } catch (err) {
121
123
  this.logger.debug(`recordSignal skipped: ${(err as Error).message}`);
122
124
  }
123
125
  }
124
126
 
127
+ /** Add one occurrence to the hint of (scope, trigger); `null` when there is none yet */
128
+ protected incrementOccurrences(scope: string, trigger: string) {
129
+ return this.dataStore.updateOne({ scope, trigger }, { $inc: { occurrences: 1 } });
130
+ }
131
+
132
+ /** Auto-approve once the threshold is reached (config) and the hint is not already decided */
133
+ protected async approveWhenDue(
134
+ hint: CoreAiPromptHint & { id?: string },
135
+ config: { autoApply?: boolean; minOccurrences: number },
136
+ ): Promise<void> {
137
+ if (config.autoApply && hint.status === 'suggested' && (hint.occurrences ?? 1) >= config.minOccurrences) {
138
+ await this.dataStore.updateOne({ id: hint.id, status: 'suggested' }, { $set: { status: 'approved' } });
139
+ }
140
+ }
141
+
125
142
  /** Resolve the `ai.promptLearning` config with safe defaults. */
126
143
  protected config(): PromptLearningConfig {
127
144
  const raw = ConfigService.get<{ autoApply?: boolean; enabled?: boolean; minOccurrences?: number }>(
@@ -1,6 +1,6 @@
1
1
  import { ForbiddenException, Inject, Injectable, Logger } from '@nestjs/common';
2
- import { InjectModel } from '@nestjs/mongoose';
3
- import { Model } from 'mongoose';
2
+ import { InjectModel } from '../../../common/persistence/mongo/mongoose-compat.js';
3
+ import type { Model } from 'mongoose';
4
4
 
5
5
  import { ServiceOptions } from '../../../common/interfaces/service-options.interface.js';
6
6
  import { RoleEnum } from '../../../common/enums/role.enum.js';
@@ -64,9 +64,11 @@ export class CoreAiPromptService extends CrudService<CoreAiPrompt, CoreAiPromptC
64
64
  // then reload the row through the full pipeline so the response carries
65
65
  // every field (and `securityCheck` returns it to the owner).
66
66
  const created = await super.create(input as any, serviceOptions);
67
- await this.mainDbModel
68
- .updateOne({ _id: created.id }, { $set: { ownerId: String(user.id), scope, tenantId } })
69
- .exec();
67
+ // `tenantId` only when the prompt is shared with a tenant: MongoDB drops an undefined key, a SQL store writes NULL —
68
+ // which row-level security refuses for a row stamped with the request's tenant
69
+ await this.dataStore.updateById(created.id, {
70
+ $set: { ownerId: String(user.id), scope, ...(tenantId !== undefined ? { tenantId } : {}) },
71
+ });
70
72
  return this.get(created.id, serviceOptions);
71
73
  }
72
74
 
@@ -105,7 +107,9 @@ export class CoreAiPromptService extends CrudService<CoreAiPrompt, CoreAiPromptC
105
107
  // stripped by `prepareInput` if passed through `super.update`.
106
108
  const updated = await super.update(id, sanitized as any, serviceOptions);
107
109
  if (scopeChange) {
108
- await this.mainDbModel.updateOne({ _id: id }, { $set: { tenantId: scopeChange.tenantId } }).exec();
110
+ if (scopeChange.tenantId !== undefined) {
111
+ await this.dataStore.updateById(id, { $set: { tenantId: scopeChange.tenantId } });
112
+ }
109
113
  return this.get(id, serviceOptions);
110
114
  }
111
115
  return updated;
@@ -131,11 +135,10 @@ export class CoreAiPromptService extends CrudService<CoreAiPrompt, CoreAiPromptC
131
135
  or.push({ scope: 'tenant', tenantId: String(tenantId) });
132
136
  }
133
137
  try {
134
- const rows = await this.mainDbModel
135
- .find({ $or: or, enabled: { $ne: false } })
136
- .sort({ order: 1, name: 1 })
137
- .lean<CoreAiPrompt[]>()
138
- .exec();
138
+ const rows = (await this.dataStore.find(
139
+ { $or: or, enabled: { $ne: false } },
140
+ { sort: { order: 1, name: 1 } },
141
+ )) as CoreAiPrompt[];
139
142
  return rows || [];
140
143
  } catch (err) {
141
144
  this.logger.warn(`Failed to list prompts: ${(err as Error).message}`);
@@ -153,7 +156,7 @@ export class CoreAiPromptService extends CrudService<CoreAiPrompt, CoreAiPromptC
153
156
  return;
154
157
  }
155
158
  try {
156
- const row = await this.mainDbModel.findById(id).lean<CoreAiPrompt>().exec();
159
+ const row = (await this.dataStore.findById(id)) as CoreAiPrompt | null;
157
160
  if (!row) {
158
161
  throw new ForbiddenException(`Prompt ${id} not found.`);
159
162
  }
@@ -1,6 +1,6 @@
1
1
  import { ForbiddenException, Inject, Injectable, Logger } from '@nestjs/common';
2
- import { InjectModel } from '@nestjs/mongoose';
3
- import { Model } from 'mongoose';
2
+ import { InjectModel } from '../../../common/persistence/mongo/mongoose-compat.js';
3
+ import type { Model } from 'mongoose';
4
4
 
5
5
  import { RoleEnum } from '../../../common/enums/role.enum.js';
6
6
  import { ServiceOptions } from '../../../common/interfaces/service-options.interface.js';
@@ -194,18 +194,21 @@ export class CoreAiSlotService extends CrudService<CoreAiSlot, CoreAiSlotCreateI
194
194
  this.assertAdmin(serviceOptions);
195
195
  const tenantId = this.tenantOf(serviceOptions);
196
196
  if (input?.key) {
197
- const existing = await this.mainDbModel
198
- .findOne({ key: input.key, tenantId: tenantId ?? { $in: [null, undefined] } })
199
- .lean<CoreAiSlot>()
200
- .exec();
201
- if (existing?.id || (existing as any)?._id) {
202
- const existingId = String(existing?.id || (existing as any)?._id);
197
+ // `null` matches a missing tenant as well, on every database
198
+ const existing = (await this.dataStore.findOne({ key: input.key, tenantId: tenantId ?? null })) as
199
+ | (CoreAiSlot & { id?: string })
200
+ | null;
201
+ if (existing?.id) {
202
+ const existingId = String(existing.id);
203
203
  const updated = await super.update(existingId, input as any, serviceOptions);
204
204
  return this.decorateWithSystemFlags(updated);
205
205
  }
206
206
  }
207
207
  const created = await super.create(input as any, serviceOptions);
208
- await this.mainDbModel.updateOne({ _id: created.id }, { $set: { tenantId } }).exec();
208
+ // Only a tenant to record: an undefined key is dropped by MongoDB and written as NULL by a SQL store
209
+ if (tenantId !== undefined) {
210
+ await this.dataStore.updateById(created.id, { $set: { tenantId } });
211
+ }
209
212
  const reloaded = await this.get(created.id, serviceOptions);
210
213
  return this.decorateWithSystemFlags(reloaded);
211
214
  }
@@ -268,10 +271,9 @@ export class CoreAiSlotService extends CrudService<CoreAiSlot, CoreAiSlotCreateI
268
271
 
269
272
  let rows: CoreAiSlot[] = [];
270
273
  try {
271
- rows = await this.mainDbModel
272
- .find(tenantId ? { tenantId } : { $or: [{ tenantId: { $exists: false } }, { tenantId: null }] })
273
- .lean<CoreAiSlot[]>()
274
- .exec();
274
+ rows = (await this.dataStore.find(
275
+ tenantId ? { tenantId } : { $or: [{ tenantId: { $exists: false } }, { tenantId: null }] },
276
+ )) as CoreAiSlot[];
275
277
  } catch (err) {
276
278
  this.logger.warn(`listEffective failed to load rows: ${(err as Error).message}`);
277
279
  rows = [];
@@ -352,7 +354,7 @@ export class CoreAiSlotService extends CrudService<CoreAiSlot, CoreAiSlotCreateI
352
354
  async resetSystemSlot(id: string, serviceOptions: ServiceOptions = {}): Promise<EffectiveSlot> {
353
355
  this.assertAdmin(serviceOptions);
354
356
  await this.assertSameTenant(id, serviceOptions);
355
- const row = await this.mainDbModel.findById(id).lean<CoreAiSlot>().exec();
357
+ const row = (await this.dataStore.findById(id)) as CoreAiSlot | null;
356
358
  if (!row) {
357
359
  throw new ForbiddenException(`Slot ${id} not found.`);
358
360
  }
@@ -361,7 +363,7 @@ export class CoreAiSlotService extends CrudService<CoreAiSlot, CoreAiSlotCreateI
361
363
  if (!fallback) {
362
364
  throw new ForbiddenException('Only system-slot overrides can be reset. Use delete for custom slots.');
363
365
  }
364
- await this.mainDbModel.deleteOne({ _id: id }).exec();
366
+ await this.dataStore.deleteById(id);
365
367
  return {
366
368
  capability: fallback.capability,
367
369
  content: fallback.content,
@@ -407,10 +409,7 @@ export class CoreAiSlotService extends CrudService<CoreAiSlot, CoreAiSlotCreateI
407
409
  const tenantFilter = tenantId
408
410
  ? { tenantId: String(tenantId) }
409
411
  : { $or: [{ tenantId: { $exists: false } }, { tenantId: null }] };
410
- rows = await this.mainDbModel
411
- .find({ enabled: { $ne: false }, ...tenantFilter })
412
- .lean<CoreAiSlot[]>()
413
- .exec();
412
+ rows = (await this.dataStore.find({ enabled: { $ne: false }, ...tenantFilter })) as CoreAiSlot[];
414
413
  } catch {
415
414
  rows = [];
416
415
  }
@@ -421,10 +420,7 @@ export class CoreAiSlotService extends CrudService<CoreAiSlot, CoreAiSlotCreateI
421
420
  const tenantFilter = tenantId
422
421
  ? { tenantId: String(tenantId) }
423
422
  : { $or: [{ tenantId: { $exists: false } }, { tenantId: null }] };
424
- disabled = await this.mainDbModel
425
- .find({ enabled: false, ...tenantFilter })
426
- .lean<CoreAiSlot[]>()
427
- .exec();
423
+ disabled = (await this.dataStore.find({ enabled: false, ...tenantFilter })) as CoreAiSlot[];
428
424
  } catch {
429
425
  disabled = [];
430
426
  }
@@ -477,7 +473,7 @@ export class CoreAiSlotService extends CrudService<CoreAiSlot, CoreAiSlotCreateI
477
473
  */
478
474
  protected async assertSameTenant(id: string, serviceOptions: ServiceOptions): Promise<void> {
479
475
  const tenantId = this.tenantOf(serviceOptions);
480
- const row = await this.mainDbModel.findById(id, { tenantId: 1 }).lean<{ tenantId?: string }>().exec();
476
+ const row = (await this.dataStore.findById(id, { select: ['tenantId'] })) as { tenantId?: string } | null;
481
477
  if (!row) {
482
478
  throw new ForbiddenException(`Slot ${id} not found.`);
483
479
  }