insforge 0.3.3 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (635) hide show
  1. package/.claude-plugin/marketplace.json +20 -0
  2. package/.dockerignore +60 -57
  3. package/.env.example +84 -49
  4. package/.github/ISSUE_TEMPLATE/bug_report.yml +36 -83
  5. package/.github/ISSUE_TEMPLATE/config.yml +11 -11
  6. package/.github/ISSUE_TEMPLATE/feature_request.yml +26 -79
  7. package/.github/PULL_REQUEST_TEMPLATE.md +7 -0
  8. package/.github/copilot-instructions.md +146 -146
  9. package/.github/workflows/build-image.yml +66 -65
  10. package/.github/workflows/ci-premerge-check.yml +23 -23
  11. package/.github/workflows/e2e.yml +63 -0
  12. package/.github/workflows/lint-and-format.yml +32 -32
  13. package/.prettierignore +64 -64
  14. package/CHANGELOG.md +44 -3
  15. package/CLAUDE_PLUGIN.md +104 -0
  16. package/CODE_OF_CONDUCT.md +128 -0
  17. package/CONTRIBUTING.md +125 -125
  18. package/Dockerfile +30 -27
  19. package/GITHUB_OAUTH_SETUP.md +49 -49
  20. package/GOOGLE_OAUTH_SETUP.md +148 -148
  21. package/LICENSE +201 -201
  22. package/README.md +182 -134
  23. package/assets/Dark.svg +23 -23
  24. package/assets/mcpInstallv2.png +0 -0
  25. package/assets/sampleResponse.png +0 -0
  26. package/auth/index.html +13 -0
  27. package/auth/package.json +28 -0
  28. package/auth/public/favicon.ico +0 -0
  29. package/auth/src/App.tsx +33 -0
  30. package/auth/src/components/ErrorCard.tsx +37 -0
  31. package/auth/src/components/Layout.tsx +13 -0
  32. package/auth/src/index.css +19 -0
  33. package/auth/src/lib/broadcastService.ts +117 -0
  34. package/auth/src/lib/utils.ts +11 -0
  35. package/auth/src/main.tsx +22 -0
  36. package/auth/src/pages/ForgotPasswordPage.tsx +11 -0
  37. package/auth/src/pages/ResetPasswordPage.tsx +11 -0
  38. package/auth/src/pages/SignInPage.tsx +60 -0
  39. package/auth/src/pages/SignUpPage.tsx +60 -0
  40. package/auth/src/pages/VerifyEmailPage.tsx +20 -0
  41. package/auth/src/vite-env.d.ts +10 -0
  42. package/auth/tsconfig.json +32 -0
  43. package/auth/tsconfig.node.json +11 -0
  44. package/auth/vite.config.ts +25 -0
  45. package/backend/package.json +78 -75
  46. package/backend/src/api/{middleware → middlewares}/auth.ts +8 -9
  47. package/backend/src/api/middlewares/rate-limiters.ts +127 -0
  48. package/backend/src/api/routes/{ai.ts → ai/index.routes.ts} +22 -26
  49. package/backend/src/api/routes/auth/index.routes.ts +667 -0
  50. package/backend/src/api/routes/auth/oauth.routes.ts +473 -0
  51. package/backend/src/api/routes/{database.advance.ts → database/advance.routes.ts} +128 -65
  52. package/backend/src/api/routes/database/index.routes.ts +90 -0
  53. package/backend/src/api/routes/{database.records.ts → database/records.routes.ts} +26 -12
  54. package/backend/src/api/routes/{database.tables.ts → database/tables.routes.ts} +6 -23
  55. package/backend/src/api/routes/docs/index.routes.ts +75 -0
  56. package/backend/src/api/routes/email/index.routes.ts +35 -0
  57. package/backend/src/api/routes/functions/index.routes.ts +194 -0
  58. package/backend/src/api/routes/{logs.ts → logs/index.routes.ts} +25 -30
  59. package/backend/src/api/routes/{metadata.ts → metadata/index.routes.ts} +33 -31
  60. package/backend/src/api/routes/realtime/channels.routes.ts +81 -0
  61. package/backend/src/api/routes/realtime/index.routes.ts +12 -0
  62. package/backend/src/api/routes/realtime/messages.routes.ts +48 -0
  63. package/backend/src/api/routes/realtime/permissions.routes.ts +19 -0
  64. package/backend/src/api/routes/{secrets.ts → secrets/index.routes.ts} +27 -22
  65. package/backend/src/api/routes/{storage.ts → storage/index.routes.ts} +48 -61
  66. package/backend/src/api/routes/usage/index.routes.ts +91 -0
  67. package/backend/src/infra/config/app.config.ts +51 -0
  68. package/backend/src/infra/database/database.manager.ts +182 -0
  69. package/backend/{migrations → src/infra/database/migrations}/000_create-base-tables.sql +141 -141
  70. package/backend/{migrations → src/infra/database/migrations}/001_create-helper-functions.sql +40 -40
  71. package/backend/{migrations → src/infra/database/migrations}/002_rename-auth-tables.sql +29 -29
  72. package/backend/{migrations → src/infra/database/migrations}/003_create-users-table.sql +55 -55
  73. package/backend/{migrations → src/infra/database/migrations}/004_add-reload-postgrest-func.sql +23 -23
  74. package/backend/{migrations → src/infra/database/migrations}/005_enable-project-admin-modify-users.sql +29 -29
  75. package/backend/{migrations → src/infra/database/migrations}/006_modify-ai-usage-table.sql +24 -24
  76. package/backend/{migrations → src/infra/database/migrations}/007_drop-metadata-table.sql +1 -1
  77. package/backend/{migrations → src/infra/database/migrations}/008_add-system-tables.sql +76 -76
  78. package/backend/{migrations → src/infra/database/migrations}/009_add-function-secrets.sql +23 -23
  79. package/backend/{migrations → src/infra/database/migrations}/010_modify-ai-config-modalities.sql +93 -93
  80. package/backend/{migrations → src/infra/database/migrations}/011_refactor-secrets-table.sql +15 -15
  81. package/backend/{migrations → src/infra/database/migrations}/012_add-storage-uploaded-by.sql +7 -7
  82. package/backend/src/infra/database/migrations/013_create-auth-schema-functions.sql +44 -0
  83. package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +8 -0
  84. package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +60 -0
  85. package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -0
  86. package/backend/src/infra/database/migrations/017_create-realtime-schema.sql +233 -0
  87. package/backend/src/infra/realtime/realtime.manager.ts +246 -0
  88. package/backend/src/infra/realtime/webhook-sender.ts +82 -0
  89. package/backend/src/{core/secrets/encryption.ts → infra/security/encryption.manager.ts} +3 -2
  90. package/backend/src/infra/security/token.manager.ts +219 -0
  91. package/backend/src/infra/socket/socket.manager.ts +522 -0
  92. package/backend/src/providers/ai/openrouter.provider.ts +380 -0
  93. package/backend/src/providers/email/base.provider.ts +38 -0
  94. package/backend/src/providers/email/cloud.provider.ts +271 -0
  95. package/backend/src/{core/logs/providers → providers/logs}/base.provider.ts +11 -11
  96. package/backend/src/{core/logs/providers → providers/logs}/cloudwatch.provider.ts +61 -38
  97. package/backend/src/providers/logs/local.provider.ts +185 -0
  98. package/backend/src/providers/oauth/apple.provider.ts +266 -0
  99. package/backend/src/providers/oauth/base.provider.ts +29 -0
  100. package/backend/src/providers/oauth/discord.provider.ts +195 -0
  101. package/backend/src/providers/oauth/facebook.provider.ts +194 -0
  102. package/backend/src/providers/oauth/github.provider.ts +208 -0
  103. package/backend/src/providers/oauth/google.provider.ts +249 -0
  104. package/backend/src/providers/oauth/index.ts +8 -0
  105. package/backend/src/providers/oauth/linkedin.provider.ts +240 -0
  106. package/backend/src/providers/oauth/microsoft.provider.ts +169 -0
  107. package/backend/src/providers/oauth/x.provider.ts +202 -0
  108. package/backend/src/providers/storage/base.provider.ts +29 -0
  109. package/backend/src/providers/storage/local.provider.ts +103 -0
  110. package/backend/src/providers/storage/s3.provider.ts +313 -0
  111. package/backend/src/server.ts +317 -288
  112. package/backend/src/{core/ai/config.ts → services/ai/ai-config.service.ts} +19 -24
  113. package/backend/src/services/ai/ai-model.service.ts +60 -0
  114. package/backend/src/{core/ai/usage.ts → services/ai/ai-usage.service.ts} +28 -35
  115. package/backend/src/{core/ai/chat.ts → services/ai/chat-completion.service.ts} +37 -24
  116. package/backend/src/services/ai/helpers.ts +64 -0
  117. package/backend/src/{core/ai/image.ts → services/ai/image-generation.service.ts} +17 -19
  118. package/backend/src/services/ai/index.ts +13 -0
  119. package/backend/src/services/auth/auth-config.service.ts +250 -0
  120. package/backend/src/services/auth/auth-otp.service.ts +424 -0
  121. package/backend/src/services/auth/auth.service.ts +1150 -0
  122. package/backend/src/services/auth/index.ts +4 -0
  123. package/backend/src/{core/auth/oauth.ts → services/auth/oauth-config.service.ts} +106 -52
  124. package/backend/src/{core/database/advance.ts → services/database/database-advance.service.ts} +97 -131
  125. package/backend/src/services/database/database-table.service.ts +802 -0
  126. package/backend/src/services/database/database.service.ts +127 -0
  127. package/backend/src/services/email/email.service.ts +73 -0
  128. package/backend/src/{core/functions/functions.ts → services/functions/function.service.ts} +95 -88
  129. package/backend/src/{core/logs/audit.ts → services/logs/audit.service.ts} +92 -75
  130. package/backend/src/services/logs/log.service.ts +73 -0
  131. package/backend/src/services/realtime/index.ts +3 -0
  132. package/backend/src/services/realtime/realtime-auth.service.ts +104 -0
  133. package/backend/src/services/realtime/realtime-channel.service.ts +237 -0
  134. package/backend/src/services/realtime/realtime-message.service.ts +260 -0
  135. package/backend/src/{core/secrets/secrets.ts → services/secrets/secret.service.ts} +48 -66
  136. package/backend/src/services/storage/storage.service.ts +617 -0
  137. package/backend/src/services/usage/usage.service.ts +149 -0
  138. package/backend/src/types/auth.ts +77 -2
  139. package/backend/src/types/email.ts +8 -0
  140. package/backend/src/types/error-constants.ts +4 -0
  141. package/backend/src/types/logs.ts +0 -29
  142. package/backend/src/types/realtime.ts +18 -0
  143. package/backend/src/{core/socket/types.ts → types/socket.ts} +11 -36
  144. package/backend/src/utils/cookies.ts +35 -0
  145. package/backend/src/utils/environment.ts +9 -3
  146. package/backend/src/utils/logger.ts +20 -2
  147. package/backend/src/utils/s3-config-loader.ts +64 -0
  148. package/backend/src/utils/seed.ts +301 -205
  149. package/backend/src/utils/sql-parser.ts +91 -1
  150. package/backend/src/utils/utils.ts +114 -0
  151. package/backend/src/utils/validations.ts +40 -4
  152. package/backend/tests/README.md +133 -133
  153. package/backend/tests/cleanup-all-test-data.sh +230 -230
  154. package/backend/tests/cloud/test-s3-multitenant.sh +131 -131
  155. package/backend/tests/local/comprehensive-curl-tests.sh +155 -155
  156. package/backend/tests/local/test-ai-config.sh +129 -0
  157. package/backend/tests/local/test-ai-usage.sh +80 -0
  158. package/backend/tests/local/test-auth-router.sh +143 -143
  159. package/backend/tests/local/test-database-router.sh +222 -222
  160. package/backend/tests/local/test-e2e.sh +240 -240
  161. package/backend/tests/local/test-fk-errors.sh +96 -96
  162. package/backend/tests/local/test-functions.sh +123 -0
  163. package/backend/tests/local/test-id-field.sh +200 -200
  164. package/backend/tests/local/test-logs.sh +132 -0
  165. package/backend/tests/local/test-public-bucket.sh +264 -264
  166. package/backend/tests/local/test-secrets.sh +249 -247
  167. package/backend/tests/local/test-serverless-functions.sh.disabled +325 -325
  168. package/backend/tests/local/test-traditional-rest.sh +208 -208
  169. package/backend/tests/manual/README.md +50 -50
  170. package/backend/tests/manual/create-large-table-simple.sql +10 -10
  171. package/backend/tests/manual/seed-large-table.sql +100 -100
  172. package/backend/tests/manual/setup-large-table-extras.sql +33 -33
  173. package/backend/tests/manual/test-bulk-upsert.sh +409 -409
  174. package/backend/tests/manual/test-database-advance.sh +296 -296
  175. package/backend/tests/manual/test-postgrest-stability.sh +191 -191
  176. package/backend/tests/manual/test-rawsql-export-import.sh +411 -411
  177. package/backend/tests/manual/test-rawsql-modes.sh +244 -0
  178. package/backend/tests/manual/test-universal-storage.sh +263 -263
  179. package/backend/tests/manual/test-users.sql +17 -17
  180. package/backend/tests/run-all-tests.sh +139 -139
  181. package/backend/tests/setup.ts +0 -0
  182. package/backend/tests/test-config.sh +338 -302
  183. package/backend/tests/unit/analyze-query.test.ts +697 -0
  184. package/backend/tests/unit/cloud-token.test.ts +48 -0
  185. package/backend/tests/unit/constant.test.ts +8 -0
  186. package/backend/tests/unit/email.test.ts +372 -0
  187. package/backend/tests/unit/environment.test.ts +59 -0
  188. package/backend/tests/unit/helpers.test.ts +63 -0
  189. package/backend/tests/unit/logger.test.ts +22 -0
  190. package/backend/tests/unit/rate-limit.test.ts +154 -0
  191. package/backend/tests/unit/response.test.ts +58 -0
  192. package/backend/tests/unit/sql-parser.test.ts +74 -0
  193. package/backend/tests/unit/uuid.test.ts +21 -0
  194. package/backend/tests/unit/validations.test.ts +80 -0
  195. package/backend/tsconfig.json +22 -22
  196. package/backend/vitest.config.ts +11 -0
  197. package/claude-plugin/.claude-plugin/plugin.json +24 -0
  198. package/claude-plugin/README.md +133 -0
  199. package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +270 -0
  200. package/docker-compose.prod.yml +204 -144
  201. package/docker-compose.yml +232 -167
  202. package/docker-init/db/db-init.sql +97 -125
  203. package/docker-init/db/jwt.sql +5 -5
  204. package/docker-init/db/postgresql.conf +16 -16
  205. package/docker-init/logs/vector.yml +236 -0
  206. package/docs/README.md +44 -0
  207. package/docs/agent-docs/real-time.md +269 -0
  208. package/docs/changelog.mdx +119 -0
  209. package/docs/core-concepts/ai/architecture.mdx +373 -0
  210. package/docs/core-concepts/ai/sdk.mdx +213 -0
  211. package/docs/core-concepts/authentication/architecture.mdx +278 -0
  212. package/docs/core-concepts/authentication/sdk.mdx +414 -0
  213. package/docs/core-concepts/authentication/ui-components/customization.mdx +529 -0
  214. package/docs/core-concepts/authentication/ui-components/nextjs.mdx +221 -0
  215. package/docs/core-concepts/authentication/ui-components/react-router.mdx +184 -0
  216. package/docs/core-concepts/authentication/ui-components/react.mdx +129 -0
  217. package/docs/core-concepts/database/architecture.mdx +256 -0
  218. package/docs/core-concepts/database/sdk.mdx +382 -0
  219. package/docs/core-concepts/email/architecture.mdx +101 -0
  220. package/docs/core-concepts/email/sdk.mdx +53 -0
  221. package/docs/core-concepts/functions/architecture.mdx +105 -0
  222. package/docs/core-concepts/functions/sdk.mdx +184 -0
  223. package/docs/core-concepts/realtime/architecture.mdx +446 -0
  224. package/docs/core-concepts/realtime/sdk.mdx +409 -0
  225. package/docs/core-concepts/storage/architecture.mdx +243 -0
  226. package/docs/core-concepts/storage/sdk.mdx +253 -0
  227. package/docs/deployment/README.md +94 -0
  228. package/docs/deployment/deploy-to-aws-ec2.md +565 -0
  229. package/docs/deployment/deploy-to-azure-virtual-machines.md +313 -0
  230. package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -0
  231. package/docs/deployment/deploy-to-render.md +441 -0
  232. package/docs/deprecated/insforge-auth-api.md +214 -214
  233. package/docs/deprecated/insforge-auth-sdk.md +99 -99
  234. package/docs/deprecated/insforge-db-api.md +358 -358
  235. package/docs/deprecated/insforge-db-sdk.md +139 -139
  236. package/docs/deprecated/insforge-debug-sdk.md +156 -156
  237. package/docs/deprecated/insforge-debug.md +64 -64
  238. package/docs/deprecated/insforge-instructions.md +123 -123
  239. package/docs/deprecated/insforge-project.md +117 -117
  240. package/docs/deprecated/insforge-storage-api.md +278 -278
  241. package/docs/deprecated/insforge-storage-sdk.md +158 -158
  242. package/docs/docs.json +232 -0
  243. package/docs/examples/framework-guides/nextjs.mdx +131 -0
  244. package/docs/examples/framework-guides/nuxt.mdx +165 -0
  245. package/docs/examples/framework-guides/react.mdx +165 -0
  246. package/docs/examples/framework-guides/svelte.mdx +153 -0
  247. package/docs/examples/framework-guides/vue.mdx +159 -0
  248. package/docs/examples/overview.mdx +67 -0
  249. package/docs/favicon.svg +19 -0
  250. package/docs/images/changelog/dec-2025/ai-integration.png +0 -0
  251. package/docs/images/changelog/dec-2025/ai-models.webp +0 -0
  252. package/docs/images/changelog/dec-2025/alipay-payment.webp +0 -0
  253. package/docs/images/changelog/dec-2025/apple-login.jpg +0 -0
  254. package/docs/images/changelog/dec-2025/mcp-installer.png +0 -0
  255. package/docs/images/changelog/dec-2025/realtime-module.jpg +0 -0
  256. package/docs/images/changelog/nov-2025/auth-components.webp +0 -0
  257. package/docs/images/changelog/nov-2025/database-metadata.webp +0 -0
  258. package/docs/images/changelog/nov-2025/quickstart-prompts.webp +0 -0
  259. package/docs/images/changelog/nov-2025/sql-editor.webp +0 -0
  260. package/docs/images/changelog/nov-2025/usage-page.webp +0 -0
  261. package/docs/images/changelog/october-2025/csv-upload.webp +0 -0
  262. package/docs/images/changelog/october-2025/logs-feature.webp +0 -0
  263. package/docs/images/changelog/october-2025/oauth-providers.webp +0 -0
  264. package/docs/images/checks-passed.png +0 -0
  265. package/docs/images/dashboard-connect-expanded.png +0 -0
  266. package/docs/images/dashboard-connect.png +0 -0
  267. package/docs/images/hero-dark.png +0 -0
  268. package/docs/images/hero-light.png +0 -0
  269. package/docs/images/icons/ai.svg +4 -0
  270. package/docs/images/icons/auth.svg +1 -0
  271. package/docs/images/icons/database.svg +1 -0
  272. package/docs/images/icons/function.svg +1 -0
  273. package/docs/images/icons/storage.svg +1 -0
  274. package/docs/images/logos/nextjs.svg +4 -0
  275. package/docs/images/logos/nuxt.svg +4 -0
  276. package/docs/images/logos/react.svg +5 -0
  277. package/docs/images/logos/svelte.svg +4 -0
  278. package/docs/images/logos/vue.svg +5 -0
  279. package/docs/images/mcp-install.png +0 -0
  280. package/docs/images/onboarding-mcp.png +0 -0
  281. package/docs/insforge-instructions-sdk.md +89 -407
  282. package/docs/introduction.mdx +45 -0
  283. package/docs/logo/dark.svg +22 -0
  284. package/docs/logo/light.svg +20 -0
  285. package/docs/partnership.mdx +652 -0
  286. package/docs/quickstart.mdx +83 -0
  287. package/docs/showcase/2048-arena.png +0 -0
  288. package/docs/showcase/framegen-cloud.png +0 -0
  289. package/docs/showcase/line-connect-race.png +0 -0
  290. package/docs/showcase/moment-vibe.png +0 -0
  291. package/docs/showcase/national-flags.png +0 -0
  292. package/docs/showcase/pokemon-vibe.png +0 -0
  293. package/docs/showcase/pure-browse-buy.png +0 -0
  294. package/docs/showcase.mdx +52 -0
  295. package/docs/snippets/sdk-installation.mdx +22 -0
  296. package/docs/snippets/service-icons.mdx +27 -0
  297. package/eslint.config.js +10 -3
  298. package/examples/oauth/frontend-oauth-example.html +250 -250
  299. package/examples/response-examples.md +443 -443
  300. package/frontend/components.json +17 -17
  301. package/frontend/package.json +69 -63
  302. package/frontend/src/App.tsx +13 -82
  303. package/frontend/src/assets/icons/checkbox_checked.svg +6 -6
  304. package/frontend/src/assets/icons/checkbox_undetermined.svg +6 -6
  305. package/frontend/src/assets/icons/checked.svg +3 -3
  306. package/frontend/src/assets/icons/connected.svg +3 -0
  307. package/frontend/src/assets/icons/error.svg +3 -3
  308. package/frontend/src/assets/icons/loader.svg +9 -0
  309. package/frontend/src/assets/icons/pencil.svg +4 -4
  310. package/frontend/src/assets/icons/refresh.svg +4 -4
  311. package/frontend/src/assets/icons/step_active.svg +3 -3
  312. package/frontend/src/assets/icons/step_inactive.svg +11 -11
  313. package/frontend/src/assets/icons/warning.svg +3 -3
  314. package/frontend/src/assets/logos/apple.svg +4 -0
  315. package/frontend/src/assets/logos/claude_code.svg +3 -3
  316. package/frontend/src/assets/logos/cline.svg +6 -6
  317. package/frontend/src/assets/logos/cursor.svg +20 -20
  318. package/frontend/src/assets/logos/discord.svg +8 -8
  319. package/frontend/src/assets/logos/facebook.svg +3 -0
  320. package/frontend/src/assets/logos/gemini.svg +19 -19
  321. package/frontend/src/assets/logos/github.svg +5 -5
  322. package/frontend/src/assets/logos/google.svg +13 -13
  323. package/frontend/src/assets/logos/grok.svg +10 -10
  324. package/frontend/src/assets/logos/insforge_dark.svg +15 -15
  325. package/frontend/src/assets/logos/insforge_light.svg +15 -15
  326. package/frontend/src/assets/logos/instagram.svg +2 -0
  327. package/frontend/src/assets/logos/linkedin.svg +3 -0
  328. package/frontend/src/assets/logos/microsoft.svg +1 -0
  329. package/frontend/src/assets/logos/openai.svg +10 -10
  330. package/frontend/src/assets/logos/roo_code.svg +9 -9
  331. package/frontend/src/assets/logos/spotify.svg +17 -0
  332. package/frontend/src/assets/logos/tiktok.svg +6 -0
  333. package/frontend/src/assets/logos/trae.svg +3 -3
  334. package/frontend/src/assets/logos/windsurf.svg +10 -10
  335. package/frontend/src/assets/logos/x.svg +3 -0
  336. package/frontend/src/components/Checkbox.tsx +27 -29
  337. package/frontend/src/components/CodeBlock.tsx +55 -2
  338. package/frontend/src/components/CodeEditor.tsx +92 -0
  339. package/frontend/src/components/ConfirmDialog.tsx +1 -1
  340. package/frontend/src/components/ConnectCTA.tsx +38 -0
  341. package/frontend/src/components/CopyButton.tsx +52 -15
  342. package/frontend/src/components/ErrorState.tsx +1 -2
  343. package/frontend/src/components/FeatureSidebar.tsx +6 -6
  344. package/frontend/src/components/FeatureSidebarItem.tsx +2 -2
  345. package/frontend/src/components/JsonHighlight.tsx +21 -9
  346. package/frontend/src/components/ProjectInfoModal.tsx +128 -0
  347. package/frontend/src/components/PromptDialog.tsx +1 -4
  348. package/frontend/src/components/SearchInput.tsx +1 -2
  349. package/frontend/src/components/Stepper.tsx +53 -0
  350. package/frontend/src/components/ThemeToggle.tsx +3 -3
  351. package/frontend/src/components/datagrid/DataGrid.tsx +25 -32
  352. package/frontend/src/components/datagrid/cell-editors/DateCellEditor.tsx +1 -2
  353. package/frontend/src/components/datagrid/cell-editors/JsonCellEditor.tsx +2 -4
  354. package/frontend/src/components/datagrid/index.ts +23 -0
  355. package/frontend/src/components/index.ts +23 -30
  356. package/frontend/src/components/layout/AppHeader.tsx +131 -91
  357. package/frontend/src/components/layout/AppSidebar.tsx +80 -170
  358. package/frontend/src/components/layout/Layout.tsx +12 -23
  359. package/frontend/src/components/layout/PrimaryMenu.tsx +187 -0
  360. package/frontend/src/components/layout/SecondaryMenu.tsx +70 -0
  361. package/frontend/src/components/layout/index.ts +5 -0
  362. package/frontend/src/components/radix/Tooltip.tsx +24 -13
  363. package/frontend/src/components/radix/index.ts +22 -0
  364. package/frontend/src/features/ai/components/AIConfigCard.tsx +129 -83
  365. package/frontend/src/features/ai/components/AIEmptyState.tsx +12 -7
  366. package/frontend/src/features/ai/components/ModalityFilterSidebar.tsx +101 -0
  367. package/frontend/src/features/ai/components/ModelSelectionDialog.tsx +135 -0
  368. package/frontend/src/features/ai/components/ModelSelectionGrid.tsx +51 -0
  369. package/frontend/src/features/ai/components/SystemPromptDialog.tsx +118 -0
  370. package/frontend/src/features/ai/components/index.ts +6 -0
  371. package/frontend/src/features/ai/helpers.ts +57 -71
  372. package/frontend/src/features/ai/hooks/useAIConfigs.ts +39 -113
  373. package/frontend/src/features/ai/hooks/useAIUsage.ts +0 -2
  374. package/frontend/src/features/ai/pages/AIPage.tsx +166 -0
  375. package/frontend/src/features/ai/services/ai.service.ts +5 -5
  376. package/frontend/src/features/auth/components/AuthPreview.tsx +96 -0
  377. package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +54 -30
  378. package/frontend/src/features/auth/components/UserFormDialog.tsx +13 -6
  379. package/frontend/src/features/auth/components/UsersDataGrid.tsx +50 -14
  380. package/frontend/src/features/auth/components/index.ts +5 -0
  381. package/frontend/src/features/auth/helpers.tsx +208 -0
  382. package/frontend/src/features/auth/hooks/useAnonToken.ts +30 -0
  383. package/frontend/src/features/auth/hooks/useAuthConfig.ts +48 -0
  384. package/frontend/src/features/auth/hooks/useOAuthConfig.ts +14 -10
  385. package/frontend/src/features/auth/hooks/useUsers.ts +43 -5
  386. package/frontend/src/features/auth/index.ts +3 -2
  387. package/frontend/src/features/auth/pages/AuthMethodsPage.tsx +275 -0
  388. package/frontend/src/features/auth/pages/ConfigurationPage.tsx +395 -0
  389. package/frontend/src/features/auth/pages/UsersPage.tsx +257 -0
  390. package/frontend/src/features/auth/services/anonToken.service.ts +11 -0
  391. package/frontend/src/features/auth/services/config.service.ts +19 -0
  392. package/frontend/src/features/auth/services/{oauth.service.ts → oauth-config.service.ts} +4 -4
  393. package/frontend/src/features/auth/services/{auth.service.ts → user.service.ts} +7 -53
  394. package/frontend/src/features/dashboard/components/ConnectionSuccessBanner.tsx +35 -0
  395. package/frontend/src/features/dashboard/components/PromptCard.tsx +21 -0
  396. package/frontend/src/features/dashboard/components/PromptDialog.tsx +103 -0
  397. package/frontend/src/features/dashboard/components/StatsCard.tsx +50 -0
  398. package/frontend/src/features/dashboard/components/index.ts +4 -0
  399. package/frontend/src/features/dashboard/pages/DashboardPage.tsx +212 -0
  400. package/frontend/src/features/dashboard/prompts/ai-chatbot.ts +13 -0
  401. package/frontend/src/features/dashboard/prompts/crm-system.ts +13 -0
  402. package/frontend/src/features/dashboard/prompts/ecommerce-platform.ts +12 -0
  403. package/frontend/src/features/dashboard/prompts/index.ts +31 -0
  404. package/frontend/src/features/dashboard/prompts/instagram-clone.ts +11 -0
  405. package/frontend/src/features/dashboard/prompts/notion-clone.ts +14 -0
  406. package/frontend/src/features/dashboard/prompts/reddit-clone.ts +12 -0
  407. package/frontend/src/features/database/components/DatabaseDataGrid.tsx +48 -17
  408. package/frontend/src/features/database/components/ForeignKeyCell.tsx +15 -34
  409. package/frontend/src/features/database/components/ForeignKeyPopover.tsx +19 -20
  410. package/frontend/src/features/database/components/LinkRecordModal.tsx +120 -125
  411. package/frontend/src/features/database/components/RecordFormDialog.tsx +22 -33
  412. package/frontend/src/features/database/components/RecordFormField.tsx +45 -47
  413. package/frontend/src/features/database/components/SQLModal.tsx +75 -0
  414. package/frontend/src/features/database/components/TableEmptyState.tsx +6 -5
  415. package/frontend/src/features/database/components/TableForm.tsx +28 -19
  416. package/frontend/src/features/database/components/TableFormColumn.tsx +2 -3
  417. package/frontend/src/features/database/components/TableSidebar.tsx +1 -1
  418. package/frontend/src/features/database/components/TablesEmptyState.tsx +48 -0
  419. package/frontend/src/features/database/components/TemplateCard.tsx +37 -0
  420. package/frontend/src/features/database/components/TemplatePreview.tsx +92 -0
  421. package/frontend/src/features/database/components/index.ts +19 -0
  422. package/frontend/src/features/database/constants.ts +28 -2
  423. package/frontend/src/features/database/contexts/SQLEditorContext.tsx +188 -0
  424. package/frontend/src/features/database/helpers.ts +2 -2
  425. package/frontend/src/features/database/hooks/useCSVImport.ts +29 -0
  426. package/frontend/src/features/database/hooks/useDatabase.ts +66 -0
  427. package/frontend/src/features/database/hooks/useRawSQL.ts +55 -0
  428. package/frontend/src/features/database/hooks/useRecords.ts +139 -0
  429. package/frontend/src/features/database/hooks/useTables.ts +135 -0
  430. package/frontend/src/features/database/index.ts +7 -1
  431. package/frontend/src/features/database/pages/FunctionsPage.tsx +203 -0
  432. package/frontend/src/features/database/pages/IndexesPage.tsx +228 -0
  433. package/frontend/src/features/database/pages/PoliciesPage.tsx +237 -0
  434. package/frontend/src/features/database/pages/SQLEditorPage.tsx +382 -0
  435. package/frontend/src/features/database/{page/DatabasePage.tsx → pages/TablesPage.tsx} +168 -209
  436. package/frontend/src/features/database/pages/TemplatesPage.tsx +39 -0
  437. package/frontend/src/features/database/pages/TriggersPage.tsx +230 -0
  438. package/frontend/src/features/database/services/advance.service.ts +40 -0
  439. package/frontend/src/features/database/services/database.service.ts +33 -194
  440. package/frontend/src/features/database/services/record.service.ts +219 -0
  441. package/frontend/src/features/database/services/table.service.ts +58 -0
  442. package/frontend/src/features/database/templates/ai-chatbot.ts +402 -0
  443. package/frontend/src/features/database/templates/crm-system.ts +528 -0
  444. package/frontend/src/features/database/templates/ecommerce-platform.ts +553 -0
  445. package/frontend/src/features/database/templates/index.ts +34 -0
  446. package/frontend/src/features/database/templates/instagram-clone.ts +222 -0
  447. package/frontend/src/features/database/templates/notion-clone.ts +483 -0
  448. package/frontend/src/features/database/templates/reddit-clone.ts +526 -0
  449. package/frontend/src/features/functions/components/FunctionRow.tsx +2 -1
  450. package/frontend/src/features/functions/components/FunctionsSidebar.tsx +1 -1
  451. package/frontend/src/features/functions/components/SecretRow.tsx +1 -1
  452. package/frontend/src/features/functions/components/index.ts +5 -0
  453. package/frontend/src/features/functions/hooks/useFunctions.ts +4 -4
  454. package/frontend/src/features/{secrets → functions}/hooks/useSecrets.ts +5 -5
  455. package/frontend/src/features/functions/pages/FunctionsPage.tsx +148 -0
  456. package/frontend/src/features/functions/{components/SecretsContent.tsx → pages/SecretsPage.tsx} +19 -21
  457. package/frontend/src/features/functions/services/{functions.service.ts → function.service.ts} +2 -2
  458. package/frontend/src/features/{secrets/services/secrets.service.ts → functions/services/secret.service.ts} +2 -2
  459. package/frontend/src/features/login/hooks/usePartnerOrigin.ts +27 -0
  460. package/frontend/src/features/login/pages/CloudLoginPage.tsx +118 -0
  461. package/frontend/src/features/login/{page → pages}/LoginPage.tsx +16 -23
  462. package/frontend/src/features/login/services/partnership.service.ts +65 -0
  463. package/frontend/src/features/logs/components/LogsDataGrid.tsx +89 -0
  464. package/frontend/src/features/logs/components/SeverityBadge.tsx +18 -0
  465. package/frontend/src/features/logs/components/index.ts +2 -0
  466. package/frontend/src/features/logs/helpers.ts +24 -0
  467. package/frontend/src/features/logs/hooks/useAuditLogs.ts +4 -4
  468. package/frontend/src/features/logs/hooks/useLogSources.ts +137 -0
  469. package/frontend/src/features/logs/hooks/useLogs.ts +163 -0
  470. package/frontend/src/features/logs/hooks/useMcpUsage.ts +128 -0
  471. package/frontend/src/features/logs/index.ts +8 -2
  472. package/frontend/src/features/logs/{page → pages}/AuditsPage.tsx +91 -38
  473. package/frontend/src/features/logs/pages/LogsPage.tsx +152 -0
  474. package/frontend/src/features/logs/pages/MCPLogsPage.tsx +84 -0
  475. package/frontend/src/features/logs/services/audit.service.ts +63 -0
  476. package/frontend/src/features/logs/services/log.service.ts +15 -110
  477. package/frontend/src/features/logs/services/usage.service.ts +31 -0
  478. package/frontend/src/features/onboard/components/McpConnectionStatus.tsx +68 -0
  479. package/frontend/src/features/onboard/components/OnboardingModal.tsx +267 -0
  480. package/frontend/src/features/onboard/components/VideoDemoModal.tsx +38 -0
  481. package/frontend/src/features/onboard/components/index.ts +4 -0
  482. package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +2 -2
  483. package/frontend/src/features/onboard/components/mcp/{mcp-helper.tsx → helpers.tsx} +8 -8
  484. package/frontend/src/features/onboard/components/mcp/index.ts +2 -3
  485. package/frontend/src/features/onboard/index.ts +13 -3
  486. package/frontend/src/features/realtime/components/ChannelRow.tsx +83 -0
  487. package/frontend/src/features/realtime/components/EditChannelModal.tsx +246 -0
  488. package/frontend/src/features/realtime/components/MessageRow.tsx +85 -0
  489. package/frontend/src/features/realtime/components/RealtimeEmptyState.tsx +30 -0
  490. package/frontend/src/features/realtime/hooks/useRealtime.ts +218 -0
  491. package/frontend/src/features/realtime/index.ts +11 -0
  492. package/frontend/src/features/realtime/pages/RealtimeChannelsPage.tsx +172 -0
  493. package/frontend/src/features/realtime/pages/RealtimeMessagesPage.tsx +211 -0
  494. package/frontend/src/features/realtime/pages/RealtimePermissionsPage.tsx +191 -0
  495. package/frontend/src/features/realtime/services/realtime.service.ts +107 -0
  496. package/frontend/src/features/storage/components/BucketEmptyState.tsx +9 -6
  497. package/frontend/src/features/storage/components/BucketFormDialog.tsx +25 -41
  498. package/frontend/src/features/storage/components/FilePreviewDialog.tsx +20 -8
  499. package/frontend/src/features/storage/components/StorageDataGrid.tsx +4 -3
  500. package/frontend/src/features/storage/components/StorageManager.tsx +23 -34
  501. package/frontend/src/features/storage/components/index.ts +12 -0
  502. package/frontend/src/features/storage/hooks/useStorage.ts +208 -0
  503. package/frontend/src/features/storage/{page → pages}/StoragePage.tsx +41 -143
  504. package/frontend/src/features/storage/services/storage.service.ts +22 -1
  505. package/frontend/src/features/visualizer/components/AuthNode.tsx +72 -56
  506. package/frontend/src/features/visualizer/components/BucketNode.tsx +4 -4
  507. package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +108 -80
  508. package/frontend/src/features/visualizer/components/TableNode.tsx +34 -41
  509. package/frontend/src/features/visualizer/components/VisualizerSkeleton.tsx +12 -4
  510. package/frontend/src/features/visualizer/pages/VisualizerPage.tsx +97 -0
  511. package/frontend/src/index.css +1 -0
  512. package/frontend/src/lib/analytics/posthog.tsx +27 -0
  513. package/frontend/src/lib/contexts/AuthContext.tsx +38 -31
  514. package/frontend/src/lib/contexts/SocketContext.tsx +123 -80
  515. package/frontend/src/{features/metadata → lib}/hooks/useMetadata.ts +1 -1
  516. package/frontend/src/lib/hooks/useToast.tsx +6 -2
  517. package/frontend/src/lib/routing/AppRoutes.tsx +99 -0
  518. package/frontend/src/lib/routing/RequireAuth.tsx +27 -0
  519. package/frontend/src/lib/utils/cloudMessaging.ts +20 -0
  520. package/frontend/src/lib/utils/menuItems.ts +207 -0
  521. package/frontend/src/lib/utils/{validation-schemas.ts → schemaValidations.ts} +10 -5
  522. package/frontend/src/lib/utils/utils.ts +32 -1
  523. package/frontend/src/vite-env.d.ts +1 -0
  524. package/frontend/tsconfig.json +25 -25
  525. package/frontend/tsconfig.node.json +9 -9
  526. package/frontend/vite.config.ts +5 -3
  527. package/functions/deno.json +24 -24
  528. package/functions/server.ts +315 -290
  529. package/functions/worker-template.js +15 -4
  530. package/i18n/README.ar.md +130 -0
  531. package/i18n/README.de.md +130 -0
  532. package/i18n/README.es.md +154 -0
  533. package/i18n/README.fr.md +134 -0
  534. package/i18n/README.hi.md +129 -0
  535. package/i18n/README.ja.md +174 -0
  536. package/i18n/README.ko.md +137 -0
  537. package/i18n/README.pt-BR.md +131 -0
  538. package/i18n/README.ru.md +129 -0
  539. package/i18n/README.zh-CN.md +133 -0
  540. package/openapi/ai.yaml +715 -688
  541. package/openapi/auth.yaml +1244 -563
  542. package/openapi/email.yaml +158 -0
  543. package/openapi/functions.yaml +475 -475
  544. package/openapi/health.yaml +29 -29
  545. package/openapi/logs.yaml +223 -223
  546. package/openapi/metadata.yaml +177 -177
  547. package/openapi/realtime.yaml +699 -0
  548. package/openapi/records.yaml +381 -381
  549. package/openapi/secrets.yaml +370 -370
  550. package/openapi/storage.yaml +875 -875
  551. package/openapi/tables.yaml +463 -463
  552. package/package.json +97 -88
  553. package/shared-schemas/package.json +31 -31
  554. package/shared-schemas/src/ai-api.schema.ts +34 -58
  555. package/shared-schemas/src/ai.schema.ts +63 -54
  556. package/shared-schemas/src/auth-api.schema.ts +352 -193
  557. package/shared-schemas/src/auth.schema.ts +43 -7
  558. package/shared-schemas/src/cloud-events.schema.ts +57 -0
  559. package/shared-schemas/src/database-api.schema.ts +35 -4
  560. package/shared-schemas/src/database.schema.ts +40 -1
  561. package/shared-schemas/src/docs.schema.ts +26 -0
  562. package/shared-schemas/src/email-api.schema.ts +30 -0
  563. package/shared-schemas/src/index.ts +5 -0
  564. package/shared-schemas/src/logs-api.schema.ts +7 -1
  565. package/shared-schemas/src/logs.schema.ts +26 -0
  566. package/shared-schemas/src/metadata.schema.ts +18 -4
  567. package/shared-schemas/src/realtime-api.schema.ts +111 -0
  568. package/shared-schemas/src/realtime.schema.ts +143 -0
  569. package/shared-schemas/tsconfig.json +21 -21
  570. package/tsconfig.json +7 -7
  571. package/zeabur/README.md +13 -0
  572. package/zeabur/template.yml +1032 -0
  573. package/.github/workflows/deploy-aws.yml +0 -130
  574. package/backend/src/api/routes/agent.ts +0 -29
  575. package/backend/src/api/routes/auth.oauth.ts +0 -482
  576. package/backend/src/api/routes/auth.ts +0 -386
  577. package/backend/src/api/routes/docs.ts +0 -66
  578. package/backend/src/api/routes/functions.ts +0 -183
  579. package/backend/src/api/routes/openapi.ts +0 -82
  580. package/backend/src/api/routes/usage.ts +0 -96
  581. package/backend/src/core/ai/client.ts +0 -242
  582. package/backend/src/core/ai/model.ts +0 -117
  583. package/backend/src/core/auth/auth.ts +0 -780
  584. package/backend/src/core/database/manager.ts +0 -178
  585. package/backend/src/core/database/table.ts +0 -772
  586. package/backend/src/core/documentation/agent.ts +0 -689
  587. package/backend/src/core/documentation/openapi.ts +0 -856
  588. package/backend/src/core/logs/analytics.ts +0 -76
  589. package/backend/src/core/logs/providers/localdb.provider.ts +0 -246
  590. package/backend/src/core/socket/socket.ts +0 -388
  591. package/backend/src/core/storage/storage.ts +0 -923
  592. package/backend/src/utils/cloud-token.ts +0 -39
  593. package/backend/src/utils/helpers.ts +0 -49
  594. package/backend/src/utils/uuid.ts +0 -9
  595. package/backend/tests/manual/test-better-auth.sh +0 -303
  596. package/docker-init/db/logs.sql +0 -9
  597. package/frontend/README.md +0 -112
  598. package/frontend/src/components/datagrid/index.tsx +0 -20
  599. package/frontend/src/components/layout/CloudLayout.tsx +0 -95
  600. package/frontend/src/features/ai/components/AIConfigDialog.tsx +0 -76
  601. package/frontend/src/features/ai/components/AIConfigForm.tsx +0 -222
  602. package/frontend/src/features/ai/components/fields/ModalityField.tsx +0 -87
  603. package/frontend/src/features/ai/components/fields/ModelSelectionField.tsx +0 -134
  604. package/frontend/src/features/ai/components/fields/SystemPromptField.tsx +0 -33
  605. package/frontend/src/features/ai/page/AIPage.tsx +0 -178
  606. package/frontend/src/features/auth/components/AddOAuthDialog.tsx +0 -106
  607. package/frontend/src/features/auth/components/AuthMethodTab.tsx +0 -238
  608. package/frontend/src/features/auth/components/UsersTab.tsx +0 -114
  609. package/frontend/src/features/auth/page/AuthenticationPage.tsx +0 -169
  610. package/frontend/src/features/dashboard/page/DashboardPage.tsx +0 -194
  611. package/frontend/src/features/database/hooks/UseLinkModal.tsx +0 -78
  612. package/frontend/src/features/functions/components/FunctionViewer.tsx +0 -46
  613. package/frontend/src/features/functions/components/FunctionsContent.tsx +0 -88
  614. package/frontend/src/features/functions/page/FunctionsPage.tsx +0 -28
  615. package/frontend/src/features/login/components/AuthErrorBoundary.tsx +0 -87
  616. package/frontend/src/features/login/components/PrivateRoute.tsx +0 -24
  617. package/frontend/src/features/login/page/CloudLoginPage.tsx +0 -93
  618. package/frontend/src/features/logs/components/AnalyticsLogsTable.tsx +0 -313
  619. package/frontend/src/features/logs/components/LogsTable.tsx +0 -199
  620. package/frontend/src/features/logs/page/AnalyticsLogsPage.tsx +0 -530
  621. package/frontend/src/features/metadata/index.ts +0 -0
  622. package/frontend/src/features/metadata/page/MetadataPage.tsx +0 -136
  623. package/frontend/src/features/onboard/components/CompletionCard.tsx +0 -41
  624. package/frontend/src/features/onboard/components/OnboardButton.tsx +0 -84
  625. package/frontend/src/features/onboard/components/StepContent.tsx +0 -91
  626. package/frontend/src/features/onboard/components/TestConnectionStep.tsx +0 -53
  627. package/frontend/src/features/onboard/components/mcp/McpInstallation.tsx +0 -144
  628. package/frontend/src/features/onboard/page/OnBoardPage.tsx +0 -104
  629. package/frontend/src/features/onboard/types.ts +0 -8
  630. package/frontend/src/features/visualizer/page/VisualizerPage.tsx +0 -127
  631. package/frontend/src/lib/contexts/OnboardStepContext.tsx +0 -68
  632. package/frontend/src/lib/hooks/useOnboardingCompletion.ts +0 -29
  633. /package/backend/src/api/{middleware → middlewares}/error.ts +0 -0
  634. /package/backend/src/api/{middleware → middlewares}/upload.ts +0 -0
  635. /package/frontend/src/{features/metadata → lib}/services/metadata.service.ts +0 -0
@@ -1,20 +1,26 @@
1
- import { DatabaseManager } from '@/core/database/manager.js';
1
+ import { Pool } from 'pg';
2
+ import { DatabaseManager } from '@/infra/database/database.manager.js';
2
3
  import logger from '@/utils/logger.js';
3
- import { AppError } from '@/api/middleware/error.js';
4
+ import { AppError } from '@/api/middlewares/error.js';
4
5
  import { ERROR_CODES } from '@/types/error-constants.js';
5
6
  import type { AuditLogEntry, AuditLogQuery } from '@/types/logs.js';
6
7
  import { AuditLogSchema, GetAuditLogStatsResponse } from '@insforge/shared-schemas';
7
8
 
8
9
  export class AuditService {
9
10
  private static instance: AuditService;
10
- private db: ReturnType<DatabaseManager['getDb']>;
11
+ private pool: Pool | null = null;
11
12
 
12
13
  private constructor() {
13
- const dbManager = DatabaseManager.getInstance();
14
- this.db = dbManager.getDb();
15
14
  logger.info('AuditService initialized');
16
15
  }
17
16
 
17
+ private getPool(): Pool {
18
+ if (!this.pool) {
19
+ this.pool = DatabaseManager.getInstance().getPool();
20
+ }
21
+ return this.pool;
22
+ }
23
+
18
24
  public static getInstance(): AuditService {
19
25
  if (!AuditService.instance) {
20
26
  AuditService.instance = new AuditService();
@@ -27,19 +33,21 @@ export class AuditService {
27
33
  */
28
34
  async log(entry: AuditLogEntry): Promise<AuditLogSchema> {
29
35
  try {
30
- const result = await this.db
31
- .prepare(
32
- `INSERT INTO _audit_logs (actor, action, module, details, ip_address)
33
- VALUES ($1, $2, $3, $4, $5)
34
- RETURNING *`
35
- )
36
- .get(
36
+ const pool = this.getPool();
37
+ const result = await pool.query(
38
+ `INSERT INTO _audit_logs (actor, action, module, details, ip_address)
39
+ VALUES ($1, $2, $3, $4, $5)
40
+ RETURNING *`,
41
+ [
37
42
  entry.actor,
38
43
  entry.action,
39
44
  entry.module,
40
45
  entry.details ? JSON.stringify(entry.details) : null,
41
- entry.ip_address || null
42
- );
46
+ entry.ip_address || null,
47
+ ]
48
+ );
49
+
50
+ const row = result.rows[0];
43
51
 
44
52
  logger.info('Audit log created', {
45
53
  actor: entry.actor,
@@ -48,14 +56,14 @@ export class AuditService {
48
56
  });
49
57
 
50
58
  return {
51
- id: result.id,
52
- actor: result.actor,
53
- action: result.action,
54
- module: result.module,
55
- details: result.details,
56
- ipAddress: result.ip_address,
57
- createdAt: result.created_at,
58
- updatedAt: result.updated_at,
59
+ id: row.id,
60
+ actor: row.actor,
61
+ action: row.action,
62
+ module: row.module,
63
+ details: row.details,
64
+ ipAddress: row.ip_address,
65
+ createdAt: row.created_at,
66
+ updatedAt: row.updated_at,
59
67
  };
60
68
  } catch (error) {
61
69
  logger.error('Failed to create audit log', error);
@@ -68,6 +76,8 @@ export class AuditService {
68
76
  */
69
77
  async query(query: AuditLogQuery): Promise<{ records: AuditLogSchema[]; total: number }> {
70
78
  try {
79
+ const pool = this.getPool();
80
+
71
81
  // Build base WHERE clause
72
82
  let whereClause = 'WHERE 1=1';
73
83
  const params: unknown[] = [];
@@ -100,8 +110,8 @@ export class AuditService {
100
110
 
101
111
  // Get total count first
102
112
  const countSql = `SELECT COUNT(*) as count FROM _audit_logs ${whereClause}`;
103
- const countResult = (await this.db.prepare(countSql).get(...params)) as { count: number };
104
- const total = countResult.count;
113
+ const countResult = await pool.query(countSql, params);
114
+ const total = parseInt(countResult.rows[0].count, 10);
105
115
 
106
116
  // Get paginated records
107
117
  let dataSql = `SELECT * FROM _audit_logs ${whereClause} ORDER BY created_at DESC`;
@@ -117,10 +127,10 @@ export class AuditService {
117
127
  dataParams.push(query.offset);
118
128
  }
119
129
 
120
- const records = await this.db.prepare(dataSql).all(...dataParams);
130
+ const dataResult = await pool.query(dataSql, dataParams);
121
131
 
122
132
  return {
123
- records: records.map((record) => ({
133
+ records: dataResult.rows.map((record) => ({
124
134
  id: record.id,
125
135
  actor: record.actor,
126
136
  action: record.action,
@@ -143,18 +153,21 @@ export class AuditService {
143
153
  */
144
154
  async getById(id: string): Promise<AuditLogSchema | null> {
145
155
  try {
146
- const result = await this.db.prepare('SELECT * FROM _audit_logs WHERE id = $1').get(id);
156
+ const pool = this.getPool();
157
+ const result = await pool.query('SELECT * FROM _audit_logs WHERE id = $1', [id]);
158
+
159
+ const row = result.rows[0];
147
160
 
148
- return result
161
+ return row
149
162
  ? {
150
- id: result.id,
151
- actor: result.actor,
152
- action: result.action,
153
- module: result.module,
154
- details: result.details,
155
- ipAddress: result.ip_address,
156
- createdAt: result.created_at,
157
- updatedAt: result.updated_at,
163
+ id: row.id,
164
+ actor: row.actor,
165
+ action: row.action,
166
+ module: row.module,
167
+ details: row.details,
168
+ ipAddress: row.ip_address,
169
+ createdAt: row.created_at,
170
+ updatedAt: row.updated_at,
158
171
  }
159
172
  : null;
160
173
  } catch (error) {
@@ -168,50 +181,52 @@ export class AuditService {
168
181
  */
169
182
  async getStats(days: number = 7): Promise<GetAuditLogStatsResponse> {
170
183
  try {
184
+ const pool = this.getPool();
171
185
  const startDate = new Date();
172
186
  startDate.setDate(startDate.getDate() - days);
173
187
 
174
- const [totalLogs] = await this.db
175
- .prepare('SELECT COUNT(*) as count FROM _audit_logs WHERE created_at >= $1')
176
- .get(startDate.toISOString());
177
-
178
- const [uniqueActors] = await this.db
179
- .prepare('SELECT COUNT(DISTINCT actor) as count FROM _audit_logs WHERE created_at >= $1')
180
- .get(startDate.toISOString());
181
-
182
- const [uniqueModules] = await this.db
183
- .prepare('SELECT COUNT(DISTINCT module) as count FROM _audit_logs WHERE created_at >= $1')
184
- .get(startDate.toISOString());
185
-
186
- const actionsByModule = await this.db
187
- .prepare(
188
- `SELECT module, COUNT(*) as count
189
- FROM _audit_logs
190
- WHERE created_at >= $1
191
- GROUP BY module`
192
- )
193
- .all(startDate.toISOString());
194
-
195
- const recentActivity = await this.db
196
- .prepare(
197
- `SELECT * FROM _audit_logs
198
- WHERE created_at >= $1
199
- ORDER BY created_at DESC
200
- LIMIT 10`
201
- )
202
- .all(startDate.toISOString());
188
+ const totalLogsResult = await pool.query(
189
+ 'SELECT COUNT(*) as count FROM _audit_logs WHERE created_at >= $1',
190
+ [startDate.toISOString()]
191
+ );
192
+
193
+ const uniqueActorsResult = await pool.query(
194
+ 'SELECT COUNT(DISTINCT actor) as count FROM _audit_logs WHERE created_at >= $1',
195
+ [startDate.toISOString()]
196
+ );
197
+
198
+ const uniqueModulesResult = await pool.query(
199
+ 'SELECT COUNT(DISTINCT module) as count FROM _audit_logs WHERE created_at >= $1',
200
+ [startDate.toISOString()]
201
+ );
202
+
203
+ const actionsByModuleResult = await pool.query(
204
+ `SELECT module, COUNT(*) as count
205
+ FROM _audit_logs
206
+ WHERE created_at >= $1
207
+ GROUP BY module`,
208
+ [startDate.toISOString()]
209
+ );
210
+
211
+ const recentActivityResult = await pool.query(
212
+ `SELECT * FROM _audit_logs
213
+ WHERE created_at >= $1
214
+ ORDER BY created_at DESC
215
+ LIMIT 10`,
216
+ [startDate.toISOString()]
217
+ );
203
218
 
204
219
  const moduleStats: Record<string, number> = {};
205
- actionsByModule.forEach((row: { module: string; count: string }) => {
206
- moduleStats[row.module] = parseInt(row.count);
220
+ actionsByModuleResult.rows.forEach((row: { module: string; count: string }) => {
221
+ moduleStats[row.module] = parseInt(row.count, 10);
207
222
  });
208
223
 
209
224
  return {
210
- totalLogs: parseInt(totalLogs?.count || 0),
211
- uniqueActors: parseInt(uniqueActors?.count || 0),
212
- uniqueModules: parseInt(uniqueModules?.count || 0),
225
+ totalLogs: parseInt(totalLogsResult.rows[0]?.count || '0', 10),
226
+ uniqueActors: parseInt(uniqueActorsResult.rows[0]?.count || '0', 10),
227
+ uniqueModules: parseInt(uniqueModulesResult.rows[0]?.count || '0', 10),
213
228
  actionsByModule: moduleStats,
214
- recentActivity: recentActivity.map((record) => ({
229
+ recentActivity: recentActivityResult.rows.map((record) => ({
215
230
  id: record.id,
216
231
  actor: record.actor,
217
232
  action: record.action,
@@ -233,14 +248,16 @@ export class AuditService {
233
248
  */
234
249
  async cleanup(daysToKeep: number = 90): Promise<number> {
235
250
  try {
251
+ const pool = this.getPool();
236
252
  const cutoffDate = new Date();
237
253
  cutoffDate.setDate(cutoffDate.getDate() - daysToKeep);
238
254
 
239
- const result = await this.db
240
- .prepare('DELETE FROM _audit_logs WHERE created_at < $1 RETURNING id')
241
- .all(cutoffDate.toISOString());
255
+ const result = await pool.query(
256
+ 'DELETE FROM _audit_logs WHERE created_at < $1 RETURNING id',
257
+ [cutoffDate.toISOString()]
258
+ );
242
259
 
243
- const deletedCount = result.length;
260
+ const deletedCount = result.rows.length;
244
261
 
245
262
  if (deletedCount > 0) {
246
263
  logger.info(`Cleaned up ${deletedCount} audit logs older than ${daysToKeep} days`);
@@ -0,0 +1,73 @@
1
+ import logger from '@/utils/logger.js';
2
+ import { CloudWatchProvider } from '@/providers/logs/cloudwatch.provider.js';
3
+ import { LocalFileProvider } from '@/providers/logs/local.provider.js';
4
+ import { LogProvider } from '@/providers/logs/base.provider.js';
5
+ import { LogSchema, LogSourceSchema, LogStatsSchema } from '@insforge/shared-schemas';
6
+ import { isCloudEnvironment } from '@/utils/environment.js';
7
+
8
+ export class LogService {
9
+ private static instance: LogService;
10
+ private provider!: LogProvider;
11
+
12
+ private constructor() {}
13
+
14
+ static getInstance(): LogService {
15
+ if (!LogService.instance) {
16
+ LogService.instance = new LogService();
17
+ }
18
+ return LogService.instance;
19
+ }
20
+
21
+ async initialize(): Promise<void> {
22
+ // Use CloudWatch if AWS credentials are available or if it's cloud environment since we provided the permissions in instance profile
23
+ // otherwise use file-based logging
24
+ const hasAwsCredentials =
25
+ (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) || isCloudEnvironment();
26
+
27
+ if (hasAwsCredentials) {
28
+ logger.info('Using log provider: CloudWatch');
29
+ this.provider = new CloudWatchProvider();
30
+ } else {
31
+ logger.info('Using log provider: File-based (no AWS credentials required)');
32
+ this.provider = new LocalFileProvider();
33
+ }
34
+
35
+ await this.provider.initialize();
36
+ }
37
+
38
+ getLogSources(): Promise<LogSourceSchema[]> {
39
+ return this.provider.getLogSources();
40
+ }
41
+
42
+ getLogsBySource(
43
+ sourceName: string,
44
+ limit: number = 100,
45
+ beforeTimestamp?: string
46
+ ): Promise<{
47
+ logs: LogSchema[];
48
+ total: number;
49
+ tableName: string;
50
+ }> {
51
+ return this.provider.getLogsBySource(sourceName, limit, beforeTimestamp);
52
+ }
53
+
54
+ getLogSourceStats(): Promise<LogStatsSchema[]> {
55
+ return this.provider.getLogSourceStats();
56
+ }
57
+
58
+ searchLogs(
59
+ query: string,
60
+ sourceName?: string,
61
+ limit: number = 100,
62
+ offset: number = 0
63
+ ): Promise<{
64
+ logs: (LogSchema & { source: string })[];
65
+ total: number;
66
+ }> {
67
+ return this.provider.searchLogs(query, sourceName, limit, offset);
68
+ }
69
+
70
+ async close(): Promise<void> {
71
+ await this.provider.close();
72
+ }
73
+ }
@@ -0,0 +1,3 @@
1
+ export { RealtimeChannelService } from './realtime-channel.service.js';
2
+ export { RealtimeAuthService } from './realtime-auth.service.js';
3
+ export { RealtimeMessageService } from './realtime-message.service.js';
@@ -0,0 +1,104 @@
1
+ import { Pool, PoolClient } from 'pg';
2
+ import { DatabaseManager } from '@/infra/database/database.manager.js';
3
+ import logger from '@/utils/logger.js';
4
+ import { RoleSchema } from '@insforge/shared-schemas';
5
+
6
+ /**
7
+ * Handles channel authorization by checking RLS policies on the messages table.
8
+ *
9
+ * Permission Model (Supabase pattern):
10
+ * - SELECT on messages = 'join' permission (can subscribe to channel)
11
+ * - INSERT on messages = 'send' permission (can publish to channel)
12
+ *
13
+ * Developers define RLS policies on realtime.messages that check:
14
+ * - current_setting('request.jwt.claim.sub', true) = user ID
15
+ * - current_setting('request.jwt.claim.role', true) = user role
16
+ * - channel_name for channel-specific access
17
+ */
18
+ export class RealtimeAuthService {
19
+ private static instance: RealtimeAuthService;
20
+ private pool: Pool | null = null;
21
+
22
+ private constructor() {}
23
+
24
+ static getInstance(): RealtimeAuthService {
25
+ if (!RealtimeAuthService.instance) {
26
+ RealtimeAuthService.instance = new RealtimeAuthService();
27
+ }
28
+ return RealtimeAuthService.instance;
29
+ }
30
+
31
+ private getPool(): Pool {
32
+ if (!this.pool) {
33
+ this.pool = DatabaseManager.getInstance().getPool();
34
+ }
35
+ return this.pool;
36
+ }
37
+
38
+ /**
39
+ * Check if user has permission to subscribe to a channel.
40
+ * Tests SELECT permission on channels table via RLS.
41
+ *
42
+ * @param channelName - The channel to check access for
43
+ * @param userId - The user ID (undefined for anonymous users)
44
+ * @param role - The database role to use (authenticated or anon)
45
+ * @returns true if user can subscribe, false otherwise
46
+ */
47
+ async checkSubscribePermission(
48
+ channelName: string,
49
+ userId: string | undefined,
50
+ role: RoleSchema
51
+ ): Promise<boolean> {
52
+ const client = await this.getPool().connect();
53
+ try {
54
+ // Begin transaction to ensure settings persist across queries
55
+ await client.query('BEGIN');
56
+ // Switch to specified role to enforce RLS policies
57
+ await client.query(`SET LOCAL ROLE ${role}`);
58
+ await this.setUserContext(client, userId, channelName);
59
+
60
+ // Test SELECT permission via RLS on channels table
61
+ const result = await client.query(
62
+ `SELECT 1 FROM realtime.channels
63
+ WHERE enabled = TRUE
64
+ AND (pattern = $1 OR $1 LIKE pattern)
65
+ LIMIT 1`,
66
+ [channelName]
67
+ );
68
+
69
+ // Commit transaction
70
+ await client.query('COMMIT');
71
+
72
+ // If query returns a row, user has permission
73
+ return result.rowCount !== null && result.rowCount > 0;
74
+ } catch (error) {
75
+ // Rollback transaction on error
76
+ await client.query('ROLLBACK').catch(() => {});
77
+ logger.debug('Subscribe permission denied', { channelName, userId, error });
78
+ return false;
79
+ } finally {
80
+ // Reset role back to default before releasing connection
81
+ await client.query('RESET ROLE');
82
+ client.release();
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Set user context variables for RLS policy evaluation.
88
+ * Can be used by other services that need to execute queries with user context.
89
+ */
90
+ async setUserContext(
91
+ client: PoolClient,
92
+ userId: string | undefined,
93
+ channelName: string
94
+ ): Promise<void> {
95
+ if (userId) {
96
+ await client.query("SELECT set_config('request.jwt.claim.sub', $1, true)", [userId]);
97
+ } else {
98
+ await client.query("SELECT set_config('request.jwt.claim.sub', '', true)");
99
+ }
100
+
101
+ // Set the channel being accessed (used by realtime.channel_name())
102
+ await client.query("SELECT set_config('realtime.channel_name', $1, true)", [channelName]);
103
+ }
104
+ }
@@ -0,0 +1,237 @@
1
+ import { Pool } from 'pg';
2
+ import { DatabaseManager } from '@/infra/database/database.manager.js';
3
+ import { AppError } from '@/api/middlewares/error.js';
4
+ import { ERROR_CODES } from '@/types/error-constants.js';
5
+ import logger from '@/utils/logger.js';
6
+ import type {
7
+ RealtimeChannel,
8
+ CreateChannelRequest,
9
+ UpdateChannelRequest,
10
+ RealtimeMetadataSchema,
11
+ RlsPolicy,
12
+ RealtimePermissionsResponse,
13
+ } from '@insforge/shared-schemas';
14
+
15
+ const SYSTEM_POLICIES = ['project_admin_policy'];
16
+
17
+ export class RealtimeChannelService {
18
+ private static instance: RealtimeChannelService;
19
+ private pool: Pool | null = null;
20
+
21
+ private constructor() {}
22
+
23
+ static getInstance(): RealtimeChannelService {
24
+ if (!RealtimeChannelService.instance) {
25
+ RealtimeChannelService.instance = new RealtimeChannelService();
26
+ }
27
+ return RealtimeChannelService.instance;
28
+ }
29
+
30
+ private getPool(): Pool {
31
+ if (!this.pool) {
32
+ this.pool = DatabaseManager.getInstance().getPool();
33
+ }
34
+ return this.pool;
35
+ }
36
+
37
+ async list(): Promise<RealtimeChannel[]> {
38
+ const result = await this.getPool().query(`
39
+ SELECT
40
+ id,
41
+ pattern,
42
+ description,
43
+ webhook_urls as "webhookUrls",
44
+ enabled,
45
+ created_at as "createdAt",
46
+ updated_at as "updatedAt"
47
+ FROM realtime.channels
48
+ ORDER BY created_at DESC
49
+ `);
50
+ return result.rows;
51
+ }
52
+
53
+ async getById(id: string): Promise<RealtimeChannel | null> {
54
+ const result = await this.getPool().query(
55
+ `SELECT
56
+ id,
57
+ pattern,
58
+ description,
59
+ webhook_urls as "webhookUrls",
60
+ enabled,
61
+ created_at as "createdAt",
62
+ updated_at as "updatedAt"
63
+ FROM realtime.channels
64
+ WHERE id = $1`,
65
+ [id]
66
+ );
67
+ return result.rows[0] || null;
68
+ }
69
+
70
+ /**
71
+ * Find a channel by name (exact match or wildcard pattern match).
72
+ * For wildcard patterns like "order:%", checks if channelName matches the pattern.
73
+ * Returns the matching channel if found and enabled, null otherwise.
74
+ */
75
+ async getByName(channelName: string): Promise<RealtimeChannel | null> {
76
+ const result = await this.getPool().query(
77
+ `SELECT
78
+ id,
79
+ pattern,
80
+ description,
81
+ webhook_urls as "webhookUrls",
82
+ enabled,
83
+ created_at as "createdAt",
84
+ updated_at as "updatedAt"
85
+ FROM realtime.channels
86
+ WHERE enabled = TRUE
87
+ AND (pattern = $1 OR $1 LIKE pattern)
88
+ ORDER BY pattern = $1 DESC
89
+ LIMIT 1`,
90
+ [channelName]
91
+ );
92
+ return result.rows[0] || null;
93
+ }
94
+
95
+ async create(input: CreateChannelRequest): Promise<RealtimeChannel> {
96
+ this.validateChannelPattern(input.pattern);
97
+
98
+ const result = await this.getPool().query(
99
+ `INSERT INTO realtime.channels (
100
+ pattern, description, webhook_urls, enabled
101
+ ) VALUES ($1, $2, $3, $4)
102
+ RETURNING
103
+ id,
104
+ pattern,
105
+ description,
106
+ webhook_urls as "webhookUrls",
107
+ enabled,
108
+ created_at as "createdAt",
109
+ updated_at as "updatedAt"`,
110
+ [input.pattern, input.description || null, input.webhookUrls || null, input.enabled ?? true]
111
+ );
112
+
113
+ logger.info('Realtime channel created', { pattern: input.pattern });
114
+ return result.rows[0];
115
+ }
116
+
117
+ async update(id: string, input: UpdateChannelRequest): Promise<RealtimeChannel> {
118
+ const existing = await this.getById(id);
119
+ if (!existing) {
120
+ throw new AppError('Channel not found', 404, ERROR_CODES.NOT_FOUND);
121
+ }
122
+
123
+ if (input.pattern) {
124
+ this.validateChannelPattern(input.pattern);
125
+ }
126
+
127
+ const result = await this.getPool().query(
128
+ `UPDATE realtime.channels
129
+ SET
130
+ pattern = COALESCE($2, pattern),
131
+ description = COALESCE($3, description),
132
+ webhook_urls = COALESCE($4, webhook_urls),
133
+ enabled = COALESCE($5, enabled)
134
+ WHERE id = $1
135
+ RETURNING
136
+ id,
137
+ pattern,
138
+ description,
139
+ webhook_urls as "webhookUrls",
140
+ enabled,
141
+ created_at as "createdAt",
142
+ updated_at as "updatedAt"`,
143
+ [id, input.pattern, input.description, input.webhookUrls, input.enabled]
144
+ );
145
+
146
+ logger.info('Realtime channel updated', { id });
147
+ return result.rows[0];
148
+ }
149
+
150
+ async delete(id: string): Promise<void> {
151
+ const existing = await this.getById(id);
152
+ if (!existing) {
153
+ throw new AppError('Channel not found', 404, ERROR_CODES.NOT_FOUND);
154
+ }
155
+
156
+ await this.getPool().query('DELETE FROM realtime.channels WHERE id = $1', [id]);
157
+ logger.info('Realtime channel deleted', { id, pattern: existing.pattern });
158
+ }
159
+
160
+ /**
161
+ * Get realtime metadata including channels and permissions
162
+ */
163
+ async getMetadata(): Promise<RealtimeMetadataSchema> {
164
+ const [channels, permissions] = await Promise.all([this.list(), this.getPermissions()]);
165
+
166
+ return {
167
+ channels,
168
+ permissions,
169
+ };
170
+ }
171
+
172
+ // ============================================================================
173
+ // Permissions Methods
174
+ // ============================================================================
175
+
176
+ /**
177
+ * Get RLS policies for a table in the realtime schema, excluding system policies
178
+ */
179
+ private async getPolicies(tableName: string): Promise<RlsPolicy[]> {
180
+ const result = await this.getPool().query(
181
+ `SELECT
182
+ policyname as "policyName",
183
+ tablename as "tableName",
184
+ cmd as "command",
185
+ roles,
186
+ qual as "using",
187
+ with_check as "withCheck"
188
+ FROM pg_policies
189
+ WHERE schemaname = 'realtime'
190
+ AND tablename = $1
191
+ ORDER BY policyname`,
192
+ [tableName]
193
+ );
194
+
195
+ // Filter out system policies
196
+ return result.rows.filter((policy) => !SYSTEM_POLICIES.includes(policy.policyName));
197
+ }
198
+
199
+ /**
200
+ * Get all realtime permissions (RLS policies for channels and messages tables)
201
+ *
202
+ * - Subscribe permission: RLS policies on realtime.channels (SELECT)
203
+ * - Publish permission: RLS policies on realtime.messages (INSERT)
204
+ */
205
+ async getPermissions(): Promise<RealtimePermissionsResponse> {
206
+ const [channelsPolicies, messagesPolicies] = await Promise.all([
207
+ this.getPolicies('channels'),
208
+ this.getPolicies('messages'),
209
+ ]);
210
+
211
+ return {
212
+ subscribe: {
213
+ policies: channelsPolicies,
214
+ },
215
+ publish: {
216
+ policies: messagesPolicies,
217
+ },
218
+ };
219
+ }
220
+
221
+ // ============================================================================
222
+ // Validation
223
+ // ============================================================================
224
+
225
+ private validateChannelPattern(pattern: string): void {
226
+ // Allow alphanumeric, colons, hyphens, and % for wildcards
227
+ // Note: underscore is not allowed as it's a SQL wildcard character
228
+ const validPattern = /^[a-zA-Z0-9-]+(:[a-zA-Z0-9%:-]+)*$/;
229
+ if (!validPattern.test(pattern)) {
230
+ throw new AppError(
231
+ 'Invalid channel pattern. Use alphanumeric characters, colons, hyphens, and % for wildcards.',
232
+ 400,
233
+ ERROR_CODES.INVALID_INPUT
234
+ );
235
+ }
236
+ }
237
+ }