insforge 0.3.1

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 (395) hide show
  1. package/.dockerignore +58 -0
  2. package/.env.example +49 -0
  3. package/.github/ISSUE_TEMPLATE/bug_report.yml +83 -0
  4. package/.github/ISSUE_TEMPLATE/config.yml +11 -0
  5. package/.github/ISSUE_TEMPLATE/feature_request.yml +79 -0
  6. package/.github/copilot-instructions.md +147 -0
  7. package/.github/workflows/build-image.yml +65 -0
  8. package/.github/workflows/ci-premerge-check.yml +24 -0
  9. package/.github/workflows/deploy-aws.yml +130 -0
  10. package/.github/workflows/lint-and-format.yml +33 -0
  11. package/.prettierignore +65 -0
  12. package/.prettierrc +9 -0
  13. package/CHANGELOG.md +3 -0
  14. package/CONTRIBUTING.md +126 -0
  15. package/Dockerfile +27 -0
  16. package/GITHUB_OAUTH_SETUP.md +49 -0
  17. package/GOOGLE_OAUTH_SETUP.md +148 -0
  18. package/LICENSE +201 -0
  19. package/README.md +134 -0
  20. package/assets/Dark.svg +23 -0
  21. package/assets/archDiagram.png +0 -0
  22. package/assets/banner.png +0 -0
  23. package/assets/mcpInstallv2.png +0 -0
  24. package/assets/sampleResponse.png +0 -0
  25. package/assets/signin.png +0 -0
  26. package/assets/userflow.png +0 -0
  27. package/backend/migrations/000_create-base-tables.sql +142 -0
  28. package/backend/migrations/001_create-helper-functions.sql +41 -0
  29. package/backend/migrations/002_rename-auth-tables.sql +30 -0
  30. package/backend/migrations/003_create-users-table.sql +56 -0
  31. package/backend/migrations/004_add-reload-postgrest-func.sql +24 -0
  32. package/backend/migrations/005_enable-project-admin-modify-users.sql +30 -0
  33. package/backend/migrations/006_modify-ai-usage-table.sql +25 -0
  34. package/backend/migrations/007_drop-metadata-table.sql +2 -0
  35. package/backend/migrations/008_add-system-tables.sql +77 -0
  36. package/backend/migrations/009_add-function-secrets.sql +24 -0
  37. package/backend/migrations/010_modify-ai-config-modalities.sql +93 -0
  38. package/backend/migrations/011_refactor-secrets-table.sql +15 -0
  39. package/backend/migrations/012_add-storage-uploaded-by.sql +8 -0
  40. package/backend/package.json +75 -0
  41. package/backend/src/api/middleware/auth.ts +240 -0
  42. package/backend/src/api/middleware/error.ts +231 -0
  43. package/backend/src/api/middleware/upload.ts +59 -0
  44. package/backend/src/api/routes/agent.ts +29 -0
  45. package/backend/src/api/routes/ai.ts +472 -0
  46. package/backend/src/api/routes/auth.oauth.ts +482 -0
  47. package/backend/src/api/routes/auth.ts +386 -0
  48. package/backend/src/api/routes/database.advance.ts +275 -0
  49. package/backend/src/api/routes/database.records.ts +246 -0
  50. package/backend/src/api/routes/database.tables.ts +161 -0
  51. package/backend/src/api/routes/docs.ts +66 -0
  52. package/backend/src/api/routes/functions.ts +183 -0
  53. package/backend/src/api/routes/logs.ts +150 -0
  54. package/backend/src/api/routes/metadata.ts +160 -0
  55. package/backend/src/api/routes/openapi.ts +82 -0
  56. package/backend/src/api/routes/secrets.ts +199 -0
  57. package/backend/src/api/routes/storage.ts +547 -0
  58. package/backend/src/api/routes/usage.ts +96 -0
  59. package/backend/src/core/ai/chat.ts +207 -0
  60. package/backend/src/core/ai/client.ts +242 -0
  61. package/backend/src/core/ai/config.ts +187 -0
  62. package/backend/src/core/ai/image.ts +156 -0
  63. package/backend/src/core/ai/model.ts +117 -0
  64. package/backend/src/core/ai/usage.ts +290 -0
  65. package/backend/src/core/auth/auth.ts +781 -0
  66. package/backend/src/core/auth/oauth.ts +398 -0
  67. package/backend/src/core/database/advance.ts +1074 -0
  68. package/backend/src/core/database/manager.ts +178 -0
  69. package/backend/src/core/database/table.ts +772 -0
  70. package/backend/src/core/documentation/agent.ts +689 -0
  71. package/backend/src/core/documentation/openapi.ts +856 -0
  72. package/backend/src/core/functions/functions.ts +310 -0
  73. package/backend/src/core/logs/analytics.ts +76 -0
  74. package/backend/src/core/logs/audit.ts +255 -0
  75. package/backend/src/core/logs/providers/base.provider.ts +83 -0
  76. package/backend/src/core/logs/providers/cloudwatch.provider.ts +510 -0
  77. package/backend/src/core/logs/providers/localdb.provider.ts +246 -0
  78. package/backend/src/core/secrets/encryption.ts +58 -0
  79. package/backend/src/core/secrets/secrets.ts +410 -0
  80. package/backend/src/core/socket/socket.ts +388 -0
  81. package/backend/src/core/socket/types.ts +79 -0
  82. package/backend/src/core/storage/storage.ts +923 -0
  83. package/backend/src/server.ts +288 -0
  84. package/backend/src/types/ai.ts +46 -0
  85. package/backend/src/types/auth.ts +90 -0
  86. package/backend/src/types/database.ts +136 -0
  87. package/backend/src/types/error-constants.ts +86 -0
  88. package/backend/src/types/logs.ts +47 -0
  89. package/backend/src/types/profile.ts +55 -0
  90. package/backend/src/types/storage.ts +23 -0
  91. package/backend/src/utils/cloud-token.ts +39 -0
  92. package/backend/src/utils/constants.ts +1 -0
  93. package/backend/src/utils/environment.ts +35 -0
  94. package/backend/src/utils/helpers.ts +49 -0
  95. package/backend/src/utils/logger.ts +13 -0
  96. package/backend/src/utils/response.ts +62 -0
  97. package/backend/src/utils/seed.ts +205 -0
  98. package/backend/src/utils/sql-parser.ts +63 -0
  99. package/backend/src/utils/uuid.ts +9 -0
  100. package/backend/src/utils/validations.ts +129 -0
  101. package/backend/tests/README.md +134 -0
  102. package/backend/tests/cleanup-all-test-data.sh +231 -0
  103. package/backend/tests/cloud/test-s3-multitenant.sh +132 -0
  104. package/backend/tests/local/comprehensive-curl-tests.sh +156 -0
  105. package/backend/tests/local/test-auth-router.sh +144 -0
  106. package/backend/tests/local/test-database-router.sh +222 -0
  107. package/backend/tests/local/test-e2e.sh +241 -0
  108. package/backend/tests/local/test-fk-errors.sh +97 -0
  109. package/backend/tests/local/test-id-field.sh +201 -0
  110. package/backend/tests/local/test-public-bucket.sh +265 -0
  111. package/backend/tests/local/test-secrets.sh +248 -0
  112. package/backend/tests/local/test-serverless-functions.sh.disabled +325 -0
  113. package/backend/tests/local/test-traditional-rest.sh +209 -0
  114. package/backend/tests/manual/README.md +51 -0
  115. package/backend/tests/manual/create-large-table-simple.sql +11 -0
  116. package/backend/tests/manual/seed-large-table.sql +101 -0
  117. package/backend/tests/manual/setup-large-table-extras.sql +34 -0
  118. package/backend/tests/manual/test-better-auth.sh +303 -0
  119. package/backend/tests/manual/test-bulk-upsert.sh +410 -0
  120. package/backend/tests/manual/test-database-advance.sh +297 -0
  121. package/backend/tests/manual/test-postgrest-stability.sh +192 -0
  122. package/backend/tests/manual/test-rawsql-export-import.sh +412 -0
  123. package/backend/tests/manual/test-universal-storage.sh +264 -0
  124. package/backend/tests/manual/test-users.sql +18 -0
  125. package/backend/tests/run-all-tests.sh +140 -0
  126. package/backend/tests/setup.ts +22 -0
  127. package/backend/tests/test-config.sh +303 -0
  128. package/backend/tsconfig.json +23 -0
  129. package/backend/tsup.config.ts +18 -0
  130. package/backend/vitest.config.ts +22 -0
  131. package/docker-compose.prod.yml +145 -0
  132. package/docker-compose.yml +167 -0
  133. package/docker-init/db/db-init.sql +125 -0
  134. package/docker-init/db/jwt.sql +5 -0
  135. package/docker-init/db/logs.sql +9 -0
  136. package/docker-init/db/postgresql.conf +17 -0
  137. package/docs/deprecated/insforge-auth-api.md +215 -0
  138. package/docs/deprecated/insforge-auth-sdk.md +100 -0
  139. package/docs/deprecated/insforge-db-api.md +359 -0
  140. package/docs/deprecated/insforge-db-sdk.md +140 -0
  141. package/docs/deprecated/insforge-debug-sdk.md +157 -0
  142. package/docs/deprecated/insforge-debug.md +65 -0
  143. package/docs/deprecated/insforge-instructions.md +124 -0
  144. package/docs/deprecated/insforge-project.md +118 -0
  145. package/docs/deprecated/insforge-storage-api.md +279 -0
  146. package/docs/deprecated/insforge-storage-sdk.md +159 -0
  147. package/docs/insforge-instructions-sdk.md +407 -0
  148. package/eslint.config.js +317 -0
  149. package/examples/oauth/frontend-oauth-example.html +251 -0
  150. package/examples/response-examples.md +444 -0
  151. package/frontend/README.md +112 -0
  152. package/frontend/components.json +17 -0
  153. package/frontend/index.html +13 -0
  154. package/frontend/package.json +63 -0
  155. package/frontend/public/favicon.ico +0 -0
  156. package/frontend/src/App.tsx +106 -0
  157. package/frontend/src/assets/icons/checkbox_checked.svg +6 -0
  158. package/frontend/src/assets/icons/checkbox_undetermined.svg +6 -0
  159. package/frontend/src/assets/icons/checked.svg +3 -0
  160. package/frontend/src/assets/icons/error.svg +3 -0
  161. package/frontend/src/assets/icons/pencil.svg +4 -0
  162. package/frontend/src/assets/icons/refresh.svg +4 -0
  163. package/frontend/src/assets/icons/step_active.svg +3 -0
  164. package/frontend/src/assets/icons/step_inactive.svg +11 -0
  165. package/frontend/src/assets/icons/warning.svg +3 -0
  166. package/frontend/src/assets/logos/amazon.svg +1 -0
  167. package/frontend/src/assets/logos/claude_code.svg +3 -0
  168. package/frontend/src/assets/logos/cline.svg +6 -0
  169. package/frontend/src/assets/logos/cursor.svg +20 -0
  170. package/frontend/src/assets/logos/discord.svg +9 -0
  171. package/frontend/src/assets/logos/gemini.svg +19 -0
  172. package/frontend/src/assets/logos/github.svg +5 -0
  173. package/frontend/src/assets/logos/google.svg +13 -0
  174. package/frontend/src/assets/logos/grok.svg +10 -0
  175. package/frontend/src/assets/logos/insforge_dark.svg +15 -0
  176. package/frontend/src/assets/logos/insforge_light.svg +15 -0
  177. package/frontend/src/assets/logos/openai.svg +10 -0
  178. package/frontend/src/assets/logos/roo_code.svg +9 -0
  179. package/frontend/src/assets/logos/trae.svg +3 -0
  180. package/frontend/src/assets/logos/windsurf.svg +10 -0
  181. package/frontend/src/components/ButtonWithLoading.tsx +27 -0
  182. package/frontend/src/components/Checkbox.tsx +61 -0
  183. package/frontend/src/components/CodeBlock.tsx +32 -0
  184. package/frontend/src/components/ConfirmDialog.tsx +96 -0
  185. package/frontend/src/components/CopyButton.tsx +69 -0
  186. package/frontend/src/components/DeleteActionButton.tsx +42 -0
  187. package/frontend/src/components/EmptyState.tsx +41 -0
  188. package/frontend/src/components/ErrorState.tsx +35 -0
  189. package/frontend/src/components/FeatureSidebar.tsx +126 -0
  190. package/frontend/src/components/FeatureSidebarItem.tsx +101 -0
  191. package/frontend/src/components/JsonHighlight.tsx +61 -0
  192. package/frontend/src/components/LoadingState.tsx +16 -0
  193. package/frontend/src/components/PaginationControls.tsx +54 -0
  194. package/frontend/src/components/PromptDialog.tsx +68 -0
  195. package/frontend/src/components/SearchInput.tsx +90 -0
  196. package/frontend/src/components/SelectionClearButton.tsx +26 -0
  197. package/frontend/src/components/Stepper.tsx +139 -0
  198. package/frontend/src/components/ThemeToggle.tsx +58 -0
  199. package/frontend/src/components/TypeBadge.tsx +20 -0
  200. package/frontend/src/components/datagrid/DataGrid.tsx +264 -0
  201. package/frontend/src/components/datagrid/DefaultCellRenderer.tsx +114 -0
  202. package/frontend/src/components/datagrid/IdCell.tsx +44 -0
  203. package/frontend/src/components/datagrid/SortableHeader.tsx +74 -0
  204. package/frontend/src/components/datagrid/cell-editors/BooleanCellEditor.tsx +54 -0
  205. package/frontend/src/components/datagrid/cell-editors/DateCellEditor.tsx +483 -0
  206. package/frontend/src/components/datagrid/cell-editors/JsonCellEditor.tsx +362 -0
  207. package/frontend/src/components/datagrid/cell-editors/TextCellEditor.tsx +38 -0
  208. package/frontend/src/components/datagrid/cell-editors/index.ts +14 -0
  209. package/frontend/src/components/datagrid/cell-editors/types.ts +43 -0
  210. package/frontend/src/components/datagrid/datagridTypes.tsx +72 -0
  211. package/frontend/src/components/datagrid/index.tsx +20 -0
  212. package/frontend/src/components/index.ts +39 -0
  213. package/frontend/src/components/layout/AppHeader.tsx +146 -0
  214. package/frontend/src/components/layout/AppSidebar.tsx +190 -0
  215. package/frontend/src/components/layout/CloudLayout.tsx +95 -0
  216. package/frontend/src/components/layout/Layout.tsx +43 -0
  217. package/frontend/src/components/radix/Alert.tsx +45 -0
  218. package/frontend/src/components/radix/AlertDialog.tsx +115 -0
  219. package/frontend/src/components/radix/Avatar.tsx +45 -0
  220. package/frontend/src/components/radix/Badge.tsx +33 -0
  221. package/frontend/src/components/radix/Button.tsx +50 -0
  222. package/frontend/src/components/radix/Card.tsx +58 -0
  223. package/frontend/src/components/radix/Dialog.tsx +98 -0
  224. package/frontend/src/components/radix/DropdownMenu.tsx +185 -0
  225. package/frontend/src/components/radix/Form.tsx +167 -0
  226. package/frontend/src/components/radix/Input.tsx +22 -0
  227. package/frontend/src/components/radix/Label.tsx +19 -0
  228. package/frontend/src/components/radix/Popover.tsx +29 -0
  229. package/frontend/src/components/radix/ScrollArea.tsx +44 -0
  230. package/frontend/src/components/radix/Select.tsx +151 -0
  231. package/frontend/src/components/radix/Separator.tsx +26 -0
  232. package/frontend/src/components/radix/Sheet.tsx +119 -0
  233. package/frontend/src/components/radix/Skeleton.tsx +7 -0
  234. package/frontend/src/components/radix/Switch.tsx +29 -0
  235. package/frontend/src/components/radix/Tabs.tsx +50 -0
  236. package/frontend/src/components/radix/Textarea.tsx +21 -0
  237. package/frontend/src/components/radix/Tooltip.tsx +28 -0
  238. package/frontend/src/features/ai/components/AIConfigCard.tsx +154 -0
  239. package/frontend/src/features/ai/components/AIConfigDialog.tsx +76 -0
  240. package/frontend/src/features/ai/components/AIConfigForm.tsx +222 -0
  241. package/frontend/src/features/ai/components/AIEmptyState.tsx +18 -0
  242. package/frontend/src/features/ai/components/fields/ModalityField.tsx +87 -0
  243. package/frontend/src/features/ai/components/fields/ModelSelectionField.tsx +134 -0
  244. package/frontend/src/features/ai/components/fields/SystemPromptField.tsx +33 -0
  245. package/frontend/src/features/ai/helpers.ts +155 -0
  246. package/frontend/src/features/ai/hooks/useAIConfigs.ts +221 -0
  247. package/frontend/src/features/ai/hooks/useAIUsage.ts +77 -0
  248. package/frontend/src/features/ai/page/AIPage.tsx +178 -0
  249. package/frontend/src/features/ai/services/ai.service.ts +148 -0
  250. package/frontend/src/features/auth/components/AddOAuthDialog.tsx +106 -0
  251. package/frontend/src/features/auth/components/AuthMethodTab.tsx +238 -0
  252. package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +303 -0
  253. package/frontend/src/features/auth/components/OAuthEmptyState.tsx +15 -0
  254. package/frontend/src/features/auth/components/UserFormDialog.tsx +248 -0
  255. package/frontend/src/features/auth/components/UsersDataGrid.tsx +183 -0
  256. package/frontend/src/features/auth/components/UsersTab.tsx +114 -0
  257. package/frontend/src/features/auth/hooks/useOAuthConfig.ts +129 -0
  258. package/frontend/src/features/auth/hooks/useUsers.ts +57 -0
  259. package/frontend/src/features/auth/index.ts +9 -0
  260. package/frontend/src/features/auth/page/AuthenticationPage.tsx +169 -0
  261. package/frontend/src/features/auth/services/auth.service.ts +112 -0
  262. package/frontend/src/features/auth/services/oauth.service.ts +49 -0
  263. package/frontend/src/features/dashboard/page/DashboardPage.tsx +194 -0
  264. package/frontend/src/features/database/components/ColumnTypeSelect.tsx +64 -0
  265. package/frontend/src/features/database/components/DatabaseDataGrid.tsx +282 -0
  266. package/frontend/src/features/database/components/ForeignKeyCell.tsx +187 -0
  267. package/frontend/src/features/database/components/ForeignKeyPopover.tsx +378 -0
  268. package/frontend/src/features/database/components/LinkRecordModal.tsx +288 -0
  269. package/frontend/src/features/database/components/RecordFormDialog.tsx +164 -0
  270. package/frontend/src/features/database/components/RecordFormField.tsx +568 -0
  271. package/frontend/src/features/database/components/TableEmptyState.tsx +21 -0
  272. package/frontend/src/features/database/components/TableForm.tsx +656 -0
  273. package/frontend/src/features/database/components/TableFormColumn.tsx +137 -0
  274. package/frontend/src/features/database/components/TableListSkeleton.tsx +9 -0
  275. package/frontend/src/features/database/components/TableSidebar.tsx +47 -0
  276. package/frontend/src/features/database/constants.ts +26 -0
  277. package/frontend/src/features/database/helpers.ts +125 -0
  278. package/frontend/src/features/database/hooks/UseLinkModal.tsx +78 -0
  279. package/frontend/src/features/database/index.ts +12 -0
  280. package/frontend/src/features/database/page/DatabasePage.tsx +626 -0
  281. package/frontend/src/features/database/schema.ts +25 -0
  282. package/frontend/src/features/database/services/database.service.ts +216 -0
  283. package/frontend/src/features/functions/components/FunctionEmptyState.tsx +15 -0
  284. package/frontend/src/features/functions/components/FunctionRow.tsx +71 -0
  285. package/frontend/src/features/functions/components/FunctionViewer.tsx +46 -0
  286. package/frontend/src/features/functions/components/FunctionsContent.tsx +88 -0
  287. package/frontend/src/features/functions/components/FunctionsSidebar.tsx +56 -0
  288. package/frontend/src/features/functions/components/SecretEmptyState.tsx +23 -0
  289. package/frontend/src/features/functions/components/SecretRow.tsx +68 -0
  290. package/frontend/src/features/functions/components/SecretsContent.tsx +120 -0
  291. package/frontend/src/features/functions/hooks/useFunctions.ts +106 -0
  292. package/frontend/src/features/functions/page/FunctionsPage.tsx +28 -0
  293. package/frontend/src/features/functions/services/functions.service.ts +48 -0
  294. package/frontend/src/features/login/components/AuthErrorBoundary.tsx +87 -0
  295. package/frontend/src/features/login/components/PrivateRoute.tsx +24 -0
  296. package/frontend/src/features/login/page/CloudLoginPage.tsx +93 -0
  297. package/frontend/src/features/login/page/LoginPage.tsx +174 -0
  298. package/frontend/src/features/logs/components/AnalyticsLogsTable.tsx +313 -0
  299. package/frontend/src/features/logs/components/LogsTable.tsx +199 -0
  300. package/frontend/src/features/logs/hooks/useAuditLogs.ts +39 -0
  301. package/frontend/src/features/logs/index.ts +5 -0
  302. package/frontend/src/features/logs/page/AnalyticsLogsPage.tsx +530 -0
  303. package/frontend/src/features/logs/page/AuditsPage.tsx +192 -0
  304. package/frontend/src/features/logs/services/log.service.ts +171 -0
  305. package/frontend/src/features/metadata/hooks/useMetadata.ts +53 -0
  306. package/frontend/src/features/metadata/index.ts +0 -0
  307. package/frontend/src/features/metadata/page/MetadataPage.tsx +136 -0
  308. package/frontend/src/features/metadata/services/metadata.service.ts +17 -0
  309. package/frontend/src/features/onboard/components/CompletionCard.tsx +41 -0
  310. package/frontend/src/features/onboard/components/OnboardButton.tsx +84 -0
  311. package/frontend/src/features/onboard/components/StepContent.tsx +91 -0
  312. package/frontend/src/features/onboard/components/TestConnectionStep.tsx +53 -0
  313. package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +35 -0
  314. package/frontend/src/features/onboard/components/mcp/McpInstallation.tsx +144 -0
  315. package/frontend/src/features/onboard/components/mcp/index.ts +4 -0
  316. package/frontend/src/features/onboard/components/mcp/mcp-helper.tsx +98 -0
  317. package/frontend/src/features/onboard/index.ts +3 -0
  318. package/frontend/src/features/onboard/page/OnBoardPage.tsx +104 -0
  319. package/frontend/src/features/onboard/types.ts +8 -0
  320. package/frontend/src/features/secrets/hooks/useSecrets.ts +139 -0
  321. package/frontend/src/features/secrets/services/secrets.service.ts +57 -0
  322. package/frontend/src/features/storage/components/BucketEmptyState.tsx +19 -0
  323. package/frontend/src/features/storage/components/BucketFormDialog.tsx +194 -0
  324. package/frontend/src/features/storage/components/BucketListSkeleton.tsx +17 -0
  325. package/frontend/src/features/storage/components/FilePreviewDialog.tsx +287 -0
  326. package/frontend/src/features/storage/components/StorageDataGrid.tsx +239 -0
  327. package/frontend/src/features/storage/components/StorageManager.tsx +236 -0
  328. package/frontend/src/features/storage/components/StorageSidebar.tsx +44 -0
  329. package/frontend/src/features/storage/components/UploadToast.tsx +46 -0
  330. package/frontend/src/features/storage/index.ts +3 -0
  331. package/frontend/src/features/storage/page/StoragePage.tsx +553 -0
  332. package/frontend/src/features/storage/services/storage.service.ts +144 -0
  333. package/frontend/src/features/visualizer/components/AuthNode.tsx +107 -0
  334. package/frontend/src/features/visualizer/components/BucketNode.tsx +34 -0
  335. package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +359 -0
  336. package/frontend/src/features/visualizer/components/TableNode.tsx +152 -0
  337. package/frontend/src/features/visualizer/components/VisualizerSkeleton.tsx +24 -0
  338. package/frontend/src/features/visualizer/components/index.ts +5 -0
  339. package/frontend/src/features/visualizer/page/VisualizerPage.tsx +127 -0
  340. package/frontend/src/index.css +248 -0
  341. package/frontend/src/lib/api/client.ts +163 -0
  342. package/frontend/src/lib/contexts/AuthContext.tsx +157 -0
  343. package/frontend/src/lib/contexts/OnboardStepContext.tsx +68 -0
  344. package/frontend/src/lib/contexts/SocketContext.tsx +303 -0
  345. package/frontend/src/lib/contexts/ThemeContext.tsx +125 -0
  346. package/frontend/src/lib/hooks/useAuth.ts +4 -0
  347. package/frontend/src/lib/hooks/useConfirm.ts +55 -0
  348. package/frontend/src/lib/hooks/useInterval.ts +27 -0
  349. package/frontend/src/lib/hooks/useMediaQuery.ts +59 -0
  350. package/frontend/src/lib/hooks/useOnboardingCompletion.ts +29 -0
  351. package/frontend/src/lib/hooks/usePagination.ts +27 -0
  352. package/frontend/src/lib/hooks/useTimeout.ts +27 -0
  353. package/frontend/src/lib/hooks/useToast.tsx +229 -0
  354. package/frontend/src/lib/utils/constants.ts +38 -0
  355. package/frontend/src/lib/utils/utils.ts +165 -0
  356. package/frontend/src/lib/utils/validation-schemas.ts +126 -0
  357. package/frontend/src/main.tsx +16 -0
  358. package/frontend/src/rdg.css +194 -0
  359. package/frontend/src/vite-env.d.ts +12 -0
  360. package/frontend/tailwind.config.js +97 -0
  361. package/frontend/tsconfig.json +26 -0
  362. package/frontend/tsconfig.node.json +10 -0
  363. package/frontend/vite.config.ts +37 -0
  364. package/frontend/vitest.config.ts +36 -0
  365. package/functions/deno.json +25 -0
  366. package/functions/server.ts +290 -0
  367. package/functions/worker-template.js +126 -0
  368. package/openapi/ai.yaml +689 -0
  369. package/openapi/auth.yaml +563 -0
  370. package/openapi/functions.yaml +476 -0
  371. package/openapi/health.yaml +30 -0
  372. package/openapi/logs.yaml +224 -0
  373. package/openapi/metadata.yaml +178 -0
  374. package/openapi/records.yaml +382 -0
  375. package/openapi/secrets.yaml +371 -0
  376. package/openapi/storage.yaml +876 -0
  377. package/openapi/tables.yaml +464 -0
  378. package/package.json +88 -0
  379. package/shared-schemas/package.json +31 -0
  380. package/shared-schemas/src/ai-api.schema.ts +167 -0
  381. package/shared-schemas/src/ai.schema.ts +54 -0
  382. package/shared-schemas/src/auth-api.schema.ts +193 -0
  383. package/shared-schemas/src/auth.schema.ts +94 -0
  384. package/shared-schemas/src/database-api.schema.ts +259 -0
  385. package/shared-schemas/src/database.schema.ts +69 -0
  386. package/shared-schemas/src/functions-api.schema.ts +25 -0
  387. package/shared-schemas/src/functions.schema.ts +16 -0
  388. package/shared-schemas/src/index.ts +13 -0
  389. package/shared-schemas/src/logs-api.schema.ts +49 -0
  390. package/shared-schemas/src/logs.schema.ts +14 -0
  391. package/shared-schemas/src/metadata.schema.ts +56 -0
  392. package/shared-schemas/src/storage-api.schema.ts +65 -0
  393. package/shared-schemas/src/storage.schema.ts +19 -0
  394. package/shared-schemas/tsconfig.json +21 -0
  395. package/tsconfig.json +8 -0
@@ -0,0 +1,482 @@
1
+ import { Router, Request, Response, NextFunction } from 'express';
2
+ import { AuthService } from '@/core/auth/auth.js';
3
+ import { OAuthConfigService } from '@/core/auth/oauth.js';
4
+ import { AuditService } from '@/core/logs/audit.js';
5
+ import { AppError } from '@/api/middleware/error.js';
6
+ import { ERROR_CODES } from '@/types/error-constants.js';
7
+ import { successResponse } from '@/utils/response.js';
8
+ import { AuthRequest, verifyAdmin } from '@/api/middleware/auth.js';
9
+ import logger from '@/utils/logger.js';
10
+ import jwt from 'jsonwebtoken';
11
+ import { SocketService } from '@/core/socket/socket.js';
12
+ import { DataUpdateResourceType, ServerEvents } from '@/core/socket/types.js';
13
+ import {
14
+ createOAuthConfigRequestSchema,
15
+ updateOAuthConfigRequestSchema,
16
+ type ListOAuthConfigsResponse,
17
+ } from '@insforge/shared-schemas';
18
+ import { isOAuthSharedKeysAvailable } from '@/utils/environment.js';
19
+
20
+ const router = Router();
21
+ const authService = AuthService.getInstance();
22
+ const oauthConfigService = OAuthConfigService.getInstance();
23
+ const auditService = AuditService.getInstance();
24
+
25
+ // GET /api/auth/oauth/google - Initialize Google OAuth flow
26
+ router.get('/google', async (req: Request, res: Response, next: NextFunction) => {
27
+ try {
28
+ const { redirect_uri } = req.query;
29
+ if (!redirect_uri) {
30
+ throw new AppError('Redirect URI is required', 400, ERROR_CODES.INVALID_INPUT);
31
+ }
32
+
33
+ const jwtPayload = {
34
+ provider: 'google',
35
+ redirectUri: redirect_uri ? (redirect_uri as string) : undefined,
36
+ createdAt: Date.now(),
37
+ };
38
+ const state = jwt.sign(jwtPayload, process.env.JWT_SECRET || 'default_secret', {
39
+ algorithm: 'HS256',
40
+ expiresIn: '1h', // Set expiration time for the state token
41
+ });
42
+ const authUrl = await authService.generateGoogleAuthUrl(state);
43
+
44
+ res.json({ authUrl });
45
+ } catch (error) {
46
+ logger.error('Google OAuth error', { error });
47
+ next(
48
+ new AppError(
49
+ 'Google OAuth is not properly configured. Please check your oauth configurations.',
50
+ 500,
51
+ ERROR_CODES.AUTH_OAUTH_CONFIG_ERROR
52
+ )
53
+ );
54
+ }
55
+ });
56
+
57
+ // GET /api/auth/oauth/github - Initialize GitHub OAuth flow
58
+ router.get('/github', async (req: Request, res: Response, next: NextFunction) => {
59
+ try {
60
+ const { redirect_uri } = req.query;
61
+ if (!redirect_uri) {
62
+ throw new AppError('Redirect URI is required', 400, ERROR_CODES.INVALID_INPUT);
63
+ }
64
+
65
+ const jwtPayload = {
66
+ provider: 'github',
67
+ redirectUri: redirect_uri ? (redirect_uri as string) : undefined,
68
+ createdAt: Date.now(),
69
+ };
70
+ const state = jwt.sign(jwtPayload, process.env.JWT_SECRET || 'default_secret', {
71
+ algorithm: 'HS256',
72
+ expiresIn: '1h', // Set expiration time for the state token
73
+ });
74
+
75
+ const authUrl = await authService.generateGitHubAuthUrl(state);
76
+
77
+ res.json({ authUrl });
78
+ } catch (error) {
79
+ logger.error('GitHub OAuth error', { error });
80
+ next(
81
+ new AppError(
82
+ 'GitHub OAuth is not properly configured. Please check your oauth configurations.',
83
+ 500,
84
+ ERROR_CODES.AUTH_OAUTH_CONFIG_ERROR
85
+ )
86
+ );
87
+ }
88
+ });
89
+
90
+ // GET /api/auth/oauth/shared/callback/:state - Shared callback for OAuth providers
91
+ router.get('/shared/callback/:state', async (req: Request, res: Response, next: NextFunction) => {
92
+ try {
93
+ const { state } = req.params;
94
+ const { success, error, payload } = req.query;
95
+
96
+ if (!state) {
97
+ logger.warn('Shared OAuth callback called without state parameter');
98
+ throw new AppError('State parameter is required', 400, ERROR_CODES.INVALID_INPUT);
99
+ }
100
+
101
+ let redirectUri: string;
102
+ let provider: string;
103
+ try {
104
+ const decodedState = jwt.verify(state, process.env.JWT_SECRET || 'default_secret') as {
105
+ provider: string;
106
+ redirectUri: string;
107
+ };
108
+ redirectUri = decodedState.redirectUri || '/';
109
+ provider = decodedState.provider || '';
110
+ } catch {
111
+ logger.warn('Invalid state parameter', { state });
112
+ throw new AppError('Invalid state parameter', 400, ERROR_CODES.INVALID_INPUT);
113
+ }
114
+
115
+ if (!['google', 'github'].includes(provider)) {
116
+ logger.warn('Invalid provider in state', { provider });
117
+ throw new AppError('Invalid provider in state', 400, ERROR_CODES.INVALID_INPUT);
118
+ }
119
+ if (!redirectUri) {
120
+ throw new AppError('Redirect URL is required', 400, ERROR_CODES.INVALID_INPUT);
121
+ }
122
+
123
+ if (success !== 'true') {
124
+ const errorMessage = error || 'OAuth authentication failed';
125
+ logger.warn('Shared OAuth callback failed', { error: errorMessage, provider });
126
+ return res.redirect(`${redirectUri}?error=${encodeURIComponent(String(errorMessage))}`);
127
+ }
128
+ if (!payload) {
129
+ throw new AppError('No payload provided in callback', 400, ERROR_CODES.INVALID_INPUT);
130
+ }
131
+
132
+ const payloadData = JSON.parse(Buffer.from(payload as string, 'base64').toString('utf8'));
133
+ let result;
134
+ if (provider === 'google') {
135
+ // Handle Google OAuth payload
136
+ const googleUserInfo = {
137
+ sub: payloadData.providerId,
138
+ email: payloadData.email,
139
+ name: payloadData.name || '',
140
+ userName: payloadData.userName || '',
141
+ picture: payloadData.avatar || '',
142
+ };
143
+ result = await authService.findOrCreateGoogleUser(googleUserInfo);
144
+ } else if (provider === 'github') {
145
+ // Handle GitHub OAuth payload
146
+ const githubUserInfo = {
147
+ id: payloadData.providerId,
148
+ login: payloadData.login || '',
149
+ email: payloadData.email,
150
+ name: payloadData.name || '',
151
+ avatar_url: payloadData.avatar || '',
152
+ };
153
+ result = await authService.findOrCreateGitHubUser(githubUserInfo);
154
+ }
155
+
156
+ const finalredirectUri = new URL(redirectUri);
157
+ finalredirectUri.searchParams.set('access_token', result?.accessToken ?? '');
158
+ finalredirectUri.searchParams.set('user_id', result?.user.id ?? '');
159
+ finalredirectUri.searchParams.set('email', result?.user.email ?? '');
160
+ finalredirectUri.searchParams.set('name', result?.user.name ?? '');
161
+ res.redirect(finalredirectUri.toString());
162
+ } catch (error) {
163
+ logger.error('Shared OAuth callback error', { error });
164
+ next(error);
165
+ }
166
+ });
167
+
168
+ // GET /api/auth/oauth/:provider/callback - OAuth provider callback
169
+ router.get('/:provider/callback', async (req: Request, res: Response, _: NextFunction) => {
170
+ try {
171
+ const { provider } = req.params;
172
+ const { code, state, token } = req.query;
173
+
174
+ let redirectUri = '/';
175
+
176
+ if (state) {
177
+ try {
178
+ const stateData = jwt.verify(
179
+ state as string,
180
+ process.env.JWT_SECRET || 'default_secret'
181
+ ) as {
182
+ provider: string;
183
+ redirectUri: string;
184
+ };
185
+ redirectUri = stateData.redirectUri || '/';
186
+ } catch {
187
+ // Invalid state
188
+ }
189
+ }
190
+
191
+ if (!['google', 'github'].includes(provider)) {
192
+ throw new AppError('Invalid provider', 400, ERROR_CODES.INVALID_INPUT);
193
+ }
194
+
195
+ let result;
196
+
197
+ if (provider === 'google') {
198
+ let id_token: string;
199
+
200
+ if (token) {
201
+ id_token = token as string;
202
+ } else if (code) {
203
+ const tokens = await authService.exchangeCodeToTokenByGoogle(code as string);
204
+ id_token = tokens.id_token;
205
+ } else {
206
+ throw new AppError(
207
+ 'No authorization code or token provided',
208
+ 400,
209
+ ERROR_CODES.INVALID_INPUT
210
+ );
211
+ }
212
+
213
+ const googleUserInfo = await authService.verifyGoogleToken(id_token);
214
+ result = await authService.findOrCreateGoogleUser(googleUserInfo);
215
+ } else if (provider === 'github') {
216
+ if (!code) {
217
+ throw new AppError('No authorization code provided', 400, ERROR_CODES.INVALID_INPUT);
218
+ }
219
+
220
+ const accessToken = await authService.exchangeGitHubCodeForToken(code as string);
221
+ const githubUserInfo = await authService.getGitHubUserInfo(accessToken);
222
+ result = await authService.findOrCreateGitHubUser(githubUserInfo);
223
+ }
224
+
225
+ // Create URL with JWT token and user info (like the working example)
226
+ const finalredirectUri = new URL(redirectUri);
227
+ finalredirectUri.searchParams.set('access_token', result?.accessToken ?? '');
228
+ finalredirectUri.searchParams.set('user_id', result?.user.id ?? '');
229
+ finalredirectUri.searchParams.set('email', result?.user.email ?? '');
230
+ finalredirectUri.searchParams.set('name', result?.user.name ?? '');
231
+
232
+ logger.info('OAuth callback successful, redirecting with token', {
233
+ redirectUri: finalredirectUri.toString(),
234
+ hasAccessToken: !!result?.accessToken,
235
+ userId: result?.user.id,
236
+ });
237
+
238
+ // Redirect directly to the app with token in URL
239
+ return res.redirect(finalredirectUri.toString());
240
+ } catch (error) {
241
+ logger.error('OAuth callback error', {
242
+ error: error instanceof Error ? error.message : error,
243
+ stack: error instanceof Error ? error.stack : undefined,
244
+ provider: req.params.provider,
245
+ hasCode: !!req.query.code,
246
+ hasState: !!req.query.state,
247
+ hasToken: !!req.query.token,
248
+ });
249
+
250
+ // Redirect to app with error message
251
+ const { state } = req.query;
252
+ const redirectUri = state
253
+ ? (() => {
254
+ try {
255
+ const stateData = JSON.parse(Buffer.from(state as string, 'base64').toString());
256
+ return stateData.redirectUri || '/';
257
+ } catch {
258
+ return '/';
259
+ }
260
+ })()
261
+ : '/';
262
+
263
+ const errorMessage = error instanceof Error ? error.message : 'OAuth authentication failed';
264
+
265
+ // Redirect with error in URL parameters
266
+ const errorredirectUri = new URL(redirectUri);
267
+ errorredirectUri.searchParams.set('error', errorMessage);
268
+
269
+ return res.redirect(errorredirectUri.toString());
270
+ }
271
+ });
272
+
273
+ // ============= OAuth Configuration Management Endpoints =============
274
+
275
+ // GET /api/auth/oauth/configs - List all OAuth configurations (admin only)
276
+ router.get('/configs', verifyAdmin, async (req: AuthRequest, res: Response, next: NextFunction) => {
277
+ try {
278
+ const configs = await oauthConfigService.getAllConfigs();
279
+
280
+ const response: ListOAuthConfigsResponse = {
281
+ data: configs,
282
+ count: configs.length,
283
+ };
284
+ successResponse(res, response);
285
+ } catch (error) {
286
+ logger.error('Failed to list OAuth configurations', { error });
287
+ next(error);
288
+ }
289
+ });
290
+
291
+ // GET /api/auth/oauth/configs/:provider - Get specific OAuth configuration (admin only)
292
+ router.get(
293
+ '/configs/:provider',
294
+ verifyAdmin,
295
+ async (req: AuthRequest, res: Response, next: NextFunction) => {
296
+ try {
297
+ const provider = req.params.provider;
298
+ if (!provider || provider.length === 0 || provider.length > 50) {
299
+ throw new AppError('Invalid provider name', 400, ERROR_CODES.INVALID_INPUT);
300
+ }
301
+ const config = await oauthConfigService.getConfigByProvider(provider);
302
+ const clientSecret = await oauthConfigService.getClientSecretByProvider(provider);
303
+
304
+ if (!config) {
305
+ throw new AppError(
306
+ `OAuth configuration for ${provider} not found`,
307
+ 404,
308
+ ERROR_CODES.NOT_FOUND
309
+ );
310
+ }
311
+
312
+ successResponse(res, { ...config, clientSecret });
313
+ } catch (error) {
314
+ logger.error('Failed to get OAuth configuration', { error, provider: req.params.provider });
315
+ next(error);
316
+ }
317
+ }
318
+ );
319
+
320
+ // POST /api/auth/oauth/configs - Create new OAuth configuration (admin only)
321
+ router.post(
322
+ '/configs',
323
+ verifyAdmin,
324
+ async (req: AuthRequest, res: Response, next: NextFunction) => {
325
+ try {
326
+ const validationResult = createOAuthConfigRequestSchema.safeParse(req.body);
327
+ if (!validationResult.success) {
328
+ throw new AppError(
329
+ validationResult.error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join(', '),
330
+ 400,
331
+ ERROR_CODES.INVALID_INPUT
332
+ );
333
+ }
334
+
335
+ const input = validationResult.data;
336
+
337
+ // Check if using shared keys when not allowed
338
+ if (input.useSharedKey && !isOAuthSharedKeysAvailable()) {
339
+ throw new AppError(
340
+ 'Shared OAuth keys are not enabled in this environment',
341
+ 400,
342
+ ERROR_CODES.AUTH_OAUTH_CONFIG_ERROR
343
+ );
344
+ }
345
+
346
+ const config = await oauthConfigService.createConfig(input);
347
+
348
+ await auditService.log({
349
+ actor: req.user?.email || 'api-key',
350
+ action: 'CREATE_OAUTH_CONFIG',
351
+ module: 'AUTH',
352
+ details: {
353
+ provider: input.provider,
354
+ useSharedKey: input.useSharedKey || false,
355
+ },
356
+ ip_address: req.ip,
357
+ });
358
+
359
+ // Broadcast configuration change
360
+ const socket = SocketService.getInstance();
361
+ socket.broadcastToRoom('role:project_admin', ServerEvents.DATA_UPDATE, {
362
+ resource: DataUpdateResourceType.AUTH_SCHEMA,
363
+ });
364
+
365
+ successResponse(res, config);
366
+ } catch (error) {
367
+ logger.error('Failed to create OAuth configuration', { error });
368
+ next(error);
369
+ }
370
+ }
371
+ );
372
+
373
+ // PUT /api/auth/oauth/configs/:provider - Update OAuth configuration (admin only)
374
+ router.put(
375
+ '/configs/:provider',
376
+ verifyAdmin,
377
+ async (req: AuthRequest, res: Response, next: NextFunction) => {
378
+ try {
379
+ const provider = req.params.provider;
380
+ if (!provider || provider.length === 0 || provider.length > 50) {
381
+ throw new AppError('Invalid provider name', 400, ERROR_CODES.INVALID_INPUT);
382
+ }
383
+
384
+ const validationResult = updateOAuthConfigRequestSchema.safeParse(req.body);
385
+ if (!validationResult.success) {
386
+ throw new AppError(
387
+ validationResult.error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join(', '),
388
+ 400,
389
+ ERROR_CODES.INVALID_INPUT
390
+ );
391
+ }
392
+
393
+ const input = validationResult.data;
394
+
395
+ // Check if using shared keys when not allowed
396
+ if (input.useSharedKey && !isOAuthSharedKeysAvailable()) {
397
+ throw new AppError(
398
+ 'Shared OAuth keys are not enabled in this environment',
399
+ 400,
400
+ ERROR_CODES.AUTH_OAUTH_CONFIG_ERROR
401
+ );
402
+ }
403
+
404
+ const config = await oauthConfigService.updateConfig(provider, input);
405
+
406
+ await auditService.log({
407
+ actor: req.user?.email || 'api-key',
408
+ action: 'UPDATE_OAUTH_CONFIG',
409
+ module: 'AUTH',
410
+ details: {
411
+ provider,
412
+ updatedFields: Object.keys(input),
413
+ },
414
+ ip_address: req.ip,
415
+ });
416
+
417
+ // Broadcast configuration change
418
+ const socket = SocketService.getInstance();
419
+ socket.broadcastToRoom('role:project_admin', ServerEvents.DATA_UPDATE, {
420
+ resource: DataUpdateResourceType.AUTH_SCHEMA,
421
+ });
422
+
423
+ successResponse(res, config);
424
+ } catch (error) {
425
+ logger.error('Failed to update OAuth configuration', {
426
+ error,
427
+ provider: req.params.provider,
428
+ });
429
+ next(error);
430
+ }
431
+ }
432
+ );
433
+
434
+ // DELETE /api/auth/oauth/configs/:provider - Delete OAuth configuration (admin only)
435
+ router.delete(
436
+ '/configs/:provider',
437
+ verifyAdmin,
438
+ async (req: AuthRequest, res: Response, next: NextFunction) => {
439
+ try {
440
+ const provider = req.params.provider;
441
+ if (!provider || provider.length === 0 || provider.length > 50) {
442
+ throw new AppError('Invalid provider name', 400, ERROR_CODES.INVALID_INPUT);
443
+ }
444
+ const deleted = await oauthConfigService.deleteConfig(provider);
445
+
446
+ if (!deleted) {
447
+ throw new AppError(
448
+ `OAuth configuration for ${provider} not found`,
449
+ 404,
450
+ ERROR_CODES.NOT_FOUND
451
+ );
452
+ }
453
+
454
+ await auditService.log({
455
+ actor: req.user?.email || 'api-key',
456
+ action: 'DELETE_OAUTH_CONFIG',
457
+ module: 'AUTH',
458
+ details: { provider },
459
+ ip_address: req.ip,
460
+ });
461
+
462
+ // Broadcast configuration change
463
+ const socket = SocketService.getInstance();
464
+ socket.broadcastToRoom('role:project_admin', ServerEvents.DATA_UPDATE, {
465
+ resource: DataUpdateResourceType.AUTH_SCHEMA,
466
+ });
467
+
468
+ successResponse(res, {
469
+ success: true,
470
+ message: `OAuth configuration for ${provider} deleted successfully`,
471
+ });
472
+ } catch (error) {
473
+ logger.error('Failed to delete OAuth configuration', {
474
+ error,
475
+ provider: req.params.provider,
476
+ });
477
+ next(error);
478
+ }
479
+ }
480
+ );
481
+
482
+ export default router;