@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,21 +1,36 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { hostname } from 'node:os';
3
+
1
4
  import { ForbiddenException, Injectable, Logger, OnApplicationBootstrap } from '@nestjs/common';
2
- import { InjectConnection } from '@nestjs/mongoose';
5
+ import { InjectConnection } from '../../common/persistence/mongo/mongoose-compat.js';
3
6
  import { isEmail } from 'class-validator';
7
+ import type { Collection } from 'mongodb';
4
8
  import type { Connection } from 'mongoose';
5
9
 
10
+ import {
11
+ defaultSqlLockStore,
12
+ SYSTEM_SETUP_CLAIM_STALE_AFTER_MS,
13
+ SYSTEM_SETUP_LOCK_COLLECTION,
14
+ SYSTEM_SETUP_LOCK_KEY,
15
+ systemSetupMongoLocks,
16
+ } from '../../common/persistence/infrastructure-locks.js';
17
+ import type { LockStore } from '../../common/persistence/lock-store.interface.js';
6
18
  import { ConfigService } from '../../common/services/config.service.js';
7
19
  import { legacyCredentialAccountIssuer } from '../better-auth/core-better-auth-account-issuer.helper.js';
8
20
  import { CoreBetterAuthUserMapper } from '../better-auth/core-better-auth-user.mapper.js';
9
21
  import { CoreBetterAuthService } from '../better-auth/core-better-auth.service.js';
10
22
  import { ErrorCode } from '../error-code/error-codes.js';
23
+ import { getPersistenceRuntime } from '../../common/persistence/persistence-runtime.registry.js';
24
+ import { getBetterAuthSqlStore } from '../better-auth/core-better-auth-sql.registry.js';
11
25
 
12
26
  /**
13
- * Collection holding the bootstrap claim markers.
27
+ * Collection holding the bootstrap claim marker on MongoDB — the 12.0.0 document (`{ _id, claimedAt }`), kept so
28
+ * an older replica in a rolling deploy claims the same marker (see `infrastructure-locks.ts`).
14
29
  *
15
30
  * Native collection access is intentional here: no Mongoose schema exists for it
16
31
  * (see docs/native-driver-security.md).
17
32
  */
18
- const SETUP_LOCK_COLLECTION = 'system-setup-locks';
33
+ const SETUP_LOCK_COLLECTION = SYSTEM_SETUP_LOCK_COLLECTION;
19
34
 
20
35
  /**
21
36
  * How long an initial-admin claim may stand before another replica takes it over.
@@ -23,10 +38,7 @@ const SETUP_LOCK_COLLECTION = 'system-setup-locks';
23
38
  * Long enough that a slow but live creation is never stolen, short enough that a crashed
24
39
  * claimer does not lock the deployment out for good.
25
40
  */
26
- const INITIAL_ADMIN_CLAIM_STALE_AFTER_MS = 5 * 60_000;
27
-
28
- /** `_id` of the marker claiming the initial-admin creation */
29
- const INITIAL_ADMIN_LOCK_ID = 'initial-admin';
41
+ const INITIAL_ADMIN_CLAIM_STALE_AFTER_MS = SYSTEM_SETUP_CLAIM_STALE_AFTER_MS;
30
42
 
31
43
  /**
32
44
  * Input for creating the initial admin user
@@ -70,6 +82,9 @@ export interface SystemSetupStatus {
70
82
  export class CoreSystemSetupService implements OnApplicationBootstrap {
71
83
  private readonly logger = new Logger(CoreSystemSetupService.name);
72
84
 
85
+ /** Who holds the claim: one owner per instance, so a second concurrent claim of the same process is refused too */
86
+ private readonly claimOwner = `${hostname()}:${process.pid}:${randomUUID()}`;
87
+
73
88
  constructor(
74
89
  @InjectConnection() private readonly connection: Connection,
75
90
  private readonly betterAuthService: CoreBetterAuthService,
@@ -149,39 +164,19 @@ export class CoreSystemSetupService implements OnApplicationBootstrap {
149
164
  /**
150
165
  * Try to claim the initial-admin creation for this instance
151
166
  *
152
- * The upsert on a fixed `_id` is atomic, so exactly one of N concurrently booting
153
- * replicas sees no previous document and wins the claim.
167
+ * A lease (`LockStore`), so exactly one of N concurrently booting replicas — or of N anonymous
168
+ * `POST /system-setup/init` callers — wins the claim.
154
169
  *
155
170
  * @returns true when this instance may create the initial admin
156
171
  */
157
172
  protected async claimInitialAdminSetup(): Promise<boolean> {
158
- try {
159
- const collection = this.connection.collection(SETUP_LOCK_COLLECTION);
160
-
161
- // The marker is a CLAIM, not a permanent record: a replica SIGKILLed between claiming and
162
- // creating (OOM, node drain, a failed first rollout — all ordinary) never reaches the
163
- // release in the catch below. Without an expiry that leaves a deployment with zero users
164
- // and no way in, recoverable only by deleting a document from an undocumented collection.
165
- // A stale claim is therefore taken over rather than obeyed.
166
- const staleBefore = new Date(Date.now() - INITIAL_ADMIN_CLAIM_STALE_AFTER_MS);
167
- await collection.deleteOne({ _id: INITIAL_ADMIN_LOCK_ID as any, claimedAt: { $lt: staleBefore } });
168
-
169
- const previous = await collection.findOneAndUpdate(
170
- { _id: INITIAL_ADMIN_LOCK_ID as any },
171
- { $setOnInsert: { claimedAt: new Date() } },
172
- { returnDocument: 'before', upsert: true },
173
- );
174
-
175
- // No previous document → this instance inserted the marker and owns the setup
176
- return !previous;
177
- } catch (error) {
178
- // Two replicas upserting the same `_id` at the very same moment: one insert wins,
179
- // the other gets a duplicate key error — which means the claim is taken.
180
- if (error instanceof Error && (error.message?.includes('duplicate key') || error.message?.includes('E11000'))) {
181
- return false;
182
- }
183
- throw error;
184
- }
173
+ // The marker is a CLAIM, not a permanent record: a replica SIGKILLed between claiming and
174
+ // creating (OOM, node drain, a failed first rollout — all ordinary) never reaches the
175
+ // release in createInitialAdmin(). Without an expiry that leaves a deployment with zero users
176
+ // and no way in, recoverable only by deleting a document from an undocumented collection.
177
+ // A stale claim is therefore taken over rather than obeyed.
178
+ const locks = await this.setupLocks();
179
+ return locks.tryAcquire(SYSTEM_SETUP_LOCK_KEY, this.claimOwner, INITIAL_ADMIN_CLAIM_STALE_AFTER_MS / 1000);
185
180
  }
186
181
 
187
182
  /**
@@ -189,7 +184,7 @@ export class CoreSystemSetupService implements OnApplicationBootstrap {
189
184
  */
190
185
  protected async releaseInitialAdminSetupClaim(): Promise<void> {
191
186
  try {
192
- await this.connection.collection(SETUP_LOCK_COLLECTION).deleteOne({ _id: INITIAL_ADMIN_LOCK_ID as any });
187
+ await (await this.setupLocks()).release(SYSTEM_SETUP_LOCK_KEY, this.claimOwner);
193
188
  } catch (error) {
194
189
  // Never mask the failure that triggered the release
195
190
  this.logger.warn(
@@ -198,11 +193,42 @@ export class CoreSystemSetupService implements OnApplicationBootstrap {
198
193
  }
199
194
  }
200
195
 
196
+ /**
197
+ * Where the claim lives: the lease table when the default data source is a SQL database, else the MongoDB marker
198
+ */
199
+ protected async setupLocks(): Promise<LockStore> {
200
+ return (
201
+ (await defaultSqlLockStore('system-setup')) ??
202
+ systemSetupMongoLocks(this.connection.collection(SETUP_LOCK_COLLECTION) as unknown as Collection<any>)
203
+ );
204
+ }
205
+
206
+ /**
207
+ * Where the claim lives, in the words an operator needs to clear it: the lease row on a SQL default source, the
208
+ * marker collection on MongoDB. The refusal log names it, so it must name the store `setupLocks()` actually uses.
209
+ */
210
+ protected async setupClaimLocation(): Promise<{ remedy: string; where: string }> {
211
+ if (await defaultSqlLockStore('system-setup')) {
212
+ const row = `system-setup:${SYSTEM_SETUP_LOCK_KEY}`;
213
+ return { remedy: `delete the row "${row}" from "lt_locks"`, where: `"lt_locks" (row "${row}")` };
214
+ }
215
+ return { remedy: `drop "${SETUP_LOCK_COLLECTION}"`, where: `"${SETUP_LOCK_COLLECTION}"` };
216
+ }
217
+
218
+ /**
219
+ * How many users exist, wherever the `users` table lives: a user model on a SQL source is counted there — counting the
220
+ * MongoDB collection instead would find none and let an anonymous caller create an administrator
221
+ */
222
+ protected async countUsers(): Promise<number> {
223
+ const users = getBetterAuthSqlStore()?.users ?? (await getPersistenceRuntime()?.iamStorage())?.users;
224
+ return users ? users.count({}) : this.connection.collection('users').countDocuments({});
225
+ }
226
+
201
227
  /**
202
228
  * Check if the system needs initial setup (zero users)
203
229
  */
204
230
  async getSetupStatus(): Promise<SystemSetupStatus> {
205
- const userCount = await this.connection.collection('users').countDocuments({});
231
+ const userCount = await this.countUsers();
206
232
  return {
207
233
  betterAuthEnabled: this.betterAuthService.isEnabled(),
208
234
  needsSetup: userCount === 0,
@@ -217,7 +243,7 @@ export class CoreSystemSetupService implements OnApplicationBootstrap {
217
243
  */
218
244
  async createInitialAdmin(input: SystemSetupInitInput): Promise<SystemSetupInitResult> {
219
245
  // Pre-check: only allow when zero users exist
220
- const userCount = await this.connection.collection('users').countDocuments({});
246
+ const userCount = await this.countUsers();
221
247
  if (userCount > 0) {
222
248
  throw new ForbiddenException(ErrorCode.SYSTEM_SETUP_NOT_AVAILABLE);
223
249
  }
@@ -253,11 +279,12 @@ export class CoreSystemSetupService implements OnApplicationBootstrap {
253
279
  // Two records with contradictory severity for one non-event trains operators to ignore the
254
280
  // louder one. The HTTP caller is not left without a diagnosis: the message is unchanged and
255
281
  // an operator investigating a 403 reads it at the default level.
282
+ const claim = await this.setupClaimLocation();
256
283
  this.logger.log(
257
- `System setup refused: the initial-admin claim in "${SETUP_LOCK_COLLECTION}" is held. ` +
284
+ `System setup refused: the initial-admin claim in ${claim.where} is held. ` +
258
285
  'Either another instance is running the setup right now, or a previous SUCCESSFUL setup ' +
259
286
  'left the marker behind — it is removed only when creation FAILS. If you reset the ' +
260
- `database to replay the setup, drop "${SETUP_LOCK_COLLECTION}" alongside "users"; ` +
287
+ `database to replay the setup, ${claim.remedy} alongside "users"; ` +
261
288
  `otherwise setup stays refused until the claim goes stale after ` +
262
289
  `${INITIAL_ADMIN_CLAIM_STALE_AFTER_MS / 60_000} minutes.`,
263
290
  );
@@ -334,10 +361,15 @@ export class CoreSystemSetupService implements OnApplicationBootstrap {
334
361
  throw new Error('Failed to sync user to nest-server collection');
335
362
  }
336
363
 
337
- // Set admin role directly
338
- await this.connection
339
- .collection('users')
340
- .updateOne({ _id: syncedUser._id }, { $set: { roles: ['admin'], updatedAt: new Date() } });
364
+ // Set admin role directly — the framework's own decision, as system work
365
+ const sql = getBetterAuthSqlStore();
366
+ if (sql) {
367
+ await sql.updateUserAsSystem(String(syncedUser._id), { roles: ['admin'] });
368
+ } else {
369
+ await this.connection
370
+ .collection('users')
371
+ .updateOne({ _id: syncedUser._id }, { $set: { roles: ['admin'], updatedAt: new Date() } });
372
+ }
341
373
 
342
374
  // Sync password to Legacy Auth for backwards compatibility
343
375
  await this.userMapper.syncPasswordToLegacy(iamUser.id, input.email, input.password);
@@ -247,11 +247,18 @@ for members, API tokens and the header-less tenant list — unless the project t
247
247
  ```typescript
248
248
  // config.env.ts
249
249
  multiTenancy: {
250
- isTenantActive: async (tenantId, { connection }) =>
251
- (await connection.collection('tenants').findOne({ _id: new Types.ObjectId(tenantId) }))?.active !== false,
250
+ // Any database: the project's tenant model, registered with CorePersistenceModule.forFeature()
251
+ isTenantActive: async (tenantId, { store }) => (await store('Tenant').findById(tenantId))?.active !== false,
252
252
  }
253
253
  ```
254
254
 
255
+ `store(modelName)` returns the data store of a model registered with `CorePersistenceModule.forFeature()` in the
256
+ running application, wherever `database` routes it. For a model registered any other way (`MongooseModule.forFeature()`,
257
+ which `lt server module` generates) it throws a `DataSourceConfigError`, and the request is refused: answering
258
+ `undefined` would make a hook written with `?.` count every deactivated tenant as active. `context.connection` (the MongoDB connection) is still passed
259
+ for a lookup on MongoDB only:
260
+ `(await connection.collection('tenants').findOne({ _id: new Types.ObjectId(tenantId) }))?.active !== false`.
261
+
255
262
  | Path | Deactivated tenant |
256
263
  | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
257
264
  | Header + tenant role, or `S_USER` / `S_VERIFIED` with a header | **403** `#LTNS_0106: Tenant is inactive` |
@@ -1,5 +1,5 @@
1
1
  import { ObjectType } from '@nestjs/graphql';
2
- import { Schema } from '@nestjs/mongoose';
2
+ import { Schema } from '../../common/persistence/mongo/mongoose-compat.js';
3
3
 
4
4
  import { Restricted } from '../../common/decorators/restricted.decorator.js';
5
5
  import { UnifiedField } from '../../common/decorators/unified-field.decorator.js';
@@ -0,0 +1,13 @@
1
+ import type { DataStore } from '../../common/persistence/data-store.interface.js';
2
+ import { getStoreForModel } from '../../common/persistence/persistence-runtime.registry.js';
3
+
4
+ /**
5
+ * The store serving the membership model when it is routed to a SQL database; `undefined` on MongoDB, where the
6
+ * guard and the service keep their Mongoose path unchanged.
7
+ *
8
+ * Read from the model INSTANCE the guard and the service were given, so it is the store of their own application.
9
+ */
10
+ export function routedMemberStore(memberModel: unknown): DataStore<any> | undefined {
11
+ const store = getStoreForModel(memberModel);
12
+ return store && !store.capabilities.mongoosePopulate ? store : undefined;
13
+ }
@@ -9,18 +9,23 @@ import {
9
9
  Optional,
10
10
  UnauthorizedException,
11
11
  } from '@nestjs/common';
12
- import { Reflector } from '@nestjs/core';
12
+ import { ModuleRef, Reflector } from '@nestjs/core';
13
13
  import { GqlExecutionContext } from '@nestjs/graphql';
14
- import { InjectModel } from '@nestjs/mongoose';
15
- import { Model } from 'mongoose';
14
+ import { InjectModel } from '../../common/persistence/mongo/mongoose-compat.js';
15
+ import type { Model } from 'mongoose';
16
+ import { firstValueFrom, isObservable } from 'rxjs';
16
17
 
17
18
  import { RoleEnum } from '../../common/enums/role.enum.js';
19
+ import { ROLE_GUARD } from '../auth/guards/role-guard.token.js';
18
20
  import { resolveGuardRequest } from '../../common/helpers/execution-context-request.helper.js';
19
21
  import {
20
22
  revalidateAllWsConnections,
21
23
  revalidateWsConnectionsForTenant,
22
24
  revalidateWsConnectionsOf,
23
25
  } from '../../common/helpers/graphql-ws-connection.helper.js';
26
+ import { DataSourceConfigError } from '../../common/persistence/data-source.config.js';
27
+ import type { DataStore } from '../../common/persistence/data-store.interface.js';
28
+ import { getStoreToken } from '../../common/persistence/persistence.tokens.js';
24
29
  import { ConfigService } from '../../common/services/config.service.js';
25
30
  import { ResolvedTenantContext, setTenantContextResolver } from '../../common/services/core-tenant-context.registry.js';
26
31
  import { CoreRedisService } from '../../common/services/core-redis.service.js';
@@ -33,6 +38,7 @@ import {
33
38
  } from '../api-token/core-api-token.helpers.js';
34
39
  import { ErrorCode } from '../error-code/error-codes.js';
35
40
  import { CoreTenantMemberModel } from './core-tenant-member.model.js';
41
+ import { routedMemberStore } from './core-tenant-member.store.js';
36
42
  import { registerActiveTenantGuard } from './core-tenant-guard.registry.js';
37
43
  import { SKIP_TENANT_CHECK_KEY } from './core-tenant.decorators.js';
38
44
  import { TENANT_MEMBER_MODEL_TOKEN, TenantMemberStatus } from './core-tenant.enums.js';
@@ -171,6 +177,7 @@ export class CoreTenantGuard implements CanActivate, OnApplicationBootstrap, OnM
171
177
  private readonly reflector: Reflector,
172
178
  @InjectModel(TENANT_MEMBER_MODEL_TOKEN) private readonly memberModel: Model<CoreTenantMemberModel>,
173
179
  @Optional() protected readonly redisService?: CoreRedisService,
180
+ @Optional() protected readonly moduleRef?: ModuleRef,
174
181
  ) {
175
182
  // Clean up expired cache entries every 60 seconds
176
183
  this.cleanupInterval = setInterval(() => this.evictExpired(), 60_000);
@@ -189,6 +196,31 @@ export class CoreTenantGuard implements CanActivate, OnApplicationBootstrap, OnM
189
196
  this.releaseTenantGuard = registerActiveTenantGuard();
190
197
  }
191
198
 
199
+ /**
200
+ * The data store of a model registered with `CorePersistenceModule.forFeature()` in THIS application, for the
201
+ * `isTenantActive` hook — the tenant model may live in a SQL database, where `connection` cannot reach it.
202
+ *
203
+ * Throws for a model that is not registered that way, never answers `undefined`: the hook decides whether a
204
+ * deactivated tenant stays locked, and `store('Tenant')?.findById(id)` on an unregistered model would read as
205
+ * "active" — every tenant open, without a log line. A thrown error refuses the request instead.
206
+ */
207
+ protected readonly storeOf = (modelName: string): DataStore<any> => {
208
+ let store: DataStore<any> | undefined;
209
+ try {
210
+ store = this.moduleRef?.get(getStoreToken(modelName), { strict: false });
211
+ } catch {
212
+ store = undefined;
213
+ }
214
+ if (!store) {
215
+ throw new DataSourceConfigError(
216
+ `multiTenancy.isTenantActive asked for the store of '${modelName}', which is not registered with ` +
217
+ 'CorePersistenceModule.forFeature() in this application — register it there, or look the tenant up ' +
218
+ 'through context.connection',
219
+ );
220
+ }
221
+ return store;
222
+ };
223
+
192
224
  /** Releases this guard's registration (see core-tenant-guard.registry.ts). */
193
225
  private releaseTenantGuard?: () => void;
194
226
 
@@ -458,6 +490,14 @@ export class CoreTenantGuard implements CanActivate, OnApplicationBootstrap, OnM
458
490
  return true;
459
491
  }
460
492
 
493
+ // Global guards run in registration order, and CoreModule registers this module AHEAD of a project's AuthModule:
494
+ // with legacy JWTs (no middleware identifies them) the role guard has not run yet and nobody is on the request.
495
+ // The documented order is role guard, then tenant guard — so let this application's role guard identify the
496
+ // caller first. It decides exactly what it would decide right after this guard, so its 401/403 is the answer.
497
+ if (!request.user) {
498
+ await this.identifyThroughRoleGuard(context);
499
+ }
500
+
461
501
  const user = request.user;
462
502
  const adminBypass = config.adminBypass !== false;
463
503
  const isAdmin = adminBypass && user?.roles?.includes(RoleEnum.ADMIN);
@@ -679,14 +719,11 @@ export class CoreTenantGuard implements CanActivate, OnApplicationBootstrap, OnM
679
719
  }
680
720
  }
681
721
 
682
- const memberships = await this.memberModel
683
- .find({
684
- status: TenantMemberStatus.ACTIVE,
685
- user: userId,
686
- })
687
- .select('tenant role')
688
- .lean()
689
- .exec();
722
+ const active = { status: TenantMemberStatus.ACTIVE, user: userId };
723
+ const memberStore = routedMemberStore(this.memberModel);
724
+ const memberships = memberStore
725
+ ? await memberStore.find(active, { select: ['tenant', 'role'] })
726
+ : await this.memberModel.find(active).select('tenant role').lean().exec();
690
727
 
691
728
  let ids: string[];
692
729
  if (minLevel !== undefined) {
@@ -823,6 +860,32 @@ export class CoreTenantGuard implements CanActivate, OnApplicationBootstrap, OnM
823
860
  }
824
861
  }
825
862
 
863
+ /**
864
+ * Run this application's role guard when no caller is identified yet — see canActivate(). A no-op without one (a
865
+ * custom guard chain) and when the role guard is this guard.
866
+ */
867
+ protected async identifyThroughRoleGuard(context: ExecutionContext): Promise<void> {
868
+ let roleGuard: CanActivate | undefined;
869
+ try {
870
+ roleGuard = this.moduleRef?.get<CanActivate>(ROLE_GUARD, { strict: false });
871
+ } catch {
872
+ return;
873
+ }
874
+ if (roleGuard && roleGuard !== (this as CanActivate)) {
875
+ const result = roleGuard.canActivate(context);
876
+ await (isObservable(result) ? firstValueFrom(result) : result);
877
+ }
878
+ }
879
+
880
+ /** The active membership, from the membership store of the database the model is routed to */
881
+ private async findActiveMembership(userId: string, tenantId: string): Promise<CoreTenantMemberModel | null> {
882
+ const where = { status: TenantMemberStatus.ACTIVE, tenant: tenantId, user: userId };
883
+ const memberStore = routedMemberStore(this.memberModel);
884
+ return (
885
+ memberStore ? await memberStore.findOne(where) : await this.memberModel.findOne(where).lean().exec()
886
+ ) as CoreTenantMemberModel | null;
887
+ }
888
+
826
889
  /**
827
890
  * Look up a membership with process-level TTL cache.
828
891
  * Avoids repeated DB queries when the same user accesses the same tenant repeatedly.
@@ -832,10 +895,7 @@ export class CoreTenantGuard implements CanActivate, OnApplicationBootstrap, OnM
832
895
 
833
896
  // Cache disabled (ttl = 0): always query DB
834
897
  if (ttl <= 0) {
835
- return this.memberModel
836
- .findOne({ status: TenantMemberStatus.ACTIVE, tenant: tenantId, user: userId })
837
- .lean()
838
- .exec() as Promise<CoreTenantMemberModel | null>;
898
+ return this.findActiveMembership(userId, tenantId);
839
899
  }
840
900
 
841
901
  const key = `${userId}:${tenantId}`;
@@ -846,14 +906,7 @@ export class CoreTenantGuard implements CanActivate, OnApplicationBootstrap, OnM
846
906
  return cached.result;
847
907
  }
848
908
 
849
- const result = (await this.memberModel
850
- .findOne({
851
- status: TenantMemberStatus.ACTIVE,
852
- tenant: tenantId,
853
- user: userId,
854
- })
855
- .lean()
856
- .exec()) as CoreTenantMemberModel | null;
909
+ const result = await this.findActiveMembership(userId, tenantId);
857
910
 
858
911
  // Only cache positive results (active membership found).
859
912
  // Negative results (null) are NOT cached to ensure that:
@@ -928,7 +981,7 @@ export class CoreTenantGuard implements CanActivate, OnApplicationBootstrap, OnM
928
981
  return cached.active;
929
982
  }
930
983
  }
931
- const active = (await hook(tenantId, { connection: this.memberModel.db })) !== false;
984
+ const active = (await hook(tenantId, { connection: this.memberModel.db, store: this.storeOf })) !== false;
932
985
  if (ttl > 0) {
933
986
  this.evictIfOverCapacity(this.tenantActiveCache);
934
987
  this.tenantActiveCache.set(tenantId, { active, expiresAt: now + ttl });
@@ -1,8 +1,9 @@
1
1
  import { CanActivate, DynamicModule, Global, Module, OnModuleDestroy, OnModuleInit, Type } from '@nestjs/common';
2
2
  import { APP_GUARD } from '@nestjs/core';
3
- import { MongooseModule, SchemaFactory, getModelToken } from '@nestjs/mongoose';
4
- import { Model } from 'mongoose';
3
+ import { getModelToken, SchemaFactory } from '../../common/persistence/mongo/mongoose-compat.js';
4
+ import type { Model } from 'mongoose';
5
5
 
6
+ import { CorePersistenceModule } from '../../common/persistence/core-persistence.module.js';
6
7
  import { roleScopeRegistry } from './core-role-scope.registry.js';
7
8
  import { registerActiveTenantGuard } from './core-tenant-guard.registry.js';
8
9
  import { CoreTenantMemberModel } from './core-tenant-member.model.js';
@@ -127,7 +128,9 @@ export class CoreTenantModule implements OnModuleDestroy, OnModuleInit {
127
128
  return {
128
129
  exports: [CoreTenantService],
129
130
  global: true,
130
- imports: [MongooseModule.forFeature([{ name: modelName, schema: memberSchema }])],
131
+ // Database-neutral registration: the membership model follows `database` like every other model, and the guard
132
+ // and the service switch to its store when it is routed to a SQL database
133
+ imports: [CorePersistenceModule.forFeature([{ name: modelName, schema: memberSchema }])],
131
134
  module: CoreTenantModule,
132
135
  providers,
133
136
  };
@@ -1,11 +1,13 @@
1
1
  import { BadRequestException, Injectable, Logger, NotFoundException, Optional } 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 { looksLikeGlobalOnlyRole, looksLikeSystemRole, SYSTEM_ROLE_PREFIX } from '../../common/enums/role.enum.js';
6
+ import type { DataStore } from '../../common/persistence/data-store.interface.js';
6
7
  import { ConfigService } from '../../common/services/config.service.js';
7
8
  import { RequestContext } from '../../common/services/request-context.service.js';
8
9
  import { CoreTenantMemberModel } from './core-tenant-member.model.js';
10
+ import { routedMemberStore } from './core-tenant-member.store.js';
9
11
  import { DEFAULT_ROLE_HIERARCHY, TENANT_MEMBER_MODEL_TOKEN, TenantMemberStatus } from './core-tenant.enums.js';
10
12
  import { CoreTenantGuard } from './core-tenant.guard.js';
11
13
 
@@ -37,6 +39,11 @@ export class CoreTenantService {
37
39
  @Optional() protected readonly tenantGuard?: CoreTenantGuard,
38
40
  ) {}
39
41
 
42
+ /** The membership store when the model is routed to SQL; `undefined` keeps the Mongoose path (MongoDB) */
43
+ protected get memberStore(): DataStore<any> | undefined {
44
+ return routedMemberStore(this.memberModel);
45
+ }
46
+
40
47
  /**
41
48
  * Get the configured role hierarchy.
42
49
  */
@@ -68,6 +75,11 @@ export class CoreTenantService {
68
75
  * Find all active tenant memberships for a user.
69
76
  */
70
77
  async findMemberships(userId: string): Promise<CoreTenantMemberModel[]> {
78
+ if (this.memberStore) {
79
+ return this.memberStore.find({ status: TenantMemberStatus.ACTIVE, user: userId }) as Promise<
80
+ CoreTenantMemberModel[]
81
+ >;
82
+ }
71
83
  return this.memberModel.find({ status: TenantMemberStatus.ACTIVE, user: userId }).lean().exec() as Promise<
72
84
  CoreTenantMemberModel[]
73
85
  >;
@@ -92,6 +104,9 @@ export class CoreTenantService {
92
104
  * For an authorization check use {@link getActiveMembership}.
93
105
  */
94
106
  async getMembership(tenantId: string, userId: string): Promise<CoreTenantMemberModel | null> {
107
+ if (this.memberStore) {
108
+ return this.memberStore.findOne({ tenant: tenantId, user: userId }) as Promise<CoreTenantMemberModel | null>;
109
+ }
95
110
  return this.memberModel
96
111
  .findOne({ tenant: tenantId, user: userId })
97
112
  .lean()
@@ -111,10 +126,11 @@ export class CoreTenantService {
111
126
  return null;
112
127
  }
113
128
 
114
- return this.memberModel
115
- .findOne({ status: TenantMemberStatus.ACTIVE, tenant: tenantId, user: userId })
116
- .lean()
117
- .exec() as Promise<CoreTenantMemberModel | null>;
129
+ const where = { status: TenantMemberStatus.ACTIVE, tenant: tenantId, user: userId };
130
+ if (this.memberStore) {
131
+ return this.memberStore.findOne(where) as Promise<CoreTenantMemberModel | null>;
132
+ }
133
+ return this.memberModel.findOne(where).lean().exec() as Promise<CoreTenantMemberModel | null>;
118
134
  }
119
135
 
120
136
  /**
@@ -146,33 +162,40 @@ export class CoreTenantService {
146
162
  }
147
163
  // Reactivate suspended/invited membership
148
164
  return RequestContext.runWithBypassTenantGuard(async () => {
149
- const result = (await this.memberModel
150
- .findOneAndUpdate(
151
- { tenant: tenantId, user: userId },
152
- {
153
- invitedBy: invitedById,
154
- joinedAt: new Date(),
155
- role: effectiveRole,
156
- status: TenantMemberStatus.ACTIVE,
157
- },
158
- { returnDocument: 'after' },
159
- )
160
- .lean()
161
- .exec()) as CoreTenantMemberModel;
165
+ const reactivation = {
166
+ invitedBy: invitedById,
167
+ joinedAt: new Date(),
168
+ role: effectiveRole,
169
+ status: TenantMemberStatus.ACTIVE,
170
+ };
171
+ const result = (
172
+ this.memberStore
173
+ ? await this.memberStore.updateOne({ tenant: tenantId, user: userId }, reactivation)
174
+ : await this.memberModel
175
+ .findOneAndUpdate({ tenant: tenantId, user: userId }, reactivation, { returnDocument: 'after' })
176
+ .lean()
177
+ .exec()
178
+ ) as CoreTenantMemberModel;
162
179
  this.tenantGuard?.invalidateUser(userId);
163
180
  return result;
164
181
  });
165
182
  }
166
183
 
167
184
  return RequestContext.runWithBypassTenantGuard(async () => {
168
- const doc = await this.memberModel.create({
185
+ const member = {
169
186
  invitedBy: invitedById,
170
187
  joinedAt: new Date(),
171
188
  role: effectiveRole,
172
189
  status: TenantMemberStatus.ACTIVE,
173
190
  tenant: tenantId,
174
191
  user: userId,
175
- });
192
+ };
193
+ if (this.memberStore) {
194
+ const created = await this.memberStore.insert(member);
195
+ this.tenantGuard?.invalidateUser(userId);
196
+ return created as CoreTenantMemberModel;
197
+ }
198
+ const doc = await this.memberModel.create(member);
176
199
  this.tenantGuard?.invalidateUser(userId);
177
200
  return doc.toObject() as CoreTenantMemberModel;
178
201
  });
@@ -192,14 +215,13 @@ export class CoreTenantService {
192
215
  await this.assertNotLastOwner(tenantId, userId);
193
216
 
194
217
  return RequestContext.runWithBypassTenantGuard(async () => {
195
- const result = await this.memberModel
196
- .findOneAndUpdate(
197
- { status: TenantMemberStatus.ACTIVE, tenant: tenantId, user: userId },
198
- { status: TenantMemberStatus.SUSPENDED },
199
- { returnDocument: 'after' },
200
- )
201
- .lean()
202
- .exec();
218
+ const where = { status: TenantMemberStatus.ACTIVE, tenant: tenantId, user: userId };
219
+ const result = this.memberStore
220
+ ? await this.memberStore.updateOne(where, { status: TenantMemberStatus.SUSPENDED })
221
+ : await this.memberModel
222
+ .findOneAndUpdate(where, { status: TenantMemberStatus.SUSPENDED }, { returnDocument: 'after' })
223
+ .lean()
224
+ .exec();
203
225
 
204
226
  if (!result) {
205
227
  throw new NotFoundException('Membership not found');
@@ -237,14 +259,10 @@ export class CoreTenantService {
237
259
  }
238
260
 
239
261
  return RequestContext.runWithBypassTenantGuard(async () => {
240
- const result = await this.memberModel
241
- .findOneAndUpdate(
242
- { status: TenantMemberStatus.ACTIVE, tenant: tenantId, user: userId },
243
- { role },
244
- { returnDocument: 'after' },
245
- )
246
- .lean()
247
- .exec();
262
+ const where = { status: TenantMemberStatus.ACTIVE, tenant: tenantId, user: userId };
263
+ const result = this.memberStore
264
+ ? await this.memberStore.updateOne(where, { role })
265
+ : await this.memberModel.findOneAndUpdate(where, { role }, { returnDocument: 'after' }).lean().exec();
248
266
 
249
267
  if (!result) {
250
268
  throw new NotFoundException('Active membership not found');
@@ -267,11 +285,10 @@ export class CoreTenantService {
267
285
  const highestRole = this.getHighestRole();
268
286
 
269
287
  return RequestContext.runWithBypassTenantGuard(async () => {
270
- const ownerCount = await this.memberModel.countDocuments({
271
- role: highestRole,
272
- status: TenantMemberStatus.ACTIVE,
273
- tenant: tenantId,
274
- });
288
+ const owners = { role: highestRole, status: TenantMemberStatus.ACTIVE, tenant: tenantId };
289
+ const ownerCount = this.memberStore
290
+ ? await this.memberStore.count(owners)
291
+ : await this.memberModel.countDocuments(owners);
275
292
 
276
293
  if (ownerCount <= 1) {
277
294
  const membership = await this.getActiveMembership(tenantId, userId);