sea-dev 1.0.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 (784) hide show
  1. package/.claude/tasks/README.md +89 -0
  2. package/.cursor/rules/commits.mdc +31 -0
  3. package/.cursor/rules/general.mdc +84 -0
  4. package/.github/workflows/ci-cd.yml +141 -0
  5. package/CLAUDE.md +337 -0
  6. package/README.md +129 -0
  7. package/apps/api/.prettierignore +6 -0
  8. package/apps/api/.prettierrc.js +3 -0
  9. package/apps/api/dotenvx-safe.sh +11 -0
  10. package/apps/api/eslint.config.mjs +3 -0
  11. package/apps/api/package.json +58 -0
  12. package/apps/api/src/clients/posthog.ts +25 -0
  13. package/apps/api/src/dal/submission.ts +59 -0
  14. package/apps/api/src/errors.ts +55 -0
  15. package/apps/api/src/index.ts +21 -0
  16. package/apps/api/src/lib/channel.ts +28 -0
  17. package/apps/api/src/lib/config.ts +9 -0
  18. package/apps/api/src/lib/fmt.test.ts +9 -0
  19. package/apps/api/src/lib/fmt.ts +62 -0
  20. package/apps/api/src/lib/invariant.ts +23 -0
  21. package/apps/api/src/middleware/auth.ts +66 -0
  22. package/apps/api/src/routes/index.ts +20 -0
  23. package/apps/api/src/routes/v2/chat/handlers.ts +693 -0
  24. package/apps/api/src/routes/v2/chat/index.ts +257 -0
  25. package/apps/api/src/routes/v2/chat/schemas.ts +43 -0
  26. package/apps/api/src/routes/v2/deals/handlers.ts +64 -0
  27. package/apps/api/src/routes/v2/deals/index.ts +88 -0
  28. package/apps/api/src/routes/v2/deals/schemas.ts +38 -0
  29. package/apps/api/src/routes/v2/forms/handlers.ts +415 -0
  30. package/apps/api/src/routes/v2/forms/index.ts +382 -0
  31. package/apps/api/src/routes/v2/forms/schemas.ts +243 -0
  32. package/apps/api/src/routes/v2/index.ts +19 -0
  33. package/apps/api/src/routes/v2/pipelines/handlers.ts +261 -0
  34. package/apps/api/src/routes/v2/pipelines/index.ts +224 -0
  35. package/apps/api/src/routes/v2/pipelines/schemas.ts +173 -0
  36. package/apps/api/src/routes/v2/submissions/handlers.ts +555 -0
  37. package/apps/api/src/routes/v2/submissions/index.ts +366 -0
  38. package/apps/api/src/routes/v2/submissions/schemas.ts +233 -0
  39. package/apps/api/src/routes/v2/workflows/handlers.ts +81 -0
  40. package/apps/api/src/routes/v2/workflows/index.ts +88 -0
  41. package/apps/api/src/routes/v2/workflows/schemas.ts +40 -0
  42. package/apps/api/src/server.ts +146 -0
  43. package/apps/api/src/static/favicon.ico +0 -0
  44. package/apps/api/src/types/api.ts +14 -0
  45. package/apps/api/src/types/result.ts +3 -0
  46. package/apps/api/tsconfig.json +22 -0
  47. package/apps/api/vite.config.ts +28 -0
  48. package/apps/api/vitest.config.ts +14 -0
  49. package/apps/conversion-worker/Dockerfile +59 -0
  50. package/apps/conversion-worker/package.json +31 -0
  51. package/apps/conversion-worker/src/lib/config.ts +7 -0
  52. package/apps/conversion-worker/src/main.ts +22 -0
  53. package/apps/conversion-worker/src/workflows/convert-pptx.ts +116 -0
  54. package/apps/conversion-worker/tsconfig.json +27 -0
  55. package/apps/conversion-worker/vite.config.ts +33 -0
  56. package/apps/main/.prettierignore +6 -0
  57. package/apps/main/.prettierrc.js +3 -0
  58. package/apps/main/CLAUDE.md +245 -0
  59. package/apps/main/Procfile +1 -0
  60. package/apps/main/README.md +193 -0
  61. package/apps/main/db-tests.jsonl +116 -0
  62. package/apps/main/dotenvx-safe.sh +11 -0
  63. package/apps/main/drizzle/meta/_journal.json +1 -0
  64. package/apps/main/drizzle.config.ts +25 -0
  65. package/apps/main/eslint.config.mjs +3 -0
  66. package/apps/main/generate-routes.mjs +5 -0
  67. package/apps/main/package.json +131 -0
  68. package/apps/main/playwright.config.ts +23 -0
  69. package/apps/main/postcss.config.ts +5 -0
  70. package/apps/main/public/bg-dark.svg +10 -0
  71. package/apps/main/public/bg.svg +10 -0
  72. package/apps/main/public/favicon.ico +0 -0
  73. package/apps/main/run.sh +146 -0
  74. package/apps/main/scripts/browser.ts +14 -0
  75. package/apps/main/scripts/db-test-cov.ts +277 -0
  76. package/apps/main/scripts/login.ts +78 -0
  77. package/apps/main/scripts/repl.ts +61 -0
  78. package/apps/main/src/_foo.ts +31 -0
  79. package/apps/main/src/_tests/db.test.ts +19 -0
  80. package/apps/main/src/_tests/mock-db.ts +60 -0
  81. package/apps/main/src/client.tsx +13 -0
  82. package/apps/main/src/clients/loops.ts +13 -0
  83. package/apps/main/src/clients/polar.ts +12 -0
  84. package/apps/main/src/clients/posthog.ts +12 -0
  85. package/apps/main/src/components/chat/chat-context.tsx +99 -0
  86. package/apps/main/src/components/chat/chat-messages.tsx +184 -0
  87. package/apps/main/src/components/chat/chat-status.tsx +140 -0
  88. package/apps/main/src/components/chat/chat.tsx +458 -0
  89. package/apps/main/src/components/chat/citation-modal.tsx +54 -0
  90. package/apps/main/src/components/cta.tsx +21 -0
  91. package/apps/main/src/components/data-display/derived.tsx +40 -0
  92. package/apps/main/src/components/data-display/group-single.tsx +57 -0
  93. package/apps/main/src/components/data-display/group-table.tsx +165 -0
  94. package/apps/main/src/components/data-display/group-wrapper.tsx +54 -0
  95. package/apps/main/src/components/data-display/item.tsx +678 -0
  96. package/apps/main/src/components/error.tsx +45 -0
  97. package/apps/main/src/components/forms/error.tsx +22 -0
  98. package/apps/main/src/components/grid.tsx +7 -0
  99. package/apps/main/src/components/header/container.tsx +73 -0
  100. package/apps/main/src/components/header/header-bar.tsx +102 -0
  101. package/apps/main/src/components/modals/copy-display.tsx +37 -0
  102. package/apps/main/src/components/modals/copy-form.tsx +152 -0
  103. package/apps/main/src/components/modals/duplicate-workflow.tsx +89 -0
  104. package/apps/main/src/components/modals/field-correction.tsx +323 -0
  105. package/apps/main/src/components/modals/form-viewer.tsx +126 -0
  106. package/apps/main/src/components/modals/modals.tsx +44 -0
  107. package/apps/main/src/components/modals/new-deal.tsx +78 -0
  108. package/apps/main/src/components/modals/new-form.tsx +133 -0
  109. package/apps/main/src/components/modals/new-pipeline.tsx +70 -0
  110. package/apps/main/src/components/modals/new-submission.tsx +321 -0
  111. package/apps/main/src/components/modals/new-workflow.tsx +342 -0
  112. package/apps/main/src/components/modals/transformation-sources-modal.tsx +157 -0
  113. package/apps/main/src/components/modals/view-report.tsx +193 -0
  114. package/apps/main/src/components/not-found.tsx +14 -0
  115. package/apps/main/src/components/search/search-bar.tsx +178 -0
  116. package/apps/main/src/components/sheet-selector.tsx +135 -0
  117. package/apps/main/src/components/side-panel/doc-list.tsx +480 -0
  118. package/apps/main/src/components/sidebar/admin-sidebar.tsx +75 -0
  119. package/apps/main/src/components/sidebar/app-sidebar.tsx +417 -0
  120. package/apps/main/src/components/sidebar/model-select.tsx +134 -0
  121. package/apps/main/src/components/sidebar/settings-sidebar.tsx +132 -0
  122. package/apps/main/src/components/sidebar/sidebar-right.tsx +22 -0
  123. package/apps/main/src/components/sidebar/stop-impersonate.tsx +21 -0
  124. package/apps/main/src/components/svg/loading.tsx +33 -0
  125. package/apps/main/src/components/theme-selector.tsx +43 -0
  126. package/apps/main/src/components/unsaved-badge.tsx +19 -0
  127. package/apps/main/src/components/upload/file-upload.tsx +354 -0
  128. package/apps/main/src/fns/submission-groups.ts +28 -0
  129. package/apps/main/src/fns/submission-items.ts +11 -0
  130. package/apps/main/src/global-middleware.ts +16 -0
  131. package/apps/main/src/hooks/use-update-state.ts +18 -0
  132. package/apps/main/src/lib/auth-client.ts +16 -0
  133. package/apps/main/src/lib/auth.test.ts +359 -0
  134. package/apps/main/src/lib/auth.ts +144 -0
  135. package/apps/main/src/lib/billing.ts +23 -0
  136. package/apps/main/src/lib/config-iso.ts +76 -0
  137. package/apps/main/src/lib/config.ts +61 -0
  138. package/apps/main/src/lib/excel.ts +16 -0
  139. package/apps/main/src/lib/feedback-cache.ts +70 -0
  140. package/apps/main/src/lib/logger.ts +44 -0
  141. package/apps/main/src/lib/models.ts +22 -0
  142. package/apps/main/src/lib/not-found.ts +17 -0
  143. package/apps/main/src/lib/pdf.ts +16 -0
  144. package/apps/main/src/lib/tabularize.ts +54 -0
  145. package/apps/main/src/lib/utils.ts +10 -0
  146. package/apps/main/src/lib/zfd.ts +217 -0
  147. package/apps/main/src/middleware.ts +55 -0
  148. package/apps/main/src/routeTree.gen.ts +1255 -0
  149. package/apps/main/src/router.tsx +24 -0
  150. package/apps/main/src/routes/__root.tsx +92 -0
  151. package/apps/main/src/routes/_authed/_app/(dashboard)/index.tsx +227 -0
  152. package/apps/main/src/routes/_authed/_app/agents/$agentId/config.tsx +224 -0
  153. package/apps/main/src/routes/_authed/_app/agents/$agentId/index.tsx +206 -0
  154. package/apps/main/src/routes/_authed/_app/agents/-components/agent-actions-menu.tsx +94 -0
  155. package/apps/main/src/routes/_authed/_app/agents/-components/agent-artifacts.tsx +153 -0
  156. package/apps/main/src/routes/_authed/_app/agents/-components/agent-chat.tsx +220 -0
  157. package/apps/main/src/routes/_authed/_app/agents/-components/agent-history-menu.tsx +81 -0
  158. package/apps/main/src/routes/_authed/_app/agents/-components/agent-model-select.tsx +84 -0
  159. package/apps/main/src/routes/_authed/_app/agents/-components/agent-relevant-items.tsx +226 -0
  160. package/apps/main/src/routes/_authed/_app/agents/-components/agent-upload-button.tsx +298 -0
  161. package/apps/main/src/routes/_authed/_app/agents/-components/context-modal.tsx +187 -0
  162. package/apps/main/src/routes/_authed/_app/agents/-fns.ts +560 -0
  163. package/apps/main/src/routes/_authed/_app/agents/index.tsx +65 -0
  164. package/apps/main/src/routes/_authed/_app/deals/$dealId/$subId/-components/citation-tree.tsx +268 -0
  165. package/apps/main/src/routes/_authed/_app/deals/$dealId/$subId.tsx +655 -0
  166. package/apps/main/src/routes/_authed/_app/deals/$dealId/-components/doc-loading.tsx +37 -0
  167. package/apps/main/src/routes/_authed/_app/deals/$dealId/-components/share-link.tsx +42 -0
  168. package/apps/main/src/routes/_authed/_app/deals/$dealId/-components/submission-card.tsx +89 -0
  169. package/apps/main/src/routes/_authed/_app/deals/$dealId/-components/submission-filter.tsx +193 -0
  170. package/apps/main/src/routes/_authed/_app/deals/$dealId/-components/submissions.tsx +36 -0
  171. package/apps/main/src/routes/_authed/_app/deals/$dealId/-components/summary.tsx +82 -0
  172. package/apps/main/src/routes/_authed/_app/deals/$dealId/-components/upload-doc.tsx +120 -0
  173. package/apps/main/src/routes/_authed/_app/deals/$dealId/-fns.ts +653 -0
  174. package/apps/main/src/routes/_authed/_app/deals/$dealId/index.tsx +259 -0
  175. package/apps/main/src/routes/_authed/_app/deals/$dealId/route.tsx +29 -0
  176. package/apps/main/src/routes/_authed/_app/deals/index.tsx +104 -0
  177. package/apps/main/src/routes/_authed/_app/feedback/index.tsx +639 -0
  178. package/apps/main/src/routes/_authed/_app/feedback/insights.tsx +250 -0
  179. package/apps/main/src/routes/_authed/_app/pipelines/$pipelineId/$runId/-components/blockers-panel.tsx +260 -0
  180. package/apps/main/src/routes/_authed/_app/pipelines/$pipelineId/$runId/-components/manual-input-panel.tsx +301 -0
  181. package/apps/main/src/routes/_authed/_app/pipelines/$pipelineId/$runId/-components/submission-selector-modal.tsx +143 -0
  182. package/apps/main/src/routes/_authed/_app/pipelines/$pipelineId/$runId/-components/upload-doc.tsx +120 -0
  183. package/apps/main/src/routes/_authed/_app/pipelines/$pipelineId/$runId/index.tsx +1485 -0
  184. package/apps/main/src/routes/_authed/_app/pipelines/$pipelineId/-components/dag-view.tsx +296 -0
  185. package/apps/main/src/routes/_authed/_app/pipelines/$pipelineId/-components/step-config-modal.tsx +634 -0
  186. package/apps/main/src/routes/_authed/_app/pipelines/$pipelineId/index.tsx +911 -0
  187. package/apps/main/src/routes/_authed/_app/pipelines/-fns.ts +510 -0
  188. package/apps/main/src/routes/_authed/_app/pipelines/index.tsx +103 -0
  189. package/apps/main/src/routes/_authed/_app/reports/$reportId.tsx +397 -0
  190. package/apps/main/src/routes/_authed/_app/reports/-fns.ts +11 -0
  191. package/apps/main/src/routes/_authed/_app/reports/index.tsx +22 -0
  192. package/apps/main/src/routes/_authed/_app/route.tsx +48 -0
  193. package/apps/main/src/routes/_authed/_app/submissions/-columns.tsx +161 -0
  194. package/apps/main/src/routes/_authed/_app/submissions/-fns.ts +128 -0
  195. package/apps/main/src/routes/_authed/_app/submissions/index.tsx +190 -0
  196. package/apps/main/src/routes/_authed/_app/workflows/$wfSlug/$formId.tsx +542 -0
  197. package/apps/main/src/routes/_authed/_app/workflows/$wfSlug/-components/derived.tsx +154 -0
  198. package/apps/main/src/routes/_authed/_app/workflows/$wfSlug/-components/field.tsx +369 -0
  199. package/apps/main/src/routes/_authed/_app/workflows/$wfSlug/-components/group.tsx +475 -0
  200. package/apps/main/src/routes/_authed/_app/workflows/$wfSlug/index.tsx +263 -0
  201. package/apps/main/src/routes/_authed/_app/workflows/$wfSlug/route.tsx +33 -0
  202. package/apps/main/src/routes/_authed/_app/workflows/-components/form-card.tsx +315 -0
  203. package/apps/main/src/routes/_authed/_app/workflows/index.tsx +86 -0
  204. package/apps/main/src/routes/_authed/admin/index.tsx +12 -0
  205. package/apps/main/src/routes/_authed/admin/route.tsx +42 -0
  206. package/apps/main/src/routes/_authed/admin/users/-columns.tsx +124 -0
  207. package/apps/main/src/routes/_authed/admin/users/-fns.ts +30 -0
  208. package/apps/main/src/routes/_authed/admin/users/index.tsx +29 -0
  209. package/apps/main/src/routes/_authed/catchNotFound.tsx +114 -0
  210. package/apps/main/src/routes/_authed/redirects/forms.$id.tsx +29 -0
  211. package/apps/main/src/routes/_authed/redirects/submissions.$id.tsx +27 -0
  212. package/apps/main/src/routes/_authed/redirects/workflows.$id.tsx +27 -0
  213. package/apps/main/src/routes/_authed/route.tsx +51 -0
  214. package/apps/main/src/routes/_authed/settings/-components/new-api-key.tsx +85 -0
  215. package/apps/main/src/routes/_authed/settings/-components/new-invite.tsx +100 -0
  216. package/apps/main/src/routes/_authed/settings/analytics.tsx +1710 -0
  217. package/apps/main/src/routes/_authed/settings/billing/-components/price-table.tsx +129 -0
  218. package/apps/main/src/routes/_authed/settings/billing/-fns.ts +76 -0
  219. package/apps/main/src/routes/_authed/settings/billing/index.tsx +119 -0
  220. package/apps/main/src/routes/_authed/settings/embed.tsx +337 -0
  221. package/apps/main/src/routes/_authed/settings/index.tsx +12 -0
  222. package/apps/main/src/routes/_authed/settings/keys.tsx +157 -0
  223. package/apps/main/src/routes/_authed/settings/members.tsx +276 -0
  224. package/apps/main/src/routes/_authed/settings/route.tsx +22 -0
  225. package/apps/main/src/routes/_authed/settings/user.tsx +87 -0
  226. package/apps/main/src/routes/_authed/settings/workspace.tsx +206 -0
  227. package/apps/main/src/routes/_public/-components/sign-in-up.tsx +96 -0
  228. package/apps/main/src/routes/_public/embedded.tsx +57 -0
  229. package/apps/main/src/routes/_public/invite.$inviteId.tsx +143 -0
  230. package/apps/main/src/routes/_public/no-access.tsx +38 -0
  231. package/apps/main/src/routes/_public/no-invite.tsx +39 -0
  232. package/apps/main/src/routes/_public/otp.tsx +103 -0
  233. package/apps/main/src/routes/_public/route.tsx +15 -0
  234. package/apps/main/src/routes/_public/sign-in.tsx +111 -0
  235. package/apps/main/src/routes/_public/sign-up.tsx +114 -0
  236. package/apps/main/src/routes/api/auth/$.ts +11 -0
  237. package/apps/main/src/routes/api/billing/paid.ts +42 -0
  238. package/apps/main/src/routes/api/billing/webhooks.ts +70 -0
  239. package/apps/main/src/routes/api/chat/agent.ts +40 -0
  240. package/apps/main/src/routes/api/chat/key.ts +42 -0
  241. package/apps/main/src/routes/api/chat/member.ts +35 -0
  242. package/apps/main/src/routes/api/test/index.ts +19 -0
  243. package/apps/main/src/server.tsx +6 -0
  244. package/apps/main/src/styles/app.css +23 -0
  245. package/apps/main/src/vite-env.d.ts +7 -0
  246. package/apps/main/test.http +6 -0
  247. package/apps/main/tsconfig.json +17 -0
  248. package/apps/main/vite.config.ts +24 -0
  249. package/apps/main/vitest.config.js +17 -0
  250. package/apps/mcp/README.md +171 -0
  251. package/apps/mcp/eslint.config.mjs +3 -0
  252. package/apps/mcp/package.json +37 -0
  253. package/apps/mcp/src/index.ts +414 -0
  254. package/apps/mcp/tsconfig.json +19 -0
  255. package/apps/mcp/vite.config.ts +22 -0
  256. package/apps/posthog-proxy/index.html +9 -0
  257. package/apps/workers/.prettierignore +7 -0
  258. package/apps/workers/.prettierrc.js +3 -0
  259. package/apps/workers/dotenvx-safe.sh +11 -0
  260. package/apps/workers/eslint.config.mjs +3 -0
  261. package/apps/workers/package.json +65 -0
  262. package/apps/workers/src/lib/config.ts +7 -0
  263. package/apps/workers/src/lib/messages.ts +0 -0
  264. package/apps/workers/src/lib/posthog.ts +25 -0
  265. package/apps/workers/src/main.ts +58 -0
  266. package/apps/workers/src/workflows/extraction.ts +866 -0
  267. package/apps/workers/src/workflows/index.ts +3 -0
  268. package/apps/workers/src/workflows/pipeline-dag.ts +210 -0
  269. package/apps/workers/src/workflows/pipeline-steps.ts +1393 -0
  270. package/apps/workers/tsconfig.json +16 -0
  271. package/apps/workers/vite.config.ts +35 -0
  272. package/docs/CHANGELOG.md +84 -0
  273. package/docs/agent-templates-and-runs.md +859 -0
  274. package/docs/aws-migration-plan.md +267 -0
  275. package/docs/impl-p0-form-builder-improvements.md +683 -0
  276. package/docs/on-prem-deployment-spec.docx +0 -0
  277. package/docs/on-prem-deployment-spec.md +378 -0
  278. package/docs/prd-form-builder-strategy.md +1120 -0
  279. package/docs/widget-ng-apf-packaging-spec.md +43 -0
  280. package/infra/k8s/charts/seadotdev/Chart.yaml +6 -0
  281. package/infra/k8s/charts/seadotdev/templates/_helpers.tpl +27 -0
  282. package/infra/k8s/charts/seadotdev/templates/api-v2.yaml +105 -0
  283. package/infra/k8s/charts/seadotdev/templates/external-secrets.yaml +83 -0
  284. package/infra/k8s/charts/seadotdev/templates/ingress.yaml +54 -0
  285. package/infra/k8s/charts/seadotdev/templates/main-app.yaml +104 -0
  286. package/infra/k8s/charts/seadotdev/templates/workers.yaml +182 -0
  287. package/infra/k8s/charts/seadotdev/values.yaml +143 -0
  288. package/infra/terraform/main.tf +399 -0
  289. package/libs/ai/.prettierignore +2 -0
  290. package/libs/ai/.prettierrc.js +5 -0
  291. package/libs/ai/README.md +139 -0
  292. package/libs/ai/eslint.config.mjs +3 -0
  293. package/libs/ai/package.json +42 -0
  294. package/libs/ai/src/index.ts +5 -0
  295. package/libs/ai/src/models.ts +19 -0
  296. package/libs/ai/src/rag/index.ts +1 -0
  297. package/libs/ai/src/rag/rag.test.ts +99 -0
  298. package/libs/ai/src/rag/rag.ts +510 -0
  299. package/libs/ai/tsconfig.json +21 -0
  300. package/libs/ai/vite.config.ts +38 -0
  301. package/libs/cache/.prettierignore +2 -0
  302. package/libs/cache/eslint.config.mjs +3 -0
  303. package/libs/cache/package.json +35 -0
  304. package/libs/cache/src/feedback.ts +77 -0
  305. package/libs/cache/src/index.ts +2 -0
  306. package/libs/cache/tsconfig.json +19 -0
  307. package/libs/cache/vite.config.ts +36 -0
  308. package/libs/clients/.prettierignore +6 -0
  309. package/libs/clients/eslint.config.mjs +3 -0
  310. package/libs/clients/package.json +59 -0
  311. package/libs/clients/src/azure.ts +249 -0
  312. package/libs/clients/src/gcp.ts +220 -0
  313. package/libs/clients/src/hatchet.ts +86 -0
  314. package/libs/clients/src/index.ts +8 -0
  315. package/libs/clients/src/loops.ts +86 -0
  316. package/libs/clients/src/polar.ts +77 -0
  317. package/libs/clients/src/posthog.ts +55 -0
  318. package/libs/clients/tsconfig.json +19 -0
  319. package/libs/clients/vite.config.ts +35 -0
  320. package/libs/config/.prettierignore +6 -0
  321. package/libs/config/.prettierrc.js +12 -0
  322. package/libs/config/eslint.config.mjs +3 -0
  323. package/libs/config/package.json +50 -0
  324. package/libs/config/src/azure.ts +54 -0
  325. package/libs/config/src/db.ts +18 -0
  326. package/libs/config/src/gcp.ts +53 -0
  327. package/libs/config/src/google.ts +17 -0
  328. package/libs/config/src/hatchet.ts +20 -0
  329. package/libs/config/src/index.ts +108 -0
  330. package/libs/config/src/llm.ts +17 -0
  331. package/libs/config/src/polar.ts +24 -0
  332. package/libs/config/src/util.ts +8 -0
  333. package/libs/config/src/vercel.ts +26 -0
  334. package/libs/config/tsconfig.json +19 -0
  335. package/libs/config/vite.config.ts +34 -0
  336. package/libs/core/.prettierignore +2 -0
  337. package/libs/core/eslint.config.mjs +3 -0
  338. package/libs/core/package.json +59 -0
  339. package/libs/core/src/chat/derived.ts +97 -0
  340. package/libs/core/src/chat/feedback.ts +293 -0
  341. package/libs/core/src/chat/index.ts +6 -0
  342. package/libs/core/src/chat/model.ts +92 -0
  343. package/libs/core/src/chat/prepare-tools.ts +286 -0
  344. package/libs/core/src/chat/prompts.ts +623 -0
  345. package/libs/core/src/chat/stream.ts +311 -0
  346. package/libs/core/src/chat/summarize.ts +168 -0
  347. package/libs/core/src/chat/tools/agent.ts +403 -0
  348. package/libs/core/src/chat/tools/chart-agent.ts +526 -0
  349. package/libs/core/src/chat/tools/chart-helpers/sandbox.ts +47 -0
  350. package/libs/core/src/chat/tools/chart.ts +86 -0
  351. package/libs/core/src/chat/tools/credit-agent.ts +1383 -0
  352. package/libs/core/src/chat/tools/credit.ts +1435 -0
  353. package/libs/core/src/chat/tools/deep-dive-agent.ts +100 -0
  354. package/libs/core/src/chat/tools/deep-dive.ts +141 -0
  355. package/libs/core/src/chat/tools/form.ts +449 -0
  356. package/libs/core/src/chat/tools/helpers.ts +91 -0
  357. package/libs/core/src/chat/tools/index.ts +42 -0
  358. package/libs/core/src/chat/tools/pipeline-artifact.ts +76 -0
  359. package/libs/core/src/chat/tools/report.ts +40 -0
  360. package/libs/core/src/chat/tools/search.ts +390 -0
  361. package/libs/core/src/chat/tools/submission.ts +227 -0
  362. package/libs/core/src/chat/tools/workflow.ts +684 -0
  363. package/libs/core/src/chat/types.ts +3 -0
  364. package/libs/core/src/data-extraction/classification/azure.ts +168 -0
  365. package/libs/core/src/data-extraction/classification/index.ts +1 -0
  366. package/libs/core/src/data-extraction/dal.ts +246 -0
  367. package/libs/core/src/data-extraction/form-structure-extractor.ts +294 -0
  368. package/libs/core/src/data-extraction/index.ts +4 -0
  369. package/libs/core/src/data-extraction/layout/azure.ts +730 -0
  370. package/libs/core/src/data-extraction/layout/excel.ts +180 -0
  371. package/libs/core/src/data-extraction/layout/gcp.ts +1071 -0
  372. package/libs/core/src/data-extraction/layout/index.ts +266 -0
  373. package/libs/core/src/data-extraction/layout/plaintext.ts +45 -0
  374. package/libs/core/src/data-extraction/models.ts +38 -0
  375. package/libs/core/src/data-extraction/pdf-utils.ts +96 -0
  376. package/libs/core/src/data-extraction/structuring/bank-statement.ts +1182 -0
  377. package/libs/core/src/data-extraction/structuring/custom.ts +495 -0
  378. package/libs/core/src/data-extraction/structuring/index.ts +290 -0
  379. package/libs/core/src/data-extraction/structuring/prompts.ts +69 -0
  380. package/libs/core/src/data-extraction/type-guards.ts +110 -0
  381. package/libs/core/src/data-extraction/types.ts +84 -0
  382. package/libs/core/src/data-extraction/utils.ts +31 -0
  383. package/libs/core/src/data-extraction/validation/bank-statement.ts +127 -0
  384. package/libs/core/src/deals.ts +17 -0
  385. package/libs/core/src/documents.ts +152 -0
  386. package/libs/core/src/index.ts +5 -0
  387. package/libs/core/src/pipelines/display.ts +678 -0
  388. package/libs/core/src/pipelines/execute.ts +2342 -0
  389. package/libs/core/src/pipelines/index.ts +4 -0
  390. package/libs/core/src/pipelines/list.ts +12 -0
  391. package/libs/core/src/pipelines/runs.ts +53 -0
  392. package/libs/core/tsconfig.json +20 -0
  393. package/libs/core/vite.config.ts +56 -0
  394. package/libs/dal/.prettierignore +6 -0
  395. package/libs/dal/.prettierrc.js +12 -0
  396. package/libs/dal/eslint.config.mjs +3 -0
  397. package/libs/dal/package.json +57 -0
  398. package/libs/dal/src/_tests/db.test.ts +19 -0
  399. package/libs/dal/src/_tests/mock-db.ts +60 -0
  400. package/libs/dal/src/api-key.test.ts +397 -0
  401. package/libs/dal/src/api-key.ts +110 -0
  402. package/libs/dal/src/billing.ts +23 -0
  403. package/libs/dal/src/conversation.test.ts +655 -0
  404. package/libs/dal/src/conversation.ts +532 -0
  405. package/libs/dal/src/deal.test.ts +45 -0
  406. package/libs/dal/src/deal.ts +87 -0
  407. package/libs/dal/src/defaults-consumer-lending-uk.ts +33 -0
  408. package/libs/dal/src/defaults-consumer-lending-us.ts +33 -0
  409. package/libs/dal/src/defaults-private-credit.ts +57 -0
  410. package/libs/dal/src/defaults-private-equity.ts +51 -0
  411. package/libs/dal/src/defaults-smb-lending-us.ts +1569 -0
  412. package/libs/dal/src/defaults-sme-lending-uk-express.ts +1527 -0
  413. package/libs/dal/src/defaults-sme-lending-uk.ts +1669 -0
  414. package/libs/dal/src/defaults-types.ts +23 -0
  415. package/libs/dal/src/defaults.ts +550 -0
  416. package/libs/dal/src/document.test.ts +70 -0
  417. package/libs/dal/src/document.ts +192 -0
  418. package/libs/dal/src/feedback.ts +255 -0
  419. package/libs/dal/src/form.test.ts +637 -0
  420. package/libs/dal/src/form.ts +1165 -0
  421. package/libs/dal/src/index.ts +20 -0
  422. package/libs/dal/src/invitation.test.ts +746 -0
  423. package/libs/dal/src/invitation.ts +207 -0
  424. package/libs/dal/src/member.test.ts +185 -0
  425. package/libs/dal/src/member.ts +80 -0
  426. package/libs/dal/src/organization.ts +116 -0
  427. package/libs/dal/src/permission.ts +25 -0
  428. package/libs/dal/src/pipeline.test.ts +388 -0
  429. package/libs/dal/src/pipeline.ts +4222 -0
  430. package/libs/dal/src/report.ts +199 -0
  431. package/libs/dal/src/result.ts +16 -0
  432. package/libs/dal/src/search.ts +172 -0
  433. package/libs/dal/src/session.test.ts +110 -0
  434. package/libs/dal/src/session.ts +31 -0
  435. package/libs/dal/src/submission.test.ts +1304 -0
  436. package/libs/dal/src/submission.ts +1396 -0
  437. package/libs/dal/src/tool.ts +159 -0
  438. package/libs/dal/src/user.ts +16 -0
  439. package/libs/dal/src/workflow.test.ts +89 -0
  440. package/libs/dal/src/workflow.ts +262 -0
  441. package/libs/dal/tsconfig.build.json +4 -0
  442. package/libs/dal/tsconfig.json +22 -0
  443. package/libs/dal/vite.config.ts +34 -0
  444. package/libs/db/.prettierignore +6 -0
  445. package/libs/db/.prettierrc.js +12 -0
  446. package/libs/db/eslint.config.mjs +3 -0
  447. package/libs/db/package.json +52 -0
  448. package/libs/db/src/index.ts +24 -0
  449. package/libs/db/src/relations.ts +549 -0
  450. package/libs/db/src/schema.ts +2 -0
  451. package/libs/db/src/schemas/api.ts +35 -0
  452. package/libs/db/src/schemas/conversations.ts +175 -0
  453. package/libs/db/src/schemas/core.ts +359 -0
  454. package/libs/db/src/schemas/documents.ts +181 -0
  455. package/libs/db/src/schemas/feedback.ts +40 -0
  456. package/libs/db/src/schemas/index.ts +26 -0
  457. package/libs/db/src/schemas/organisations.ts +97 -0
  458. package/libs/db/src/schemas/pipelines.ts +440 -0
  459. package/libs/db/src/schemas/users.ts +95 -0
  460. package/libs/db/src/types.ts +190 -0
  461. package/libs/db/src/utils.ts +14 -0
  462. package/libs/db/tsconfig.json +19 -0
  463. package/libs/db/vite.config.ts +31 -0
  464. package/libs/lint/.prettierignore +6 -0
  465. package/libs/lint/eslint.config.mjs +61 -0
  466. package/libs/lint/package.json +29 -0
  467. package/libs/lint/prettier.config.js +12 -0
  468. package/libs/schemas/.prettierignore +6 -0
  469. package/libs/schemas/.prettierrc.js +12 -0
  470. package/libs/schemas/README.md +15 -0
  471. package/libs/schemas/eslint.config.mjs +3 -0
  472. package/libs/schemas/package.json +67 -0
  473. package/libs/schemas/src/core/chat.ts +67 -0
  474. package/libs/schemas/src/core/core-result.ts +15 -0
  475. package/libs/schemas/src/core/data-extraction.ts +184 -0
  476. package/libs/schemas/src/core/layout.ts +478 -0
  477. package/libs/schemas/src/core/pipeline.ts +128 -0
  478. package/libs/schemas/src/core/submission.ts +97 -0
  479. package/libs/schemas/src/db/account.ts +57 -0
  480. package/libs/schemas/src/db/apiKey.ts +57 -0
  481. package/libs/schemas/src/db/context.ts +33 -0
  482. package/libs/schemas/src/db/conversation.ts +65 -0
  483. package/libs/schemas/src/db/deal.ts +42 -0
  484. package/libs/schemas/src/db/document.ts +103 -0
  485. package/libs/schemas/src/db/documentCitation.ts +58 -0
  486. package/libs/schemas/src/db/documentExtraction.ts +69 -0
  487. package/libs/schemas/src/db/fieldCorrection.ts +85 -0
  488. package/libs/schemas/src/db/form.ts +45 -0
  489. package/libs/schemas/src/db/formField.ts +59 -0
  490. package/libs/schemas/src/db/formGroup.ts +42 -0
  491. package/libs/schemas/src/db/impersonation.ts +39 -0
  492. package/libs/schemas/src/db/index.ts +25 -0
  493. package/libs/schemas/src/db/invitation.ts +42 -0
  494. package/libs/schemas/src/db/member.ts +36 -0
  495. package/libs/schemas/src/db/message.ts +58 -0
  496. package/libs/schemas/src/db/organization.ts +62 -0
  497. package/libs/schemas/src/db/session.ts +48 -0
  498. package/libs/schemas/src/db/submission.ts +54 -0
  499. package/libs/schemas/src/db/submissionGroup.ts +36 -0
  500. package/libs/schemas/src/db/submissionItem.ts +33 -0
  501. package/libs/schemas/src/db/submissionItemVersion.ts +70 -0
  502. package/libs/schemas/src/db/user.ts +51 -0
  503. package/libs/schemas/src/db/utils.ts +3 -0
  504. package/libs/schemas/src/db/verification.ts +36 -0
  505. package/libs/schemas/src/db/workflow.ts +42 -0
  506. package/libs/schemas/src/index.ts +10 -0
  507. package/libs/schemas/tsconfig.json +21 -0
  508. package/libs/schemas/vite.config.ts +38 -0
  509. package/libs/ui/.prettierignore +6 -0
  510. package/libs/ui/.prettierrc.js +12 -0
  511. package/libs/ui/components.json +24 -0
  512. package/libs/ui/eslint.config.mjs +3 -0
  513. package/libs/ui/package.json +142 -0
  514. package/libs/ui/src/components/chart-viz/chart.tsx +255 -0
  515. package/libs/ui/src/components/chart-viz/converters.ts +474 -0
  516. package/libs/ui/src/components/chart-viz/dashboard.tsx +146 -0
  517. package/libs/ui/src/components/chart-viz/index.ts +37 -0
  518. package/libs/ui/src/components/chart-viz/markdown.tsx +344 -0
  519. package/libs/ui/src/components/chart-viz/table.tsx +446 -0
  520. package/libs/ui/src/components/chart-viz/theme-context.tsx +70 -0
  521. package/libs/ui/src/components/chart-viz/themes/dark.ts +98 -0
  522. package/libs/ui/src/components/chart-viz/themes/index.ts +69 -0
  523. package/libs/ui/src/components/chart-viz/themes/light.ts +98 -0
  524. package/libs/ui/src/components/chart-viz/themes/tailwind.ts +326 -0
  525. package/libs/ui/src/components/chart-viz/themes/types.ts +99 -0
  526. package/libs/ui/src/components/chart-viz/tool-display.tsx +150 -0
  527. package/libs/ui/src/components/chart-viz/types.ts +95 -0
  528. package/libs/ui/src/components/doc-viewers/excel/index.tsx +431 -0
  529. package/libs/ui/src/components/doc-viewers/excel/themes.ts +160 -0
  530. package/libs/ui/src/components/doc-viewers/image/index.tsx +410 -0
  531. package/libs/ui/src/components/doc-viewers/pdf/index.tsx +258 -0
  532. package/libs/ui/src/components/doc-viewers/pdf/virtualized-pdf.tsx +556 -0
  533. package/libs/ui/src/components/misc/rel-date.tsx +52 -0
  534. package/libs/ui/src/components/misc/styled-link.tsx +2 -0
  535. package/libs/ui/src/components/table/data-table.tsx +546 -0
  536. package/libs/ui/src/components/table/report-table.tsx +305 -0
  537. package/libs/ui/src/components/table/sortable-column.tsx +34 -0
  538. package/libs/ui/src/components/ui/accordion.tsx +62 -0
  539. package/libs/ui/src/components/ui/alert-dialog.tsx +142 -0
  540. package/libs/ui/src/components/ui/alert.tsx +62 -0
  541. package/libs/ui/src/components/ui/artifact.tsx +118 -0
  542. package/libs/ui/src/components/ui/attachments.tsx +388 -0
  543. package/libs/ui/src/components/ui/avatar.tsx +39 -0
  544. package/libs/ui/src/components/ui/badge.tsx +43 -0
  545. package/libs/ui/src/components/ui/breadcrumb.tsx +102 -0
  546. package/libs/ui/src/components/ui/button-group.tsx +78 -0
  547. package/libs/ui/src/components/ui/button.tsx +79 -0
  548. package/libs/ui/src/components/ui/card.tsx +32 -0
  549. package/libs/ui/src/components/ui/carousel.tsx +228 -0
  550. package/libs/ui/src/components/ui/chain-of-thought.tsx +198 -0
  551. package/libs/ui/src/components/ui/checkbox.tsx +27 -0
  552. package/libs/ui/src/components/ui/citation.tsx +34 -0
  553. package/libs/ui/src/components/ui/code-block.tsx +500 -0
  554. package/libs/ui/src/components/ui/collapsible.tsx +19 -0
  555. package/libs/ui/src/components/ui/command.tsx +161 -0
  556. package/libs/ui/src/components/ui/conversation.tsx +90 -0
  557. package/libs/ui/src/components/ui/dialog.tsx +142 -0
  558. package/libs/ui/src/components/ui/dropdown-menu.tsx +246 -0
  559. package/libs/ui/src/components/ui/highlight.tsx +3 -0
  560. package/libs/ui/src/components/ui/hover-card.tsx +36 -0
  561. package/libs/ui/src/components/ui/inline-citation.tsx +251 -0
  562. package/libs/ui/src/components/ui/input-group.tsx +156 -0
  563. package/libs/ui/src/components/ui/input-otp.tsx +78 -0
  564. package/libs/ui/src/components/ui/input.tsx +21 -0
  565. package/libs/ui/src/components/ui/label.tsx +19 -0
  566. package/libs/ui/src/components/ui/model-selector.tsx +174 -0
  567. package/libs/ui/src/components/ui/multisidebar.tsx +750 -0
  568. package/libs/ui/src/components/ui/popover.tsx +43 -0
  569. package/libs/ui/src/components/ui/progress.tsx +28 -0
  570. package/libs/ui/src/components/ui/reasoning.tsx +178 -0
  571. package/libs/ui/src/components/ui/resizable.tsx +49 -0
  572. package/libs/ui/src/components/ui/scroll-area.tsx +54 -0
  573. package/libs/ui/src/components/ui/select.tsx +171 -0
  574. package/libs/ui/src/components/ui/separator.tsx +26 -0
  575. package/libs/ui/src/components/ui/sheet.tsx +128 -0
  576. package/libs/ui/src/components/ui/shimmer.tsx +53 -0
  577. package/libs/ui/src/components/ui/skeleton.tsx +13 -0
  578. package/libs/ui/src/components/ui/sonner.tsx +23 -0
  579. package/libs/ui/src/components/ui/switch.tsx +26 -0
  580. package/libs/ui/src/components/ui/table.tsx +96 -0
  581. package/libs/ui/src/components/ui/tabs.tsx +52 -0
  582. package/libs/ui/src/components/ui/textarea.tsx +41 -0
  583. package/libs/ui/src/components/ui/tool.tsx +209 -0
  584. package/libs/ui/src/components/ui/tooltip.tsx +58 -0
  585. package/libs/ui/src/components/ui/typography.tsx +113 -0
  586. package/libs/ui/src/fonts/manrope-v15-latin-300.woff2 +0 -0
  587. package/libs/ui/src/fonts/manrope-v15-latin-400.woff2 +0 -0
  588. package/libs/ui/src/fonts/manrope-v15-latin-500.woff2 +0 -0
  589. package/libs/ui/src/fonts/manrope-v15-latin-600.woff2 +0 -0
  590. package/libs/ui/src/hooks/use-mobile.ts +19 -0
  591. package/libs/ui/src/lib/utils.ts +6 -0
  592. package/libs/ui/src/styles/fonts.css +35 -0
  593. package/libs/ui/src/styles/style.css +218 -0
  594. package/libs/ui/tsconfig.json +21 -0
  595. package/libs/ui/vite.config.ts +80 -0
  596. package/libs/ui-lit/README.md +245 -0
  597. package/libs/ui-lit/TESTING_GUIDE.md +296 -0
  598. package/libs/ui-lit/eslint.config.mjs +3 -0
  599. package/libs/ui-lit/package.json +41 -0
  600. package/libs/ui-lit/scripts/build-css.js +43 -0
  601. package/libs/ui-lit/src/components/sea-alert.ts +132 -0
  602. package/libs/ui-lit/src/components/sea-button.ts +95 -0
  603. package/libs/ui-lit/src/components/sea-card.ts +113 -0
  604. package/libs/ui-lit/src/components/sea-input.ts +184 -0
  605. package/libs/ui-lit/src/components/sea-spinner.ts +65 -0
  606. package/libs/ui-lit/src/index.ts +15 -0
  607. package/libs/ui-lit/src/lib/utils.ts +6 -0
  608. package/libs/ui-lit/src/styles/tailwind.css +76 -0
  609. package/libs/ui-lit/src/theme.css +66 -0
  610. package/libs/ui-lit/src/theme.ts +79 -0
  611. package/libs/ui-lit/src/vite-env.d.ts +6 -0
  612. package/libs/ui-lit/tailwind.config.ts +50 -0
  613. package/libs/ui-lit/test.html +289 -0
  614. package/libs/ui-lit/tsconfig.json +23 -0
  615. package/libs/ui-lit/vite.config.ts +31 -0
  616. package/libs/ui-lit/vite.css.config.ts +20 -0
  617. package/libs/util/.prettierignore +6 -0
  618. package/libs/util/.prettierrc.js +12 -0
  619. package/libs/util/eslint.config.mjs +3 -0
  620. package/libs/util/package.json +45 -0
  621. package/libs/util/src/billing.ts +10 -0
  622. package/libs/util/src/data-transform.ts +19 -0
  623. package/libs/util/src/encryption.ts +45 -0
  624. package/libs/util/src/fmt.test.ts +9 -0
  625. package/libs/util/src/fmt.ts +71 -0
  626. package/libs/util/src/fuzzy.ts +47 -0
  627. package/libs/util/src/id.ts +24 -0
  628. package/libs/util/src/invariant.ts +31 -0
  629. package/libs/util/src/sub-name.ts +7 -0
  630. package/libs/util/tsconfig.json +19 -0
  631. package/libs/util/vite.config.ts +34 -0
  632. package/package.json +28 -0
  633. package/packages/widget/.prettierignore +6 -0
  634. package/packages/widget/.prettierrc.js +12 -0
  635. package/packages/widget/README.md +95 -0
  636. package/packages/widget/eslint.config.mjs +11 -0
  637. package/packages/widget/openapi-ts.config.ts +8 -0
  638. package/packages/widget/package.json +89 -0
  639. package/packages/widget/postcss.config.mjs +10 -0
  640. package/packages/widget/src/clients/api/client/client.ts +187 -0
  641. package/packages/widget/src/clients/api/client/index.ts +22 -0
  642. package/packages/widget/src/clients/api/client/types.ts +192 -0
  643. package/packages/widget/src/clients/api/client/utils.ts +394 -0
  644. package/packages/widget/src/clients/api/client.gen.ts +18 -0
  645. package/packages/widget/src/clients/api/core/auth.ts +39 -0
  646. package/packages/widget/src/clients/api/core/bodySerializer.ts +74 -0
  647. package/packages/widget/src/clients/api/core/params.ts +132 -0
  648. package/packages/widget/src/clients/api/core/pathSerializer.ts +169 -0
  649. package/packages/widget/src/clients/api/core/types.ts +80 -0
  650. package/packages/widget/src/clients/api/index.ts +3 -0
  651. package/packages/widget/src/clients/api/sdk.gen.ts +805 -0
  652. package/packages/widget/src/clients/api/types.gen.ts +2085 -0
  653. package/packages/widget/src/components/container.tsx +42 -0
  654. package/packages/widget/src/components/data-display.tsx +384 -0
  655. package/packages/widget/src/components/data-viewer.tsx +311 -0
  656. package/packages/widget/src/components/doc-list.tsx +102 -0
  657. package/packages/widget/src/components/field-correction-modal.tsx +265 -0
  658. package/packages/widget/src/components/header.tsx +71 -0
  659. package/packages/widget/src/components/new-submission.tsx +290 -0
  660. package/packages/widget/src/components/sidebar-right.tsx +19 -0
  661. package/packages/widget/src/components/submission-card.tsx +66 -0
  662. package/packages/widget/src/components/submission-page.tsx +75 -0
  663. package/packages/widget/src/components/upload-doc.tsx +241 -0
  664. package/packages/widget/src/components/widget.tsx +101 -0
  665. package/packages/widget/src/index.tsx +167 -0
  666. package/packages/widget/src/lib/config.ts +2 -0
  667. package/packages/widget/src/lib/util.ts +40 -0
  668. package/packages/widget/src/styles/index.css +5 -0
  669. package/packages/widget/src/styles/tw-properties.css +337 -0
  670. package/packages/widget/src/vite-env.d.ts +3 -0
  671. package/packages/widget/tsconfig.app.json +35 -0
  672. package/packages/widget/tsconfig.json +4 -0
  673. package/packages/widget/tsconfig.node.json +24 -0
  674. package/packages/widget/vite.config.ts +116 -0
  675. package/packages/widget-lit/BOTTLENECKS.md +250 -0
  676. package/packages/widget-lit/IMPLEMENTATION_SUMMARY.md +295 -0
  677. package/packages/widget-lit/README.md +232 -0
  678. package/packages/widget-lit/eslint.config.mjs +3 -0
  679. package/packages/widget-lit/package.json +52 -0
  680. package/packages/widget-lit/src/api-client.ts +230 -0
  681. package/packages/widget-lit/src/api-client.ts.backup +218 -0
  682. package/packages/widget-lit/src/components/sea-chat.ts +382 -0
  683. package/packages/widget-lit/src/components/sea-submission-viewer.ts +267 -0
  684. package/packages/widget-lit/src/components/sea-widget.ts +317 -0
  685. package/packages/widget-lit/src/index.ts +48 -0
  686. package/packages/widget-lit/src/react.ts +58 -0
  687. package/packages/widget-lit/src/style.css +47 -0
  688. package/packages/widget-lit/tsconfig.json +24 -0
  689. package/packages/widget-lit/vite.config.ts +29 -0
  690. package/packages/widget-ng/DEVELOPMENT.md +74 -0
  691. package/packages/widget-ng/README.md +657 -0
  692. package/packages/widget-ng/dev.sh +14 -0
  693. package/packages/widget-ng/eslint.config.mjs +24 -0
  694. package/packages/widget-ng/ng-package.json +9 -0
  695. package/packages/widget-ng/package.json +85 -0
  696. package/packages/widget-ng/src/index.ts +45 -0
  697. package/packages/widget-ng/src/lib/components/sea-chat.component.ts +737 -0
  698. package/packages/widget-ng/src/lib/components/sea-data-viewer.component.ts +2240 -0
  699. package/packages/widget-ng/src/lib/components/sea-deal-form-modal.component.ts +702 -0
  700. package/packages/widget-ng/src/lib/components/sea-document-list.component.ts +350 -0
  701. package/packages/widget-ng/src/lib/components/sea-feedback-modal.component.ts +461 -0
  702. package/packages/widget-ng/src/lib/components/sea-file-upload.component.ts +655 -0
  703. package/packages/widget-ng/src/lib/components/sea-model-selection-modal.component.ts +367 -0
  704. package/packages/widget-ng/src/lib/components/sea-new-submission-modal.component.ts +414 -0
  705. package/packages/widget-ng/src/lib/components/sea-pdf-viewer.component.ts +869 -0
  706. package/packages/widget-ng/src/lib/components/sea-submission-card.component.ts +251 -0
  707. package/packages/widget-ng/src/lib/components/sea-widget.component.ts +684 -0
  708. package/packages/widget-ng/src/lib/models/submission.model.ts +170 -0
  709. package/packages/widget-ng/src/lib/pipes/markdown.pipe.ts +57 -0
  710. package/packages/widget-ng/src/lib/services/api-client.service.ts +715 -0
  711. package/packages/widget-ng/src/lib/services/chat.service.ts +330 -0
  712. package/packages/widget-ng/src/lib/services/config.service.ts +107 -0
  713. package/packages/widget-ng/src/web-component.ts +56 -0
  714. package/packages/widget-ng/tsconfig.json +25 -0
  715. package/packages/widget-ng/tsconfig.lib.json +9 -0
  716. package/packages/widget-ng/vite.config.elements.ts +26 -0
  717. package/packages/widget-ng/vitest.config.ts +19 -0
  718. package/packages/widget-ng/vitest.setup.ts +13 -0
  719. package/pnpm-workspace.yaml +18 -0
  720. package/render.yaml +136 -0
  721. package/scripts/README.md +57 -0
  722. package/scripts/package.json +22 -0
  723. package/scripts/python/.python-version +1 -0
  724. package/scripts/python/README.md +3 -0
  725. package/scripts/python/export-org-data.py +693 -0
  726. package/scripts/python/pyproject.toml +29 -0
  727. package/scripts/python/requirements-dev.lock +36 -0
  728. package/scripts/python/requirements.lock +36 -0
  729. package/scripts/python/src/gen.py +297 -0
  730. package/scripts/python/test.py +34 -0
  731. package/scripts/src/fix-storage-provider-mismatch.ts +239 -0
  732. package/scripts/src/sync-render-yaml.ts +290 -0
  733. package/scripts/src/test-chat-stream.ts +300 -0
  734. package/scripts/src/test-reconciliation.ts +230 -0
  735. package/scripts/tsconfig.json +15 -0
  736. package/tests/angular-test-app/.vscode/extensions.json +4 -0
  737. package/tests/angular-test-app/.vscode/launch.json +13 -0
  738. package/tests/angular-test-app/.vscode/tasks.json +24 -0
  739. package/tests/angular-test-app/README.md +59 -0
  740. package/tests/angular-test-app/angular.json +111 -0
  741. package/tests/angular-test-app/clean-start.sh +14 -0
  742. package/tests/angular-test-app/package.json +36 -0
  743. package/tests/angular-test-app/public/favicon.ico +0 -0
  744. package/tests/angular-test-app/src/app/app.component.ts +220 -0
  745. package/tests/angular-test-app/src/app/app.config.ts +5 -0
  746. package/tests/angular-test-app/src/env.d.ts +13 -0
  747. package/tests/angular-test-app/src/index.html +13 -0
  748. package/tests/angular-test-app/src/main.ts +6 -0
  749. package/tests/angular-test-app/src/styles.css +8 -0
  750. package/tests/angular-test-app/tsconfig.app.json +15 -0
  751. package/tests/angular-test-app/tsconfig.json +27 -0
  752. package/tests/crm-viewer-app/API_INTEGRATION_SUMMARY.md +295 -0
  753. package/tests/crm-viewer-app/CURRENT_ASSETS_FIELDS.md +148 -0
  754. package/tests/crm-viewer-app/FIELD_ID_MAPPING.md +206 -0
  755. package/tests/crm-viewer-app/INTEGRATION_GUIDE.md +309 -0
  756. package/tests/crm-viewer-app/README.md +174 -0
  757. package/tests/crm-viewer-app/REAL_API_INTEGRATION.md +240 -0
  758. package/tests/crm-viewer-app/UPDATED_IMPLEMENTATION.md +279 -0
  759. package/tests/crm-viewer-app/angular.json +114 -0
  760. package/tests/crm-viewer-app/package.json +35 -0
  761. package/tests/crm-viewer-app/src/app/app.component.ts +534 -0
  762. package/tests/crm-viewer-app/src/app/citation.service.ts +316 -0
  763. package/tests/crm-viewer-app/src/env.d.ts +16 -0
  764. package/tests/crm-viewer-app/src/index.html +19 -0
  765. package/tests/crm-viewer-app/src/main.ts +7 -0
  766. package/tests/crm-viewer-app/src/styles.css +409 -0
  767. package/tests/crm-viewer-app/src/template.html +2678 -0
  768. package/tests/crm-viewer-app/tsconfig.app.json +15 -0
  769. package/tests/crm-viewer-app/tsconfig.json +27 -0
  770. package/tests/e2e/package.json +17 -0
  771. package/tests/e2e/playwright.config.ts +75 -0
  772. package/tests/e2e/tests/api/health.spec.ts +10 -0
  773. package/tests/e2e/tests/app/example.spec.ts +10 -0
  774. package/tests/widget-test-app/.prettierignore +6 -0
  775. package/tests/widget-test-app/README.md +48 -0
  776. package/tests/widget-test-app/index.html +12 -0
  777. package/tests/widget-test-app/package.json +24 -0
  778. package/tests/widget-test-app/src/App.css +192 -0
  779. package/tests/widget-test-app/src/App.tsx +80 -0
  780. package/tests/widget-test-app/src/main.tsx +9 -0
  781. package/tests/widget-test-app/src/vite-env.d.ts +4 -0
  782. package/tests/widget-test-app/tsconfig.json +25 -0
  783. package/tests/widget-test-app/tsconfig.node.json +11 -0
  784. package/tests/widget-test-app/vite.config.ts +14 -0
@@ -0,0 +1,746 @@
1
+ import { resetTestDb } from "./_tests/mock-db"; // Must always be the first import
2
+
3
+ import type { MemberHydrated } from "@sea/dal/member";
4
+ import { db, schema } from "@sea/db";
5
+ import { addDays } from "date-fns";
6
+ import { eq } from "drizzle-orm";
7
+ import { beforeEach, describe, expect, it, vi } from "vitest";
8
+ import {
9
+ acceptInvite,
10
+ cancelInvite,
11
+ createInvite,
12
+ getInvite,
13
+ getPendingInvites,
14
+ rejectInvite,
15
+ resendInvite,
16
+ } from "./invitation";
17
+
18
+ // Mock the loops client
19
+ vi.mock("@/clients/loops", () => ({
20
+ sendEmailInvite: vi.fn().mockResolvedValue(undefined),
21
+ sendEmailOtp: vi.fn().mockResolvedValue(undefined),
22
+ }));
23
+
24
+ describe("dbtest: acceptInvite", () => {
25
+ beforeEach(async () => {
26
+ await resetTestDb();
27
+ });
28
+
29
+ it("prevents cross-organization access when accepting invites", async () => {
30
+ // Create two organizations
31
+ const [org1, org2] = await db
32
+ .insert(schema.organization)
33
+ .values([{ name: "Org 1" }, { name: "Org 2" }])
34
+ .returning();
35
+
36
+ // Create users for both organizations
37
+ const [user1, user2] = await db
38
+ .insert(schema.user)
39
+ .values([
40
+ { name: "User 1", email: "user1@example.com", emailVerified: true },
41
+ { name: "User 2", email: "user2@example.com", emailVerified: true },
42
+ ])
43
+ .returning();
44
+
45
+ // Create inviter members for both organizations
46
+ const [inviter1, inviter2] = await db
47
+ .insert(schema.member)
48
+ .values([
49
+ { organizationId: org1!.id, userId: user1!.id, role: "admin" },
50
+ { organizationId: org2!.id, userId: user2!.id, role: "admin" },
51
+ ])
52
+ .returning();
53
+
54
+ // Create a new user who will be invited
55
+ const [invitedUser] = await db
56
+ .insert(schema.user)
57
+ .values([{ name: "Invited User", email: "invited@example.com", emailVerified: true }])
58
+ .returning();
59
+
60
+ // Create sessions for the invited user
61
+ const [session1, session2] = await db
62
+ .insert(schema.session)
63
+ .values([
64
+ {
65
+ userId: invitedUser!.id,
66
+ expiresAt: addDays(new Date(), 30),
67
+ token: "session-token-1",
68
+ },
69
+ {
70
+ userId: invitedUser!.id,
71
+ expiresAt: addDays(new Date(), 30),
72
+ token: "session-token-2",
73
+ },
74
+ ])
75
+ .returning();
76
+
77
+ // Create invitation for org1 to invited user
78
+ const [invitation1] = await db
79
+ .insert(schema.invitation)
80
+ .values([
81
+ {
82
+ organizationId: org1!.id,
83
+ email: invitedUser!.email,
84
+ status: "pending",
85
+ expiresAt: addDays(new Date(), 14),
86
+ inviterId: inviter1!.userId,
87
+ },
88
+ ])
89
+ .returning();
90
+
91
+ // Create invitation for org2 to invited user
92
+ const [invitation2] = await db
93
+ .insert(schema.invitation)
94
+ .values([
95
+ {
96
+ organizationId: org2!.id,
97
+ email: invitedUser!.email,
98
+ status: "pending",
99
+ expiresAt: addDays(new Date(), 14),
100
+ inviterId: inviter2!.userId,
101
+ },
102
+ ])
103
+ .returning();
104
+
105
+ // Test that invited user can accept invitation to org1
106
+ await acceptInvite({
107
+ inviteId: invitation1!.id,
108
+ session: session1!,
109
+ user: invitedUser!,
110
+ });
111
+
112
+ // Verify that member was created for org1
113
+ const org1Member = await db.query.member.findFirst({
114
+ where: eq(schema.member.userId, invitedUser!.id),
115
+ });
116
+ expect(org1Member).toBeDefined();
117
+ expect(org1Member!.organizationId).toBe(org1!.id);
118
+
119
+ // Verify that session was updated to org1
120
+ const updatedSession1 = await db.query.session.findFirst({
121
+ where: eq(schema.session.id, session1!.id),
122
+ });
123
+ expect(updatedSession1!.activeOrganizationId).toBe(org1!.id);
124
+
125
+ // Verify that invitation1 status was updated
126
+ const updatedInvitation1 = await db.query.invitation.findFirst({
127
+ where: eq(schema.invitation.id, invitation1!.id),
128
+ });
129
+ expect(updatedInvitation1!.status).toBe("accepted");
130
+
131
+ // Test cross-organization access prevention:
132
+ // Try to accept org2's invitation but with wrong user email
133
+ const [wrongUser] = await db
134
+ .insert(schema.user)
135
+ .values([{ name: "Wrong User", email: "wrong@example.com", emailVerified: true }])
136
+ .returning();
137
+
138
+ // This should fail because getInvite validates email matches
139
+ await expect(
140
+ acceptInvite({
141
+ inviteId: invitation2!.id,
142
+ session: session2!,
143
+ user: wrongUser!,
144
+ }),
145
+ ).rejects.toThrow(); // Should throw due to invariant check when getInvite returns undefined
146
+
147
+ // Verify that no member was created for org2 with wrong user
148
+ const org2WrongMember = await db.query.member.findFirst({
149
+ where: eq(schema.member.userId, wrongUser!.id),
150
+ });
151
+ expect(org2WrongMember).toBeUndefined();
152
+
153
+ // Verify that invitation2 status was not updated
154
+ const unchangedInvitation2 = await db.query.invitation.findFirst({
155
+ where: eq(schema.invitation.id, invitation2!.id),
156
+ });
157
+ expect(unchangedInvitation2!.status).toBe("pending");
158
+ });
159
+ });
160
+
161
+ describe("dbtest: createInvite", () => {
162
+ beforeEach(async () => {
163
+ await resetTestDb();
164
+ });
165
+
166
+ it("prevents cross-organization access when creating invites", async () => {
167
+ // Create two organizations
168
+ const [org1, org2] = await db
169
+ .insert(schema.organization)
170
+ .values([{ name: "Org 1" }, { name: "Org 2" }])
171
+ .returning();
172
+
173
+ // Create users for both organizations
174
+ const [user1, user2] = await db
175
+ .insert(schema.user)
176
+ .values([
177
+ { name: "User 1", email: "create-user1@example.com", emailVerified: true },
178
+ { name: "User 2", email: "create-user2@example.com", emailVerified: true },
179
+ ])
180
+ .returning();
181
+
182
+ // Create members for both organizations
183
+ const [member1, member2] = await db
184
+ .insert(schema.member)
185
+ .values([
186
+ { organizationId: org1!.id, userId: user1!.id, role: "admin" },
187
+ { organizationId: org2!.id, userId: user2!.id, role: "admin" },
188
+ ])
189
+ .returning();
190
+
191
+ // Create hydrated members (with organization and user data)
192
+ const hydratedMember1: MemberHydrated = {
193
+ ...member1!,
194
+ organization: org1!,
195
+ user: user1!,
196
+ };
197
+
198
+ const hydratedMember2: MemberHydrated = {
199
+ ...member2!,
200
+ organization: org2!,
201
+ user: user2!,
202
+ };
203
+
204
+ // Create invite from org1 member
205
+ const result1 = await createInvite({
206
+ member: hydratedMember1,
207
+ email: "invited@example.com",
208
+ emailSender: () => Promise.resolve(undefined),
209
+ });
210
+
211
+ expect(result1.success).toBe(true);
212
+ expect(result1.inviteId).toBeDefined();
213
+
214
+ // Verify invitation was created for org1
215
+ const invitation1 = await db.query.invitation.findFirst({
216
+ where: eq(schema.invitation.id, result1.inviteId!),
217
+ });
218
+ expect(invitation1).toBeDefined();
219
+ expect(invitation1!.organizationId).toBe(org1!.id);
220
+ expect(invitation1!.email).toBe("invited@example.com");
221
+ expect(invitation1!.inviterId).toBe(user1!.id);
222
+
223
+ // Create invite from org2 member
224
+ const result2 = await createInvite({
225
+ member: hydratedMember2,
226
+ email: "invited2@example.com",
227
+ emailSender: () => Promise.resolve(undefined),
228
+ });
229
+
230
+ expect(result2.success).toBe(true);
231
+ expect(result2.inviteId).toBeDefined();
232
+
233
+ // Verify invitation was created for org2
234
+ const invitation2 = await db.query.invitation.findFirst({
235
+ where: eq(schema.invitation.id, result2.inviteId!),
236
+ });
237
+ expect(invitation2).toBeDefined();
238
+ expect(invitation2!.organizationId).toBe(org2!.id);
239
+ expect(invitation2!.email).toBe("invited2@example.com");
240
+ expect(invitation2!.inviterId).toBe(user2!.id);
241
+
242
+ // Verify that invitations are properly scoped to their respective organizations
243
+ expect(invitation1!.organizationId).not.toBe(invitation2!.organizationId);
244
+
245
+ // Verify that org1 member cannot see org2's invitation
246
+ const org1Invitations = await db.query.invitation.findMany({
247
+ where: eq(schema.invitation.organizationId, org1!.id),
248
+ });
249
+ expect(org1Invitations).toHaveLength(1);
250
+ expect(org1Invitations[0]!.email).toBe("invited@example.com");
251
+
252
+ // Verify that org2 member cannot see org1's invitation
253
+ const org2Invitations = await db.query.invitation.findMany({
254
+ where: eq(schema.invitation.organizationId, org2!.id),
255
+ });
256
+ expect(org2Invitations).toHaveLength(1);
257
+ expect(org2Invitations[0]!.email).toBe("invited2@example.com");
258
+ });
259
+ });
260
+
261
+ describe("dbtest: getPendingInvites", () => {
262
+ beforeEach(async () => {
263
+ await resetTestDb();
264
+ });
265
+
266
+ it("prevents cross-organization access when getting pending invites", async () => {
267
+ // Create two organizations
268
+ const [org1, org2] = await db
269
+ .insert(schema.organization)
270
+ .values([{ name: "Org 1" }, { name: "Org 2" }])
271
+ .returning();
272
+
273
+ // Create users for both organizations
274
+ const [user1, user2] = await db
275
+ .insert(schema.user)
276
+ .values([
277
+ { name: "User 1", email: "pending-user1@example.com", emailVerified: true },
278
+ { name: "User 2", email: "pending-user2@example.com", emailVerified: true },
279
+ ])
280
+ .returning();
281
+
282
+ // Create members for both organizations
283
+ const [member1, member2] = await db
284
+ .insert(schema.member)
285
+ .values([
286
+ { organizationId: org1!.id, userId: user1!.id, role: "admin" },
287
+ { organizationId: org2!.id, userId: user2!.id, role: "admin" },
288
+ ])
289
+ .returning();
290
+
291
+ // Create pending invitations for both organizations
292
+ const [_invite1a, _invite1b] = await db
293
+ .insert(schema.invitation)
294
+ .values([
295
+ {
296
+ organizationId: org1!.id,
297
+ email: "invite1a@example.com",
298
+ status: "pending",
299
+ expiresAt: addDays(new Date(), 14),
300
+ inviterId: user1!.id,
301
+ },
302
+ {
303
+ organizationId: org1!.id,
304
+ email: "invite1b@example.com",
305
+ status: "pending",
306
+ expiresAt: addDays(new Date(), 14),
307
+ inviterId: user1!.id,
308
+ },
309
+ ])
310
+ .returning();
311
+
312
+ const [_invite2a, _invite2b] = await db
313
+ .insert(schema.invitation)
314
+ .values([
315
+ {
316
+ organizationId: org2!.id,
317
+ email: "invite2a@example.com",
318
+ status: "pending",
319
+ expiresAt: addDays(new Date(), 14),
320
+ inviterId: user2!.id,
321
+ },
322
+ {
323
+ organizationId: org2!.id,
324
+ email: "invite2b@example.com",
325
+ status: "accepted",
326
+ expiresAt: addDays(new Date(), 14),
327
+ inviterId: user2!.id,
328
+ },
329
+ ])
330
+ .returning();
331
+
332
+ // Test that org1 member can only see org1 pending invites
333
+ const org1Invites = await getPendingInvites({ member: member1! });
334
+ expect(org1Invites).toHaveLength(2);
335
+ expect(org1Invites.map((i) => i.email).sort()).toEqual([
336
+ "invite1a@example.com",
337
+ "invite1b@example.com",
338
+ ]);
339
+ expect(org1Invites.every((i) => i.organizationId === org1!.id)).toBe(true);
340
+ expect(org1Invites.every((i) => i.status === "pending")).toBe(true);
341
+
342
+ // Test that org2 member can only see org2 pending invites (excluding accepted ones)
343
+ const org2Invites = await getPendingInvites({ member: member2! });
344
+ expect(org2Invites).toHaveLength(1);
345
+ expect(org2Invites[0]!.email).toBe("invite2a@example.com");
346
+ expect(org2Invites[0]!.organizationId).toBe(org2!.id);
347
+ expect(org2Invites[0]!.status).toBe("pending");
348
+
349
+ // Verify cross-organization access is prevented
350
+ expect(org1Invites.some((i) => i.organizationId === org2!.id)).toBe(false);
351
+ expect(org2Invites.some((i) => i.organizationId === org1!.id)).toBe(false);
352
+ });
353
+ });
354
+
355
+ describe("dbtest: getInvite", () => {
356
+ beforeEach(async () => {
357
+ await resetTestDb();
358
+ });
359
+
360
+ it("prevents cross-organization access when getting invites", async () => {
361
+ // Create two organizations
362
+ const [org1, org2] = await db
363
+ .insert(schema.organization)
364
+ .values([{ name: "Org 1" }, { name: "Org 2" }])
365
+ .returning();
366
+
367
+ // Create users for both organizations
368
+ const [user1, user2] = await db
369
+ .insert(schema.user)
370
+ .values([
371
+ { name: "User 1", email: "getinvite-user1@example.com", emailVerified: true },
372
+ { name: "User 2", email: "getinvite-user2@example.com", emailVerified: true },
373
+ ])
374
+ .returning();
375
+
376
+ // Create members for both organizations
377
+ const [_member1, _member2] = await db
378
+ .insert(schema.member)
379
+ .values([
380
+ { organizationId: org1!.id, userId: user1!.id, role: "admin" },
381
+ { organizationId: org2!.id, userId: user2!.id, role: "admin" },
382
+ ])
383
+ .returning();
384
+
385
+ // Create a target user who will receive invitations
386
+ const [targetUser] = await db
387
+ .insert(schema.user)
388
+ .values([{ name: "Target User", email: "target@example.com", emailVerified: true }])
389
+ .returning();
390
+
391
+ // Create invitations from both organizations to the target user
392
+ const [invitation1, invitation2] = await db
393
+ .insert(schema.invitation)
394
+ .values([
395
+ {
396
+ organizationId: org1!.id,
397
+ email: targetUser!.email,
398
+ status: "pending",
399
+ expiresAt: addDays(new Date(), 14),
400
+ inviterId: user1!.id,
401
+ },
402
+ {
403
+ organizationId: org2!.id,
404
+ email: targetUser!.email,
405
+ status: "pending",
406
+ expiresAt: addDays(new Date(), 14),
407
+ inviterId: user2!.id,
408
+ },
409
+ ])
410
+ .returning();
411
+
412
+ // Test that target user can access both invitations (since they're addressed to their email)
413
+ const result1 = await getInvite({
414
+ inviteId: invitation1!.id,
415
+ user: targetUser!,
416
+ });
417
+ expect(result1.type).toBe("valid");
418
+ if (result1.type === "valid") {
419
+ expect(result1.invitation.organizationId).toBe(org1!.id);
420
+ expect(result1.invitation.email).toBe(targetUser!.email);
421
+ expect(result1.invitation.organization).toBeDefined();
422
+ expect(result1.invitation.organization.name).toBe("Org 1");
423
+ }
424
+
425
+ const result2 = await getInvite({
426
+ inviteId: invitation2!.id,
427
+ user: targetUser!,
428
+ });
429
+ expect(result2.type).toBe("valid");
430
+ if (result2.type === "valid") {
431
+ expect(result2.invitation.organizationId).toBe(org2!.id);
432
+ expect(result2.invitation.email).toBe(targetUser!.email);
433
+ expect(result2.invitation.organization).toBeDefined();
434
+ expect(result2.invitation.organization.name).toBe("Org 2");
435
+ }
436
+
437
+ // Test cross-organization access prevention: user1 should NOT be able to access invitation2
438
+ const crossOrgResult = await getInvite({
439
+ inviteId: invitation2!.id,
440
+ user: user1!, // Wrong user - invitation2 is for target@example.com, not user1@example.com
441
+ });
442
+ expect(crossOrgResult.type).toBe("email-mismatch");
443
+
444
+ // Test that user2 also cannot access invitation1
445
+ const crossOrgResult2 = await getInvite({
446
+ inviteId: invitation1!.id,
447
+ user: user2!, // Wrong user - invitation1 is for target@example.com, not user2@example.com
448
+ });
449
+ expect(crossOrgResult2.type).toBe("email-mismatch");
450
+
451
+ // Test that function properly validates expiration and status
452
+ const [expiredInvitation] = await db
453
+ .insert(schema.invitation)
454
+ .values([
455
+ {
456
+ organizationId: org1!.id,
457
+ email: targetUser!.email,
458
+ status: "pending",
459
+ expiresAt: addDays(new Date(), -1), // Expired
460
+ inviterId: user1!.id,
461
+ },
462
+ ])
463
+ .returning();
464
+
465
+ const expiredResult = await getInvite({
466
+ inviteId: expiredInvitation!.id,
467
+ user: targetUser!,
468
+ });
469
+ expect(expiredResult.type).toBe("not-found");
470
+
471
+ // Test that function properly validates status
472
+ const [acceptedInvitation] = await db
473
+ .insert(schema.invitation)
474
+ .values([
475
+ {
476
+ organizationId: org1!.id,
477
+ email: targetUser!.email,
478
+ status: "accepted",
479
+ expiresAt: addDays(new Date(), 14),
480
+ inviterId: user1!.id,
481
+ },
482
+ ])
483
+ .returning();
484
+
485
+ const acceptedResult = await getInvite({
486
+ inviteId: acceptedInvitation!.id,
487
+ user: targetUser!,
488
+ });
489
+ expect(acceptedResult.type).toBe("not-found");
490
+ });
491
+ });
492
+
493
+ describe("dbtest: rejectInvite", () => {
494
+ // TODO CLAUDE 2025-07-17: CRITICAL SECURITY ISSUE - Function does not validate that the user has the right to reject the invitation. It does not check if invitation.email matches user.email or if invitation is in valid state (pending, not expired). This allows ANY user to reject ANY invitation if they know the invitation ID, creating a major cross-organization access vulnerability.
495
+
496
+ beforeEach(async () => {
497
+ await resetTestDb();
498
+ });
499
+
500
+ it("prevents cross-organization access when rejecting invites", async () => {
501
+ // Create two organizations
502
+ const [org1, org2] = await db
503
+ .insert(schema.organization)
504
+ .values([{ name: "Org 1" }, { name: "Org 2" }])
505
+ .returning();
506
+
507
+ // Create users for both organizations
508
+ const [user1, user2] = await db
509
+ .insert(schema.user)
510
+ .values([
511
+ { name: "User 1", email: "reject-user1@example.com", emailVerified: true },
512
+ { name: "User 2", email: "reject-user2@example.com", emailVerified: true },
513
+ ])
514
+ .returning();
515
+
516
+ // Create members for both organizations
517
+ const [_member1, _member2] = await db
518
+ .insert(schema.member)
519
+ .values([
520
+ { organizationId: org1!.id, userId: user1!.id, role: "admin" },
521
+ { organizationId: org2!.id, userId: user2!.id, role: "admin" },
522
+ ])
523
+ .returning();
524
+
525
+ // Create a target user who should receive the invitation
526
+ const [targetUser] = await db
527
+ .insert(schema.user)
528
+ .values([{ name: "Target User", email: "reject-target@example.com", emailVerified: true }])
529
+ .returning();
530
+
531
+ // Create an invitation from org1 to target user
532
+ const [invitation] = await db
533
+ .insert(schema.invitation)
534
+ .values([
535
+ {
536
+ organizationId: org1!.id,
537
+ email: targetUser!.email,
538
+ status: "pending",
539
+ expiresAt: addDays(new Date(), 14),
540
+ inviterId: user1!.id,
541
+ },
542
+ ])
543
+ .returning();
544
+
545
+ // Test that the target user can reject their own invitation
546
+ await rejectInvite({
547
+ inviteId: invitation!.id,
548
+ user: targetUser!,
549
+ });
550
+
551
+ // Verify invitation was rejected
552
+ const rejectedInvitation = await db.query.invitation.findFirst({
553
+ where: eq(schema.invitation.id, invitation!.id),
554
+ });
555
+ expect(rejectedInvitation!.status).toBe("rejected");
556
+
557
+ // Create another invitation for testing cross-organization access
558
+ const [invitation2] = await db
559
+ .insert(schema.invitation)
560
+ .values([
561
+ {
562
+ organizationId: org2!.id,
563
+ email: targetUser!.email,
564
+ status: "pending",
565
+ expiresAt: addDays(new Date(), 14),
566
+ inviterId: user2!.id,
567
+ },
568
+ ])
569
+ .returning();
570
+
571
+ // SECURITY VULNERABILITY TEST: user1 from org1 should NOT be able to reject org2's invitation
572
+ // However, the current implementation allows this due to lack of validation
573
+ await rejectInvite({
574
+ inviteId: invitation2!.id,
575
+ user: user1!, // Wrong user - should not be able to reject this invitation
576
+ });
577
+
578
+ // This demonstrates the vulnerability - the invitation gets rejected even though user1 shouldn't have access
579
+ const vulnerableInvitation = await db.query.invitation.findFirst({
580
+ where: eq(schema.invitation.id, invitation2!.id),
581
+ });
582
+ expect(vulnerableInvitation!.status).toBe("rejected"); // This exposes the vulnerability
583
+
584
+ // The function should have prevented this cross-organization access
585
+ // but it doesn't validate the user's permission to reject the invitation
586
+ });
587
+ });
588
+
589
+ describe("dbtest: resendInvite", () => {
590
+ beforeEach(async () => {
591
+ await resetTestDb();
592
+ });
593
+
594
+ it("prevents cross-organization access when resending invites", async () => {
595
+ // Create two organizations
596
+ const [org1, org2] = await db
597
+ .insert(schema.organization)
598
+ .values([{ name: "Org 1" }, { name: "Org 2" }])
599
+ .returning();
600
+
601
+ // Create users for both organizations
602
+ const [user1, user2] = await db
603
+ .insert(schema.user)
604
+ .values([
605
+ { name: "User 1", email: "resend-user1@example.com", emailVerified: true },
606
+ { name: "User 2", email: "resend-user2@example.com", emailVerified: true },
607
+ ])
608
+ .returning();
609
+
610
+ // Create members for both organizations
611
+ const [member1, _member2] = await db
612
+ .insert(schema.member)
613
+ .values([
614
+ { organizationId: org1!.id, userId: user1!.id, role: "admin" },
615
+ { organizationId: org2!.id, userId: user2!.id, role: "admin" },
616
+ ])
617
+ .returning();
618
+
619
+ // Create hydrated members (with organization and user data)
620
+ const hydratedMember1: MemberHydrated = {
621
+ ...member1!,
622
+ organization: org1!,
623
+ user: user1!,
624
+ };
625
+
626
+ // Create an invitation in org2
627
+ const [invitation2] = await db
628
+ .insert(schema.invitation)
629
+ .values([
630
+ {
631
+ organizationId: org2!.id,
632
+ email: "resend-target2@example.com",
633
+ status: "pending",
634
+ expiresAt: addDays(new Date(), 14),
635
+ inviterId: user2!.id,
636
+ },
637
+ ])
638
+ .returning();
639
+
640
+ // Test cross-organization access prevention: org1 member should NOT be able to resend org2's invitation
641
+ await expect(
642
+ resendInvite({
643
+ member: hydratedMember1,
644
+ inviteId: invitation2!.id, // This belongs to org2, not org1
645
+ emailSender: () => undefined,
646
+ }),
647
+ ).rejects.toThrow(); // Should throw due to invariant check when existingInvite is not found
648
+
649
+ // Verify that org2's invitation remains unchanged
650
+ const unchangedInvitation = await db.query.invitation.findFirst({
651
+ where: eq(schema.invitation.id, invitation2!.id),
652
+ });
653
+ expect(unchangedInvitation!.status).toBe("pending"); // Should still be pending
654
+ expect(unchangedInvitation!.organizationId).toBe(org2!.id);
655
+ });
656
+ });
657
+
658
+ describe("dbtest: cancelInvite", () => {
659
+ beforeEach(async () => {
660
+ await resetTestDb();
661
+ });
662
+
663
+ it("prevents cross-organization access when canceling invites", async () => {
664
+ // Create two organizations
665
+ const [org1, org2] = await db
666
+ .insert(schema.organization)
667
+ .values([{ name: "Org 1" }, { name: "Org 2" }])
668
+ .returning();
669
+
670
+ // Create users for both organizations
671
+ const [user1, user2] = await db
672
+ .insert(schema.user)
673
+ .values([
674
+ { name: "User 1", email: "cancel-user1@example.com", emailVerified: true },
675
+ { name: "User 2", email: "cancel-user2@example.com", emailVerified: true },
676
+ ])
677
+ .returning();
678
+
679
+ // Create members for both organizations
680
+ const [member1, member2] = await db
681
+ .insert(schema.member)
682
+ .values([
683
+ { organizationId: org1!.id, userId: user1!.id, role: "admin" },
684
+ { organizationId: org2!.id, userId: user2!.id, role: "admin" },
685
+ ])
686
+ .returning();
687
+
688
+ // Create invitations in both organizations
689
+ const [invitation1, invitation2] = await db
690
+ .insert(schema.invitation)
691
+ .values([
692
+ {
693
+ organizationId: org1!.id,
694
+ email: "cancel-invite1@example.com",
695
+ status: "pending",
696
+ expiresAt: addDays(new Date(), 14),
697
+ inviterId: user1!.id,
698
+ },
699
+ {
700
+ organizationId: org2!.id,
701
+ email: "cancel-invite2@example.com",
702
+ status: "pending",
703
+ expiresAt: addDays(new Date(), 14),
704
+ inviterId: user2!.id,
705
+ },
706
+ ])
707
+ .returning();
708
+
709
+ // Test that org1 member can cancel their own organization's invitation
710
+ await cancelInvite({
711
+ inviteId: invitation1!.id,
712
+ member: member1!,
713
+ });
714
+
715
+ // Verify invitation1 was canceled
716
+ const canceledInvitation1 = await db.query.invitation.findFirst({
717
+ where: eq(schema.invitation.id, invitation1!.id),
718
+ });
719
+ expect(canceledInvitation1!.status).toBe("canceled");
720
+
721
+ // Test cross-organization access prevention:
722
+ // org1 member should NOT be able to cancel org2's invitation
723
+ await cancelInvite({
724
+ inviteId: invitation2!.id,
725
+ member: member1!, // Wrong member - from org1 trying to cancel org2 invitation
726
+ });
727
+
728
+ // Verify invitation2 was NOT canceled (should still be pending)
729
+ const unchangedInvitation2 = await db.query.invitation.findFirst({
730
+ where: eq(schema.invitation.id, invitation2!.id),
731
+ });
732
+ expect(unchangedInvitation2!.status).toBe("pending");
733
+
734
+ // Test that org2 member can cancel their own organization's invitation
735
+ await cancelInvite({
736
+ inviteId: invitation2!.id,
737
+ member: member2!,
738
+ });
739
+
740
+ // Verify invitation2 was now canceled
741
+ const canceledInvitation2 = await db.query.invitation.findFirst({
742
+ where: eq(schema.invitation.id, invitation2!.id),
743
+ });
744
+ expect(canceledInvitation2!.status).toBe("canceled");
745
+ });
746
+ });