insforge 0.3.3 → 1.2.10

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 (507) hide show
  1. package/.claude-plugin/marketplace.json +20 -0
  2. package/.cursor/rules/cursor-rules.mdc +94 -0
  3. package/.dockerignore +3 -0
  4. package/.env.example +33 -4
  5. package/.github/ISSUE_TEMPLATE/bug_report.yml +13 -60
  6. package/.github/ISSUE_TEMPLATE/config.yml +2 -2
  7. package/.github/ISSUE_TEMPLATE/feature_request.yml +10 -63
  8. package/.github/PULL_REQUEST_TEMPLATE.md +7 -0
  9. package/.github/workflows/build-image.yml +2 -1
  10. package/.github/workflows/e2e.yml +63 -0
  11. package/CHANGELOG.md +41 -0
  12. package/CLAUDE_PLUGIN.md +104 -0
  13. package/CODE_OF_CONDUCT.md +128 -0
  14. package/CONTRIBUTING.md +1 -1
  15. package/Dockerfile +4 -1
  16. package/README.md +66 -18
  17. package/assets/mcpInstallv2.png +0 -0
  18. package/assets/sampleResponse.png +0 -0
  19. package/auth/index.html +13 -0
  20. package/auth/package.json +28 -0
  21. package/auth/public/favicon.ico +0 -0
  22. package/auth/src/App.tsx +33 -0
  23. package/auth/src/components/ErrorCard.tsx +37 -0
  24. package/auth/src/components/Layout.tsx +13 -0
  25. package/auth/src/index.css +19 -0
  26. package/auth/src/lib/broadcastService.ts +115 -0
  27. package/auth/src/lib/utils.ts +11 -0
  28. package/auth/src/main.tsx +22 -0
  29. package/auth/src/pages/ForgotPasswordPage.tsx +11 -0
  30. package/auth/src/pages/ResetPasswordPage.tsx +11 -0
  31. package/auth/src/pages/SignInPage.tsx +57 -0
  32. package/auth/src/pages/SignUpPage.tsx +57 -0
  33. package/auth/src/pages/VerifyEmailPage.tsx +20 -0
  34. package/auth/src/vite-env.d.ts +10 -0
  35. package/auth/tsconfig.json +32 -0
  36. package/auth/tsconfig.node.json +11 -0
  37. package/auth/vite.config.ts +25 -0
  38. package/backend/package.json +9 -9
  39. package/backend/src/api/{middleware → middlewares}/auth.ts +8 -9
  40. package/backend/src/api/middlewares/rate-limiters.ts +127 -0
  41. package/backend/src/api/routes/{ai.ts → ai/index.routes.ts} +20 -24
  42. package/backend/src/api/routes/auth/index.routes.ts +570 -0
  43. package/backend/src/api/routes/auth/oauth.routes.ts +448 -0
  44. package/backend/src/api/routes/{database.advance.ts → database/advance.routes.ts} +107 -65
  45. package/backend/src/api/routes/database/index.routes.ts +13 -0
  46. package/backend/src/api/routes/{database.records.ts → database/records.routes.ts} +22 -8
  47. package/backend/src/api/routes/{database.tables.ts → database/tables.routes.ts} +20 -23
  48. package/backend/src/api/routes/docs/index.routes.ts +76 -0
  49. package/backend/src/api/routes/functions/index.routes.ts +188 -0
  50. package/backend/src/api/routes/{logs.ts → logs/index.routes.ts} +25 -30
  51. package/backend/src/api/routes/{metadata.ts → metadata/index.routes.ts} +21 -31
  52. package/backend/src/api/routes/{secrets.ts → secrets/index.routes.ts} +27 -22
  53. package/backend/src/api/routes/{storage.ts → storage/index.routes.ts} +34 -53
  54. package/backend/src/api/routes/usage/index.routes.ts +89 -0
  55. package/backend/src/infra/config/app.config.ts +51 -0
  56. package/backend/src/{core/database/manager.ts → infra/database/database.manager.ts} +76 -85
  57. package/backend/src/infra/database/migrations/013_create-auth-schema-functions.sql +44 -0
  58. package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +8 -0
  59. package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +60 -0
  60. package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -0
  61. package/backend/src/{core/secrets/encryption.ts → infra/security/encryption.manager.ts} +3 -2
  62. package/backend/src/infra/security/token.manager.ts +125 -0
  63. package/backend/src/{core/socket/socket.ts → infra/socket/socket.manager.ts} +15 -15
  64. package/backend/src/providers/ai/openrouter.provider.ts +377 -0
  65. package/backend/src/providers/email/base.provider.ts +41 -0
  66. package/backend/src/providers/email/cloud.provider.ts +187 -0
  67. package/backend/src/{core/logs/providers → providers/logs}/base.provider.ts +11 -11
  68. package/backend/src/{core/logs/providers → providers/logs}/cloudwatch.provider.ts +61 -38
  69. package/backend/src/providers/logs/local.provider.ts +185 -0
  70. package/backend/src/providers/oauth/base.provider.ts +29 -0
  71. package/backend/src/providers/oauth/discord.provider.ts +195 -0
  72. package/backend/src/providers/oauth/facebook.provider.ts +194 -0
  73. package/backend/src/providers/oauth/github.provider.ts +208 -0
  74. package/backend/src/providers/oauth/google.provider.ts +249 -0
  75. package/backend/src/providers/oauth/index.ts +7 -0
  76. package/backend/src/providers/oauth/linkedin.provider.ts +240 -0
  77. package/backend/src/providers/oauth/microsoft.provider.ts +169 -0
  78. package/backend/src/providers/oauth/x.provider.ts +202 -0
  79. package/backend/src/providers/storage/base.provider.ts +29 -0
  80. package/backend/src/providers/storage/local.provider.ts +103 -0
  81. package/backend/src/providers/storage/s3.provider.ts +313 -0
  82. package/backend/src/server.ts +70 -74
  83. package/backend/src/{core/ai/config.ts → services/ai/ai-config.service.ts} +19 -24
  84. package/backend/src/services/ai/ai-model.service.ts +60 -0
  85. package/backend/src/{core/ai/usage.ts → services/ai/ai-usage.service.ts} +28 -35
  86. package/backend/src/{core/ai/chat.ts → services/ai/chat-completion.service.ts} +37 -24
  87. package/backend/src/services/ai/helpers.ts +64 -0
  88. package/backend/src/{core/ai/image.ts → services/ai/image-generation.service.ts} +17 -19
  89. package/backend/src/services/ai/index.ts +13 -0
  90. package/backend/src/services/auth/auth-config.service.ts +250 -0
  91. package/backend/src/services/auth/auth-otp.service.ts +424 -0
  92. package/backend/src/services/auth/auth.service.ts +1136 -0
  93. package/backend/src/services/auth/index.ts +4 -0
  94. package/backend/src/{core/auth/oauth.ts → services/auth/oauth-config.service.ts} +106 -52
  95. package/backend/src/{core/database/advance.ts → services/database/database-advance.service.ts} +97 -131
  96. package/backend/src/services/database/database-table.service.ts +811 -0
  97. package/backend/src/services/email/email.service.ts +75 -0
  98. package/backend/src/{core/functions/functions.ts → services/functions/function.service.ts} +95 -88
  99. package/backend/src/{core/logs/audit.ts → services/logs/audit.service.ts} +92 -75
  100. package/backend/src/services/logs/log.service.ts +73 -0
  101. package/backend/src/{core/secrets/secrets.ts → services/secrets/secret.service.ts} +48 -66
  102. package/backend/src/services/storage/storage.service.ts +617 -0
  103. package/backend/src/services/usage/usage.service.ts +149 -0
  104. package/backend/src/types/auth.ts +66 -2
  105. package/backend/src/types/email.ts +8 -0
  106. package/backend/src/types/error-constants.ts +4 -0
  107. package/backend/src/types/logs.ts +0 -29
  108. package/backend/src/{core/socket/types.ts → types/socket.ts} +5 -6
  109. package/backend/src/utils/environment.ts +9 -3
  110. package/backend/src/utils/logger.ts +20 -2
  111. package/backend/src/utils/seed.ts +150 -57
  112. package/backend/src/utils/sql-parser.ts +1 -1
  113. package/backend/src/utils/utils.ts +114 -0
  114. package/backend/src/utils/validations.ts +40 -4
  115. package/backend/tests/local/test-ai-config.sh +129 -0
  116. package/backend/tests/local/test-ai-usage.sh +80 -0
  117. package/backend/tests/local/test-auth-router.sh +1 -1
  118. package/backend/tests/local/test-e2e.sh +1 -1
  119. package/backend/tests/local/test-functions.sh +123 -0
  120. package/backend/tests/local/test-logs.sh +132 -0
  121. package/backend/tests/local/test-public-bucket.sh +3 -3
  122. package/backend/tests/local/test-secrets.sh +14 -12
  123. package/backend/tests/local/test-traditional-rest.sh +2 -2
  124. package/backend/tests/manual/test-rawsql-modes.sh +244 -0
  125. package/backend/tests/test-config.sh +37 -1
  126. package/backend/tests/unit/cloud-token.test.ts +48 -0
  127. package/backend/tests/unit/constant.test.ts +8 -0
  128. package/backend/tests/unit/email.test.ts +372 -0
  129. package/backend/tests/unit/environment.test.ts +59 -0
  130. package/backend/tests/unit/helpers.test.ts +63 -0
  131. package/backend/tests/unit/logger.test.ts +22 -0
  132. package/backend/tests/unit/rate-limit.test.ts +154 -0
  133. package/backend/tests/unit/response.test.ts +58 -0
  134. package/backend/tests/unit/sql-parser.test.ts +74 -0
  135. package/backend/tests/unit/uuid.test.ts +21 -0
  136. package/backend/tests/unit/validations.test.ts +80 -0
  137. package/backend/tsconfig.json +1 -1
  138. package/backend/vitest.config.ts +11 -0
  139. package/claude-plugin/.claude-plugin/plugin.json +24 -0
  140. package/claude-plugin/README.md +133 -0
  141. package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +270 -0
  142. package/docker-compose.prod.yml +60 -4
  143. package/docker-compose.yml +65 -4
  144. package/docker-init/db/db-init.sql +6 -34
  145. package/docker-init/logs/vector.yml +236 -0
  146. package/docs/README.md +44 -0
  147. package/docs/changelog.mdx +67 -0
  148. package/docs/core-concepts/ai/architecture.mdx +373 -0
  149. package/docs/core-concepts/ai/sdk.mdx +213 -0
  150. package/docs/core-concepts/authentication/architecture.mdx +278 -0
  151. package/docs/core-concepts/authentication/sdk.mdx +414 -0
  152. package/docs/core-concepts/authentication/ui-components/customization.mdx +529 -0
  153. package/docs/core-concepts/authentication/ui-components/nextjs.mdx +221 -0
  154. package/docs/core-concepts/authentication/ui-components/react-router.mdx +184 -0
  155. package/docs/core-concepts/authentication/ui-components/react.mdx +129 -0
  156. package/docs/core-concepts/database/architecture.mdx +256 -0
  157. package/docs/core-concepts/database/sdk.mdx +382 -0
  158. package/docs/core-concepts/functions/architecture.mdx +105 -0
  159. package/docs/core-concepts/functions/sdk.mdx +184 -0
  160. package/docs/core-concepts/storage/architecture.mdx +243 -0
  161. package/docs/core-concepts/storage/sdk.mdx +253 -0
  162. package/docs/deployment/README.md +94 -0
  163. package/docs/deployment/deploy-to-aws-ec2.md +565 -0
  164. package/docs/deployment/deploy-to-azure-virtual-machines.md +313 -0
  165. package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -0
  166. package/docs/deployment/deploy-to-render.md +441 -0
  167. package/docs/docs.json +210 -0
  168. package/docs/examples/framework-guides/nextjs.mdx +131 -0
  169. package/docs/examples/framework-guides/nuxt.mdx +165 -0
  170. package/docs/examples/framework-guides/react.mdx +165 -0
  171. package/docs/examples/framework-guides/svelte.mdx +153 -0
  172. package/docs/examples/framework-guides/vue.mdx +159 -0
  173. package/docs/examples/overview.mdx +67 -0
  174. package/docs/favicon.svg +19 -0
  175. package/docs/images/changelog/nov-2025/auth-components.webp +0 -0
  176. package/docs/images/changelog/nov-2025/database-metadata.webp +0 -0
  177. package/docs/images/changelog/nov-2025/quickstart-prompts.webp +0 -0
  178. package/docs/images/changelog/nov-2025/sql-editor.webp +0 -0
  179. package/docs/images/changelog/nov-2025/usage-page.webp +0 -0
  180. package/docs/images/changelog/october-2025/csv-upload.webp +0 -0
  181. package/docs/images/changelog/october-2025/logs-feature.webp +0 -0
  182. package/docs/images/changelog/october-2025/oauth-providers.webp +0 -0
  183. package/docs/images/checks-passed.png +0 -0
  184. package/docs/images/dashboard-connect-expanded.png +0 -0
  185. package/docs/images/dashboard-connect.png +0 -0
  186. package/docs/images/hero-dark.png +0 -0
  187. package/docs/images/hero-light.png +0 -0
  188. package/docs/images/icons/ai.svg +4 -0
  189. package/docs/images/icons/auth.svg +1 -0
  190. package/docs/images/icons/database.svg +1 -0
  191. package/docs/images/icons/function.svg +1 -0
  192. package/docs/images/icons/storage.svg +1 -0
  193. package/docs/images/logos/nextjs.svg +4 -0
  194. package/docs/images/logos/nuxt.svg +4 -0
  195. package/docs/images/logos/react.svg +5 -0
  196. package/docs/images/logos/svelte.svg +4 -0
  197. package/docs/images/logos/vue.svg +5 -0
  198. package/docs/images/mcp-install.png +0 -0
  199. package/docs/images/onboarding-mcp.png +0 -0
  200. package/docs/insforge-instructions-sdk.md +55 -374
  201. package/docs/introduction.mdx +45 -0
  202. package/docs/logo/dark.svg +22 -0
  203. package/docs/logo/light.svg +20 -0
  204. package/docs/partnership.mdx +647 -0
  205. package/docs/quickstart.mdx +83 -0
  206. package/docs/showcase/2048-arena.png +0 -0
  207. package/docs/showcase/framegen-cloud.png +0 -0
  208. package/docs/showcase/line-connect-race.png +0 -0
  209. package/docs/showcase/moment-vibe.png +0 -0
  210. package/docs/showcase/national-flags.png +0 -0
  211. package/docs/showcase/pokemon-vibe.png +0 -0
  212. package/docs/showcase/pure-browse-buy.png +0 -0
  213. package/docs/showcase.mdx +52 -0
  214. package/docs/snippets/sdk-installation.mdx +22 -0
  215. package/docs/snippets/service-icons.mdx +27 -0
  216. package/eslint.config.js +10 -3
  217. package/frontend/package.json +10 -4
  218. package/frontend/src/App.tsx +13 -82
  219. package/frontend/src/assets/icons/connected.svg +3 -0
  220. package/frontend/src/assets/icons/loader.svg +9 -0
  221. package/frontend/src/assets/logos/apple.svg +4 -0
  222. package/frontend/src/assets/logos/discord.svg +1 -1
  223. package/frontend/src/assets/logos/facebook.svg +3 -0
  224. package/frontend/src/assets/logos/instagram.svg +2 -0
  225. package/frontend/src/assets/logos/linkedin.svg +3 -0
  226. package/frontend/src/assets/logos/microsoft.svg +1 -0
  227. package/frontend/src/assets/logos/spotify.svg +17 -0
  228. package/frontend/src/assets/logos/tiktok.svg +6 -0
  229. package/frontend/src/assets/logos/x.svg +3 -0
  230. package/frontend/src/components/Checkbox.tsx +27 -29
  231. package/frontend/src/components/CodeBlock.tsx +55 -2
  232. package/frontend/src/components/CodeEditor.tsx +92 -0
  233. package/frontend/src/components/ConfirmDialog.tsx +1 -1
  234. package/frontend/src/components/ConnectCTA.tsx +38 -0
  235. package/frontend/src/components/CopyButton.tsx +52 -15
  236. package/frontend/src/components/ErrorState.tsx +1 -2
  237. package/frontend/src/components/FeatureSidebar.tsx +6 -6
  238. package/frontend/src/components/FeatureSidebarItem.tsx +2 -2
  239. package/frontend/src/components/JsonHighlight.tsx +21 -9
  240. package/frontend/src/components/ProjectInfoModal.tsx +128 -0
  241. package/frontend/src/components/PromptDialog.tsx +1 -4
  242. package/frontend/src/components/SearchInput.tsx +1 -2
  243. package/frontend/src/components/Stepper.tsx +53 -0
  244. package/frontend/src/components/ThemeToggle.tsx +3 -3
  245. package/frontend/src/components/datagrid/DataGrid.tsx +25 -32
  246. package/frontend/src/components/datagrid/cell-editors/DateCellEditor.tsx +1 -2
  247. package/frontend/src/components/datagrid/cell-editors/JsonCellEditor.tsx +2 -4
  248. package/frontend/src/components/datagrid/index.ts +23 -0
  249. package/frontend/src/components/index.ts +23 -30
  250. package/frontend/src/components/layout/AppHeader.tsx +133 -92
  251. package/frontend/src/components/layout/AppSidebar.tsx +80 -170
  252. package/frontend/src/components/layout/Layout.tsx +12 -23
  253. package/frontend/src/components/layout/PrimaryMenu.tsx +187 -0
  254. package/frontend/src/components/layout/SecondaryMenu.tsx +70 -0
  255. package/frontend/src/components/layout/index.ts +5 -0
  256. package/frontend/src/components/radix/Tooltip.tsx +24 -13
  257. package/frontend/src/components/radix/index.ts +22 -0
  258. package/frontend/src/features/ai/components/AIConfigCard.tsx +129 -83
  259. package/frontend/src/features/ai/components/AIEmptyState.tsx +12 -7
  260. package/frontend/src/features/ai/components/ModalityFilterSidebar.tsx +101 -0
  261. package/frontend/src/features/ai/components/ModelSelectionDialog.tsx +135 -0
  262. package/frontend/src/features/ai/components/ModelSelectionGrid.tsx +51 -0
  263. package/frontend/src/features/ai/components/SystemPromptDialog.tsx +118 -0
  264. package/frontend/src/features/ai/components/index.ts +6 -0
  265. package/frontend/src/features/ai/helpers.ts +57 -71
  266. package/frontend/src/features/ai/hooks/useAIConfigs.ts +39 -113
  267. package/frontend/src/features/ai/hooks/useAIUsage.ts +0 -2
  268. package/frontend/src/features/ai/page/AIPage.tsx +67 -79
  269. package/frontend/src/features/ai/services/ai.service.ts +5 -5
  270. package/frontend/src/features/auth/components/AuthPreview.tsx +96 -0
  271. package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +53 -30
  272. package/frontend/src/features/auth/components/UserFormDialog.tsx +13 -6
  273. package/frontend/src/features/auth/components/UsersDataGrid.tsx +44 -14
  274. package/frontend/src/features/auth/components/index.ts +5 -0
  275. package/frontend/src/features/auth/helpers.tsx +200 -0
  276. package/frontend/src/features/auth/hooks/useAnonToken.ts +30 -0
  277. package/frontend/src/features/auth/hooks/useAuthConfig.ts +48 -0
  278. package/frontend/src/features/auth/hooks/useOAuthConfig.ts +14 -10
  279. package/frontend/src/features/auth/hooks/useUsers.ts +43 -5
  280. package/frontend/src/features/auth/index.ts +3 -2
  281. package/frontend/src/features/auth/page/AuthMethodsPage.tsx +275 -0
  282. package/frontend/src/features/auth/page/ConfigurationPage.tsx +395 -0
  283. package/frontend/src/features/auth/page/UsersPage.tsx +285 -0
  284. package/frontend/src/features/auth/services/anonToken.service.ts +11 -0
  285. package/frontend/src/features/auth/services/config.service.ts +19 -0
  286. package/frontend/src/features/auth/services/{oauth.service.ts → oauth-config.service.ts} +4 -4
  287. package/frontend/src/features/auth/services/{auth.service.ts → user.service.ts} +7 -53
  288. package/frontend/src/features/dashboard/components/ConnectionSuccessBanner.tsx +35 -0
  289. package/frontend/src/features/dashboard/components/PromptCard.tsx +21 -0
  290. package/frontend/src/features/dashboard/components/PromptDialog.tsx +103 -0
  291. package/frontend/src/features/dashboard/components/StatsCard.tsx +50 -0
  292. package/frontend/src/features/dashboard/components/index.ts +4 -0
  293. package/frontend/src/features/dashboard/page/DashboardPage.tsx +187 -169
  294. package/frontend/src/features/dashboard/prompts/ai-chatbot.ts +13 -0
  295. package/frontend/src/features/dashboard/prompts/crm-system.ts +13 -0
  296. package/frontend/src/features/dashboard/prompts/ecommerce-platform.ts +12 -0
  297. package/frontend/src/features/dashboard/prompts/index.ts +31 -0
  298. package/frontend/src/features/dashboard/prompts/instagram-clone.ts +11 -0
  299. package/frontend/src/features/dashboard/prompts/notion-clone.ts +14 -0
  300. package/frontend/src/features/dashboard/prompts/reddit-clone.ts +12 -0
  301. package/frontend/src/features/database/components/DatabaseDataGrid.tsx +48 -17
  302. package/frontend/src/features/database/components/ForeignKeyCell.tsx +15 -34
  303. package/frontend/src/features/database/components/ForeignKeyPopover.tsx +19 -20
  304. package/frontend/src/features/database/components/LinkRecordModal.tsx +120 -125
  305. package/frontend/src/features/database/components/RecordFormDialog.tsx +22 -33
  306. package/frontend/src/features/database/components/RecordFormField.tsx +45 -47
  307. package/frontend/src/features/database/components/TableEmptyState.tsx +6 -5
  308. package/frontend/src/features/database/components/TableForm.tsx +28 -15
  309. package/frontend/src/features/database/components/TableFormColumn.tsx +2 -3
  310. package/frontend/src/features/database/components/TableSidebar.tsx +1 -1
  311. package/frontend/src/features/database/components/TablesEmptyState.tsx +48 -0
  312. package/frontend/src/features/database/components/TemplateCard.tsx +37 -0
  313. package/frontend/src/features/database/components/TemplatePreview.tsx +92 -0
  314. package/frontend/src/features/database/components/index.ts +19 -0
  315. package/frontend/src/features/database/constants.ts +28 -2
  316. package/frontend/src/features/database/contexts/SQLEditorContext.tsx +188 -0
  317. package/frontend/src/features/database/helpers.ts +2 -2
  318. package/frontend/src/features/database/hooks/useCSVImport.ts +29 -0
  319. package/frontend/src/features/database/hooks/useFullMetadata.ts +18 -0
  320. package/frontend/src/features/database/hooks/useRawSQL.ts +55 -0
  321. package/frontend/src/features/database/hooks/useRecords.ts +139 -0
  322. package/frontend/src/features/database/hooks/useTables.ts +131 -0
  323. package/frontend/src/features/database/index.ts +6 -1
  324. package/frontend/src/features/database/page/FunctionsPage.tsx +211 -0
  325. package/frontend/src/features/database/page/IndexesPage.tsx +240 -0
  326. package/frontend/src/features/database/page/PoliciesPage.tsx +248 -0
  327. package/frontend/src/features/database/page/SQLEditorPage.tsx +382 -0
  328. package/frontend/src/features/database/page/{DatabasePage.tsx → TablesPage.tsx} +186 -185
  329. package/frontend/src/features/database/page/TemplatesPage.tsx +39 -0
  330. package/frontend/src/features/database/page/TriggersPage.tsx +242 -0
  331. package/frontend/src/features/database/services/advance.service.ts +66 -0
  332. package/frontend/src/features/database/services/{database.service.ts → record.service.ts} +67 -64
  333. package/frontend/src/features/database/services/table.service.ts +64 -0
  334. package/frontend/src/features/database/templates/ai-chatbot.ts +402 -0
  335. package/frontend/src/features/database/templates/crm-system.ts +528 -0
  336. package/frontend/src/features/database/templates/ecommerce-platform.ts +553 -0
  337. package/frontend/src/features/database/templates/index.ts +34 -0
  338. package/frontend/src/features/database/templates/instagram-clone.ts +222 -0
  339. package/frontend/src/features/database/templates/notion-clone.ts +483 -0
  340. package/frontend/src/features/database/templates/reddit-clone.ts +526 -0
  341. package/frontend/src/features/functions/components/FunctionRow.tsx +2 -1
  342. package/frontend/src/features/functions/components/FunctionsSidebar.tsx +1 -1
  343. package/frontend/src/features/functions/components/SecretRow.tsx +1 -1
  344. package/frontend/src/features/functions/components/index.ts +5 -0
  345. package/frontend/src/features/functions/hooks/useFunctions.ts +4 -4
  346. package/frontend/src/features/{secrets → functions}/hooks/useSecrets.ts +5 -5
  347. package/frontend/src/features/functions/page/FunctionsPage.tsx +160 -17
  348. package/frontend/src/features/functions/{components/SecretsContent.tsx → page/SecretsPage.tsx} +8 -12
  349. package/frontend/src/features/functions/services/{functions.service.ts → function.service.ts} +2 -2
  350. package/frontend/src/features/{secrets/services/secrets.service.ts → functions/services/secret.service.ts} +2 -2
  351. package/frontend/src/features/login/hooks/usePartnerOrigin.ts +27 -0
  352. package/frontend/src/features/login/page/CloudLoginPage.tsx +79 -54
  353. package/frontend/src/features/login/page/LoginPage.tsx +16 -23
  354. package/frontend/src/features/login/services/partnership.service.ts +65 -0
  355. package/frontend/src/features/logs/components/LogsDataGrid.tsx +89 -0
  356. package/frontend/src/features/logs/components/SeverityBadge.tsx +18 -0
  357. package/frontend/src/features/logs/components/index.ts +2 -0
  358. package/frontend/src/features/logs/helpers.ts +24 -0
  359. package/frontend/src/features/logs/hooks/useAuditLogs.ts +4 -4
  360. package/frontend/src/features/logs/hooks/useLogSources.ts +137 -0
  361. package/frontend/src/features/logs/hooks/useLogs.ts +163 -0
  362. package/frontend/src/features/logs/hooks/useMcpUsage.ts +181 -0
  363. package/frontend/src/features/logs/index.ts +8 -2
  364. package/frontend/src/features/logs/page/AuditsPage.tsx +91 -38
  365. package/frontend/src/features/logs/page/LogsPage.tsx +152 -0
  366. package/frontend/src/features/logs/page/MCPLogsPage.tsx +84 -0
  367. package/frontend/src/features/logs/services/audit.service.ts +63 -0
  368. package/frontend/src/features/logs/services/log.service.ts +15 -110
  369. package/frontend/src/features/logs/services/usage.service.ts +31 -0
  370. package/frontend/src/features/onboard/components/McpConnectionStatus.tsx +68 -0
  371. package/frontend/src/features/onboard/components/OnboardingModal.tsx +267 -0
  372. package/frontend/src/features/onboard/components/VideoDemoModal.tsx +38 -0
  373. package/frontend/src/features/onboard/components/index.ts +4 -0
  374. package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +2 -2
  375. package/frontend/src/features/onboard/components/mcp/{mcp-helper.tsx → helpers.tsx} +8 -8
  376. package/frontend/src/features/onboard/components/mcp/index.ts +2 -3
  377. package/frontend/src/features/onboard/index.ts +13 -3
  378. package/frontend/src/features/storage/components/BucketEmptyState.tsx +9 -6
  379. package/frontend/src/features/storage/components/BucketFormDialog.tsx +25 -41
  380. package/frontend/src/features/storage/components/FilePreviewDialog.tsx +20 -8
  381. package/frontend/src/features/storage/components/StorageDataGrid.tsx +4 -3
  382. package/frontend/src/features/storage/components/StorageManager.tsx +23 -34
  383. package/frontend/src/features/storage/components/index.ts +12 -0
  384. package/frontend/src/features/storage/hooks/useStorage.ts +208 -0
  385. package/frontend/src/features/storage/page/StoragePage.tsx +41 -115
  386. package/frontend/src/features/storage/services/storage.service.ts +22 -1
  387. package/frontend/src/features/visualizer/components/AuthNode.tsx +72 -56
  388. package/frontend/src/features/visualizer/components/BucketNode.tsx +4 -4
  389. package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +108 -80
  390. package/frontend/src/features/visualizer/components/TableNode.tsx +34 -41
  391. package/frontend/src/features/visualizer/components/VisualizerSkeleton.tsx +12 -4
  392. package/frontend/src/features/visualizer/page/VisualizerPage.tsx +33 -29
  393. package/frontend/src/index.css +1 -0
  394. package/frontend/src/lib/analytics/posthog.tsx +27 -0
  395. package/frontend/src/lib/contexts/AuthContext.tsx +38 -31
  396. package/frontend/src/lib/contexts/SocketContext.tsx +5 -6
  397. package/frontend/src/{features/metadata → lib}/hooks/useMetadata.ts +1 -1
  398. package/frontend/src/lib/hooks/useToast.tsx +6 -2
  399. package/frontend/src/lib/routing/AppRoutes.tsx +84 -0
  400. package/frontend/src/lib/routing/RequireAuth.tsx +27 -0
  401. package/frontend/src/lib/utils/cloudMessaging.ts +20 -0
  402. package/frontend/src/lib/utils/menuItems.ts +183 -0
  403. package/frontend/src/lib/utils/{validation-schemas.ts → schemaValidations.ts} +10 -5
  404. package/frontend/src/lib/utils/utils.ts +19 -1
  405. package/frontend/src/vite-env.d.ts +1 -0
  406. package/frontend/vite.config.ts +5 -3
  407. package/functions/server.ts +28 -3
  408. package/functions/worker-template.js +15 -4
  409. package/i18n/README.ar.md +130 -0
  410. package/i18n/README.de.md +130 -0
  411. package/i18n/README.es.md +154 -0
  412. package/i18n/README.fr.md +134 -0
  413. package/i18n/README.hi.md +129 -0
  414. package/i18n/README.ja.md +174 -0
  415. package/i18n/README.ko.md +137 -0
  416. package/i18n/README.pt-BR.md +131 -0
  417. package/i18n/README.ru.md +129 -0
  418. package/i18n/README.zh-CN.md +133 -0
  419. package/openapi/ai.yaml +31 -4
  420. package/openapi/auth.yaml +827 -146
  421. package/package.json +16 -7
  422. package/shared-schemas/package.json +1 -1
  423. package/shared-schemas/src/ai-api.schema.ts +34 -58
  424. package/shared-schemas/src/ai.schema.ts +5 -0
  425. package/shared-schemas/src/auth-api.schema.ts +154 -8
  426. package/shared-schemas/src/auth.schema.ts +42 -6
  427. package/shared-schemas/src/cloud-events.schema.ts +57 -0
  428. package/shared-schemas/src/database-api.schema.ts +3 -3
  429. package/shared-schemas/src/database.schema.ts +1 -1
  430. package/shared-schemas/src/index.ts +1 -0
  431. package/shared-schemas/src/logs-api.schema.ts +7 -1
  432. package/shared-schemas/src/logs.schema.ts +26 -0
  433. package/shared-schemas/src/metadata.schema.ts +9 -4
  434. package/test-gemini.sh +35 -0
  435. package/test-usage-admin.sh +57 -0
  436. package/test-usage.sh +50 -0
  437. package/zeabur/README.md +13 -0
  438. package/zeabur/template.yml +1032 -0
  439. package/.github/workflows/deploy-aws.yml +0 -130
  440. package/backend/src/api/routes/agent.ts +0 -29
  441. package/backend/src/api/routes/auth.oauth.ts +0 -482
  442. package/backend/src/api/routes/auth.ts +0 -386
  443. package/backend/src/api/routes/docs.ts +0 -66
  444. package/backend/src/api/routes/functions.ts +0 -183
  445. package/backend/src/api/routes/openapi.ts +0 -82
  446. package/backend/src/api/routes/usage.ts +0 -96
  447. package/backend/src/core/ai/client.ts +0 -242
  448. package/backend/src/core/ai/model.ts +0 -117
  449. package/backend/src/core/auth/auth.ts +0 -780
  450. package/backend/src/core/database/table.ts +0 -772
  451. package/backend/src/core/documentation/agent.ts +0 -689
  452. package/backend/src/core/documentation/openapi.ts +0 -856
  453. package/backend/src/core/logs/analytics.ts +0 -76
  454. package/backend/src/core/logs/providers/localdb.provider.ts +0 -246
  455. package/backend/src/core/storage/storage.ts +0 -923
  456. package/backend/src/utils/cloud-token.ts +0 -39
  457. package/backend/src/utils/helpers.ts +0 -49
  458. package/backend/src/utils/uuid.ts +0 -9
  459. package/backend/tests/manual/test-better-auth.sh +0 -303
  460. package/docker-init/db/logs.sql +0 -9
  461. package/frontend/README.md +0 -112
  462. package/frontend/src/components/datagrid/index.tsx +0 -20
  463. package/frontend/src/components/layout/CloudLayout.tsx +0 -95
  464. package/frontend/src/features/ai/components/AIConfigDialog.tsx +0 -76
  465. package/frontend/src/features/ai/components/AIConfigForm.tsx +0 -222
  466. package/frontend/src/features/ai/components/fields/ModalityField.tsx +0 -87
  467. package/frontend/src/features/ai/components/fields/ModelSelectionField.tsx +0 -134
  468. package/frontend/src/features/ai/components/fields/SystemPromptField.tsx +0 -33
  469. package/frontend/src/features/auth/components/AddOAuthDialog.tsx +0 -106
  470. package/frontend/src/features/auth/components/AuthMethodTab.tsx +0 -238
  471. package/frontend/src/features/auth/components/UsersTab.tsx +0 -114
  472. package/frontend/src/features/auth/page/AuthenticationPage.tsx +0 -169
  473. package/frontend/src/features/database/hooks/UseLinkModal.tsx +0 -78
  474. package/frontend/src/features/functions/components/FunctionViewer.tsx +0 -46
  475. package/frontend/src/features/functions/components/FunctionsContent.tsx +0 -88
  476. package/frontend/src/features/login/components/AuthErrorBoundary.tsx +0 -87
  477. package/frontend/src/features/login/components/PrivateRoute.tsx +0 -24
  478. package/frontend/src/features/logs/components/AnalyticsLogsTable.tsx +0 -313
  479. package/frontend/src/features/logs/components/LogsTable.tsx +0 -199
  480. package/frontend/src/features/logs/page/AnalyticsLogsPage.tsx +0 -530
  481. package/frontend/src/features/metadata/index.ts +0 -0
  482. package/frontend/src/features/metadata/page/MetadataPage.tsx +0 -136
  483. package/frontend/src/features/onboard/components/CompletionCard.tsx +0 -41
  484. package/frontend/src/features/onboard/components/OnboardButton.tsx +0 -84
  485. package/frontend/src/features/onboard/components/StepContent.tsx +0 -91
  486. package/frontend/src/features/onboard/components/TestConnectionStep.tsx +0 -53
  487. package/frontend/src/features/onboard/components/mcp/McpInstallation.tsx +0 -144
  488. package/frontend/src/features/onboard/page/OnBoardPage.tsx +0 -104
  489. package/frontend/src/features/onboard/types.ts +0 -8
  490. package/frontend/src/lib/contexts/OnboardStepContext.tsx +0 -68
  491. package/frontend/src/lib/hooks/useOnboardingCompletion.ts +0 -29
  492. /package/backend/src/api/{middleware → middlewares}/error.ts +0 -0
  493. /package/backend/src/api/{middleware → middlewares}/upload.ts +0 -0
  494. /package/backend/{migrations → src/infra/database/migrations}/000_create-base-tables.sql +0 -0
  495. /package/backend/{migrations → src/infra/database/migrations}/001_create-helper-functions.sql +0 -0
  496. /package/backend/{migrations → src/infra/database/migrations}/002_rename-auth-tables.sql +0 -0
  497. /package/backend/{migrations → src/infra/database/migrations}/003_create-users-table.sql +0 -0
  498. /package/backend/{migrations → src/infra/database/migrations}/004_add-reload-postgrest-func.sql +0 -0
  499. /package/backend/{migrations → src/infra/database/migrations}/005_enable-project-admin-modify-users.sql +0 -0
  500. /package/backend/{migrations → src/infra/database/migrations}/006_modify-ai-usage-table.sql +0 -0
  501. /package/backend/{migrations → src/infra/database/migrations}/007_drop-metadata-table.sql +0 -0
  502. /package/backend/{migrations → src/infra/database/migrations}/008_add-system-tables.sql +0 -0
  503. /package/backend/{migrations → src/infra/database/migrations}/009_add-function-secrets.sql +0 -0
  504. /package/backend/{migrations → src/infra/database/migrations}/010_modify-ai-config-modalities.sql +0 -0
  505. /package/backend/{migrations → src/infra/database/migrations}/011_refactor-secrets-table.sql +0 -0
  506. /package/backend/{migrations → src/infra/database/migrations}/012_add-storage-uploaded-by.sql +0 -0
  507. /package/frontend/src/{features/metadata → lib}/services/metadata.service.ts +0 -0
@@ -0,0 +1,570 @@
1
+ import { Router, Request, Response, NextFunction } from 'express';
2
+ import { AuthService } from '@/services/auth/auth.service.js';
3
+ import { AuthConfigService } from '@/services/auth/auth-config.service.js';
4
+ import { OAuthConfigService } from '@/services/auth/oauth-config.service.js';
5
+ import { AuditService } from '@/services/logs/audit.service.js';
6
+ import { TokenManager } from '@/infra/security/token.manager.js';
7
+ import { AppError } from '@/api/middlewares/error.js';
8
+ import { ERROR_CODES } from '@/types/error-constants.js';
9
+ import { successResponse } from '@/utils/response.js';
10
+ import { AuthRequest, verifyAdmin, verifyToken } from '@/api/middlewares/auth.js';
11
+ import oauthRouter from './oauth.routes.js';
12
+ import { sendEmailOTPLimiter, verifyOTPLimiter } from '@/api/middlewares/rate-limiters.js';
13
+ import {
14
+ userIdSchema,
15
+ createUserRequestSchema,
16
+ createSessionRequestSchema,
17
+ createAdminSessionRequestSchema,
18
+ deleteUsersRequestSchema,
19
+ listUsersRequestSchema,
20
+ sendVerificationEmailRequestSchema,
21
+ verifyEmailRequestSchema,
22
+ sendResetPasswordEmailRequestSchema,
23
+ exchangeResetPasswordTokenRequestSchema,
24
+ resetPasswordRequestSchema,
25
+ type CreateUserResponse,
26
+ type CreateSessionResponse,
27
+ type VerifyEmailResponse,
28
+ type ExchangeResetPasswordTokenResponse,
29
+ type ResetPasswordResponse,
30
+ type CreateAdminSessionResponse,
31
+ type GetCurrentSessionResponse,
32
+ type ListUsersResponse,
33
+ type DeleteUsersResponse,
34
+ type GetPublicAuthConfigResponse,
35
+ exchangeAdminSessionRequestSchema,
36
+ type GetAuthConfigResponse,
37
+ updateAuthConfigRequestSchema,
38
+ } from '@insforge/shared-schemas';
39
+ import { SocketManager } from '@/infra/socket/socket.manager.js';
40
+ import { DataUpdateResourceType, ServerEvents } from '@/types/socket.js';
41
+
42
+ const router = Router();
43
+ const authService = AuthService.getInstance();
44
+ const authConfigService = AuthConfigService.getInstance();
45
+ const oAuthConfigService = OAuthConfigService.getInstance();
46
+ const auditService = AuditService.getInstance();
47
+
48
+ // Mount OAuth routes
49
+ router.use('/oauth', oauthRouter);
50
+
51
+ // Public Authentication Configuration Routes
52
+ // GET /api/auth/public-config - Get all public authentication configuration (public endpoint)
53
+ router.get('/public-config', async (req: Request, res: Response, next: NextFunction) => {
54
+ try {
55
+ const [oAuthProviders, authConfigs] = await Promise.all([
56
+ oAuthConfigService.getConfiguredProviders(),
57
+ authConfigService.getPublicAuthConfig(),
58
+ ]);
59
+
60
+ const response: GetPublicAuthConfigResponse = {
61
+ oAuthProviders,
62
+ ...authConfigs,
63
+ };
64
+
65
+ successResponse(res, response);
66
+ } catch (error) {
67
+ next(error);
68
+ }
69
+ });
70
+
71
+ // Email Authentication Configuration Routes
72
+ // GET /api/auth/config - Get authentication configurations (admin only)
73
+ router.get('/config', verifyAdmin, async (req: AuthRequest, res: Response, next: NextFunction) => {
74
+ try {
75
+ const config: GetAuthConfigResponse = await authConfigService.getAuthConfig();
76
+ successResponse(res, config);
77
+ } catch (error) {
78
+ next(error);
79
+ }
80
+ });
81
+
82
+ // PUT /api/auth/config - Update authentication configurations (admin only)
83
+ router.put('/config', verifyAdmin, async (req: AuthRequest, res: Response, next: NextFunction) => {
84
+ try {
85
+ const validationResult = updateAuthConfigRequestSchema.safeParse(req.body);
86
+ if (!validationResult.success) {
87
+ throw new AppError(
88
+ validationResult.error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join(', '),
89
+ 400,
90
+ ERROR_CODES.INVALID_INPUT
91
+ );
92
+ }
93
+
94
+ const input = validationResult.data;
95
+ const config: GetAuthConfigResponse = await authConfigService.updateAuthConfig(input);
96
+
97
+ await auditService.log({
98
+ actor: req.user?.email || 'api-key',
99
+ action: 'UPDATE_AUTH_CONFIG',
100
+ module: 'AUTH',
101
+ details: {
102
+ updatedFields: Object.keys(input),
103
+ },
104
+ ip_address: req.ip,
105
+ });
106
+
107
+ successResponse(res, config);
108
+ } catch (error) {
109
+ next(error);
110
+ }
111
+ });
112
+
113
+ // POST /api/auth/users - Create a new user (registration)
114
+ router.post('/users', async (req: Request, res: Response, next: NextFunction) => {
115
+ try {
116
+ const validationResult = createUserRequestSchema.safeParse(req.body);
117
+ if (!validationResult.success) {
118
+ throw new AppError(
119
+ validationResult.error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join(', '),
120
+ 400,
121
+ ERROR_CODES.INVALID_INPUT
122
+ );
123
+ }
124
+
125
+ const { email, password, name } = validationResult.data;
126
+ const result: CreateUserResponse = await authService.register(email, password, name);
127
+
128
+ const socket = SocketManager.getInstance();
129
+ socket.broadcastToRoom('role:project_admin', ServerEvents.DATA_UPDATE, {
130
+ resource: DataUpdateResourceType.USERS,
131
+ });
132
+
133
+ successResponse(res, result);
134
+ } catch (error) {
135
+ next(error);
136
+ }
137
+ });
138
+
139
+ // POST /api/auth/sessions - Create a new session (login)
140
+ router.post('/sessions', async (req: Request, res: Response, next: NextFunction) => {
141
+ try {
142
+ const validationResult = createSessionRequestSchema.safeParse(req.body);
143
+ if (!validationResult.success) {
144
+ throw new AppError(
145
+ validationResult.error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join(', '),
146
+ 400,
147
+ ERROR_CODES.INVALID_INPUT
148
+ );
149
+ }
150
+
151
+ const { email, password } = validationResult.data;
152
+ const result: CreateSessionResponse = await authService.login(email, password);
153
+
154
+ successResponse(res, result);
155
+ } catch (error) {
156
+ next(error);
157
+ }
158
+ });
159
+
160
+ // POST /api/auth/admin/sessions/exchange - Create admin session
161
+ router.post('/admin/sessions/exchange', async (req: Request, res: Response, next: NextFunction) => {
162
+ try {
163
+ const validationResult = exchangeAdminSessionRequestSchema.safeParse(req.body);
164
+ if (!validationResult.success) {
165
+ throw new AppError(
166
+ validationResult.error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join(', '),
167
+ 400,
168
+ ERROR_CODES.INVALID_INPUT
169
+ );
170
+ }
171
+
172
+ const { code } = validationResult.data;
173
+ const result: CreateAdminSessionResponse =
174
+ await authService.adminLoginWithAuthorizationCode(code);
175
+
176
+ successResponse(res, result);
177
+ } catch (error) {
178
+ if (error instanceof AppError) {
179
+ next(error);
180
+ } else {
181
+ // Convert other errors (like JWT verification errors) to 400
182
+ next(
183
+ new AppError(
184
+ 'Failed to exchange admin session' + (error instanceof Error ? `: ${error.message}` : ''),
185
+ 400,
186
+ ERROR_CODES.INVALID_INPUT
187
+ )
188
+ );
189
+ }
190
+ }
191
+ });
192
+
193
+ // POST /api/auth/admin/sessions - Create admin session
194
+ router.post('/admin/sessions', (req: Request, res: Response, next: NextFunction) => {
195
+ try {
196
+ const validationResult = createAdminSessionRequestSchema.safeParse(req.body);
197
+ if (!validationResult.success) {
198
+ throw new AppError(
199
+ validationResult.error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join(', '),
200
+ 400,
201
+ ERROR_CODES.INVALID_INPUT
202
+ );
203
+ }
204
+
205
+ const { email, password } = validationResult.data;
206
+ const result: CreateAdminSessionResponse = authService.adminLogin(email, password);
207
+
208
+ successResponse(res, result);
209
+ } catch (error) {
210
+ next(error);
211
+ }
212
+ });
213
+
214
+ // GET /api/auth/sessions/current - Get current session user
215
+ router.get(
216
+ '/sessions/current',
217
+ verifyToken,
218
+ (req: AuthRequest, res: Response, next: NextFunction) => {
219
+ try {
220
+ if (!req.user) {
221
+ throw new AppError('User not authenticated', 401, ERROR_CODES.AUTH_INVALID_CREDENTIALS);
222
+ }
223
+
224
+ const response: GetCurrentSessionResponse = {
225
+ user: {
226
+ id: req.user.id,
227
+ email: req.user.email,
228
+ role: req.user.role as 'authenticated' | 'project_admin',
229
+ },
230
+ };
231
+
232
+ successResponse(res, response);
233
+ } catch (error) {
234
+ next(error);
235
+ }
236
+ }
237
+ );
238
+
239
+ // GET /api/auth/users - List all users (admin only)
240
+ router.get('/users', verifyAdmin, async (req: Request, res: Response, next: NextFunction) => {
241
+ try {
242
+ const queryValidation = listUsersRequestSchema.safeParse(req.query);
243
+ const queryParams = queryValidation.success ? queryValidation.data : req.query;
244
+ const { limit = '10', offset = '0', search } = queryParams || {};
245
+
246
+ const parsedLimit = parseInt(limit as string);
247
+ const parsedOffset = parseInt(offset as string);
248
+
249
+ const { users, total } = await authService.listUsers(
250
+ parsedLimit,
251
+ parsedOffset,
252
+ search as string | undefined
253
+ );
254
+
255
+ const response: ListUsersResponse = {
256
+ data: users,
257
+ pagination: {
258
+ offset: parsedOffset,
259
+ limit: parsedLimit,
260
+ total: total,
261
+ },
262
+ };
263
+
264
+ successResponse(res, response);
265
+ } catch (error) {
266
+ next(error);
267
+ }
268
+ });
269
+
270
+ // GET /api/auth/users/:id - Get specific user (admin only)
271
+ router.get(
272
+ '/users/:userId',
273
+ verifyAdmin,
274
+ async (req: Request, res: Response, next: NextFunction) => {
275
+ try {
276
+ // Validate userId path parameter directly
277
+ const userIdValidation = userIdSchema.safeParse(req.params.userId);
278
+ if (!userIdValidation.success) {
279
+ throw new AppError('Invalid user ID format', 400, ERROR_CODES.INVALID_INPUT);
280
+ }
281
+
282
+ const userId = userIdValidation.data;
283
+ const user = await authService.getUserSchemaById(userId);
284
+
285
+ if (!user) {
286
+ throw new AppError('User not found', 404, ERROR_CODES.NOT_FOUND);
287
+ }
288
+
289
+ successResponse(res, user);
290
+ } catch (error) {
291
+ next(error);
292
+ }
293
+ }
294
+ );
295
+
296
+ // DELETE /api/auth/users - Delete users (batch operation, admin only)
297
+ router.delete(
298
+ '/users',
299
+ verifyAdmin,
300
+ async (req: AuthRequest, res: Response, next: NextFunction) => {
301
+ try {
302
+ const validationResult = deleteUsersRequestSchema.safeParse(req.body);
303
+ if (!validationResult.success) {
304
+ throw new AppError(
305
+ validationResult.error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join(', '),
306
+ 400,
307
+ ERROR_CODES.INVALID_INPUT
308
+ );
309
+ }
310
+
311
+ const { userIds } = validationResult.data;
312
+
313
+ const deletedCount = await authService.deleteUsers(userIds);
314
+
315
+ // Log audit for user deletion
316
+ await auditService.log({
317
+ actor: req.user?.email || 'api-key',
318
+ action: 'DELETE_USERS',
319
+ module: 'AUTH',
320
+ details: {
321
+ userIds,
322
+ deletedCount,
323
+ },
324
+ ip_address: req.ip,
325
+ });
326
+
327
+ const response: DeleteUsersResponse = {
328
+ message: 'Users deleted successfully',
329
+ deletedCount,
330
+ };
331
+
332
+ successResponse(res, response);
333
+ } catch (error) {
334
+ next(error);
335
+ }
336
+ }
337
+ );
338
+
339
+ // POST /api/auth/tokens/anon - Generate anonymous JWT token (never expires)
340
+ router.post('/tokens/anon', verifyAdmin, (_req: Request, res: Response, next: NextFunction) => {
341
+ try {
342
+ const tokenManager = TokenManager.getInstance();
343
+ const token = tokenManager.generateAnonToken();
344
+
345
+ successResponse(res, {
346
+ accessToken: token,
347
+ message: 'Anonymous token generated successfully (never expires)',
348
+ });
349
+ } catch (error) {
350
+ next(error);
351
+ }
352
+ });
353
+
354
+ // POST /api/auth/email/send-verification - Send email verification (code or link based on config)
355
+ router.post(
356
+ '/email/send-verification',
357
+ sendEmailOTPLimiter,
358
+ async (req: Request, res: Response, next: NextFunction) => {
359
+ try {
360
+ const validationResult = sendVerificationEmailRequestSchema.safeParse(req.body);
361
+ if (!validationResult.success) {
362
+ throw new AppError(
363
+ validationResult.error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join(', '),
364
+ 400,
365
+ ERROR_CODES.INVALID_INPUT
366
+ );
367
+ }
368
+
369
+ const { email } = validationResult.data;
370
+
371
+ // Get auth config to determine verification method
372
+ const authConfig = await authConfigService.getAuthConfig();
373
+ const method = authConfig.verifyEmailMethod;
374
+
375
+ // Note: User enumeration is prevented at service layer
376
+ // Service returns gracefully (no error) if user not found
377
+ if (method === 'link') {
378
+ await authService.sendVerificationEmailWithLink(email);
379
+ } else {
380
+ await authService.sendVerificationEmailWithCode(email);
381
+ }
382
+
383
+ // Always return 202 Accepted with generic message
384
+ const message =
385
+ method === 'link'
386
+ ? 'If your email is registered, we have sent you a verification link. Please check your inbox.'
387
+ : 'If your email is registered, we have sent you a verification code. Please check your inbox.';
388
+
389
+ successResponse(
390
+ res,
391
+ {
392
+ success: true,
393
+ message,
394
+ },
395
+ 202
396
+ );
397
+ } catch (error) {
398
+ next(error);
399
+ }
400
+ }
401
+ );
402
+
403
+ // POST /api/auth/email/verify - Verify email with OTP
404
+ // Uses verifyEmailMethod from auth config to determine verification type:
405
+ // - 'code': expects email + 6-digit numeric code
406
+ // - 'link': expects 64-char hex token only
407
+ router.post(
408
+ '/email/verify',
409
+ verifyOTPLimiter,
410
+ async (req: Request, res: Response, next: NextFunction) => {
411
+ try {
412
+ const validationResult = verifyEmailRequestSchema.safeParse(req.body);
413
+ if (!validationResult.success) {
414
+ throw new AppError(
415
+ validationResult.error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join(', '),
416
+ 400,
417
+ ERROR_CODES.INVALID_INPUT
418
+ );
419
+ }
420
+
421
+ const { email, otp } = validationResult.data;
422
+
423
+ // Get auth config to determine verification method
424
+ const authConfig = await authConfigService.getAuthConfig();
425
+ const method = authConfig.verifyEmailMethod;
426
+
427
+ let result: VerifyEmailResponse;
428
+
429
+ if (method === 'link') {
430
+ // Link verification: otp is 64-char hex token
431
+ result = await authService.verifyEmailWithToken(otp);
432
+ } else {
433
+ // Code verification: requires email + 6-digit code
434
+ if (!email) {
435
+ throw new AppError(
436
+ 'Email is required for code verification',
437
+ 400,
438
+ ERROR_CODES.INVALID_INPUT
439
+ );
440
+ }
441
+ result = await authService.verifyEmailWithCode(email, otp);
442
+ }
443
+
444
+ successResponse(res, result); // Return session info with optional redirectTo upon successful verification
445
+ } catch (error) {
446
+ next(error);
447
+ }
448
+ }
449
+ );
450
+
451
+ // POST /api/auth/email/send-reset-password - Send password reset (code or link based on config)
452
+ router.post(
453
+ '/email/send-reset-password',
454
+ sendEmailOTPLimiter,
455
+ async (req: Request, res: Response, next: NextFunction) => {
456
+ try {
457
+ const validationResult = sendResetPasswordEmailRequestSchema.safeParse(req.body);
458
+ if (!validationResult.success) {
459
+ throw new AppError(
460
+ validationResult.error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join(', '),
461
+ 400,
462
+ ERROR_CODES.INVALID_INPUT
463
+ );
464
+ }
465
+
466
+ const { email } = validationResult.data;
467
+
468
+ // Get auth config to determine reset password method
469
+ const authConfig = await authConfigService.getAuthConfig();
470
+ const method = authConfig.resetPasswordMethod;
471
+
472
+ // Note: User enumeration is prevented at service layer
473
+ // Service returns gracefully (no error) if user not found
474
+ if (method === 'link') {
475
+ await authService.sendResetPasswordEmailWithLink(email);
476
+ } else {
477
+ await authService.sendResetPasswordEmailWithCode(email);
478
+ }
479
+
480
+ // Always return 202 Accepted with generic message
481
+ const message =
482
+ method === 'link'
483
+ ? 'If your email is registered, we have sent you a password reset link. Please check your inbox.'
484
+ : 'If your email is registered, we have sent you a password reset code. Please check your inbox.';
485
+
486
+ successResponse(
487
+ res,
488
+ {
489
+ success: true,
490
+ message,
491
+ },
492
+ 202
493
+ );
494
+ } catch (error) {
495
+ next(error);
496
+ }
497
+ }
498
+ );
499
+
500
+ // POST /api/auth/email/exchange-reset-password-token - Exchange reset password code for reset token
501
+ // Step 1 of two-step password reset flow: verify code → get reset token
502
+ // Only used when resetPasswordMethod is 'code'
503
+ router.post(
504
+ '/email/exchange-reset-password-token',
505
+ verifyOTPLimiter,
506
+ async (req: Request, res: Response, next: NextFunction) => {
507
+ try {
508
+ const validationResult = exchangeResetPasswordTokenRequestSchema.safeParse(req.body);
509
+ if (!validationResult.success) {
510
+ throw new AppError(
511
+ validationResult.error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join(', '),
512
+ 400,
513
+ ERROR_CODES.INVALID_INPUT
514
+ );
515
+ }
516
+
517
+ const { email, code } = validationResult.data;
518
+
519
+ const result = await authService.exchangeResetPasswordToken(email, code);
520
+
521
+ const response: ExchangeResetPasswordTokenResponse = {
522
+ token: result.token,
523
+ expiresAt: result.expiresAt.toISOString(),
524
+ };
525
+
526
+ successResponse(res, response);
527
+ } catch (error) {
528
+ next(error);
529
+ }
530
+ }
531
+ );
532
+
533
+ // POST /api/auth/email/reset-password - Reset password with token
534
+ // Token can be:
535
+ // - Magic link token (from send-reset-password endpoint when method is 'link')
536
+ // - Reset token (from exchange-reset-password-token endpoint after code verification)
537
+ // Both use RESET_PASSWORD purpose and are verified the same way
538
+ // Flow:
539
+ // Code: send-reset-password → exchange-reset-password-token → reset-password (with resetToken)
540
+ // Link: send-reset-password → reset-password (with link token)
541
+ router.post(
542
+ '/email/reset-password',
543
+ verifyOTPLimiter,
544
+ async (req: Request, res: Response, next: NextFunction) => {
545
+ try {
546
+ const validationResult = resetPasswordRequestSchema.safeParse(req.body);
547
+ if (!validationResult.success) {
548
+ throw new AppError(
549
+ validationResult.error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join(', '),
550
+ 400,
551
+ ERROR_CODES.INVALID_INPUT
552
+ );
553
+ }
554
+
555
+ const { newPassword, otp } = validationResult.data;
556
+
557
+ // Both magic link tokens and code-verified reset tokens use RESET_PASSWORD purpose
558
+ const result: ResetPasswordResponse = await authService.resetPasswordWithToken(
559
+ newPassword,
560
+ otp
561
+ );
562
+
563
+ successResponse(res, result); // Return message with optional redirectTo
564
+ } catch (error) {
565
+ next(error);
566
+ }
567
+ }
568
+ );
569
+
570
+ export default router;