insforge 1.2.10 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (335) 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 +44 -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 +28 -28
  25. package/auth/src/lib/broadcastService.ts +117 -115
  26. package/auth/src/pages/SignInPage.tsx +60 -57
  27. package/auth/src/pages/SignUpPage.tsx +60 -57
  28. package/auth/tsconfig.json +32 -32
  29. package/auth/tsconfig.node.json +11 -11
  30. package/backend/package.json +78 -75
  31. package/backend/src/api/routes/ai/index.routes.ts +3 -3
  32. package/backend/src/api/routes/auth/index.routes.ts +667 -570
  33. package/backend/src/api/routes/auth/oauth.routes.ts +473 -448
  34. package/backend/src/api/routes/database/advance.routes.ts +37 -16
  35. package/backend/src/api/routes/database/index.routes.ts +78 -1
  36. package/backend/src/api/routes/database/records.routes.ts +10 -10
  37. package/backend/src/api/routes/database/tables.routes.ts +0 -14
  38. package/backend/src/api/routes/docs/index.routes.ts +75 -76
  39. package/backend/src/api/routes/email/index.routes.ts +35 -0
  40. package/backend/src/api/routes/functions/index.routes.ts +18 -12
  41. package/backend/src/api/routes/metadata/index.routes.ts +12 -0
  42. package/backend/src/api/routes/realtime/channels.routes.ts +81 -0
  43. package/backend/src/api/routes/realtime/index.routes.ts +12 -0
  44. package/backend/src/api/routes/realtime/messages.routes.ts +48 -0
  45. package/backend/src/api/routes/realtime/permissions.routes.ts +19 -0
  46. package/backend/src/api/routes/storage/index.routes.ts +18 -12
  47. package/backend/src/api/routes/usage/index.routes.ts +6 -4
  48. package/backend/src/infra/database/database.manager.ts +14 -1
  49. package/backend/src/infra/database/migrations/000_create-base-tables.sql +141 -141
  50. package/backend/src/infra/database/migrations/001_create-helper-functions.sql +40 -40
  51. package/backend/src/infra/database/migrations/002_rename-auth-tables.sql +29 -29
  52. package/backend/src/infra/database/migrations/003_create-users-table.sql +55 -55
  53. package/backend/src/infra/database/migrations/004_add-reload-postgrest-func.sql +23 -23
  54. package/backend/src/infra/database/migrations/005_enable-project-admin-modify-users.sql +29 -29
  55. package/backend/src/infra/database/migrations/006_modify-ai-usage-table.sql +24 -24
  56. package/backend/src/infra/database/migrations/007_drop-metadata-table.sql +1 -1
  57. package/backend/src/infra/database/migrations/008_add-system-tables.sql +76 -76
  58. package/backend/src/infra/database/migrations/009_add-function-secrets.sql +23 -23
  59. package/backend/src/infra/database/migrations/010_modify-ai-config-modalities.sql +93 -93
  60. package/backend/src/infra/database/migrations/011_refactor-secrets-table.sql +15 -15
  61. package/backend/src/infra/database/migrations/012_add-storage-uploaded-by.sql +7 -7
  62. package/backend/src/infra/database/migrations/013_create-auth-schema-functions.sql +44 -44
  63. package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +7 -7
  64. package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +59 -59
  65. package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -24
  66. package/backend/src/infra/database/migrations/017_create-realtime-schema.sql +233 -0
  67. package/backend/src/infra/realtime/realtime.manager.ts +246 -0
  68. package/backend/src/infra/realtime/webhook-sender.ts +82 -0
  69. package/backend/src/infra/security/token.manager.ts +219 -125
  70. package/backend/src/infra/socket/socket.manager.ts +198 -64
  71. package/backend/src/providers/ai/openrouter.provider.ts +12 -9
  72. package/backend/src/providers/email/base.provider.ts +4 -7
  73. package/backend/src/providers/email/cloud.provider.ts +84 -0
  74. package/backend/src/providers/oauth/apple.provider.ts +266 -0
  75. package/backend/src/providers/oauth/index.ts +1 -0
  76. package/backend/src/server.ts +317 -284
  77. package/backend/src/services/ai/ai-model.service.ts +5 -5
  78. package/backend/src/services/ai/chat-completion.service.ts +4 -4
  79. package/backend/src/services/ai/image-generation.service.ts +3 -3
  80. package/backend/src/services/auth/auth.service.ts +14 -0
  81. package/backend/src/services/database/database-table.service.ts +0 -9
  82. package/backend/src/services/database/database.service.ts +127 -0
  83. package/backend/src/services/email/email.service.ts +5 -7
  84. package/backend/src/services/realtime/index.ts +3 -0
  85. package/backend/src/services/realtime/realtime-auth.service.ts +104 -0
  86. package/backend/src/services/realtime/realtime-channel.service.ts +237 -0
  87. package/backend/src/services/realtime/realtime-message.service.ts +260 -0
  88. package/backend/src/types/auth.ts +11 -0
  89. package/backend/src/types/realtime.ts +18 -0
  90. package/backend/src/types/socket.ts +7 -31
  91. package/backend/src/utils/cookies.ts +35 -0
  92. package/backend/src/utils/s3-config-loader.ts +64 -0
  93. package/backend/src/utils/seed.ts +301 -298
  94. package/backend/src/utils/sql-parser.ts +90 -0
  95. package/backend/tests/README.md +133 -133
  96. package/backend/tests/cleanup-all-test-data.sh +230 -230
  97. package/backend/tests/cloud/test-s3-multitenant.sh +131 -131
  98. package/backend/tests/local/comprehensive-curl-tests.sh +155 -155
  99. package/backend/tests/local/test-ai-config.sh +129 -129
  100. package/backend/tests/local/test-ai-usage.sh +80 -80
  101. package/backend/tests/local/test-auth-router.sh +143 -143
  102. package/backend/tests/local/test-database-router.sh +222 -222
  103. package/backend/tests/local/test-e2e.sh +240 -240
  104. package/backend/tests/local/test-fk-errors.sh +96 -96
  105. package/backend/tests/local/test-functions.sh +123 -123
  106. package/backend/tests/local/test-id-field.sh +200 -200
  107. package/backend/tests/local/test-logs.sh +132 -132
  108. package/backend/tests/local/test-public-bucket.sh +264 -264
  109. package/backend/tests/local/test-secrets.sh +249 -249
  110. package/backend/tests/local/test-serverless-functions.sh.disabled +325 -325
  111. package/backend/tests/local/test-traditional-rest.sh +208 -208
  112. package/backend/tests/manual/README.md +50 -50
  113. package/backend/tests/manual/create-large-table-simple.sql +10 -10
  114. package/backend/tests/manual/seed-large-table.sql +100 -100
  115. package/backend/tests/manual/setup-large-table-extras.sql +33 -33
  116. package/backend/tests/manual/test-bulk-upsert.sh +409 -409
  117. package/backend/tests/manual/test-database-advance.sh +296 -296
  118. package/backend/tests/manual/test-postgrest-stability.sh +191 -191
  119. package/backend/tests/manual/test-rawsql-export-import.sh +411 -411
  120. package/backend/tests/manual/test-rawsql-modes.sh +244 -244
  121. package/backend/tests/manual/test-universal-storage.sh +263 -263
  122. package/backend/tests/manual/test-users.sql +17 -17
  123. package/backend/tests/run-all-tests.sh +139 -139
  124. package/backend/tests/setup.ts +0 -0
  125. package/backend/tests/test-config.sh +338 -338
  126. package/backend/tests/unit/analyze-query.test.ts +697 -0
  127. package/backend/tsconfig.json +22 -22
  128. package/claude-plugin/.claude-plugin/plugin.json +24 -24
  129. package/claude-plugin/README.md +133 -133
  130. package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +270 -270
  131. package/docker-compose.prod.yml +204 -200
  132. package/docker-compose.yml +232 -228
  133. package/docker-init/db/db-init.sql +97 -97
  134. package/docker-init/db/jwt.sql +5 -5
  135. package/docker-init/db/postgresql.conf +16 -16
  136. package/docker-init/logs/vector.yml +236 -236
  137. package/docs/README.md +44 -44
  138. package/docs/agent-docs/real-time.md +269 -0
  139. package/docs/changelog.mdx +119 -67
  140. package/docs/core-concepts/ai/architecture.mdx +372 -372
  141. package/docs/core-concepts/ai/sdk.mdx +213 -213
  142. package/docs/core-concepts/authentication/architecture.mdx +278 -278
  143. package/docs/core-concepts/authentication/sdk.mdx +414 -414
  144. package/docs/core-concepts/authentication/ui-components/customization.mdx +529 -529
  145. package/docs/core-concepts/authentication/ui-components/nextjs.mdx +221 -221
  146. package/docs/core-concepts/authentication/ui-components/react-router.mdx +184 -184
  147. package/docs/core-concepts/authentication/ui-components/react.mdx +129 -129
  148. package/docs/core-concepts/database/architecture.mdx +255 -255
  149. package/docs/core-concepts/database/sdk.mdx +382 -382
  150. package/docs/core-concepts/email/architecture.mdx +101 -0
  151. package/docs/core-concepts/email/sdk.mdx +53 -0
  152. package/docs/core-concepts/functions/architecture.mdx +105 -105
  153. package/docs/core-concepts/functions/sdk.mdx +184 -184
  154. package/docs/core-concepts/realtime/architecture.mdx +446 -0
  155. package/docs/core-concepts/realtime/sdk.mdx +409 -0
  156. package/docs/core-concepts/storage/architecture.mdx +243 -243
  157. package/docs/core-concepts/storage/sdk.mdx +253 -253
  158. package/docs/deployment/README.md +94 -94
  159. package/docs/deployment/deploy-to-aws-ec2.md +564 -564
  160. package/docs/deployment/deploy-to-azure-virtual-machines.md +312 -312
  161. package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -613
  162. package/docs/deployment/deploy-to-render.md +441 -441
  163. package/docs/deprecated/insforge-auth-api.md +214 -214
  164. package/docs/deprecated/insforge-auth-sdk.md +99 -99
  165. package/docs/deprecated/insforge-db-api.md +358 -358
  166. package/docs/deprecated/insforge-db-sdk.md +139 -139
  167. package/docs/deprecated/insforge-debug-sdk.md +156 -156
  168. package/docs/deprecated/insforge-debug.md +64 -64
  169. package/docs/deprecated/insforge-instructions.md +123 -123
  170. package/docs/deprecated/insforge-project.md +117 -117
  171. package/docs/deprecated/insforge-storage-api.md +278 -278
  172. package/docs/deprecated/insforge-storage-sdk.md +158 -158
  173. package/docs/docs.json +232 -210
  174. package/docs/examples/framework-guides/nextjs.mdx +131 -131
  175. package/docs/examples/framework-guides/nuxt.mdx +165 -165
  176. package/docs/examples/framework-guides/react.mdx +165 -165
  177. package/docs/examples/framework-guides/svelte.mdx +153 -153
  178. package/docs/examples/framework-guides/vue.mdx +159 -159
  179. package/docs/examples/overview.mdx +67 -67
  180. package/docs/favicon.svg +19 -19
  181. package/docs/images/changelog/dec-2025/ai-integration.png +0 -0
  182. package/docs/images/changelog/dec-2025/ai-models.webp +0 -0
  183. package/docs/images/changelog/dec-2025/alipay-payment.webp +0 -0
  184. package/docs/images/changelog/dec-2025/apple-login.jpg +0 -0
  185. package/docs/images/changelog/dec-2025/mcp-installer.png +0 -0
  186. package/docs/images/changelog/dec-2025/realtime-module.jpg +0 -0
  187. package/docs/images/icons/ai.svg +4 -4
  188. package/docs/images/logos/nextjs.svg +4 -4
  189. package/docs/images/logos/nuxt.svg +4 -4
  190. package/docs/images/logos/react.svg +5 -5
  191. package/docs/images/logos/svelte.svg +4 -4
  192. package/docs/images/logos/vue.svg +5 -5
  193. package/docs/insforge-instructions-sdk.md +89 -88
  194. package/docs/introduction.mdx +45 -45
  195. package/docs/logo/dark.svg +22 -22
  196. package/docs/logo/light.svg +20 -20
  197. package/docs/partnership.mdx +651 -646
  198. package/docs/quickstart.mdx +82 -82
  199. package/docs/showcase.mdx +52 -52
  200. package/docs/snippets/sdk-installation.mdx +21 -21
  201. package/docs/snippets/service-icons.mdx +27 -27
  202. package/examples/oauth/frontend-oauth-example.html +250 -250
  203. package/examples/response-examples.md +443 -443
  204. package/frontend/components.json +17 -17
  205. package/frontend/package.json +69 -69
  206. package/frontend/src/assets/icons/checkbox_checked.svg +6 -6
  207. package/frontend/src/assets/icons/checkbox_undetermined.svg +6 -6
  208. package/frontend/src/assets/icons/checked.svg +3 -3
  209. package/frontend/src/assets/icons/connected.svg +3 -3
  210. package/frontend/src/assets/icons/error.svg +3 -3
  211. package/frontend/src/assets/icons/loader.svg +9 -9
  212. package/frontend/src/assets/icons/pencil.svg +4 -4
  213. package/frontend/src/assets/icons/refresh.svg +4 -4
  214. package/frontend/src/assets/icons/step_active.svg +3 -3
  215. package/frontend/src/assets/icons/step_inactive.svg +11 -11
  216. package/frontend/src/assets/icons/warning.svg +3 -3
  217. package/frontend/src/assets/logos/apple.svg +3 -3
  218. package/frontend/src/assets/logos/claude_code.svg +3 -3
  219. package/frontend/src/assets/logos/cline.svg +6 -6
  220. package/frontend/src/assets/logos/cursor.svg +20 -20
  221. package/frontend/src/assets/logos/discord.svg +8 -8
  222. package/frontend/src/assets/logos/facebook.svg +3 -3
  223. package/frontend/src/assets/logos/gemini.svg +19 -19
  224. package/frontend/src/assets/logos/github.svg +5 -5
  225. package/frontend/src/assets/logos/google.svg +13 -13
  226. package/frontend/src/assets/logos/grok.svg +10 -10
  227. package/frontend/src/assets/logos/insforge_dark.svg +15 -15
  228. package/frontend/src/assets/logos/insforge_light.svg +15 -15
  229. package/frontend/src/assets/logos/instagram.svg +1 -1
  230. package/frontend/src/assets/logos/linkedin.svg +3 -3
  231. package/frontend/src/assets/logos/openai.svg +10 -10
  232. package/frontend/src/assets/logos/roo_code.svg +9 -9
  233. package/frontend/src/assets/logos/spotify.svg +16 -16
  234. package/frontend/src/assets/logos/tiktok.svg +5 -5
  235. package/frontend/src/assets/logos/trae.svg +3 -3
  236. package/frontend/src/assets/logos/windsurf.svg +10 -10
  237. package/frontend/src/assets/logos/x.svg +3 -3
  238. package/frontend/src/components/layout/AppHeader.tsx +9 -10
  239. package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +1 -0
  240. package/frontend/src/features/auth/components/UsersDataGrid.tsx +6 -0
  241. package/frontend/src/features/auth/helpers.tsx +8 -0
  242. package/frontend/src/features/auth/{page → pages}/UsersPage.tsx +0 -28
  243. package/frontend/src/features/database/components/SQLModal.tsx +75 -0
  244. package/frontend/src/features/database/components/TableForm.tsx +0 -4
  245. package/frontend/src/features/database/hooks/useDatabase.ts +66 -0
  246. package/frontend/src/features/database/hooks/useTables.ts +32 -28
  247. package/frontend/src/features/database/index.ts +1 -0
  248. package/frontend/src/features/database/{page → pages}/FunctionsPage.tsx +29 -37
  249. package/frontend/src/features/database/{page → pages}/IndexesPage.tsx +35 -47
  250. package/frontend/src/features/database/{page → pages}/PoliciesPage.tsx +43 -54
  251. package/frontend/src/features/database/{page → pages}/TablesPage.tsx +0 -42
  252. package/frontend/src/features/database/{page → pages}/TriggersPage.tsx +35 -47
  253. package/frontend/src/features/database/services/advance.service.ts +0 -26
  254. package/frontend/src/features/database/services/database.service.ts +55 -0
  255. package/frontend/src/features/database/services/table.service.ts +0 -6
  256. package/frontend/src/features/functions/{page → pages}/FunctionsPage.tsx +21 -44
  257. package/frontend/src/features/functions/{page → pages}/SecretsPage.tsx +11 -9
  258. package/frontend/src/features/logs/hooks/useMcpUsage.ts +13 -66
  259. package/frontend/src/features/realtime/components/ChannelRow.tsx +83 -0
  260. package/frontend/src/features/realtime/components/EditChannelModal.tsx +246 -0
  261. package/frontend/src/features/realtime/components/MessageRow.tsx +85 -0
  262. package/frontend/src/features/realtime/components/RealtimeEmptyState.tsx +30 -0
  263. package/frontend/src/features/realtime/hooks/useRealtime.ts +218 -0
  264. package/frontend/src/features/realtime/index.ts +11 -0
  265. package/frontend/src/features/realtime/pages/RealtimeChannelsPage.tsx +172 -0
  266. package/frontend/src/features/realtime/pages/RealtimeMessagesPage.tsx +211 -0
  267. package/frontend/src/features/realtime/pages/RealtimePermissionsPage.tsx +191 -0
  268. package/frontend/src/features/realtime/services/realtime.service.ts +107 -0
  269. package/frontend/src/features/storage/{page → pages}/StoragePage.tsx +1 -29
  270. package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +3 -3
  271. package/frontend/src/features/visualizer/{page → pages}/VisualizerPage.tsx +1 -35
  272. package/frontend/src/lib/contexts/SocketContext.tsx +119 -75
  273. package/frontend/src/lib/routing/AppRoutes.tsx +35 -20
  274. package/frontend/src/lib/utils/cloudMessaging.ts +1 -1
  275. package/frontend/src/lib/utils/menuItems.ts +24 -0
  276. package/frontend/src/lib/utils/utils.ts +14 -1
  277. package/frontend/tsconfig.json +25 -25
  278. package/frontend/tsconfig.node.json +9 -9
  279. package/functions/deno.json +24 -24
  280. package/functions/server.ts +315 -315
  281. package/i18n/README.ar.md +130 -130
  282. package/i18n/README.de.md +130 -130
  283. package/i18n/README.es.md +154 -154
  284. package/i18n/README.fr.md +134 -134
  285. package/i18n/README.hi.md +129 -129
  286. package/i18n/README.ja.md +174 -174
  287. package/i18n/README.ko.md +136 -136
  288. package/i18n/README.pt-BR.md +131 -131
  289. package/i18n/README.ru.md +129 -129
  290. package/i18n/README.zh-CN.md +133 -133
  291. package/openapi/ai.yaml +715 -715
  292. package/openapi/auth.yaml +1244 -1244
  293. package/openapi/email.yaml +158 -0
  294. package/openapi/functions.yaml +475 -475
  295. package/openapi/health.yaml +29 -29
  296. package/openapi/logs.yaml +223 -223
  297. package/openapi/metadata.yaml +177 -177
  298. package/openapi/realtime.yaml +699 -0
  299. package/openapi/records.yaml +381 -381
  300. package/openapi/secrets.yaml +370 -370
  301. package/openapi/storage.yaml +875 -875
  302. package/openapi/tables.yaml +463 -463
  303. package/package.json +97 -97
  304. package/shared-schemas/package.json +31 -31
  305. package/shared-schemas/src/ai.schema.ts +63 -59
  306. package/shared-schemas/src/auth-api.schema.ts +352 -339
  307. package/shared-schemas/src/auth.schema.ts +1 -1
  308. package/shared-schemas/src/database-api.schema.ts +32 -1
  309. package/shared-schemas/src/database.schema.ts +39 -0
  310. package/shared-schemas/src/docs.schema.ts +26 -0
  311. package/shared-schemas/src/email-api.schema.ts +30 -0
  312. package/shared-schemas/src/index.ts +4 -0
  313. package/shared-schemas/src/metadata.schema.ts +9 -0
  314. package/shared-schemas/src/realtime-api.schema.ts +111 -0
  315. package/shared-schemas/src/realtime.schema.ts +143 -0
  316. package/shared-schemas/tsconfig.json +21 -21
  317. package/tsconfig.json +7 -7
  318. package/zeabur/README.md +13 -13
  319. package/zeabur/template.yml +1032 -1032
  320. package/.cursor/rules/cursor-rules.mdc +0 -94
  321. package/frontend/src/features/database/hooks/useFullMetadata.ts +0 -18
  322. package/test-gemini.sh +0 -35
  323. package/test-usage-admin.sh +0 -57
  324. package/test-usage.sh +0 -50
  325. /package/frontend/src/features/ai/{page → pages}/AIPage.tsx +0 -0
  326. /package/frontend/src/features/auth/{page → pages}/AuthMethodsPage.tsx +0 -0
  327. /package/frontend/src/features/auth/{page → pages}/ConfigurationPage.tsx +0 -0
  328. /package/frontend/src/features/dashboard/{page → pages}/DashboardPage.tsx +0 -0
  329. /package/frontend/src/features/database/{page → pages}/SQLEditorPage.tsx +0 -0
  330. /package/frontend/src/features/database/{page → pages}/TemplatesPage.tsx +0 -0
  331. /package/frontend/src/features/login/{page → pages}/CloudLoginPage.tsx +0 -0
  332. /package/frontend/src/features/login/{page → pages}/LoginPage.tsx +0 -0
  333. /package/frontend/src/features/logs/{page → pages}/AuditsPage.tsx +0 -0
  334. /package/frontend/src/features/logs/{page → pages}/LogsPage.tsx +0 -0
  335. /package/frontend/src/features/logs/{page → pages}/MCPLogsPage.tsx +0 -0
@@ -1,44 +1,44 @@
1
- -- Migration: 013 - Create auth schema and copy helper functions
2
- -- Creates auth schema if it doesn't exist and copies JWT helper functions
3
-
4
- -- Create auth schema if not exists
5
- CREATE SCHEMA IF NOT EXISTS auth;
6
-
7
- -- Function to get current user ID from JWT (in auth schema)
8
- CREATE OR REPLACE FUNCTION auth.uid()
9
- RETURNS uuid
10
- LANGUAGE sql STABLE
11
- AS $$
12
- SELECT
13
- nullif(
14
- coalesce(
15
- current_setting('request.jwt.claim.sub', true),
16
- (current_setting('request.jwt.claims', true)::jsonb ->> 'sub')
17
- ),
18
- ''
19
- )::uuid
20
- $$;
21
-
22
- -- Function to get current user role from JWT (in auth schema)
23
- CREATE OR REPLACE FUNCTION auth.role()
24
- RETURNS text
25
- LANGUAGE sql STABLE
26
- AS $$
27
- SELECT
28
- coalesce(
29
- current_setting('request.jwt.claim.role', true),
30
- (current_setting('request.jwt.claims', true)::jsonb ->> 'role')
31
- )::text
32
- $$;
33
-
34
- -- Function to get current user email from JWT (in auth schema)
35
- CREATE OR REPLACE FUNCTION auth.email()
36
- RETURNS text
37
- LANGUAGE sql STABLE
38
- AS $$
39
- SELECT
40
- coalesce(
41
- current_setting('request.jwt.claim.email', true),
42
- (current_setting('request.jwt.claims', true)::jsonb ->> 'email')
43
- )::text
44
- $$;
1
+ -- Migration: 013 - Create auth schema and copy helper functions
2
+ -- Creates auth schema if it doesn't exist and copies JWT helper functions
3
+
4
+ -- Create auth schema if not exists
5
+ CREATE SCHEMA IF NOT EXISTS auth;
6
+
7
+ -- Function to get current user ID from JWT (in auth schema)
8
+ CREATE OR REPLACE FUNCTION auth.uid()
9
+ RETURNS uuid
10
+ LANGUAGE sql STABLE
11
+ AS $$
12
+ SELECT
13
+ nullif(
14
+ coalesce(
15
+ current_setting('request.jwt.claim.sub', true),
16
+ (current_setting('request.jwt.claims', true)::jsonb ->> 'sub')
17
+ ),
18
+ ''
19
+ )::uuid
20
+ $$;
21
+
22
+ -- Function to get current user role from JWT (in auth schema)
23
+ CREATE OR REPLACE FUNCTION auth.role()
24
+ RETURNS text
25
+ LANGUAGE sql STABLE
26
+ AS $$
27
+ SELECT
28
+ coalesce(
29
+ current_setting('request.jwt.claim.role', true),
30
+ (current_setting('request.jwt.claims', true)::jsonb ->> 'role')
31
+ )::text
32
+ $$;
33
+
34
+ -- Function to get current user email from JWT (in auth schema)
35
+ CREATE OR REPLACE FUNCTION auth.email()
36
+ RETURNS text
37
+ LANGUAGE sql STABLE
38
+ AS $$
39
+ SELECT
40
+ coalesce(
41
+ current_setting('request.jwt.claim.email', true),
42
+ (current_setting('request.jwt.claims', true)::jsonb ->> 'email')
43
+ )::text
44
+ $$;
@@ -1,8 +1,8 @@
1
- -- Migration: 014 - Add updated_at trigger to users table
2
- -- Adds the updated_at trigger to the users table for automatic timestamp management
3
-
4
-
5
- DROP TRIGGER IF EXISTS update_users_updated_at ON users;
6
- CREATE TRIGGER update_users_updated_at
7
- BEFORE UPDATE ON users
1
+ -- Migration: 014 - Add updated_at trigger to users table
2
+ -- Adds the updated_at trigger to the users table for automatic timestamp management
3
+
4
+
5
+ DROP TRIGGER IF EXISTS update_users_updated_at ON users;
6
+ CREATE TRIGGER update_users_updated_at
7
+ BEFORE UPDATE ON users
8
8
  FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
@@ -1,60 +1,60 @@
1
- -- Migration: 015 - Create email OTP verification table and email auth configs
2
- -- This migration creates:
3
- -- 1. _email_otps: Stores one-time tokens for email verification purposes
4
- -- - Supports both short numeric codes (6 digits) for manual entry
5
- -- - Supports long cryptographic tokens (64 chars) for magic links
6
- -- - Uses dual hashing strategy:
7
- -- * NUMERIC_CODE (6 digits): Bcrypt hash (slow, defense against brute force)
8
- -- * LINK_TOKEN (64 hex chars): SHA-256 hash (fast, enables direct O(1) lookup)
9
- -- 2. _auth_configs: Stores email authentication configuration (single-row table)
10
-
11
- -- 1. Create email OTP verification table
12
- CREATE TABLE IF NOT EXISTS _email_otps (
13
- id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
14
- email TEXT NOT NULL,
15
- purpose TEXT NOT NULL,
16
- otp_hash TEXT NOT NULL, -- Hash of OTP: bcrypt for NUMERIC_CODE, SHA-256 for LINK_TOKEN
17
- expires_at TIMESTAMPTZ NOT NULL,
18
- consumed_at TIMESTAMPTZ,
19
- attempts_count INTEGER DEFAULT 0 NOT NULL,
20
- created_at TIMESTAMPTZ DEFAULT NOW(),
21
- updated_at TIMESTAMPTZ DEFAULT NOW(),
22
- UNIQUE (email, purpose) -- Only one active token per email/purpose combination
23
- );
24
-
25
- -- Create indexes for better query performance
26
- CREATE INDEX IF NOT EXISTS idx_email_otps_email_purpose ON _email_otps(email, purpose);
27
- CREATE INDEX IF NOT EXISTS idx_email_otps_expires_at ON _email_otps(expires_at);
28
- CREATE INDEX IF NOT EXISTS idx_email_otps_otp_hash ON _email_otps(otp_hash); -- For direct LINK_TOKEN lookup
29
-
30
- -- Add trigger for updated_at
31
- DROP TRIGGER IF EXISTS update__email_otps_updated_at ON _email_otps;
32
- CREATE TRIGGER update__email_otps_updated_at
33
- BEFORE UPDATE ON _email_otps
34
- FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
35
-
36
- -- 2. Create email authentication configuration table (single-row design)
37
- -- This table stores global email authentication settings for the project
38
- CREATE TABLE IF NOT EXISTS _auth_configs (
39
- id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
40
- require_email_verification BOOLEAN DEFAULT FALSE NOT NULL,
41
- password_min_length INTEGER DEFAULT 6 NOT NULL CHECK (password_min_length >= 4 AND password_min_length <= 128),
42
- require_number BOOLEAN DEFAULT FALSE NOT NULL,
43
- require_lowercase BOOLEAN DEFAULT FALSE NOT NULL,
44
- require_uppercase BOOLEAN DEFAULT FALSE NOT NULL,
45
- require_special_char BOOLEAN DEFAULT FALSE NOT NULL,
46
- verify_email_redirect_to TEXT, -- Custom URL to redirect after successful email verification (defaults to no redirect if NULL)
47
- reset_password_redirect_to TEXT, -- Custom URL to redirect after successful password reset (defaults to no redirect if NULL)
48
- created_at TIMESTAMPTZ DEFAULT NOW(),
49
- updated_at TIMESTAMPTZ DEFAULT NOW()
50
- );
51
-
52
- -- Ensure only one row exists (singleton pattern)
53
- -- This constraint prevents multiple configuration rows
54
- CREATE UNIQUE INDEX IF NOT EXISTS idx_auth_configs_singleton ON _auth_configs ((1));
55
-
56
- -- Add trigger for updated_at
57
- DROP TRIGGER IF EXISTS update__auth_configs_updated_at ON _auth_configs;
58
- CREATE TRIGGER update__auth_configs_updated_at
59
- BEFORE UPDATE ON _auth_configs
1
+ -- Migration: 015 - Create email OTP verification table and email auth configs
2
+ -- This migration creates:
3
+ -- 1. _email_otps: Stores one-time tokens for email verification purposes
4
+ -- - Supports both short numeric codes (6 digits) for manual entry
5
+ -- - Supports long cryptographic tokens (64 chars) for magic links
6
+ -- - Uses dual hashing strategy:
7
+ -- * NUMERIC_CODE (6 digits): Bcrypt hash (slow, defense against brute force)
8
+ -- * LINK_TOKEN (64 hex chars): SHA-256 hash (fast, enables direct O(1) lookup)
9
+ -- 2. _auth_configs: Stores email authentication configuration (single-row table)
10
+
11
+ -- 1. Create email OTP verification table
12
+ CREATE TABLE IF NOT EXISTS _email_otps (
13
+ id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
14
+ email TEXT NOT NULL,
15
+ purpose TEXT NOT NULL,
16
+ otp_hash TEXT NOT NULL, -- Hash of OTP: bcrypt for NUMERIC_CODE, SHA-256 for LINK_TOKEN
17
+ expires_at TIMESTAMPTZ NOT NULL,
18
+ consumed_at TIMESTAMPTZ,
19
+ attempts_count INTEGER DEFAULT 0 NOT NULL,
20
+ created_at TIMESTAMPTZ DEFAULT NOW(),
21
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
22
+ UNIQUE (email, purpose) -- Only one active token per email/purpose combination
23
+ );
24
+
25
+ -- Create indexes for better query performance
26
+ CREATE INDEX IF NOT EXISTS idx_email_otps_email_purpose ON _email_otps(email, purpose);
27
+ CREATE INDEX IF NOT EXISTS idx_email_otps_expires_at ON _email_otps(expires_at);
28
+ CREATE INDEX IF NOT EXISTS idx_email_otps_otp_hash ON _email_otps(otp_hash); -- For direct LINK_TOKEN lookup
29
+
30
+ -- Add trigger for updated_at
31
+ DROP TRIGGER IF EXISTS update__email_otps_updated_at ON _email_otps;
32
+ CREATE TRIGGER update__email_otps_updated_at
33
+ BEFORE UPDATE ON _email_otps
34
+ FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
35
+
36
+ -- 2. Create email authentication configuration table (single-row design)
37
+ -- This table stores global email authentication settings for the project
38
+ CREATE TABLE IF NOT EXISTS _auth_configs (
39
+ id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
40
+ require_email_verification BOOLEAN DEFAULT FALSE NOT NULL,
41
+ password_min_length INTEGER DEFAULT 6 NOT NULL CHECK (password_min_length >= 4 AND password_min_length <= 128),
42
+ require_number BOOLEAN DEFAULT FALSE NOT NULL,
43
+ require_lowercase BOOLEAN DEFAULT FALSE NOT NULL,
44
+ require_uppercase BOOLEAN DEFAULT FALSE NOT NULL,
45
+ require_special_char BOOLEAN DEFAULT FALSE NOT NULL,
46
+ verify_email_redirect_to TEXT, -- Custom URL to redirect after successful email verification (defaults to no redirect if NULL)
47
+ reset_password_redirect_to TEXT, -- Custom URL to redirect after successful password reset (defaults to no redirect if NULL)
48
+ created_at TIMESTAMPTZ DEFAULT NOW(),
49
+ updated_at TIMESTAMPTZ DEFAULT NOW()
50
+ );
51
+
52
+ -- Ensure only one row exists (singleton pattern)
53
+ -- This constraint prevents multiple configuration rows
54
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_auth_configs_singleton ON _auth_configs ((1));
55
+
56
+ -- Add trigger for updated_at
57
+ DROP TRIGGER IF EXISTS update__auth_configs_updated_at ON _auth_configs;
58
+ CREATE TRIGGER update__auth_configs_updated_at
59
+ BEFORE UPDATE ON _auth_configs
60
60
  FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
@@ -1,24 +1,24 @@
1
- -- Migration 016: Update _email_otps and _auth_configs tables
2
- --
3
- -- Changes:
4
- -- 1. _email_otps table:
5
- -- - Remove attempts_count column (brute force protection moved to API rate limiter)
6
- -- 2. _auth_configs table:
7
- -- - Remove verify_email_redirect_to and reset_password_redirect_to columns
8
- -- - Add verify_email_method and reset_password_method columns (code or link)
9
- -- - Add sign_in_redirect_to column
10
-
11
- -- Update _email_otps: Remove attempts_count column
12
- ALTER TABLE _email_otps DROP COLUMN IF EXISTS attempts_count;
13
-
14
- -- Update _auth_configs: Remove old redirect columns
15
- ALTER TABLE _auth_configs
16
- DROP COLUMN IF EXISTS verify_email_redirect_to,
17
- DROP COLUMN IF EXISTS reset_password_redirect_to;
18
-
19
- -- Add new columns to _auth_configs
20
- -- Note: DEFAULT 'code' NOT NULL ensures existing rows automatically get 'code' value
21
- ALTER TABLE _auth_configs
22
- ADD COLUMN IF NOT EXISTS verify_email_method TEXT DEFAULT 'code' NOT NULL CHECK (verify_email_method IN ('code', 'link')),
23
- ADD COLUMN IF NOT EXISTS reset_password_method TEXT DEFAULT 'code' NOT NULL CHECK (reset_password_method IN ('code', 'link')),
24
- ADD COLUMN IF NOT EXISTS sign_in_redirect_to TEXT;
1
+ -- Migration 016: Update _email_otps and _auth_configs tables
2
+ --
3
+ -- Changes:
4
+ -- 1. _email_otps table:
5
+ -- - Remove attempts_count column (brute force protection moved to API rate limiter)
6
+ -- 2. _auth_configs table:
7
+ -- - Remove verify_email_redirect_to and reset_password_redirect_to columns
8
+ -- - Add verify_email_method and reset_password_method columns (code or link)
9
+ -- - Add sign_in_redirect_to column
10
+
11
+ -- Update _email_otps: Remove attempts_count column
12
+ ALTER TABLE _email_otps DROP COLUMN IF EXISTS attempts_count;
13
+
14
+ -- Update _auth_configs: Remove old redirect columns
15
+ ALTER TABLE _auth_configs
16
+ DROP COLUMN IF EXISTS verify_email_redirect_to,
17
+ DROP COLUMN IF EXISTS reset_password_redirect_to;
18
+
19
+ -- Add new columns to _auth_configs
20
+ -- Note: DEFAULT 'code' NOT NULL ensures existing rows automatically get 'code' value
21
+ ALTER TABLE _auth_configs
22
+ ADD COLUMN IF NOT EXISTS verify_email_method TEXT DEFAULT 'code' NOT NULL CHECK (verify_email_method IN ('code', 'link')),
23
+ ADD COLUMN IF NOT EXISTS reset_password_method TEXT DEFAULT 'code' NOT NULL CHECK (reset_password_method IN ('code', 'link')),
24
+ ADD COLUMN IF NOT EXISTS sign_in_redirect_to TEXT;
@@ -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;