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