insforge 1.2.10 → 1.4.8

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 (506) hide show
  1. package/.claude-plugin/marketplace.json +20 -20
  2. package/.dockerignore +60 -60
  3. package/.env.example +83 -77
  4. package/.github/ISSUE_TEMPLATE/bug_report.yml +36 -36
  5. package/.github/ISSUE_TEMPLATE/config.yml +11 -11
  6. package/.github/ISSUE_TEMPLATE/feature_request.yml +26 -26
  7. package/.github/PULL_REQUEST_TEMPLATE.md +7 -7
  8. package/.github/copilot-instructions.md +146 -146
  9. package/.github/workflows/build-image.yml +65 -65
  10. package/.github/workflows/ci-premerge-check.yml +23 -23
  11. package/.github/workflows/e2e.yml +63 -63
  12. package/.github/workflows/lint-and-format.yml +32 -32
  13. package/.prettierignore +64 -64
  14. package/CHANGELOG.md +46 -44
  15. package/CLAUDE_PLUGIN.md +104 -104
  16. package/CODE_OF_CONDUCT.md +128 -128
  17. package/CONTRIBUTING.md +125 -125
  18. package/Dockerfile +30 -30
  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 -182
  23. package/assets/Dark.svg +23 -23
  24. package/auth/package.json +30 -28
  25. package/auth/src/lib/broadcastService.ts +4 -4
  26. package/auth/src/lib/insforge.ts +8 -0
  27. package/auth/src/main.tsx +2 -4
  28. package/auth/src/pages/SignInPage.tsx +5 -2
  29. package/auth/src/pages/SignUpPage.tsx +5 -2
  30. package/auth/src/pages/VerifyEmailPage.tsx +18 -0
  31. package/auth/tsconfig.json +33 -32
  32. package/auth/tsconfig.node.json +11 -11
  33. package/backend/package.json +82 -75
  34. package/backend/src/api/middlewares/rate-limiters.ts +127 -127
  35. package/backend/src/api/routes/ai/index.routes.ts +475 -468
  36. package/backend/src/api/routes/auth/index.routes.ts +720 -570
  37. package/backend/src/api/routes/auth/oauth.routes.ts +478 -448
  38. package/backend/src/api/routes/database/advance.routes.ts +37 -16
  39. package/backend/src/api/routes/database/index.routes.ts +80 -1
  40. package/backend/src/api/routes/database/records.routes.ts +48 -184
  41. package/backend/src/api/routes/database/rpc.routes.ts +69 -0
  42. package/backend/src/api/routes/database/tables.routes.ts +0 -14
  43. package/backend/src/api/routes/deployments/index.routes.ts +192 -0
  44. package/backend/src/api/routes/docs/index.routes.ts +76 -76
  45. package/backend/src/api/routes/email/index.routes.ts +35 -0
  46. package/backend/src/api/routes/functions/index.routes.ts +21 -15
  47. package/backend/src/api/routes/metadata/index.routes.ts +38 -0
  48. package/backend/src/api/routes/realtime/channels.routes.ts +81 -0
  49. package/backend/src/api/routes/realtime/index.routes.ts +12 -0
  50. package/backend/src/api/routes/realtime/messages.routes.ts +48 -0
  51. package/backend/src/api/routes/realtime/permissions.routes.ts +19 -0
  52. package/backend/src/api/routes/storage/index.routes.ts +18 -12
  53. package/backend/src/api/routes/usage/index.routes.ts +6 -4
  54. package/backend/src/api/routes/webhooks/index.routes.ts +109 -0
  55. package/backend/src/infra/database/database.manager.ts +14 -11
  56. package/backend/src/infra/database/migrations/000_create-base-tables.sql +141 -141
  57. package/backend/src/infra/database/migrations/001_create-helper-functions.sql +40 -40
  58. package/backend/src/infra/database/migrations/002_rename-auth-tables.sql +29 -29
  59. package/backend/src/infra/database/migrations/003_create-users-table.sql +55 -55
  60. package/backend/src/infra/database/migrations/004_add-reload-postgrest-func.sql +23 -23
  61. package/backend/src/infra/database/migrations/005_enable-project-admin-modify-users.sql +29 -29
  62. package/backend/src/infra/database/migrations/006_modify-ai-usage-table.sql +24 -24
  63. package/backend/src/infra/database/migrations/007_drop-metadata-table.sql +1 -1
  64. package/backend/src/infra/database/migrations/008_add-system-tables.sql +76 -76
  65. package/backend/src/infra/database/migrations/009_add-function-secrets.sql +23 -23
  66. package/backend/src/infra/database/migrations/010_modify-ai-config-modalities.sql +93 -93
  67. package/backend/src/infra/database/migrations/011_refactor-secrets-table.sql +15 -15
  68. package/backend/src/infra/database/migrations/012_add-storage-uploaded-by.sql +7 -7
  69. package/backend/src/infra/database/migrations/013_create-auth-schema-functions.sql +44 -44
  70. package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +7 -7
  71. package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +59 -59
  72. package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -24
  73. package/backend/src/infra/database/migrations/017_create-realtime-schema.sql +233 -0
  74. package/backend/src/infra/database/migrations/018_schema-rework.sql +441 -0
  75. package/backend/src/infra/database/migrations/019_create-deployments-table.sql +36 -0
  76. package/backend/src/infra/database/migrations/020_add-audio-modality.sql +11 -0
  77. package/backend/src/infra/database/migrations/bootstrap/bootstrap-migrations.js +103 -0
  78. package/backend/src/infra/realtime/realtime.manager.ts +246 -0
  79. package/backend/src/infra/realtime/webhook-sender.ts +82 -0
  80. package/backend/src/infra/security/token.manager.ts +216 -125
  81. package/backend/src/infra/socket/socket.manager.ts +198 -64
  82. package/backend/src/providers/ai/openrouter.provider.ts +24 -12
  83. package/backend/src/providers/database/base.provider.ts +39 -0
  84. package/backend/src/providers/database/cloud.provider.ts +159 -0
  85. package/backend/src/providers/deployments/vercel.provider.ts +516 -0
  86. package/backend/src/providers/email/base.provider.ts +4 -7
  87. package/backend/src/providers/email/cloud.provider.ts +84 -0
  88. package/backend/src/providers/oauth/apple.provider.ts +266 -0
  89. package/backend/src/providers/oauth/index.ts +1 -0
  90. package/backend/src/server.ts +329 -284
  91. package/backend/src/services/ai/ai-config.service.ts +6 -6
  92. package/backend/src/services/ai/ai-model.service.ts +60 -60
  93. package/backend/src/services/ai/ai-usage.service.ts +7 -7
  94. package/backend/src/services/ai/chat-completion.service.ts +415 -220
  95. package/backend/src/services/ai/helpers.ts +64 -64
  96. package/backend/src/services/ai/image-generation.service.ts +3 -3
  97. package/backend/src/services/ai/index.ts +13 -13
  98. package/backend/src/services/auth/auth-config.service.ts +4 -4
  99. package/backend/src/services/auth/auth-otp.service.ts +6 -6
  100. package/backend/src/services/auth/auth.service.ts +148 -74
  101. package/backend/src/services/auth/index.ts +4 -4
  102. package/backend/src/services/auth/oauth-config.service.ts +12 -12
  103. package/backend/src/services/database/database-advance.service.ts +19 -55
  104. package/backend/src/services/database/database-table.service.ts +38 -94
  105. package/backend/src/services/database/database.service.ts +127 -0
  106. package/backend/src/services/database/postgrest-proxy.service.ts +165 -0
  107. package/backend/src/services/deployments/deployment.service.ts +693 -0
  108. package/backend/src/services/email/email.service.ts +5 -7
  109. package/backend/src/services/functions/function.service.ts +61 -41
  110. package/backend/src/services/logs/audit.service.ts +10 -10
  111. package/backend/src/services/realtime/index.ts +3 -0
  112. package/backend/src/services/realtime/realtime-auth.service.ts +104 -0
  113. package/backend/src/services/realtime/realtime-channel.service.ts +237 -0
  114. package/backend/src/services/realtime/realtime-message.service.ts +260 -0
  115. package/backend/src/services/secrets/secret.service.ts +101 -27
  116. package/backend/src/services/storage/storage.service.ts +30 -30
  117. package/backend/src/services/usage/usage.service.ts +6 -6
  118. package/backend/src/types/ai.ts +8 -0
  119. package/backend/src/types/auth.ts +16 -1
  120. package/backend/src/types/database.ts +2 -0
  121. package/backend/src/types/deployments.ts +33 -0
  122. package/backend/src/types/realtime.ts +18 -0
  123. package/backend/src/types/socket.ts +7 -31
  124. package/backend/src/types/storage.ts +1 -1
  125. package/backend/src/types/webhooks.ts +45 -0
  126. package/backend/src/utils/cookies.ts +34 -0
  127. package/backend/src/utils/environment.ts +0 -14
  128. package/backend/src/utils/s3-config-loader.ts +64 -0
  129. package/backend/src/utils/seed.ts +79 -43
  130. package/backend/src/utils/sql-parser.ts +216 -0
  131. package/backend/src/utils/utils.ts +114 -114
  132. package/backend/src/utils/validations.ts +10 -10
  133. package/backend/tests/README.md +133 -133
  134. package/backend/tests/cleanup-all-test-data.sh +230 -230
  135. package/backend/tests/cloud/test-s3-multitenant.sh +131 -131
  136. package/backend/tests/local/comprehensive-curl-tests.sh +155 -155
  137. package/backend/tests/local/test-ai-config.sh +129 -129
  138. package/backend/tests/local/test-ai-usage.sh +80 -80
  139. package/backend/tests/local/test-auth-router.sh +143 -143
  140. package/backend/tests/local/test-database-router.sh +222 -222
  141. package/backend/tests/local/test-e2e.sh +240 -240
  142. package/backend/tests/local/test-fk-errors.sh +96 -96
  143. package/backend/tests/local/test-functions.sh +123 -123
  144. package/backend/tests/local/test-id-field.sh +200 -200
  145. package/backend/tests/local/test-logs.sh +132 -132
  146. package/backend/tests/local/test-public-bucket.sh +264 -264
  147. package/backend/tests/local/test-rpc.sh +141 -0
  148. package/backend/tests/local/test-secrets.sh +249 -249
  149. package/backend/tests/local/test-serverless-functions.sh.disabled +325 -325
  150. package/backend/tests/local/test-traditional-rest.sh +208 -208
  151. package/backend/tests/manual/README.md +50 -50
  152. package/backend/tests/manual/create-large-table-simple.sql +10 -10
  153. package/backend/tests/manual/seed-large-table.sql +100 -100
  154. package/backend/tests/manual/setup-large-table-extras.sql +33 -33
  155. package/backend/tests/manual/test-ai-model-plugins.sh +258 -0
  156. package/backend/tests/manual/test-bulk-upsert.sh +409 -409
  157. package/backend/tests/manual/test-database-advance.sh +296 -296
  158. package/backend/tests/manual/test-postgrest-stability.sh +191 -191
  159. package/backend/tests/manual/test-rawsql-export-import.sh +411 -411
  160. package/backend/tests/manual/test-rawsql-modes.sh +244 -244
  161. package/backend/tests/manual/test-universal-storage.sh +263 -263
  162. package/backend/tests/manual/test-users.sql +17 -17
  163. package/backend/tests/run-all-tests.sh +139 -139
  164. package/backend/tests/setup.ts +0 -0
  165. package/backend/tests/test-config.sh +338 -338
  166. package/backend/tests/unit/analyze-query.test.ts +697 -0
  167. package/backend/tests/unit/database-advance.test.ts +326 -0
  168. package/backend/tests/unit/helpers.test.ts +2 -2
  169. package/backend/tsconfig.json +22 -22
  170. package/claude-plugin/.claude-plugin/plugin.json +24 -24
  171. package/claude-plugin/README.md +133 -133
  172. package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +273 -270
  173. package/docker-compose.prod.yml +204 -200
  174. package/docker-compose.yml +232 -228
  175. package/docker-init/db/db-init.sql +97 -97
  176. package/docker-init/db/jwt.sql +5 -5
  177. package/docker-init/db/postgresql.conf +16 -16
  178. package/docker-init/logs/vector.yml +236 -236
  179. package/docs/README.md +44 -44
  180. package/docs/agent-docs/deployment.md +79 -0
  181. package/docs/agent-docs/real-time.md +269 -0
  182. package/docs/changelog.mdx +212 -67
  183. package/docs/core-concepts/ai/architecture.mdx +350 -372
  184. package/docs/core-concepts/ai/sdk.mdx +238 -213
  185. package/docs/core-concepts/authentication/architecture.mdx +276 -278
  186. package/docs/core-concepts/authentication/sdk.mdx +710 -414
  187. package/docs/core-concepts/authentication/ui-components/customization.mdx +733 -529
  188. package/docs/core-concepts/authentication/ui-components/nextjs.mdx +247 -221
  189. package/docs/core-concepts/authentication/ui-components/react-router.mdx +183 -184
  190. package/docs/core-concepts/authentication/ui-components/react.mdx +136 -129
  191. package/docs/core-concepts/database/architecture.mdx +292 -255
  192. package/docs/core-concepts/database/pgvector.mdx +138 -0
  193. package/docs/core-concepts/database/sdk.mdx +382 -382
  194. package/docs/core-concepts/deployments/architecture.mdx +152 -0
  195. package/docs/core-concepts/email/architecture.mdx +103 -0
  196. package/docs/core-concepts/email/sdk.mdx +53 -0
  197. package/docs/core-concepts/functions/architecture.mdx +105 -105
  198. package/docs/core-concepts/functions/sdk.mdx +183 -184
  199. package/docs/core-concepts/realtime/architecture.mdx +446 -0
  200. package/docs/core-concepts/realtime/sdk.mdx +409 -0
  201. package/docs/core-concepts/storage/architecture.mdx +243 -243
  202. package/docs/core-concepts/storage/sdk.mdx +253 -253
  203. package/docs/deployment/README.md +94 -94
  204. package/docs/deployment/deploy-to-aws-ec2.md +564 -564
  205. package/docs/deployment/deploy-to-azure-virtual-machines.md +312 -312
  206. package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -613
  207. package/docs/deployment/deploy-to-render.md +441 -441
  208. package/docs/deprecated/insforge-auth-api.md +214 -214
  209. package/docs/deprecated/insforge-auth-sdk.md +99 -99
  210. package/docs/deprecated/insforge-db-api.md +358 -358
  211. package/docs/deprecated/insforge-db-sdk.md +139 -139
  212. package/docs/deprecated/insforge-debug-sdk.md +156 -156
  213. package/docs/deprecated/insforge-debug.md +64 -64
  214. package/docs/deprecated/insforge-instructions.md +123 -123
  215. package/docs/deprecated/insforge-project.md +117 -117
  216. package/docs/deprecated/insforge-storage-api.md +278 -278
  217. package/docs/deprecated/insforge-storage-sdk.md +158 -158
  218. package/docs/docs.json +240 -210
  219. package/docs/examples/framework-guides/nextjs.mdx +131 -131
  220. package/docs/examples/framework-guides/nuxt.mdx +165 -165
  221. package/docs/examples/framework-guides/react.mdx +165 -165
  222. package/docs/examples/framework-guides/svelte.mdx +153 -153
  223. package/docs/examples/framework-guides/vue.mdx +159 -159
  224. package/docs/examples/overview.mdx +67 -67
  225. package/docs/favicon.png +0 -0
  226. package/docs/favicon.svg +4 -19
  227. package/docs/images/changelog/dec-2025/ai-integration.png +0 -0
  228. package/docs/images/changelog/dec-2025/ai-models.webp +0 -0
  229. package/docs/images/changelog/dec-2025/alipay-payment.webp +0 -0
  230. package/docs/images/changelog/dec-2025/apple-login.jpg +0 -0
  231. package/docs/images/changelog/dec-2025/apple-oauth.mp4 +0 -0
  232. package/docs/images/changelog/dec-2025/mcp-installer.png +0 -0
  233. package/docs/images/changelog/dec-2025/moreModels.png +0 -0
  234. package/docs/images/changelog/dec-2025/multi-region.webp +0 -0
  235. package/docs/images/changelog/dec-2025/postgres-connection.webp +0 -0
  236. package/docs/images/changelog/dec-2025/realtime-module.jpg +0 -0
  237. package/docs/images/changelog/dec-2025/realtime2.png +0 -0
  238. package/docs/images/icons/ai.svg +4 -4
  239. package/docs/images/logos/nextjs.svg +4 -4
  240. package/docs/images/logos/nuxt.svg +4 -4
  241. package/docs/images/logos/react.svg +5 -5
  242. package/docs/images/logos/svelte.svg +4 -4
  243. package/docs/images/logos/vue.svg +5 -5
  244. package/docs/images/mcp-setup/CC-MCP-1.mp4 +0 -0
  245. package/docs/images/mcp-setup/CC-MCP-2.mp4 +0 -0
  246. package/docs/images/mcp-setup/Cursor-MCP-1.mp4 +0 -0
  247. package/docs/images/mcp-setup/Cursor-MCP-2.mp4 +0 -0
  248. package/docs/images/mcp-setup/Cursor-MCP-3.mp4 +0 -0
  249. package/docs/images/mcp-setup/claude-code-connect.png +0 -0
  250. package/docs/images/mcp-setup/cline-1.png +0 -0
  251. package/docs/images/mcp-setup/cline-2.png +0 -0
  252. package/docs/images/mcp-setup/cline-3.png +0 -0
  253. package/docs/images/mcp-setup/connect-project.png +0 -0
  254. package/docs/images/mcp-setup/copilot-1.png +0 -0
  255. package/docs/images/mcp-setup/copilot-2.png +0 -0
  256. package/docs/images/mcp-setup/copilot-3.png +0 -0
  257. package/docs/images/mcp-setup/mcp-json-1.png +0 -0
  258. package/docs/images/mcp-setup/mcp-json-2.png +0 -0
  259. package/docs/images/mcp-setup/qoder-1.png +0 -0
  260. package/docs/images/mcp-setup/qoder-2.png +0 -0
  261. package/docs/images/mcp-setup/roocode-1.png +0 -0
  262. package/docs/images/mcp-setup/roocode-2.png +0 -0
  263. package/docs/images/mcp-setup/trae-1.png +0 -0
  264. package/docs/images/mcp-setup/trae-2.png +0 -0
  265. package/docs/images/mcp-setup/trae-3.png +0 -0
  266. package/docs/images/mcp-setup/trae-4.png +0 -0
  267. package/docs/images/mcp-setup/trae-5.png +0 -0
  268. package/docs/images/mcp-setup/windsurf-1.png +0 -0
  269. package/docs/images/mcp-setup/windsurf-2.png +0 -0
  270. package/docs/insforge-instructions-sdk.md +93 -88
  271. package/docs/introduction.mdx +46 -45
  272. package/docs/logo/dark.svg +22 -22
  273. package/docs/logo/light.svg +20 -20
  274. package/docs/mcp-setup.mdx +332 -0
  275. package/docs/oauth-server.mdx +563 -0
  276. package/docs/partnership.mdx +720 -646
  277. package/docs/quickstart.mdx +82 -82
  278. package/docs/showcase.mdx +52 -52
  279. package/docs/snippets/sdk-installation.mdx +21 -21
  280. package/docs/snippets/service-icons.mdx +27 -27
  281. package/docs/vscode-extension.mdx +74 -0
  282. package/eslint.config.js +1 -0
  283. package/examples/oauth/frontend-oauth-example.html +250 -250
  284. package/examples/response-examples.md +443 -443
  285. package/frontend/components.json +17 -17
  286. package/frontend/package.json +69 -69
  287. package/frontend/src/App.tsx +8 -3
  288. package/frontend/src/assets/icons/checkbox_checked.svg +6 -6
  289. package/frontend/src/assets/icons/checkbox_undetermined.svg +6 -6
  290. package/frontend/src/assets/icons/checked.svg +3 -3
  291. package/frontend/src/assets/icons/connected.svg +3 -3
  292. package/frontend/src/assets/icons/error.svg +3 -3
  293. package/frontend/src/assets/icons/loader.svg +9 -9
  294. package/frontend/src/assets/icons/pencil.svg +4 -4
  295. package/frontend/src/assets/icons/refresh.svg +4 -4
  296. package/frontend/src/assets/icons/step_active.svg +3 -3
  297. package/frontend/src/assets/icons/step_inactive.svg +11 -11
  298. package/frontend/src/assets/icons/warning.svg +3 -3
  299. package/frontend/src/assets/logos/antigravity.svg +1 -0
  300. package/frontend/src/assets/logos/apple.svg +3 -3
  301. package/frontend/src/assets/logos/claude_code.svg +3 -3
  302. package/frontend/src/assets/logos/cline.svg +6 -6
  303. package/frontend/src/assets/logos/copilot.svg +10 -0
  304. package/frontend/src/assets/logos/cursor.svg +20 -20
  305. package/frontend/src/assets/logos/deepseek.svg +139 -0
  306. package/frontend/src/assets/logos/discord.svg +8 -8
  307. package/frontend/src/assets/logos/facebook.svg +3 -3
  308. package/frontend/src/assets/logos/gemini.svg +19 -19
  309. package/frontend/src/assets/logos/github.svg +5 -5
  310. package/frontend/src/assets/logos/google.svg +13 -13
  311. package/frontend/src/assets/logos/grok.svg +10 -10
  312. package/frontend/src/assets/logos/insforge_dark.svg +15 -15
  313. package/frontend/src/assets/logos/insforge_light.svg +15 -15
  314. package/frontend/src/assets/logos/instagram.svg +1 -1
  315. package/frontend/src/assets/logos/kiro.svg +9 -0
  316. package/frontend/src/assets/logos/linkedin.svg +3 -3
  317. package/frontend/src/assets/logos/openai.svg +10 -10
  318. package/frontend/src/assets/logos/qoder.svg +4 -0
  319. package/frontend/src/assets/logos/qwen.svg +15 -0
  320. package/frontend/src/assets/logos/roo_code.svg +9 -9
  321. package/frontend/src/assets/logos/spotify.svg +16 -16
  322. package/frontend/src/assets/logos/tiktok.svg +5 -5
  323. package/frontend/src/assets/logos/trae.svg +3 -3
  324. package/frontend/src/assets/logos/windsurf.svg +10 -10
  325. package/frontend/src/assets/logos/x.svg +3 -3
  326. package/frontend/src/components/CodeBlock.tsx +2 -2
  327. package/frontend/src/components/ConnectCTA.tsx +3 -2
  328. package/frontend/src/components/datagrid/DataGrid.tsx +90 -62
  329. package/frontend/src/components/datagrid/datagridTypes.tsx +2 -1
  330. package/frontend/src/components/datagrid/index.ts +1 -1
  331. package/frontend/src/components/index.ts +0 -1
  332. package/frontend/src/components/layout/AppHeader.tsx +13 -37
  333. package/frontend/src/components/layout/AppSidebar.tsx +85 -100
  334. package/frontend/src/components/layout/Layout.tsx +34 -32
  335. package/frontend/src/components/layout/PrimaryMenu.tsx +12 -4
  336. package/frontend/src/components/radix/Select.tsx +151 -151
  337. package/frontend/src/features/ai/components/AIConfigCard.tsx +200 -200
  338. package/frontend/src/features/ai/components/AIEmptyState.tsx +23 -23
  339. package/frontend/src/features/ai/components/ModalityFilterSidebar.tsx +102 -101
  340. package/frontend/src/features/ai/components/ModelSelectionDialog.tsx +135 -135
  341. package/frontend/src/features/ai/components/ModelSelectionGrid.tsx +51 -51
  342. package/frontend/src/features/ai/components/SystemPromptDialog.tsx +118 -118
  343. package/frontend/src/features/ai/components/index.ts +6 -6
  344. package/frontend/src/features/ai/helpers.ts +147 -141
  345. package/frontend/src/features/ai/{page → pages}/AIPage.tsx +166 -166
  346. package/frontend/src/features/auth/components/AuthPreview.tsx +96 -96
  347. package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +1 -0
  348. package/frontend/src/features/auth/components/UsersDataGrid.tsx +61 -31
  349. package/frontend/src/features/auth/components/index.ts +5 -5
  350. package/frontend/src/features/auth/helpers.tsx +8 -0
  351. package/frontend/src/features/auth/{page → pages}/AuthMethodsPage.tsx +275 -275
  352. package/frontend/src/features/auth/{page → pages}/UsersPage.tsx +0 -28
  353. package/frontend/src/features/dashboard/{page → pages}/DashboardPage.tsx +1 -1
  354. package/frontend/src/features/database/components/DatabaseDataGrid.tsx +0 -2
  355. package/frontend/src/features/database/components/ForeignKeyCell.tsx +38 -11
  356. package/frontend/src/features/database/components/ForeignKeyPopover.tsx +18 -8
  357. package/frontend/src/features/database/components/LinkRecordModal.tsx +61 -13
  358. package/frontend/src/features/database/components/RecordFormField.tsx +1 -1
  359. package/frontend/src/features/database/components/SQLModal.tsx +75 -0
  360. package/frontend/src/features/database/components/TableForm.tsx +0 -4
  361. package/frontend/src/features/database/components/TableSidebar.tsx +0 -3
  362. package/frontend/src/features/database/components/TablesEmptyState.tsx +1 -1
  363. package/frontend/src/features/database/components/TemplatePreview.tsx +1 -2
  364. package/frontend/src/features/database/constants.ts +16 -28
  365. package/frontend/src/features/database/hooks/useCSVImport.ts +3 -2
  366. package/frontend/src/features/database/hooks/useDatabase.ts +66 -0
  367. package/frontend/src/features/database/hooks/useRawSQL.ts +3 -2
  368. package/frontend/src/features/database/hooks/useTables.ts +30 -28
  369. package/frontend/src/features/database/index.ts +1 -0
  370. package/frontend/src/features/database/{page → pages}/FunctionsPage.tsx +29 -42
  371. package/frontend/src/features/database/{page → pages}/IndexesPage.tsx +34 -51
  372. package/frontend/src/features/database/{page → pages}/PoliciesPage.tsx +42 -58
  373. package/frontend/src/features/database/{page → pages}/SQLEditorPage.tsx +2 -2
  374. package/frontend/src/features/database/{page → pages}/TablesPage.tsx +0 -42
  375. package/frontend/src/features/database/{page → pages}/TriggersPage.tsx +34 -51
  376. package/frontend/src/features/database/services/advance.service.ts +1 -41
  377. package/frontend/src/features/database/services/database.service.ts +55 -0
  378. package/frontend/src/features/database/services/record.service.ts +4 -20
  379. package/frontend/src/features/database/services/table.service.ts +1 -10
  380. package/frontend/src/features/database/templates/ai-chatbot.ts +6 -6
  381. package/frontend/src/features/database/templates/ecommerce-platform.ts +2 -2
  382. package/frontend/src/features/database/templates/instagram-clone.ts +10 -10
  383. package/frontend/src/features/database/templates/notion-clone.ts +8 -8
  384. package/frontend/src/features/database/templates/reddit-clone.ts +10 -10
  385. package/frontend/src/features/deployments/components/DeploymentRow.tsx +93 -0
  386. package/frontend/src/features/deployments/components/DeploymentsEmptyState.tsx +15 -0
  387. package/frontend/src/features/deployments/hooks/useDeployments.ts +157 -0
  388. package/frontend/src/features/deployments/pages/DeploymentsPage.tsx +318 -0
  389. package/frontend/src/features/deployments/services/deployments.service.ts +63 -0
  390. package/frontend/src/features/functions/components/FunctionRow.tsx +72 -72
  391. package/frontend/src/features/functions/components/FunctionsSidebar.tsx +56 -56
  392. package/frontend/src/features/functions/components/SecretRow.tsx +3 -3
  393. package/frontend/src/features/functions/components/index.ts +5 -5
  394. package/frontend/src/features/functions/hooks/useFunctions.ts +5 -4
  395. package/frontend/src/features/functions/hooks/useSecrets.ts +6 -9
  396. package/frontend/src/features/functions/{page → pages}/FunctionsPage.tsx +21 -44
  397. package/frontend/src/features/functions/{page → pages}/SecretsPage.tsx +118 -116
  398. package/frontend/src/features/functions/services/function.service.ts +8 -25
  399. package/frontend/src/features/functions/services/secret.service.ts +23 -41
  400. package/frontend/src/features/login/{page → pages}/CloudLoginPage.tsx +125 -118
  401. package/frontend/src/features/logs/components/LogDetailPanel.tsx +41 -0
  402. package/frontend/src/features/logs/components/LogsDataGrid.tsx +32 -1
  403. package/frontend/src/features/logs/components/index.ts +1 -0
  404. package/frontend/src/features/logs/hooks/useMcpUsage.ts +13 -66
  405. package/frontend/src/features/logs/{page → pages}/LogsPage.tsx +36 -6
  406. package/frontend/src/features/onboard/components/ApiCredentialsSection.tsx +59 -0
  407. package/frontend/src/features/onboard/components/ConnectionStringSection.tsx +180 -0
  408. package/frontend/src/features/onboard/components/McpConnectionSection.tsx +159 -0
  409. package/frontend/src/features/onboard/components/OnboardingController.tsx +68 -0
  410. package/frontend/src/features/onboard/components/OnboardingModal.tsx +121 -267
  411. package/frontend/src/features/onboard/components/ShowPasswordButton.tsx +21 -0
  412. package/frontend/src/features/onboard/components/index.ts +9 -4
  413. package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +1 -1
  414. package/frontend/src/features/onboard/components/mcp/QoderDeeplinkGenerator.tsx +36 -0
  415. package/frontend/src/features/onboard/components/mcp/helpers.tsx +123 -98
  416. package/frontend/src/features/onboard/components/mcp/index.ts +4 -3
  417. package/frontend/src/features/onboard/index.ts +17 -13
  418. package/frontend/src/features/realtime/components/ChannelRow.tsx +83 -0
  419. package/frontend/src/features/realtime/components/EditChannelModal.tsx +246 -0
  420. package/frontend/src/features/realtime/components/MessageRow.tsx +85 -0
  421. package/frontend/src/features/realtime/components/RealtimeEmptyState.tsx +30 -0
  422. package/frontend/src/features/realtime/hooks/useRealtime.ts +218 -0
  423. package/frontend/src/features/realtime/index.ts +11 -0
  424. package/frontend/src/features/realtime/pages/RealtimeChannelsPage.tsx +172 -0
  425. package/frontend/src/features/realtime/pages/RealtimeMessagesPage.tsx +211 -0
  426. package/frontend/src/features/realtime/pages/RealtimePermissionsPage.tsx +191 -0
  427. package/frontend/src/features/realtime/services/realtime.service.ts +107 -0
  428. package/frontend/src/features/settings/pages/SettingsPage.tsx +349 -0
  429. package/frontend/src/features/storage/{page → pages}/StoragePage.tsx +1 -29
  430. package/frontend/src/features/visualizer/components/AuthNode.tsx +4 -4
  431. package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +24 -11
  432. package/frontend/src/features/visualizer/{page → pages}/VisualizerPage.tsx +11 -36
  433. package/frontend/src/index.css +249 -249
  434. package/frontend/src/lib/contexts/ModalContext.tsx +35 -0
  435. package/frontend/src/lib/contexts/SocketContext.tsx +119 -75
  436. package/frontend/src/lib/hooks/useMetadata.ts +45 -1
  437. package/frontend/src/lib/hooks/useModal.tsx +2 -0
  438. package/frontend/src/lib/routing/AppRoutes.tsx +103 -84
  439. package/frontend/src/lib/services/metadata.service.ts +20 -3
  440. package/frontend/src/lib/utils/cloudMessaging.ts +1 -1
  441. package/frontend/src/lib/utils/menuItems.ts +223 -183
  442. package/frontend/src/lib/utils/utils.ts +196 -183
  443. package/frontend/tsconfig.json +25 -25
  444. package/frontend/tsconfig.node.json +9 -9
  445. package/functions/deno.json +24 -24
  446. package/functions/server.ts +6 -6
  447. package/functions/worker-template.js +1 -1
  448. package/i18n/README.ar.md +130 -130
  449. package/i18n/README.de.md +130 -130
  450. package/i18n/README.es.md +154 -154
  451. package/i18n/README.fr.md +134 -134
  452. package/i18n/README.hi.md +129 -129
  453. package/i18n/README.ja.md +174 -174
  454. package/i18n/README.ko.md +136 -136
  455. package/i18n/README.pt-BR.md +131 -131
  456. package/i18n/README.ru.md +129 -129
  457. package/i18n/README.zh-CN.md +133 -133
  458. package/openapi/ai.yaml +825 -715
  459. package/openapi/auth.yaml +1324 -1244
  460. package/openapi/email.yaml +158 -0
  461. package/openapi/functions.yaml +475 -475
  462. package/openapi/health.yaml +29 -29
  463. package/openapi/logs.yaml +221 -223
  464. package/openapi/metadata.yaml +175 -177
  465. package/openapi/realtime.yaml +699 -0
  466. package/openapi/records.yaml +381 -381
  467. package/openapi/secrets.yaml +370 -370
  468. package/openapi/storage.yaml +875 -875
  469. package/openapi/tables.yaml +462 -463
  470. package/package.json +97 -97
  471. package/shared-schemas/package.json +31 -31
  472. package/shared-schemas/src/ai-api.schema.ts +251 -143
  473. package/shared-schemas/src/ai.schema.ts +8 -4
  474. package/shared-schemas/src/auth-api.schema.ts +380 -339
  475. package/shared-schemas/src/auth.schema.ts +18 -11
  476. package/shared-schemas/src/cloud-events.schema.ts +26 -0
  477. package/shared-schemas/src/database-api.schema.ts +32 -1
  478. package/shared-schemas/src/database.schema.ts +39 -0
  479. package/shared-schemas/src/deployments-api.schema.ts +55 -0
  480. package/shared-schemas/src/deployments.schema.ts +30 -0
  481. package/shared-schemas/src/docs.schema.ts +32 -0
  482. package/shared-schemas/src/email-api.schema.ts +30 -0
  483. package/shared-schemas/src/functions-api.schema.ts +13 -4
  484. package/shared-schemas/src/functions.schema.ts +1 -1
  485. package/shared-schemas/src/index.ts +22 -14
  486. package/shared-schemas/src/metadata.schema.ts +39 -4
  487. package/shared-schemas/src/realtime-api.schema.ts +111 -0
  488. package/shared-schemas/src/realtime.schema.ts +143 -0
  489. package/shared-schemas/src/secrets-api.schema.ts +44 -0
  490. package/shared-schemas/src/secrets.schema.ts +15 -0
  491. package/shared-schemas/tsconfig.json +21 -21
  492. package/tsconfig.json +7 -7
  493. package/zeabur/README.md +26 -13
  494. package/zeabur/template.yml +1001 -1032
  495. package/.cursor/rules/cursor-rules.mdc +0 -94
  496. package/backend/src/types/profile.ts +0 -55
  497. package/frontend/src/components/ProjectInfoModal.tsx +0 -128
  498. package/frontend/src/features/database/hooks/useFullMetadata.ts +0 -18
  499. package/test-gemini.sh +0 -35
  500. package/test-usage-admin.sh +0 -57
  501. package/test-usage.sh +0 -50
  502. /package/frontend/src/features/auth/{page → pages}/ConfigurationPage.tsx +0 -0
  503. /package/frontend/src/features/database/{page → pages}/TemplatesPage.tsx +0 -0
  504. /package/frontend/src/features/login/{page → pages}/LoginPage.tsx +0 -0
  505. /package/frontend/src/features/logs/{page → pages}/AuditsPage.tsx +0 -0
  506. /package/frontend/src/features/logs/{page → pages}/MCPLogsPage.tsx +0 -0
@@ -13,6 +13,7 @@ import type {
13
13
  CreateAdminSessionResponse,
14
14
  AuthMetadataSchema,
15
15
  OAuthProvidersSchema,
16
+ AuthOptions,
16
17
  } from '@insforge/shared-schemas';
17
18
  import { OAuthConfigService } from '@/services/auth/oauth-config.service.js';
18
19
  import { AuthConfigService } from './auth-config.service.js';
@@ -33,6 +34,7 @@ import {
33
34
  LinkedInUserInfo,
34
35
  DiscordUserInfo,
35
36
  XUserInfo,
37
+ AppleUserInfo,
36
38
  UserRecord,
37
39
  OAuthUserData,
38
40
  } from '@/types/auth.js';
@@ -42,6 +44,7 @@ import { AppError } from '@/api/middlewares/error.js';
42
44
  import { ERROR_CODES } from '@/types/error-constants.js';
43
45
  import { EmailService } from '@/services/email/email.service.js';
44
46
  import { XOAuthProvider } from '@/providers/oauth/x.provider.js';
47
+ import { AppleOAuthProvider } from '@/providers/oauth/apple.provider.js';
45
48
 
46
49
  /**
47
50
  * Simplified JWT-based auth service
@@ -62,6 +65,7 @@ export class AuthService {
62
65
  private facebookOAuthProvider: FacebookOAuthProvider;
63
66
  private microsoftOAuthProvider: MicrosoftOAuthProvider;
64
67
  private xOAuthProvider: XOAuthProvider;
68
+ private appleOAuthProvider: AppleOAuthProvider;
65
69
 
66
70
  private constructor() {
67
71
  this.adminEmail = process.env.ADMIN_EMAIL ?? '';
@@ -82,6 +86,7 @@ export class AuthService {
82
86
  this.facebookOAuthProvider = FacebookOAuthProvider.getInstance();
83
87
  this.microsoftOAuthProvider = MicrosoftOAuthProvider.getInstance();
84
88
  this.xOAuthProvider = XOAuthProvider.getInstance();
89
+ this.appleOAuthProvider = AppleOAuthProvider.getInstance();
85
90
 
86
91
  logger.info('AuthService initialized');
87
92
  }
@@ -105,7 +110,12 @@ export class AuthService {
105
110
  * User registration
106
111
  * Otherwise, returns user with access token for immediate login
107
112
  */
108
- async register(email: string, password: string, name?: string): Promise<CreateUserResponse> {
113
+ async register(
114
+ email: string,
115
+ password: string,
116
+ name?: string,
117
+ options?: AuthOptions
118
+ ): Promise<CreateUserResponse> {
109
119
  // Get email auth configuration and validate password
110
120
  const authConfigService = AuthConfigService.getInstance();
111
121
  const emailAuthConfig = await authConfigService.getAuthConfig();
@@ -126,16 +136,11 @@ export class AuthService {
126
136
  try {
127
137
  await client.query('BEGIN');
128
138
 
139
+ const profile = name ? JSON.stringify({ name }) : '{}';
129
140
  await client.query(
130
- `INSERT INTO _accounts (id, email, password, name, email_verified, created_at, updated_at)
131
- VALUES ($1, $2, $3, $4, $5, NOW(), NOW())`,
132
- [userId, email, hashedPassword, name || null, false]
133
- );
134
-
135
- await client.query(
136
- `INSERT INTO users (id, nickname, created_at, updated_at)
137
- VALUES ($1, $2, NOW(), NOW())`,
138
- [userId, name || null]
141
+ `INSERT INTO auth.users (id, email, password, profile, email_verified, created_at, updated_at)
142
+ VALUES ($1, $2, $3, $4::jsonb, $5, NOW(), NOW())`,
143
+ [userId, email, hashedPassword, profile, false]
139
144
  );
140
145
 
141
146
  await client.query('COMMIT');
@@ -159,7 +164,8 @@ export class AuthService {
159
164
  if (emailAuthConfig.requireEmailVerification) {
160
165
  try {
161
166
  if (emailAuthConfig.verifyEmailMethod === 'link') {
162
- await this.sendVerificationEmailWithLink(email);
167
+ const redirectTo = emailAuthConfig.signInRedirectTo || options?.emailRedirectTo;
168
+ await this.sendVerificationEmailWithLink(email, redirectTo);
163
169
  } else {
164
170
  await this.sendVerificationEmailWithCode(email);
165
171
  }
@@ -239,7 +245,7 @@ export class AuthService {
239
245
  async sendVerificationEmailWithCode(email: string): Promise<void> {
240
246
  // Check if user exists
241
247
  const pool = this.getPool();
242
- const result = await pool.query('SELECT * FROM _accounts WHERE email = $1', [email]);
248
+ const result = await pool.query('SELECT * FROM auth.users WHERE email = $1', [email]);
243
249
  const dbUser = result.rows[0];
244
250
  if (!dbUser) {
245
251
  // Silently succeed to prevent user enumeration
@@ -257,7 +263,8 @@ export class AuthService {
257
263
 
258
264
  // Send email with verification code
259
265
  const emailService = EmailService.getInstance();
260
- await emailService.sendWithTemplate(email, dbUser.name || 'User', 'email-verification-code', {
266
+ const userName = dbUser.profile?.name || 'User';
267
+ await emailService.sendWithTemplate(email, userName, 'email-verification-code', {
261
268
  token: code,
262
269
  });
263
270
  }
@@ -267,10 +274,10 @@ export class AuthService {
267
274
  * Creates a long cryptographic token and sends it via email as a clickable link
268
275
  * The link contains only the token (no email) for better privacy and security
269
276
  */
270
- async sendVerificationEmailWithLink(email: string): Promise<void> {
277
+ async sendVerificationEmailWithLink(email: string, emailRedirectTo?: string): Promise<void> {
271
278
  // Check if user exists
272
279
  const pool = this.getPool();
273
- const result = await pool.query('SELECT * FROM _accounts WHERE email = $1', [email]);
280
+ const result = await pool.query('SELECT * FROM auth.users WHERE email = $1', [email]);
274
281
  const dbUser = result.rows[0];
275
282
  if (!dbUser) {
276
283
  // Silently succeed to prevent user enumeration
@@ -287,11 +294,13 @@ export class AuthService {
287
294
  );
288
295
 
289
296
  // Build verification link URL using backend API endpoint
290
- const linkUrl = `${getApiBaseUrl()}/auth/verify-email?token=${token}`;
297
+ // Include redirectTo parameter if provided
298
+ const linkUrl = `${getApiBaseUrl()}/auth/verify-email?token=${token}${emailRedirectTo ? `&redirectTo=${encodeURIComponent(emailRedirectTo)}` : ''}`;
291
299
 
292
300
  // Send email with verification link
293
301
  const emailService = EmailService.getInstance();
294
- await emailService.sendWithTemplate(email, dbUser.name || 'User', 'email-verification-link', {
302
+ const userName = dbUser.profile?.name || 'User';
303
+ await emailService.sendWithTemplate(email, userName, 'email-verification-link', {
295
304
  link: linkUrl,
296
305
  });
297
306
  }
@@ -319,7 +328,7 @@ export class AuthService {
319
328
 
320
329
  // Update account email verification status
321
330
  const result = await client.query(
322
- `UPDATE _accounts
331
+ `UPDATE auth.users
323
332
  SET email_verified = true, updated_at = NOW()
324
333
  WHERE email = $1
325
334
  RETURNING id`,
@@ -385,7 +394,7 @@ export class AuthService {
385
394
 
386
395
  // Update account email verification status
387
396
  const result = await client.query(
388
- `UPDATE _accounts
397
+ `UPDATE auth.users
389
398
  SET email_verified = true, updated_at = NOW()
390
399
  WHERE email = $1
391
400
  RETURNING id`,
@@ -435,7 +444,7 @@ export class AuthService {
435
444
  async sendResetPasswordEmailWithCode(email: string): Promise<void> {
436
445
  // Check if user exists
437
446
  const pool = this.getPool();
438
- const result = await pool.query('SELECT * FROM _accounts WHERE email = $1', [email]);
447
+ const result = await pool.query('SELECT * FROM auth.users WHERE email = $1', [email]);
439
448
  const dbUser = result.rows[0];
440
449
  if (!dbUser) {
441
450
  // Silently succeed to prevent user enumeration
@@ -453,7 +462,8 @@ export class AuthService {
453
462
 
454
463
  // Send email with reset password code
455
464
  const emailService = EmailService.getInstance();
456
- await emailService.sendWithTemplate(email, dbUser.name || 'User', 'reset-password-code', {
465
+ const userName = dbUser.profile?.name || 'User';
466
+ await emailService.sendWithTemplate(email, userName, 'reset-password-code', {
457
467
  token: code,
458
468
  });
459
469
  }
@@ -466,7 +476,7 @@ export class AuthService {
466
476
  async sendResetPasswordEmailWithLink(email: string): Promise<void> {
467
477
  // Check if user exists
468
478
  const pool = this.getPool();
469
- const result = await pool.query('SELECT * FROM _accounts WHERE email = $1', [email]);
479
+ const result = await pool.query('SELECT * FROM auth.users WHERE email = $1', [email]);
470
480
  const dbUser = result.rows[0];
471
481
  if (!dbUser) {
472
482
  // Silently succeed to prevent user enumeration
@@ -487,7 +497,8 @@ export class AuthService {
487
497
 
488
498
  // Send email with password reset link
489
499
  const emailService = EmailService.getInstance();
490
- await emailService.sendWithTemplate(email, dbUser.name || 'User', 'reset-password-link', {
500
+ const userName = dbUser.profile?.name || 'User';
501
+ await emailService.sendWithTemplate(email, userName, 'reset-password-link', {
491
502
  link: linkUrl,
492
503
  });
493
504
  }
@@ -558,7 +569,7 @@ export class AuthService {
558
569
 
559
570
  // Update password in the database
560
571
  const result = await client.query(
561
- `UPDATE _accounts
572
+ `UPDATE auth.users
562
573
  SET password = $1, updated_at = NOW()
563
574
  WHERE email = $2
564
575
  RETURNING id`,
@@ -608,10 +619,11 @@ export class AuthService {
608
619
  user: {
609
620
  id: ADMIN_ID,
610
621
  email: email,
611
- name: 'Administrator',
612
622
  emailVerified: true,
613
623
  createdAt: new Date().toISOString(),
614
624
  updatedAt: new Date().toISOString(),
625
+ profile: { name: 'Administrator' },
626
+ metadata: null,
615
627
  },
616
628
  accessToken,
617
629
  };
@@ -639,10 +651,11 @@ export class AuthService {
639
651
  user: {
640
652
  id: ADMIN_ID,
641
653
  email: email as string,
642
- name: 'Administrator',
643
654
  emailVerified: true,
644
655
  createdAt: new Date().toISOString(),
645
656
  updatedAt: new Date().toISOString(),
657
+ profile: { name: 'Administrator' },
658
+ metadata: null,
646
659
  },
647
660
  accessToken,
648
661
  };
@@ -670,13 +683,14 @@ export class AuthService {
670
683
  | MicrosoftUserInfo
671
684
  | FacebookUserInfo
672
685
  | XUserInfo
686
+ | AppleUserInfo
673
687
  | Record<string, unknown>
674
688
  ): Promise<CreateSessionResponse> {
675
689
  const pool = this.getPool();
676
690
 
677
- // First, try to find existing user by provider ID in _account_providers table
691
+ // First, try to find existing user by provider ID in auth.user_providers table
678
692
  const accountResult = await pool.query(
679
- 'SELECT * FROM _account_providers WHERE provider = $1 AND provider_account_id = $2',
693
+ 'SELECT * FROM auth.user_providers WHERE provider = $1 AND provider_account_id = $2',
680
694
  [provider, providerId]
681
695
  );
682
696
  const account = accountResult.rows[0];
@@ -684,13 +698,13 @@ export class AuthService {
684
698
  if (account) {
685
699
  // Found existing OAuth user, update last login time
686
700
  await pool.query(
687
- 'UPDATE _account_providers SET updated_at = CURRENT_TIMESTAMP WHERE provider = $1 AND provider_account_id = $2',
701
+ 'UPDATE auth.user_providers SET updated_at = CURRENT_TIMESTAMP WHERE provider = $1 AND provider_account_id = $2',
688
702
  [provider, providerId]
689
703
  );
690
704
 
691
705
  // Update email_verified to true if not already verified (OAuth login means email is trusted)
692
706
  await pool.query(
693
- 'UPDATE _accounts SET email_verified = true WHERE id = $1 AND email_verified = false',
707
+ 'UPDATE auth.users SET email_verified = true WHERE id = $1 AND email_verified = false',
694
708
  [account.user_id]
695
709
  );
696
710
 
@@ -710,16 +724,16 @@ export class AuthService {
710
724
  }
711
725
 
712
726
  // If not found by provider_id, try to find by email in _user table
713
- const existingUserResult = await pool.query('SELECT * FROM _accounts WHERE email = $1', [
727
+ const existingUserResult = await pool.query('SELECT * FROM auth.users WHERE email = $1', [
714
728
  email,
715
729
  ]);
716
730
  const existingUser = existingUserResult.rows[0];
717
731
 
718
732
  if (existingUser) {
719
- // Found existing user by email, create _account_providers record to link OAuth
733
+ // Found existing user by email, create auth.user_providers record to link OAuth
720
734
  await pool.query(
721
735
  `
722
- INSERT INTO _account_providers (
736
+ INSERT INTO auth.user_providers (
723
737
  user_id, provider, provider_account_id,
724
738
  provider_data, created_at, updated_at
725
739
  )
@@ -730,7 +744,7 @@ export class AuthService {
730
744
 
731
745
  // Update email_verified to true (OAuth login means email is trusted)
732
746
  await pool.query(
733
- 'UPDATE _accounts SET email_verified = true WHERE id = $1 AND email_verified = false',
747
+ 'UPDATE auth.users SET email_verified = true WHERE id = $1 AND email_verified = false',
734
748
  [existingUser.id]
735
749
  );
736
750
 
@@ -777,6 +791,7 @@ export class AuthService {
777
791
  | MicrosoftUserInfo
778
792
  | FacebookUserInfo
779
793
  | XUserInfo
794
+ | AppleUserInfo
780
795
  | Record<string, unknown>,
781
796
  avatarUrl: string
782
797
  ): Promise<CreateSessionResponse> {
@@ -789,26 +804,19 @@ export class AuthService {
789
804
  await client.query('BEGIN');
790
805
 
791
806
  // Create user record (without password for OAuth users)
807
+ const profile = JSON.stringify({ name: userName, avatar_url: avatarUrl });
792
808
  await client.query(
793
809
  `
794
- INSERT INTO _accounts (id, email, name, email_verified, created_at, updated_at)
795
- VALUES ($1, $2, $3, true, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
796
- `,
797
- [userId, email, userName]
798
- );
799
-
800
- await client.query(
801
- `
802
- INSERT INTO users (id, nickname, avatar_url, created_at, updated_at)
803
- VALUES ($1, $2, $3, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
810
+ INSERT INTO auth.users (id, email, profile, email_verified, created_at, updated_at)
811
+ VALUES ($1, $2, $3::jsonb, true, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
804
812
  `,
805
- [userId, userName, avatarUrl]
813
+ [userId, email, profile]
806
814
  );
807
815
 
808
- // Create _account_providers record
816
+ // Create auth.user_providers record
809
817
  await client.query(
810
818
  `
811
- INSERT INTO _account_providers (
819
+ INSERT INTO auth.user_providers (
812
820
  user_id, provider, provider_account_id,
813
821
  provider_data, created_at, updated_at
814
822
  )
@@ -822,10 +830,11 @@ export class AuthService {
822
830
  const user: UserSchema = {
823
831
  id: userId,
824
832
  email,
825
- name: userName,
826
833
  emailVerified: true,
827
834
  createdAt: new Date().toISOString(),
828
835
  updatedAt: new Date().toISOString(),
836
+ profile: { name: userName, avatar_url: avatarUrl },
837
+ metadata: null,
829
838
  };
830
839
 
831
840
  const accessToken = this.tokenManager.generateToken({
@@ -844,10 +853,15 @@ export class AuthService {
844
853
  }
845
854
 
846
855
  async getMetadata(): Promise<AuthMetadataSchema> {
856
+ const authConfigService = AuthConfigService.getInstance();
847
857
  const oAuthConfigService = OAuthConfigService.getInstance();
848
- const oAuthConfigs = await oAuthConfigService.getAllConfigs();
858
+ const [oAuthProviders, authConfigs] = await Promise.all([
859
+ oAuthConfigService.getConfiguredProviders(),
860
+ authConfigService.getPublicAuthConfig(),
861
+ ]);
849
862
  return {
850
- oauths: oAuthConfigs,
863
+ oAuthProviders,
864
+ ...authConfigs,
851
865
  };
852
866
  }
853
867
 
@@ -870,6 +884,8 @@ export class AuthService {
870
884
  return this.microsoftOAuthProvider.generateOAuthUrl(state);
871
885
  case 'x':
872
886
  return this.xOAuthProvider.generateOAuthUrl(state);
887
+ case 'apple':
888
+ return this.appleOAuthProvider.generateOAuthUrl(state);
873
889
  default:
874
890
  throw new Error(`OAuth provider ${provider} is not implemented yet.`);
875
891
  }
@@ -906,6 +922,9 @@ export class AuthService {
906
922
  case 'x':
907
923
  userData = await this.xOAuthProvider.handleCallback(payload);
908
924
  break;
925
+ case 'apple':
926
+ userData = await this.appleOAuthProvider.handleCallback(payload);
927
+ break;
909
928
  default:
910
929
  throw new Error(`OAuth provider ${provider} is not implemented yet.`);
911
930
  }
@@ -949,6 +968,9 @@ export class AuthService {
949
968
  case 'x':
950
969
  userData = this.xOAuthProvider.handleSharedCallback(payloadData);
951
970
  break;
971
+ case 'apple':
972
+ userData = this.appleOAuthProvider.handleSharedCallback(payloadData);
973
+ break;
952
974
  case 'microsoft':
953
975
  default:
954
976
  throw new Error(`OAuth provider ${provider} is not supported for shared callback.`);
@@ -975,14 +997,17 @@ export class AuthService {
975
997
  SELECT
976
998
  u.id,
977
999
  u.email,
978
- u.name,
1000
+ u.profile,
1001
+ u.metadata,
979
1002
  u.email_verified,
1003
+ u.is_project_admin,
1004
+ u.is_anonymous,
980
1005
  u.created_at,
981
1006
  u.updated_at,
982
1007
  u.password,
983
1008
  STRING_AGG(a.provider, ',') as providers
984
- FROM _accounts u
985
- LEFT JOIN _account_providers a ON u.id = a.user_id
1009
+ FROM auth.users u
1010
+ LEFT JOIN auth.user_providers a ON u.id = a.user_id
986
1011
  WHERE u.email = $1
987
1012
  GROUP BY u.id
988
1013
  `,
@@ -1003,14 +1028,17 @@ export class AuthService {
1003
1028
  SELECT
1004
1029
  u.id,
1005
1030
  u.email,
1006
- u.name,
1031
+ u.profile,
1032
+ u.metadata,
1007
1033
  u.email_verified,
1034
+ u.is_project_admin,
1035
+ u.is_anonymous,
1008
1036
  u.created_at,
1009
1037
  u.updated_at,
1010
1038
  u.password,
1011
1039
  STRING_AGG(a.provider, ',') as providers
1012
- FROM _accounts u
1013
- LEFT JOIN _account_providers a ON u.id = a.user_id
1040
+ FROM auth.users u
1041
+ LEFT JOIN auth.user_providers a ON u.id = a.user_id
1014
1042
  WHERE u.id = $1
1015
1043
  GROUP BY u.id
1016
1044
  `,
@@ -1025,36 +1053,29 @@ export class AuthService {
1025
1053
  * @private
1026
1054
  */
1027
1055
  private transformUserRecordToSchema(dbUser: UserRecord): UserSchema {
1028
- const identities = [];
1029
1056
  const providers: string[] = [];
1030
1057
 
1031
1058
  // Add social providers if any
1032
1059
  if (dbUser.providers) {
1033
1060
  dbUser.providers.split(',').forEach((provider: string) => {
1034
- identities.push({ provider });
1035
1061
  providers.push(provider);
1036
1062
  });
1037
1063
  }
1038
1064
 
1039
1065
  // Add email provider if password exists
1040
1066
  if (dbUser.password) {
1041
- identities.push({ provider: 'email' });
1042
1067
  providers.push('email');
1043
1068
  }
1044
1069
 
1045
- // Use first provider to determine type: 'email' or 'social'
1046
- const firstProvider = providers[0];
1047
- const providerType = firstProvider === 'email' ? 'email' : 'social';
1048
-
1049
1070
  return {
1050
1071
  id: dbUser.id,
1051
1072
  email: dbUser.email,
1052
- name: dbUser.name,
1053
1073
  emailVerified: dbUser.email_verified,
1054
1074
  createdAt: dbUser.created_at,
1055
1075
  updatedAt: dbUser.updated_at,
1056
- identities: identities,
1057
- providerType: providerType,
1076
+ providers: providers,
1077
+ profile: dbUser.profile,
1078
+ metadata: dbUser.metadata,
1058
1079
  };
1059
1080
  }
1060
1081
 
@@ -1071,19 +1092,23 @@ export class AuthService {
1071
1092
  SELECT
1072
1093
  u.id,
1073
1094
  u.email,
1074
- u.name,
1095
+ u.profile,
1096
+ u.metadata,
1075
1097
  u.email_verified,
1098
+ u.is_project_admin,
1099
+ u.is_anonymous,
1076
1100
  u.created_at,
1077
1101
  u.updated_at,
1078
1102
  u.password,
1079
1103
  STRING_AGG(a.provider, ',') as providers
1080
- FROM _accounts u
1081
- LEFT JOIN _account_providers a ON u.id = a.user_id
1104
+ FROM auth.users u
1105
+ LEFT JOIN auth.user_providers a ON u.id = a.user_id
1106
+ WHERE u.is_project_admin = false AND u.is_anonymous = false
1082
1107
  `;
1083
1108
  const params: (string | number)[] = [];
1084
1109
 
1085
1110
  if (search) {
1086
- query += ' WHERE u.email LIKE $1 OR u.name LIKE $2';
1111
+ query += ` AND (u.email LIKE $1 OR u.profile->>'name' LIKE $2)`;
1087
1112
  params.push(`%${search}%`, `%${search}%`);
1088
1113
  }
1089
1114
 
@@ -1096,11 +1121,12 @@ export class AuthService {
1096
1121
  // Transform users
1097
1122
  const users = dbUsers.map((dbUser) => this.transformUserRecordToSchema(dbUser));
1098
1123
 
1099
- // Get total count
1100
- let countQuery = 'SELECT COUNT(*) as count FROM _accounts';
1124
+ // Get total count (exclude admins and anonymous users)
1125
+ let countQuery =
1126
+ 'SELECT COUNT(*) as count FROM auth.users WHERE is_project_admin = false AND is_anonymous = false';
1101
1127
  const countParams: string[] = [];
1102
1128
  if (search) {
1103
- countQuery += ' WHERE email LIKE $1 OR name LIKE $2';
1129
+ countQuery += ` AND (email LIKE $1 OR profile->>'name' LIKE $2)`;
1104
1130
  countParams.push(`%${search}%`, `%${search}%`);
1105
1131
  }
1106
1132
  const countResult = await pool.query(countQuery, countParams);
@@ -1123,13 +1149,61 @@ export class AuthService {
1123
1149
  return this.transformUserRecordToSchema(dbUser);
1124
1150
  }
1125
1151
 
1152
+ /**
1153
+ * Get user profile by ID (public endpoint - returns id and profile)
1154
+ */
1155
+ async getProfileById(
1156
+ userId: string
1157
+ ): Promise<{ id: string; profile: Record<string, unknown> | null } | null> {
1158
+ const pool = this.getPool();
1159
+ const result = await pool.query(`SELECT id, profile FROM auth.users WHERE id = $1`, [userId]);
1160
+
1161
+ if (result.rows.length === 0) {
1162
+ return null;
1163
+ }
1164
+
1165
+ return {
1166
+ id: result.rows[0].id,
1167
+ profile: result.rows[0].profile,
1168
+ };
1169
+ }
1170
+
1171
+ /**
1172
+ * Update user profile (for authenticated user updating their own profile)
1173
+ */
1174
+ async updateProfile(
1175
+ userId: string,
1176
+ profile: Record<string, unknown>
1177
+ ): Promise<{ id: string; profile: Record<string, unknown> | null }> {
1178
+ const pool = this.getPool();
1179
+ const result = await pool.query(
1180
+ `UPDATE auth.users
1181
+ SET profile = COALESCE(profile, '{}'::jsonb) || $1::jsonb, updated_at = NOW()
1182
+ WHERE id = $2
1183
+ RETURNING id, profile`,
1184
+ [profile, userId]
1185
+ );
1186
+
1187
+ if (result.rows.length === 0) {
1188
+ throw new AppError('User not found', 404, ERROR_CODES.NOT_FOUND);
1189
+ }
1190
+
1191
+ return {
1192
+ id: result.rows[0].id,
1193
+ profile: result.rows[0].profile,
1194
+ };
1195
+ }
1196
+
1126
1197
  /**
1127
1198
  * Delete multiple users by IDs
1128
1199
  */
1129
1200
  async deleteUsers(userIds: string[]): Promise<number> {
1130
1201
  const pool = this.getPool();
1131
1202
  const placeholders = userIds.map((_, i) => `$${i + 1}`).join(',');
1132
- const result = await pool.query(`DELETE FROM _accounts WHERE id IN (${placeholders})`, userIds);
1203
+ const result = await pool.query(
1204
+ `DELETE FROM auth.users WHERE id IN (${placeholders})`,
1205
+ userIds
1206
+ );
1133
1207
 
1134
1208
  return result.rowCount || 0;
1135
1209
  }
@@ -1,4 +1,4 @@
1
- export { AuthService } from './auth.service.js';
2
- export { AuthConfigService } from './auth-config.service.js';
3
- export { AuthOTPService } from './auth-otp.service.js';
4
- export { OAuthConfigService } from './oauth-config.service.js';
1
+ export { AuthService } from './auth.service.js';
2
+ export { AuthConfigService } from './auth-config.service.js';
3
+ export { AuthOTPService } from './auth-otp.service.js';
4
+ export { OAuthConfigService } from './oauth-config.service.js';
@@ -62,7 +62,7 @@ export class OAuthConfigService {
62
62
  use_shared_key as "useSharedKey",
63
63
  created_at as "createdAt",
64
64
  updated_at as "updatedAt"
65
- FROM _oauth_configs
65
+ FROM auth.oauth_configs
66
66
  ORDER BY provider ASC`
67
67
  );
68
68
 
@@ -82,7 +82,7 @@ export class OAuthConfigService {
82
82
  const result = await this.getPool().query(
83
83
  `SELECT
84
84
  provider
85
- FROM _oauth_configs
85
+ FROM auth.oauth_configs
86
86
  ORDER BY provider ASC`
87
87
  );
88
88
 
@@ -108,7 +108,7 @@ export class OAuthConfigService {
108
108
  use_shared_key as "useSharedKey",
109
109
  created_at as "createdAt",
110
110
  updated_at as "updatedAt"
111
- FROM _oauth_configs
111
+ FROM auth.oauth_configs
112
112
  WHERE LOWER(provider) = LOWER($1)
113
113
  LIMIT 1`,
114
114
  [provider]
@@ -133,7 +133,7 @@ export class OAuthConfigService {
133
133
  const result = await this.getPool().query(
134
134
  `SELECT
135
135
  secret_id as "secretId"
136
- FROM _oauth_configs
136
+ FROM auth.oauth_configs
137
137
  WHERE LOWER(provider) = LOWER($1)
138
138
  LIMIT 1`,
139
139
  [provider]
@@ -167,7 +167,7 @@ export class OAuthConfigService {
167
167
 
168
168
  // Check if config already exists for this provider
169
169
  const existingConfig = await client.query(
170
- 'SELECT id FROM _oauth_configs WHERE LOWER(provider) = LOWER($1)',
170
+ 'SELECT id FROM auth.oauth_configs WHERE LOWER(provider) = LOWER($1)',
171
171
  [input.provider]
172
172
  );
173
173
 
@@ -235,7 +235,7 @@ export class OAuthConfigService {
235
235
 
236
236
  // Create new OAuth config
237
237
  const result = await client.query(
238
- `INSERT INTO _oauth_configs (provider, client_id, secret_id, redirect_uri, scopes, use_shared_key)
238
+ `INSERT INTO auth.oauth_configs (provider, client_id, secret_id, redirect_uri, scopes, use_shared_key)
239
239
  VALUES ($1, $2, $3, $4, $5, $6)
240
240
  RETURNING
241
241
  id,
@@ -282,7 +282,7 @@ export class OAuthConfigService {
282
282
 
283
283
  // Get existing config with secret_id
284
284
  const existingResult = await client.query(
285
- `SELECT id, secret_id as "secretId" FROM _oauth_configs WHERE LOWER(provider) = LOWER($1)`,
285
+ `SELECT id, secret_id as "secretId" FROM auth.oauth_configs WHERE LOWER(provider) = LOWER($1)`,
286
286
  [provider]
287
287
  );
288
288
 
@@ -306,7 +306,7 @@ export class OAuthConfigService {
306
306
  value: input.clientSecret,
307
307
  });
308
308
  // Add secret_id to the update query
309
- await client.query(`UPDATE _oauth_configs SET secret_id = $1 WHERE id = $2`, [
309
+ await client.query(`UPDATE auth.oauth_configs SET secret_id = $1 WHERE id = $2`, [
310
310
  secret.id,
311
311
  existingConfig.id,
312
312
  ]);
@@ -353,7 +353,7 @@ export class OAuthConfigService {
353
353
  values.push(provider.toLowerCase());
354
354
 
355
355
  const result = await client.query(
356
- `UPDATE _oauth_configs
356
+ `UPDATE auth.oauth_configs
357
357
  SET ${updates.join(', ')}
358
358
  WHERE LOWER(provider) = $${paramCount}
359
359
  RETURNING
@@ -406,7 +406,7 @@ export class OAuthConfigService {
406
406
 
407
407
  // Get existing config with secret_id
408
408
  const existingResult = await client.query(
409
- `SELECT id, secret_id as "secretId" FROM _oauth_configs WHERE LOWER(provider) = LOWER($1)`,
409
+ `SELECT id, secret_id as "secretId" FROM auth.oauth_configs WHERE LOWER(provider) = LOWER($1)`,
410
410
  [provider]
411
411
  );
412
412
 
@@ -419,13 +419,13 @@ export class OAuthConfigService {
419
419
 
420
420
  // Delete OAuth config (secret will be restricted due to foreign key)
421
421
  const result = await client.query(
422
- 'DELETE FROM _oauth_configs WHERE LOWER(provider) = LOWER($1)',
422
+ 'DELETE FROM auth.oauth_configs WHERE LOWER(provider) = LOWER($1)',
423
423
  [provider]
424
424
  );
425
425
 
426
426
  // Try to delete the associated secret (will fail if still referenced)
427
427
  try {
428
- await client.query('DELETE FROM _secrets WHERE id = $1', [existingConfig.secretId]);
428
+ await client.query('DELETE FROM system.secrets WHERE id = $1', [existingConfig.secretId]);
429
429
  logger.info('Associated secret deleted', { secretId: existingConfig.secretId });
430
430
  } catch {
431
431
  logger.warn('Could not delete associated secret, it may be in use elsewhere', {