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
@@ -0,0 +1,233 @@
1
+ -- Migration 017: Create Realtime Schema
2
+ --
3
+ -- Creates the realtime schema with:
4
+ -- 1. channels table - Channel definitions with webhook configuration
5
+ -- 2. messages table - All realtime messages with delivery statistics
6
+ -- 3. publish() function - Called by developer triggers to publish events
7
+ --
8
+ -- Permission Model (Supabase pattern):
9
+ -- - SELECT on channels = 'subscribe' permission (subscribe to channel)
10
+ -- - INSERT on messages = 'publish' permission (publish to channel)
11
+ -- Developers define RLS policies on channels/messages table to control access.
12
+
13
+ -- ============================================================================
14
+ -- CREATE SCHEMA
15
+ -- ============================================================================
16
+
17
+ CREATE SCHEMA IF NOT EXISTS realtime;
18
+
19
+ -- ============================================================================
20
+ -- CHANNELS TABLE
21
+ -- ============================================================================
22
+ -- Stores channel definitions with delivery configuration.
23
+ -- RLS policies control subscribe permissions.
24
+ -- - SELECT policy = 'subscribe' permission (can subscribe to channel)
25
+ -- Channel names use : as separator and % for wildcards (LIKE pattern).
26
+ -- Examples: "orders", "order:%", "chat:%:messages"
27
+
28
+ CREATE TABLE IF NOT EXISTS realtime.channels (
29
+ id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
30
+
31
+ -- Channel name pattern (e.g., "orders", "order:%", "chat:%:messages")
32
+ -- Convention: use : as separator, % for wildcards (LIKE pattern)
33
+ pattern TEXT UNIQUE NOT NULL,
34
+
35
+ -- Human-readable description
36
+ description TEXT,
37
+
38
+ -- Webhook URLs to POST events to (NULL or empty array = no webhooks)
39
+ webhook_urls TEXT[],
40
+
41
+ -- Whether this channel is active
42
+ enabled BOOLEAN DEFAULT TRUE NOT NULL,
43
+
44
+ created_at TIMESTAMPTZ DEFAULT NOW(),
45
+ updated_at TIMESTAMPTZ DEFAULT NOW()
46
+ );
47
+
48
+ -- ============================================================================
49
+ -- MESSAGES TABLE
50
+ -- ============================================================================
51
+ -- Stores all realtime messages published through the system.
52
+ -- RLS policies on this table control publish permissions:
53
+ -- - INSERT policy = 'publish' permission (can publish to channel)
54
+
55
+ CREATE TABLE IF NOT EXISTS realtime.messages (
56
+ id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
57
+
58
+ -- Event metadata
59
+ event_name TEXT NOT NULL,
60
+
61
+ -- Channel reference (SET NULL on delete to preserve history)
62
+ channel_id UUID REFERENCES realtime.channels(id) ON DELETE SET NULL,
63
+ channel_name TEXT NOT NULL, -- Denormalized for query convenience after channel deletion
64
+
65
+ -- Event payload (stored for audit/replay purposes)
66
+ payload JSONB DEFAULT '{}'::jsonb NOT NULL,
67
+
68
+ -- Sender information
69
+ -- 'system' = triggered by database trigger (via publish() function)
70
+ -- 'user' = published by client via WebSocket
71
+ sender_type TEXT DEFAULT 'system' NOT NULL CHECK (sender_type IN ('system', 'user')),
72
+ sender_id UUID, -- User ID for 'user' type, NULL for 'system' type
73
+
74
+ -- Delivery statistics for WebSocket
75
+ ws_audience_count INTEGER DEFAULT 0 NOT NULL, -- How many clients were subscribed
76
+
77
+ -- Delivery statistics for Webhooks
78
+ wh_audience_count INTEGER DEFAULT 0 NOT NULL, -- How many webhook URLs configured
79
+ wh_delivered_count INTEGER DEFAULT 0 NOT NULL, -- How many succeeded (2xx response)
80
+
81
+ created_at TIMESTAMPTZ DEFAULT NOW()
82
+ );
83
+
84
+ -- ============================================================================
85
+ -- INDEXES
86
+ -- ============================================================================
87
+
88
+ CREATE INDEX IF NOT EXISTS idx_realtime_channels_pattern ON realtime.channels(pattern);
89
+ CREATE INDEX IF NOT EXISTS idx_realtime_channels_enabled ON realtime.channels(enabled);
90
+ CREATE INDEX IF NOT EXISTS idx_realtime_messages_channel_id ON realtime.messages(channel_id);
91
+ CREATE INDEX IF NOT EXISTS idx_realtime_messages_channel_name ON realtime.messages(channel_name);
92
+ CREATE INDEX IF NOT EXISTS idx_realtime_messages_created_at ON realtime.messages(created_at DESC);
93
+ CREATE INDEX IF NOT EXISTS idx_realtime_messages_event_name ON realtime.messages(event_name);
94
+ CREATE INDEX IF NOT EXISTS idx_realtime_messages_sender ON realtime.messages(sender_type, sender_id);
95
+
96
+ -- ============================================================================
97
+ -- UPDATED_AT TRIGGER
98
+ -- ============================================================================
99
+
100
+ CREATE OR REPLACE FUNCTION realtime.update_updated_at()
101
+ RETURNS TRIGGER AS $$
102
+ BEGIN
103
+ NEW.updated_at = NOW();
104
+ RETURN NEW;
105
+ END;
106
+ $$ LANGUAGE plpgsql;
107
+
108
+ DROP TRIGGER IF EXISTS trg_channels_updated_at ON realtime.channels;
109
+ CREATE TRIGGER trg_channels_updated_at
110
+ BEFORE UPDATE ON realtime.channels
111
+ FOR EACH ROW EXECUTE FUNCTION realtime.update_updated_at();
112
+
113
+ -- ============================================================================
114
+ -- ROW LEVEL SECURITY (DISABLED BY DEFAULT)
115
+ -- ============================================================================
116
+ -- RLS is disabled by default for the best developer experience.
117
+ -- Channels and messages are open to all authenticated/anon users out of the box.
118
+ --
119
+ -- To enable access control, developers can:
120
+ -- 1. Enable RLS: ALTER TABLE realtime.channels ENABLE ROW LEVEL SECURITY;
121
+ -- 2. Add policies using the helper function realtime.channel_name()
122
+ --
123
+ -- See documentation for policy examples.
124
+
125
+ -- ============================================================================
126
+ -- HELPER FUNCTIONS FOR RLS POLICIES
127
+ -- ============================================================================
128
+
129
+ -- Returns the channel name being accessed (set by backend during permission checks)
130
+ -- Developers use this in policies instead of writing current_setting directly
131
+ CREATE OR REPLACE FUNCTION realtime.channel_name()
132
+ RETURNS TEXT AS $$
133
+ SELECT current_setting('realtime.channel_name', true);
134
+ $$ LANGUAGE SQL STABLE;
135
+
136
+ -- ============================================================================
137
+ -- PUBLISH FUNCTION
138
+ -- ============================================================================
139
+ -- Called by developer triggers to publish events to channels.
140
+ -- This function can only be executed by the backend (SECURITY DEFINER).
141
+ --
142
+ -- Usage in a trigger:
143
+ -- PERFORM realtime.publish(
144
+ -- 'order:' || NEW.id::text, -- channel name (resolved instance)
145
+ -- 'order_updated', -- event name
146
+ -- jsonb_build_object('id', NEW.id, 'status', NEW.status) -- payload
147
+ -- );
148
+
149
+ CREATE OR REPLACE FUNCTION realtime.publish(
150
+ p_channel_name TEXT,
151
+ p_event_name TEXT,
152
+ p_payload JSONB
153
+ )
154
+ RETURNS UUID AS $$
155
+ DECLARE
156
+ v_channel_id UUID;
157
+ v_message_id UUID;
158
+ BEGIN
159
+ -- Find matching channel: exact match first, then wildcard pattern match
160
+ -- For wildcard patterns like "order:%", check if p_channel_name LIKE pattern
161
+ SELECT id INTO v_channel_id
162
+ FROM realtime.channels
163
+ WHERE enabled = TRUE
164
+ AND (pattern = p_channel_name OR p_channel_name LIKE pattern)
165
+ ORDER BY pattern = p_channel_name DESC
166
+ LIMIT 1;
167
+
168
+ -- If no channel found, raise a warning and return NULL
169
+ IF v_channel_id IS NULL THEN
170
+ RAISE WARNING 'Realtime: No matching channel found for "%"', p_channel_name;
171
+ RETURN NULL;
172
+ END IF;
173
+
174
+ -- Insert message record (system-triggered, so sender_type = 'system')
175
+ INSERT INTO realtime.messages (
176
+ event_name,
177
+ channel_id,
178
+ channel_name,
179
+ payload,
180
+ sender_type
181
+ ) VALUES (
182
+ p_event_name,
183
+ v_channel_id,
184
+ p_channel_name,
185
+ p_payload,
186
+ 'system'
187
+ )
188
+ RETURNING id INTO v_message_id;
189
+
190
+ RETURN v_message_id;
191
+ END;
192
+ $$ LANGUAGE plpgsql SECURITY DEFINER;
193
+
194
+ -- Revoke execute from public, only backend can call this
195
+ REVOKE ALL ON FUNCTION realtime.publish FROM PUBLIC;
196
+
197
+ -- ============================================================================
198
+ -- TRIGGER FOR PG_NOTIFY
199
+ -- ============================================================================
200
+ -- Trigger function that sends pg_notify for every new message (both system and client).
201
+
202
+ CREATE OR REPLACE FUNCTION realtime.notify_on_message_insert()
203
+ RETURNS TRIGGER AS $$
204
+ BEGIN
205
+ -- Send only message_id to bypass pg_notify 8KB payload limit
206
+ -- Backend will fetch full message from DB
207
+ PERFORM pg_notify('realtime_message', NEW.id::text);
208
+ RETURN NEW;
209
+ END;
210
+ $$ LANGUAGE plpgsql;
211
+
212
+ -- Create trigger on messages table
213
+ DROP TRIGGER IF EXISTS trg_message_notify ON realtime.messages;
214
+ CREATE TRIGGER trg_message_notify
215
+ AFTER INSERT ON realtime.messages
216
+ FOR EACH ROW
217
+ EXECUTE FUNCTION realtime.notify_on_message_insert();
218
+
219
+ -- ============================================================================
220
+ -- GRANTS
221
+ -- ============================================================================
222
+
223
+ -- Grant schema access to both authenticated and anonymous users
224
+ GRANT USAGE ON SCHEMA realtime TO authenticated, anon;
225
+
226
+ -- Grant SELECT on channels table (allows subscribe)
227
+ GRANT SELECT ON realtime.channels TO authenticated, anon;
228
+
229
+ -- Grant INSERT on messages table (allows publish)
230
+ GRANT INSERT ON realtime.messages TO authenticated, anon;
231
+
232
+ -- Grant execution permission on helper function (used when RLS is enabled)
233
+ GRANT EXECUTE ON FUNCTION realtime.channel_name() TO authenticated, anon;
@@ -0,0 +1,441 @@
1
+ -- Migration: 018 - Create system and auth schemas, move and rename system tables
2
+ -- This migration creates dedicated schemas for internal system and auth tables,
3
+ -- moves tables into them, and removes the underscore prefix from table names.
4
+
5
+ -- ============================================================================
6
+ -- PART 1: SYSTEM SCHEMA (secrets, audit_logs, mcp_usage)
7
+ -- Note: migrations table is handled by bootstrap/bootstrap-migrations.js before this runs
8
+ -- ============================================================================
9
+
10
+ -- 1.1 Create the system schema (may already exist from bootstrap)
11
+ CREATE SCHEMA IF NOT EXISTS system;
12
+
13
+ -- 1.2 Move _secrets table to system schema and rename to 'secrets'
14
+ -- First, drop the foreign key constraint from _oauth_configs that references _secrets
15
+ ALTER TABLE public._oauth_configs
16
+ DROP CONSTRAINT IF EXISTS _oauth_configs_secret_id_fkey;
17
+
18
+ -- Move and rename the _secrets table to system.secrets
19
+ ALTER TABLE public._secrets SET SCHEMA system;
20
+ ALTER TABLE system._secrets RENAME TO secrets;
21
+
22
+ -- Note: We'll recreate the FK constraint after moving _oauth_configs to auth schema
23
+
24
+ -- 1.3 Move _audit_logs table to system schema and rename to 'audit_logs'
25
+ ALTER TABLE public._audit_logs SET SCHEMA system;
26
+ ALTER TABLE system._audit_logs RENAME TO audit_logs;
27
+
28
+ -- 1.4 Move _mcp_usage table to system schema and rename to 'mcp_usage'
29
+ ALTER TABLE public._mcp_usage SET SCHEMA system;
30
+ ALTER TABLE system._mcp_usage RENAME TO mcp_usage;
31
+
32
+ -- Note: system schema is internal and should NOT be exposed to PUBLIC.
33
+ -- Access is controlled through the application's database connection.
34
+
35
+ -- ============================================================================
36
+ -- PART 2: AUTH SCHEMA (users, user_providers, configs, oauth_configs, email_otps)
37
+ -- ============================================================================
38
+
39
+ -- 2.1 Create the auth schema
40
+ CREATE SCHEMA IF NOT EXISTS auth;
41
+
42
+ -- 2.2 Drop all foreign key constraints that reference tables being moved
43
+ -- FK: _account_providers.user_id -> _accounts(id)
44
+ ALTER TABLE public._account_providers
45
+ DROP CONSTRAINT IF EXISTS _account_providers_user_id_fkey;
46
+
47
+ -- FK: users.id -> _accounts(id) (public users table references _accounts)
48
+ ALTER TABLE public.users
49
+ DROP CONSTRAINT IF EXISTS users_id_fkey;
50
+
51
+ -- FK: _storage.uploaded_by -> _accounts(id)
52
+ ALTER TABLE public._storage
53
+ DROP CONSTRAINT IF EXISTS _storage_uploaded_by_fkey;
54
+
55
+ -- 2.3 Move _accounts table to auth schema and rename to 'users'
56
+ ALTER TABLE public._accounts SET SCHEMA auth;
57
+ ALTER TABLE auth._accounts RENAME TO users;
58
+
59
+ -- 2.4 Move _account_providers table to auth schema and rename to 'user_providers'
60
+ ALTER TABLE public._account_providers SET SCHEMA auth;
61
+ ALTER TABLE auth._account_providers RENAME TO user_providers;
62
+
63
+ -- 2.5 Recreate FK: auth.user_providers.user_id -> auth.users(id)
64
+ ALTER TABLE auth.user_providers
65
+ ADD CONSTRAINT user_providers_user_id_fkey
66
+ FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE;
67
+
68
+ -- 2.6 Add profile and metadata JSONB columns to auth.users BEFORE migrating data
69
+ -- profile: stores user profile data (name, avatar_url, bio, etc.)
70
+ -- metadata: reserved for system use (device ID, login IP, etc.)
71
+ ALTER TABLE auth.users ADD COLUMN IF NOT EXISTS profile JSONB DEFAULT '{}'::jsonb;
72
+ ALTER TABLE auth.users ADD COLUMN IF NOT EXISTS metadata JSONB DEFAULT '{}'::jsonb;
73
+
74
+ -- 2.7 Migrate data from public.users into auth.users.profile
75
+ -- Priority for name: public.users.nickname first, then auth.users.name as fallback
76
+ -- Also migrate: avatar_url, bio, birthday from public.users
77
+ UPDATE auth.users AS au
78
+ SET profile = jsonb_strip_nulls(jsonb_build_object(
79
+ 'name', COALESCE(pu.nickname, au.name),
80
+ 'avatar_url', pu.avatar_url,
81
+ 'bio', pu.bio,
82
+ 'birthday', pu.birthday
83
+ ))
84
+ FROM public.users AS pu
85
+ WHERE au.id = pu.id;
86
+
87
+ -- 2.8 For users without a public.users row, migrate auth.users.name to profile
88
+ UPDATE auth.users
89
+ SET profile = jsonb_build_object('name', name)
90
+ WHERE name IS NOT NULL
91
+ AND (profile IS NULL OR profile = '{}'::jsonb)
92
+ AND id NOT IN (SELECT id FROM public.users);
93
+
94
+ -- 2.9 Update all foreign key constraints that reference public.users to use auth.users instead
95
+ -- This handles any custom tables developers may have created that reference public.users
96
+ DO $$
97
+ DECLARE
98
+ fk_record RECORD;
99
+ drop_sql TEXT;
100
+ create_sql TEXT;
101
+ BEGIN
102
+ -- Find all foreign keys that reference public.users
103
+ FOR fk_record IN
104
+ SELECT
105
+ tc.table_schema,
106
+ tc.table_name,
107
+ tc.constraint_name,
108
+ kcu.column_name,
109
+ rc.delete_rule,
110
+ rc.update_rule
111
+ FROM information_schema.table_constraints tc
112
+ JOIN information_schema.key_column_usage kcu
113
+ ON tc.constraint_name = kcu.constraint_name
114
+ AND tc.table_schema = kcu.table_schema
115
+ JOIN information_schema.referential_constraints rc
116
+ ON tc.constraint_name = rc.constraint_name
117
+ AND tc.table_schema = rc.constraint_schema
118
+ JOIN information_schema.constraint_column_usage ccu
119
+ ON rc.unique_constraint_name = ccu.constraint_name
120
+ AND rc.unique_constraint_schema = ccu.constraint_schema
121
+ WHERE tc.constraint_type = 'FOREIGN KEY'
122
+ AND ccu.table_schema = 'public'
123
+ AND ccu.table_name = 'users'
124
+ LOOP
125
+ -- Drop the old foreign key
126
+ drop_sql := format(
127
+ 'ALTER TABLE %I.%I DROP CONSTRAINT IF EXISTS %I',
128
+ fk_record.table_schema,
129
+ fk_record.table_name,
130
+ fk_record.constraint_name
131
+ );
132
+ EXECUTE drop_sql;
133
+
134
+ -- Recreate with reference to auth.users
135
+ create_sql := format(
136
+ 'ALTER TABLE %I.%I ADD CONSTRAINT %I FOREIGN KEY (%I) REFERENCES auth.users(id) ON DELETE %s ON UPDATE %s',
137
+ fk_record.table_schema,
138
+ fk_record.table_name,
139
+ fk_record.constraint_name,
140
+ fk_record.column_name,
141
+ fk_record.delete_rule,
142
+ fk_record.update_rule
143
+ );
144
+ EXECUTE create_sql;
145
+
146
+ RAISE NOTICE 'Updated FK constraint % on %.% to reference auth.users',
147
+ fk_record.constraint_name, fk_record.table_schema, fk_record.table_name;
148
+ END LOOP;
149
+ END $$;
150
+
151
+ -- 2.10 Drop public.users table (profile data now stored in auth.users.profile)
152
+ -- First drop RLS policies
153
+ DROP POLICY IF EXISTS "Enable read access for all users" ON public.users;
154
+ DROP POLICY IF EXISTS "Disable delete for users" ON public.users;
155
+ DROP POLICY IF EXISTS "Enable update for users based on user_id" ON public.users;
156
+ -- Drop the table (CASCADE will handle any remaining dependencies)
157
+ DROP TABLE IF EXISTS public.users CASCADE;
158
+
159
+ -- 2.11 Drop the name column from auth.users (data already migrated to profile)
160
+ ALTER TABLE auth.users DROP COLUMN IF EXISTS name;
161
+
162
+ -- Note: _storage.uploaded_by FK is handled in Part 4 when moving to storage schema
163
+
164
+ -- 2.12 Add is_project_admin and is_anonymous columns to auth.users
165
+ ALTER TABLE auth.users ADD COLUMN IF NOT EXISTS is_project_admin BOOLEAN NOT NULL DEFAULT false;
166
+ ALTER TABLE auth.users ADD COLUMN IF NOT EXISTS is_anonymous BOOLEAN NOT NULL DEFAULT false;
167
+
168
+ -- 2.13 Move _auth_configs table to auth schema and rename to 'configs'
169
+ ALTER TABLE public._auth_configs SET SCHEMA auth;
170
+ ALTER TABLE auth._auth_configs RENAME TO configs;
171
+
172
+ -- 2.14 Move _oauth_configs table to auth schema and rename to 'oauth_configs'
173
+ ALTER TABLE public._oauth_configs SET SCHEMA auth;
174
+ ALTER TABLE auth._oauth_configs RENAME TO oauth_configs;
175
+
176
+ -- 2.15 Recreate FK: auth.oauth_configs.secret_id -> system.secrets(id)
177
+ ALTER TABLE auth.oauth_configs
178
+ ADD CONSTRAINT oauth_configs_secret_id_fkey
179
+ FOREIGN KEY (secret_id) REFERENCES system.secrets(id) ON DELETE RESTRICT;
180
+
181
+ -- 2.16 Move _email_otps table to auth schema and rename to 'email_otps'
182
+ ALTER TABLE public._email_otps SET SCHEMA auth;
183
+ ALTER TABLE auth._email_otps RENAME TO email_otps;
184
+
185
+ -- Note: auth schema is internal and should NOT be exposed to PUBLIC.
186
+ -- However, we grant limited access to auth.users for public profile info.
187
+
188
+ -- 2.17 Grant limited public access to auth.users (only safe columns)
189
+ GRANT USAGE ON SCHEMA auth TO PUBLIC;
190
+
191
+ -- Grant SELECT on specific columns only (public profile info)
192
+ GRANT SELECT (id, profile, created_at) ON auth.users TO PUBLIC;
193
+
194
+ -- Grant UPDATE on profile column only (users can update their own profile)
195
+ GRANT UPDATE (profile) ON auth.users TO PUBLIC;
196
+
197
+ -- 2.18 Enable RLS on auth.users for row-level access control
198
+ -- Note: auth.uid() function already exists from migration 013
199
+ ALTER TABLE auth.users ENABLE ROW LEVEL SECURITY;
200
+
201
+ -- Policy: Everyone can SELECT public columns (id, profile, created_at)
202
+ -- Column-level GRANT above already restricts which columns can be read
203
+ CREATE POLICY "Public can view user profiles" ON auth.users
204
+ FOR SELECT
205
+ USING (true);
206
+
207
+ -- Policy: Users can only UPDATE their own row
208
+ CREATE POLICY "Users can update own profile" ON auth.users
209
+ FOR UPDATE
210
+ USING (id = auth.uid())
211
+ WITH CHECK (id = auth.uid());
212
+
213
+ -- 2.19 Drop obsolete public schema helper functions (migrated to auth schema)
214
+ -- NOTE: CASCADE intentionally used to force migration from public.uid() to auth.uid()
215
+ -- Any dependent objects (policies, views, functions, defaults) will be dropped.
216
+ -- Users must recreate them using auth.uid(), auth.role(), auth.email() instead.
217
+ DROP FUNCTION IF EXISTS public.uid() CASCADE;
218
+ DROP FUNCTION IF EXISTS public.role() CASCADE;
219
+ DROP FUNCTION IF EXISTS public.email() CASCADE;
220
+
221
+ -- ============================================================================
222
+ -- PART 3: AI SCHEMA (configs, usage)
223
+ -- ============================================================================
224
+
225
+ -- 3.1 Create the ai schema
226
+ CREATE SCHEMA IF NOT EXISTS ai;
227
+
228
+ -- 3.2 Drop FK constraint from _ai_usage to _ai_configs before moving
229
+ ALTER TABLE public._ai_usage
230
+ DROP CONSTRAINT IF EXISTS _ai_usage_config_id_fkey;
231
+
232
+ -- 3.3 Move _ai_configs table to ai schema and rename to 'configs'
233
+ ALTER TABLE public._ai_configs SET SCHEMA ai;
234
+ ALTER TABLE ai._ai_configs RENAME TO configs;
235
+
236
+ -- 3.4 Move _ai_usage table to ai schema and rename to 'usage'
237
+ ALTER TABLE public._ai_usage SET SCHEMA ai;
238
+ ALTER TABLE ai._ai_usage RENAME TO usage;
239
+
240
+ -- 3.5 Recreate FK: ai.usage.config_id -> ai.configs(id)
241
+ ALTER TABLE ai.usage
242
+ ADD CONSTRAINT usage_config_id_fkey
243
+ FOREIGN KEY (config_id) REFERENCES ai.configs(id) ON DELETE NO ACTION;
244
+
245
+ -- Note: ai schema is internal and should NOT be exposed to PUBLIC.
246
+ -- Access is controlled through the application's database connection.
247
+
248
+ -- ============================================================================
249
+ -- PART 4: STORAGE SCHEMA (buckets, objects)
250
+ -- ============================================================================
251
+
252
+ -- 4.1 Create the storage schema
253
+ CREATE SCHEMA IF NOT EXISTS storage;
254
+
255
+ -- 4.2 Drop FK constraints from _storage before moving
256
+ ALTER TABLE public._storage
257
+ DROP CONSTRAINT IF EXISTS _storage_bucket_fkey;
258
+
259
+ ALTER TABLE public._storage
260
+ DROP CONSTRAINT IF EXISTS _storage_uploaded_by_fkey;
261
+
262
+ -- 4.3 Move _storage_buckets table to storage schema and rename to 'buckets'
263
+ ALTER TABLE public._storage_buckets SET SCHEMA storage;
264
+ ALTER TABLE storage._storage_buckets RENAME TO buckets;
265
+
266
+ -- 4.4 Move _storage table to storage schema and rename to 'objects'
267
+ ALTER TABLE public._storage SET SCHEMA storage;
268
+ ALTER TABLE storage._storage RENAME TO objects;
269
+
270
+ -- 4.5 Recreate FK: storage.objects.bucket -> storage.buckets(name)
271
+ ALTER TABLE storage.objects
272
+ ADD CONSTRAINT objects_bucket_fkey
273
+ FOREIGN KEY (bucket) REFERENCES storage.buckets(name) ON DELETE CASCADE;
274
+
275
+ -- 4.6 Recreate FK: storage.objects.uploaded_by -> auth.users(id)
276
+ ALTER TABLE storage.objects
277
+ ADD CONSTRAINT objects_uploaded_by_fkey
278
+ FOREIGN KEY (uploaded_by) REFERENCES auth.users(id) ON DELETE SET NULL;
279
+
280
+ -- Note: storage schema is internal and should NOT be exposed to PUBLIC.
281
+ -- Access is controlled through the application's database connection.
282
+
283
+ -- ============================================================================
284
+ -- PART 5: FUNCTIONS SCHEMA (definitions)
285
+ -- ============================================================================
286
+
287
+ -- 5.1 Create the functions schema
288
+ CREATE SCHEMA IF NOT EXISTS functions;
289
+
290
+ -- 5.2 Move _functions table to functions schema and rename to 'definitions'
291
+ ALTER TABLE public._functions SET SCHEMA functions;
292
+ ALTER TABLE functions._functions RENAME TO definitions;
293
+
294
+ -- Note: functions schema is internal and should NOT be exposed to PUBLIC.
295
+ -- Access is controlled through the application's database connection.
296
+
297
+ -- ============================================================================
298
+ -- PART 6: UTILITY FUNCTIONS CLEANUP
299
+ -- ============================================================================
300
+
301
+ -- 6.1 Create system.update_updated_at() function (replaces public.update_updated_at_column)
302
+ CREATE OR REPLACE FUNCTION system.update_updated_at()
303
+ RETURNS trigger AS $$
304
+ BEGIN
305
+ NEW.updated_at = NOW();
306
+ RETURN NEW;
307
+ END;
308
+ $$ LANGUAGE plpgsql;
309
+
310
+ -- 6.2 Update all triggers to use system.update_updated_at() and rename (remove double underscore)
311
+
312
+ -- system.secrets: update__secrets_updated_at -> update_secrets_updated_at
313
+ DROP TRIGGER IF EXISTS update__secrets_updated_at ON system.secrets;
314
+ CREATE TRIGGER update_secrets_updated_at
315
+ BEFORE UPDATE ON system.secrets
316
+ FOR EACH ROW EXECUTE FUNCTION system.update_updated_at();
317
+
318
+ -- system.audit_logs: update__audit_logs_updated_at -> update_audit_logs_updated_at
319
+ DROP TRIGGER IF EXISTS update__audit_logs_updated_at ON system.audit_logs;
320
+ CREATE TRIGGER update_audit_logs_updated_at
321
+ BEFORE UPDATE ON system.audit_logs
322
+ FOR EACH ROW EXECUTE FUNCTION system.update_updated_at();
323
+
324
+ -- auth.configs: update__auth_configs_updated_at -> update_configs_updated_at
325
+ DROP TRIGGER IF EXISTS update__auth_configs_updated_at ON auth.configs;
326
+ CREATE TRIGGER update_configs_updated_at
327
+ BEFORE UPDATE ON auth.configs
328
+ FOR EACH ROW EXECUTE FUNCTION system.update_updated_at();
329
+
330
+ -- auth.oauth_configs: update__oauth_configs_updated_at -> update_oauth_configs_updated_at
331
+ DROP TRIGGER IF EXISTS update__oauth_configs_updated_at ON auth.oauth_configs;
332
+ CREATE TRIGGER update_oauth_configs_updated_at
333
+ BEFORE UPDATE ON auth.oauth_configs
334
+ FOR EACH ROW EXECUTE FUNCTION system.update_updated_at();
335
+
336
+ -- auth.email_otps: update__email_otps_updated_at -> update_email_otps_updated_at
337
+ DROP TRIGGER IF EXISTS update__email_otps_updated_at ON auth.email_otps;
338
+ CREATE TRIGGER update_email_otps_updated_at
339
+ BEFORE UPDATE ON auth.email_otps
340
+ FOR EACH ROW EXECUTE FUNCTION system.update_updated_at();
341
+
342
+ -- functions.definitions: update__edge_functions_updated_at -> update_definitions_updated_at
343
+ DROP TRIGGER IF EXISTS update__edge_functions_updated_at ON functions.definitions;
344
+ CREATE TRIGGER update_definitions_updated_at
345
+ BEFORE UPDATE ON functions.definitions
346
+ FOR EACH ROW EXECUTE FUNCTION system.update_updated_at();
347
+
348
+ -- realtime.channels: trg_channels_updated_at -> update_channels_updated_at
349
+ DROP TRIGGER IF EXISTS trg_channels_updated_at ON realtime.channels;
350
+ CREATE TRIGGER update_channels_updated_at
351
+ BEFORE UPDATE ON realtime.channels
352
+ FOR EACH ROW EXECUTE FUNCTION system.update_updated_at();
353
+
354
+ -- 6.3 Move reload_postgrest_schema to system schema
355
+ -- Recreate in system schema (ALTER FUNCTION SET SCHEMA doesn't work well with search_path)
356
+ CREATE OR REPLACE FUNCTION system.reload_postgrest_schema()
357
+ RETURNS void AS $$
358
+ BEGIN
359
+ NOTIFY pgrst, 'reload schema';
360
+ RAISE NOTICE 'PostgREST schema reload notification sent';
361
+ END
362
+ $$ LANGUAGE plpgsql;
363
+
364
+ -- 6.4 Move event trigger functions to system schema
365
+ -- These functions auto-create project_admin_policy when RLS is enabled on tables
366
+
367
+ -- First, drop the event triggers (they reference the old functions)
368
+ DROP EVENT TRIGGER IF EXISTS create_policies_on_table_create;
369
+ DROP EVENT TRIGGER IF EXISTS create_policies_on_rls_enable;
370
+
371
+ -- Recreate functions in system schema
372
+ CREATE OR REPLACE FUNCTION system.create_default_policies()
373
+ RETURNS event_trigger AS $$
374
+ DECLARE
375
+ obj record;
376
+ table_schema text;
377
+ table_name text;
378
+ has_rls boolean;
379
+ BEGIN
380
+ FOR obj IN SELECT * FROM pg_event_trigger_ddl_commands() WHERE command_tag = 'CREATE TABLE'
381
+ LOOP
382
+ SELECT INTO table_schema, table_name
383
+ split_part(obj.object_identity, '.', 1),
384
+ trim(both '"' from split_part(obj.object_identity, '.', 2));
385
+ SELECT INTO has_rls
386
+ rowsecurity
387
+ FROM pg_tables
388
+ WHERE schemaname = table_schema
389
+ AND tablename = table_name;
390
+ IF has_rls THEN
391
+ EXECUTE format('CREATE POLICY "project_admin_policy" ON %s FOR ALL TO project_admin USING (true) WITH CHECK (true)', obj.object_identity);
392
+ END IF;
393
+ END LOOP;
394
+ END;
395
+ $$ LANGUAGE plpgsql;
396
+
397
+ CREATE OR REPLACE FUNCTION system.create_policies_after_rls()
398
+ RETURNS event_trigger AS $$
399
+ DECLARE
400
+ obj record;
401
+ table_schema text;
402
+ table_name text;
403
+ BEGIN
404
+ FOR obj IN SELECT * FROM pg_event_trigger_ddl_commands() WHERE command_tag = 'ALTER TABLE'
405
+ LOOP
406
+ SELECT INTO table_schema, table_name
407
+ split_part(obj.object_identity, '.', 1),
408
+ trim(both '"' from split_part(obj.object_identity, '.', 2));
409
+ IF EXISTS (
410
+ SELECT 1 FROM pg_tables
411
+ WHERE schemaname = table_schema
412
+ AND tablename = table_name
413
+ AND rowsecurity = true
414
+ ) AND NOT EXISTS (
415
+ SELECT 1 FROM pg_policies
416
+ WHERE schemaname = table_schema
417
+ AND tablename = table_name
418
+ ) THEN
419
+ EXECUTE format('CREATE POLICY "project_admin_policy" ON %s FOR ALL TO project_admin USING (true) WITH CHECK (true)', obj.object_identity);
420
+ END IF;
421
+ END LOOP;
422
+ END;
423
+ $$ LANGUAGE plpgsql;
424
+
425
+ -- Recreate event triggers pointing to system schema functions
426
+ CREATE EVENT TRIGGER create_policies_on_table_create
427
+ ON ddl_command_end
428
+ WHEN TAG IN ('CREATE TABLE')
429
+ EXECUTE FUNCTION system.create_default_policies();
430
+
431
+ CREATE EVENT TRIGGER create_policies_on_rls_enable
432
+ ON ddl_command_end
433
+ WHEN TAG IN ('ALTER TABLE')
434
+ EXECUTE FUNCTION system.create_policies_after_rls();
435
+
436
+ -- 6.5 Drop obsolete functions
437
+ DROP FUNCTION IF EXISTS public.create_default_policies() CASCADE;
438
+ DROP FUNCTION IF EXISTS public.create_policies_after_rls() CASCADE;
439
+ DROP FUNCTION IF EXISTS public.reload_postgrest_schema() CASCADE;
440
+ DROP FUNCTION IF EXISTS public.update_updated_at_column() CASCADE;
441
+ DROP FUNCTION IF EXISTS realtime.update_updated_at() CASCADE;