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
@@ -0,0 +1,446 @@
1
+ ---
2
+ title: Architecture
3
+ description: Real-time messaging with PostgreSQL triggers, WebSockets, and webhooks
4
+ ---
5
+
6
+ ## Overview
7
+
8
+ InsForge Realtime provides a powerful event-driven messaging system that bridges database changes to connected clients. Events are triggered by PostgreSQL triggers, delivered through WebSocket connections via Socket.IO, and optionally forwarded to webhook endpoints.
9
+
10
+ ## Technology Stack
11
+
12
+ ```mermaid
13
+ graph TB
14
+ Trigger[Database Trigger] --> Publish[realtime.publish]
15
+ Publish --> Messages[(realtime.messages)]
16
+ Messages --> PGNotify[pg_notify]
17
+ PGNotify --> Manager[Realtime Manager]
18
+ Manager --> SocketIO[Socket.IO Server]
19
+ Manager --> Webhooks[Webhook Sender]
20
+ SocketIO --> SDK[InsForge SDK]
21
+ SDK --> App[Client Application]
22
+ Webhooks --> External[External Services]
23
+
24
+ Channels[(realtime.channels)]
25
+ RLS[RLS Policies]
26
+ RLS -.->|SELECT| Channels
27
+ RLS -.->|INSERT| Messages
28
+
29
+ style Trigger fill:#4c1d95,stroke:#8b5cf6,color:#ede9fe
30
+ style Publish fill:#4c1d95,stroke:#8b5cf6,color:#ede9fe
31
+ style Messages fill:#0e7490,stroke:#06b6d4,color:#cffafe
32
+ style Channels fill:#0e7490,stroke:#06b6d4,color:#cffafe
33
+ style PGNotify fill:#0e7490,stroke:#06b6d4,color:#cffafe
34
+ style RLS fill:#7c2d12,stroke:#f97316,color:#fed7aa
35
+ style Manager fill:#166534,stroke:#22c55e,color:#dcfce7
36
+ style SocketIO fill:#c2410c,stroke:#fb923c,color:#fed7aa
37
+ style Webhooks fill:#c2410c,stroke:#fb923c,color:#fed7aa
38
+ style SDK fill:#1e40af,stroke:#3b82f6,color:#dbeafe
39
+ style App fill:#1e293b,stroke:#475569,color:#e2e8f0
40
+ style External fill:#1e293b,stroke:#475569,color:#e2e8f0
41
+ ```
42
+
43
+ ## Core Components
44
+
45
+ | Component | Technology | Purpose |
46
+ |-----------|------------|---------|
47
+ | **Realtime Schema** | PostgreSQL | Channels, messages tables and publish function |
48
+ | **Permission Model** | Grants + RLS (optional) | Controls subscribe and publish access |
49
+ | **Notification Bridge** | pg_notify | Bridges database to Node.js process |
50
+ | **Realtime Manager** | Node.js | Listens for notifications, dispatches messages |
51
+ | **WebSocket Server** | Socket.IO | Bidirectional client communication |
52
+ | **Webhook Sender** | Axios | HTTP delivery to external endpoints |
53
+ | **SDK** | @insforge/sdk | Client-side subscription and messaging |
54
+
55
+ ## Database Schema
56
+
57
+ ### Channels Table
58
+
59
+ The `realtime.channels` table defines available channel patterns and their configuration:
60
+
61
+ | Column | Type | Description |
62
+ |--------|------|-------------|
63
+ | `id` | UUID | Primary key |
64
+ | `pattern` | TEXT | Channel name pattern (e.g., `orders`, `order:%`) |
65
+ | `description` | TEXT | Human-readable description |
66
+ | `webhook_urls` | TEXT[] | Array of webhook endpoints |
67
+ | `enabled` | BOOLEAN | Whether the channel is active |
68
+
69
+ <Note>
70
+ Channel patterns use `:` as separator and `%` for wildcards (SQL LIKE pattern). For example, `order:%` matches `order:123`, `order:456`, etc.
71
+ </Note>
72
+
73
+ ### Messages Table
74
+
75
+ The `realtime.messages` table stores all published messages for audit purposes:
76
+
77
+ | Column | Type | Description |
78
+ |--------|------|-------------|
79
+ | `id` | UUID | Primary key |
80
+ | `event_name` | TEXT | Event type (e.g., `order_created`) |
81
+ | `channel_id` | UUID | Reference to channels table |
82
+ | `channel_name` | TEXT | Resolved channel name (e.g., `order:123`) |
83
+ | `payload` | JSONB | Event data |
84
+ | `sender_type` | TEXT | `system` (trigger) or `user` (client) |
85
+ | `sender_id` | UUID | User ID for client-initiated messages |
86
+ | `ws_audience_count` | INTEGER | WebSocket subscribers at time of delivery |
87
+ | `wh_audience_count` | INTEGER | Webhook URLs configured |
88
+ | `wh_delivered_count` | INTEGER | Successful webhook deliveries |
89
+
90
+ ## Permission Model
91
+
92
+ InsForge Realtime uses PostgreSQL grants and optional Row Level Security (RLS) to control channel access.
93
+
94
+ <Note>
95
+ **RLS is disabled by default** for the best developer experience. Channels and messages are open to all authenticated and anonymous users out of the box. Enable RLS when you need fine-grained access control.
96
+ </Note>
97
+
98
+ ### Default Permissions (RLS Disabled)
99
+
100
+ | Permission | Table | Grant | Access |
101
+ |------------|-------|-------|--------|
102
+ | **Subscribe** | `realtime.channels` | SELECT | All authenticated/anon users |
103
+ | **Publish** | `realtime.messages` | INSERT | All authenticated/anon users |
104
+
105
+ ### Enabling Access Control
106
+
107
+ To restrict access, enable RLS and add policies:
108
+
109
+ ```sql
110
+ -- Step 1: Enable RLS
111
+ ALTER TABLE realtime.channels ENABLE ROW LEVEL SECURITY;
112
+ ALTER TABLE realtime.messages ENABLE ROW LEVEL SECURITY;
113
+
114
+ -- Step 2: Add policies (see examples below)
115
+ ```
116
+
117
+ ### How RLS Works (When Enabled)
118
+
119
+ | Permission | Table | Policy Type | Description |
120
+ |------------|-------|-------------|-------------|
121
+ | **Subscribe** | `realtime.channels` | SELECT | Who can subscribe to a channel |
122
+ | **Publish** | `realtime.messages` | INSERT | Who can publish to a channel |
123
+
124
+ 1. When a client subscribes, the backend executes a SELECT query on `realtime.channels` with the user's role
125
+ 2. RLS policies filter the result. If a matching channel is returned, subscription is allowed
126
+ 3. When a client publishes, the backend attempts an INSERT into `realtime.messages`
127
+ 4. RLS policies evaluate the INSERT. If allowed, the message is stored and broadcast
128
+
129
+ ### Helper Function
130
+
131
+ Use `realtime.channel_name()` in your policies to access the channel being requested:
132
+
133
+ ```sql
134
+ -- Allow authenticated users to subscribe to their own order channels
135
+ CREATE POLICY "users_can_subscribe_own_orders"
136
+ ON realtime.channels
137
+ FOR SELECT
138
+ TO authenticated
139
+ USING (
140
+ pattern = 'order:%'
141
+ AND EXISTS (
142
+ SELECT 1 FROM orders
143
+ WHERE id = NULLIF(split_part(realtime.channel_name(), ':', 2), '')::uuid
144
+ AND user_id = auth.uid()
145
+ )
146
+ );
147
+ ```
148
+
149
+ ## Message Flow
150
+
151
+ ### System Events (Database Triggers)
152
+
153
+ ```mermaid
154
+ sequenceDiagram
155
+ participant App as Application
156
+ participant DB as PostgreSQL
157
+ participant Pub as publish()
158
+ participant Msg as messages table
159
+ participant Manager as Realtime Manager
160
+ participant WS as WebSocket Clients
161
+ participant WH as Webhooks
162
+
163
+ App->>DB: INSERT/UPDATE/DELETE
164
+ DB->>Pub: Trigger fires
165
+ Pub->>Msg: INSERT message
166
+ Msg->>Manager: pg_notify with message_id
167
+ Manager->>Msg: Fetch full message
168
+ Manager->>WS: Broadcast to room
169
+ Manager->>WH: POST to webhook URLs
170
+ Manager->>Msg: Update delivery stats
171
+ ```
172
+
173
+ ### Client Events (User-Initiated)
174
+
175
+ ```mermaid
176
+ sequenceDiagram
177
+ participant Client as SDK Client
178
+ participant Socket as Socket.IO
179
+ participant Msg as messages table
180
+ participant RLS as RLS Policies
181
+ participant Manager as Realtime Manager
182
+
183
+ Client->>Socket: realtime:publish
184
+ Socket->>Msg: insertMessage()
185
+ Msg->>RLS: Evaluate INSERT policy
186
+ Note over Msg: Trigger fires pg_notify
187
+ Manager->>Msg: Fetch message
188
+ Manager->>Socket: Broadcast to room
189
+ ```
190
+
191
+ ## Publish Function
192
+
193
+ The `realtime.publish()` function is called by your database triggers:
194
+
195
+ ```sql
196
+ CREATE OR REPLACE FUNCTION notify_order_changes()
197
+ RETURNS TRIGGER AS $$
198
+ BEGIN
199
+ PERFORM realtime.publish(
200
+ 'order:' || NEW.id::text, -- channel name
201
+ TG_OP || '_order', -- event: INSERT_order, UPDATE_order, etc.
202
+ jsonb_build_object(
203
+ 'id', NEW.id,
204
+ 'status', NEW.status,
205
+ 'total', NEW.total
206
+ )
207
+ );
208
+ RETURN NEW;
209
+ END;
210
+ $$ LANGUAGE plpgsql SECURITY DEFINER;
211
+
212
+ CREATE TRIGGER order_changes_trigger
213
+ AFTER INSERT OR UPDATE ON orders
214
+ FOR EACH ROW
215
+ EXECUTE FUNCTION notify_order_changes();
216
+ ```
217
+
218
+ <Warning>
219
+ The `realtime.publish()` function can only be called by database triggers (SECURITY DEFINER). It bypasses RLS to insert system messages.
220
+ </Warning>
221
+
222
+ ## WebSocket Events
223
+
224
+ ### Client-to-Server Events
225
+
226
+ | Event | Payload | Description |
227
+ |-------|---------|-------------|
228
+ | `realtime:subscribe` | `{ channel: string }` | Subscribe to a channel |
229
+ | `realtime:unsubscribe` | `{ channel: string }` | Unsubscribe from a channel |
230
+ | `realtime:publish` | `{ channel, event, payload }` | Publish a message |
231
+
232
+ ### Server-to-Client Events
233
+
234
+ | Event | Payload | Description |
235
+ |-------|---------|-------------|
236
+ | `{eventName}` | Message payload + meta | Custom event from channel |
237
+ | `realtime:error` | `{ code, message }` | Error notification |
238
+
239
+ ### Socket Message Structure
240
+
241
+ All WebSocket messages include a `meta` object with server-enforced fields alongside the event payload:
242
+
243
+ ```typescript
244
+ interface SocketMessage {
245
+ meta: {
246
+ channel?: string // Channel the message was sent to
247
+ messageId: string // Unique message ID (UUID)
248
+ senderType: 'system' | 'user'
249
+ senderId?: string // User ID for client messages
250
+ timestamp: Date // Server timestamp
251
+ }
252
+ // ...event payload fields
253
+ }
254
+ ```
255
+
256
+ ## Webhook Delivery
257
+
258
+ When channels have `webhook_urls` configured, messages are delivered via HTTP POST:
259
+
260
+ ### Request Format
261
+
262
+ ```http
263
+ POST /your-webhook-endpoint HTTP/1.1
264
+ Content-Type: application/json
265
+ X-InsForge-Event: order_created
266
+ X-InsForge-Channel: order:123
267
+ X-InsForge-Message-Id: a1b2c3d4-e5f6-...
268
+
269
+ {
270
+ "id": "123",
271
+ "status": "confirmed",
272
+ "total": 99.99
273
+ }
274
+ ```
275
+
276
+ ### Delivery Guarantees
277
+
278
+ | Feature | Behavior |
279
+ |---------|----------|
280
+ | **Retries** | 2 retries with 1s, 2s backoff |
281
+ | **Timeout** | 10 seconds per request |
282
+ | **Parallel** | All webhook URLs called concurrently |
283
+ | **Tracking** | Success/failure counts stored per message |
284
+
285
+ ## Sender Types
286
+
287
+ | Type | Source | Description |
288
+ |------|--------|-------------|
289
+ | **system** | Database triggers | Events from `realtime.publish()` function |
290
+ | **user** | Client SDK | Events from `insforge.realtime.publish()` |
291
+
292
+ <Tip>
293
+ System events are trusted and bypass publish RLS checks. User events must pass INSERT policy on `realtime.messages`.
294
+ </Tip>
295
+
296
+ ## Developer Workflow
297
+
298
+ <Steps>
299
+ <Step title="Define Channels">
300
+ Create channel patterns in `realtime.channels`:
301
+ ```sql
302
+ INSERT INTO realtime.channels (pattern, description)
303
+ VALUES ('order:%', 'Order-specific events');
304
+ ```
305
+ </Step>
306
+
307
+ <Step title="Configure Permissions (Optional)">
308
+ RLS is disabled by default, so all users can subscribe and publish. To restrict access, enable RLS and add policies:
309
+ ```sql
310
+ -- Step 1: Enable RLS
311
+ ALTER TABLE realtime.channels ENABLE ROW LEVEL SECURITY;
312
+ ALTER TABLE realtime.messages ENABLE ROW LEVEL SECURITY;
313
+
314
+ -- Step 2: Add policies
315
+ -- Subscribe: users can only subscribe to their own order channels
316
+ CREATE POLICY "users_subscribe_own_orders"
317
+ ON realtime.channels FOR SELECT
318
+ TO authenticated
319
+ USING (
320
+ pattern = 'order:%'
321
+ AND EXISTS (
322
+ SELECT 1 FROM orders
323
+ WHERE id = NULLIF(split_part(realtime.channel_name(), ':', 2), '')::uuid
324
+ AND user_id = auth.uid()
325
+ )
326
+ );
327
+
328
+ -- Publish: only admins can publish to order channels
329
+ CREATE POLICY "admins_publish_orders"
330
+ ON realtime.messages FOR INSERT
331
+ TO authenticated
332
+ WITH CHECK (
333
+ channel_name LIKE 'order:%'
334
+ AND EXISTS (
335
+ SELECT 1 FROM admins
336
+ WHERE user_id = auth.uid()
337
+ )
338
+ );
339
+ ```
340
+ </Step>
341
+
342
+ <Step title="Create Triggers">
343
+ Add trigger function and trigger to emit events on database changes:
344
+ ```sql
345
+ CREATE OR REPLACE FUNCTION notify_order_changes()
346
+ RETURNS TRIGGER AS $$
347
+ BEGIN
348
+ PERFORM realtime.publish(
349
+ 'order:' || NEW.id::text,
350
+ TG_OP || '_order',
351
+ jsonb_build_object('id', NEW.id, 'status', NEW.status)
352
+ );
353
+ RETURN NEW;
354
+ END;
355
+ $$ LANGUAGE plpgsql SECURITY DEFINER;
356
+
357
+ CREATE TRIGGER order_realtime
358
+ AFTER INSERT OR UPDATE ON orders
359
+ FOR EACH ROW EXECUTE FUNCTION notify_order_changes();
360
+ ```
361
+ </Step>
362
+
363
+ <Step title="Subscribe in Client">
364
+ Use the SDK to subscribe and listen:
365
+ ```javascript
366
+ await insforge.realtime.connect()
367
+ await insforge.realtime.subscribe('order:123')
368
+ insforge.realtime.on('UPDATE_order', (data) => {
369
+ console.log('Order updated:', data)
370
+ })
371
+ ```
372
+ </Step>
373
+ </Steps>
374
+
375
+ ## Architecture Features
376
+
377
+ <CardGroup cols={2}>
378
+ <Card title="Database-Driven" icon="database">
379
+ Events originate from PostgreSQL triggers, ensuring consistency with your data
380
+ </Card>
381
+
382
+ <Card title="Optional RLS Security" icon="shield">
383
+ Works out of the box, with optional RLS for fine-grained access control
384
+ </Card>
385
+
386
+ <Card title="Dual Delivery" icon="arrows-split-up-and-left">
387
+ Messages delivered to both WebSocket clients and webhook endpoints simultaneously
388
+ </Card>
389
+
390
+ <Card title="Audit Trail" icon="clipboard-list">
391
+ All messages stored in database with delivery statistics for debugging and replay
392
+ </Card>
393
+
394
+ <Card title="Pattern Matching" icon="asterisk">
395
+ Wildcard channel patterns let you define permissions for dynamic channels
396
+ </Card>
397
+
398
+ <Card title="Bidirectional" icon="arrows-left-right">
399
+ Clients can both receive events and publish their own messages (subject to RLS)
400
+ </Card>
401
+ </CardGroup>
402
+
403
+ ## Performance Characteristics
404
+
405
+ | Metric | Value | Notes |
406
+ |--------|-------|-------|
407
+ | **Latency** | ~10-50ms | Database to client, depends on network |
408
+ | **Throughput** | High | Limited by PostgreSQL NOTIFY and Socket.IO |
409
+ | **Persistence** | Full | All messages stored in database |
410
+ | **Reconnection** | Automatic | Socket.IO handles reconnection |
411
+ | **Webhook Timeout** | 10s | Per webhook request |
412
+
413
+ ## Best Practices
414
+
415
+ <CardGroup cols={2}>
416
+ <Card title="Keep Payloads Small" icon="compress">
417
+ Only include necessary data in payloads
418
+ </Card>
419
+
420
+ <Card title="Use Specific Channels" icon="bullseye">
421
+ Prefer `order:123` over broadcasting to `orders` for reducing the traffic
422
+ </Card>
423
+
424
+ <Card title="Add RLS When Needed" icon="gavel">
425
+ Enable RLS and add policies when you need to restrict channel access
426
+ </Card>
427
+
428
+ <Card title="Monitor Delivery" icon="chart-bar">
429
+ Check `ws_audience_count` and `wh_delivered_count` to debug delivery issues
430
+ </Card>
431
+
432
+ <Card title="Handle Reconnection" icon="rotate">
433
+ Design clients to refetch state on reconnect since missed messages are not replayed
434
+ </Card>
435
+
436
+ <Card title="Use Webhooks for Reliability" icon="webhook">
437
+ For critical notifications, configure webhook URLs as backup delivery method
438
+ </Card>
439
+ </CardGroup>
440
+
441
+ ## Limitations
442
+
443
+ - **No Message Replay**: Clients don't receive messages missed during disconnection
444
+ - **No Presence**: No built-in tracking of who's online in a channel
445
+ - **Single Region**: Messages delivered from single backend instance
446
+ - **Webhook Retries**: Limited to 2 retries with short timeout