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,1304 @@
1
+ import { resetTestDb } from "@/_tests/mock-db"; // Must always be the first import
2
+
3
+ import { db, schema } from "@sea/db";
4
+ import { eq } from "drizzle-orm";
5
+ import { beforeEach, describe, expect, it } from "vitest";
6
+ import {
7
+ addSubmissionGroupRow,
8
+ getDenormSubmission,
9
+ getSubmission,
10
+ getSubmissionGroup,
11
+ resetSubmission,
12
+ syncSubmissionToForm,
13
+ updateSubmissionValue,
14
+ } from "./submission";
15
+
16
+ describe("dbtest: addSubmissionGroupRow", () => {
17
+ beforeEach(async () => {
18
+ await resetTestDb();
19
+ });
20
+
21
+ it("prevents adding submission group rows across organizations", async () => {
22
+ // Create two organizations
23
+ const [org1, org2] = await db
24
+ .insert(schema.organization)
25
+ .values([{ name: "Org 1" }, { name: "Org 2" }])
26
+ .returning();
27
+
28
+ // Create users for both organizations
29
+ const [user1, user2] = await db
30
+ .insert(schema.user)
31
+ .values([
32
+ { name: "User 1", email: "user1-addsubmissiongrouprow@example.com", emailVerified: true },
33
+ { name: "User 2", email: "user2-addsubmissiongrouprow@example.com", emailVerified: true },
34
+ ])
35
+ .returning();
36
+
37
+ // Create members for both organizations
38
+ const [member1, _member2] = await db
39
+ .insert(schema.member)
40
+ .values([
41
+ { organizationId: org1!.id, userId: user1!.id, role: "member" },
42
+ { organizationId: org2!.id, userId: user2!.id, role: "member" },
43
+ ])
44
+ .returning();
45
+
46
+ // Create conversations for both organizations
47
+ const [conversation1, conversation2] = await db
48
+ .insert(schema.conversation)
49
+ .values([
50
+ { organizationId: org1!.id, model: "gpt-4.1" },
51
+ { organizationId: org2!.id, model: "gpt-4.1" },
52
+ ])
53
+ .returning();
54
+
55
+ // Create workflow for both organizations
56
+ const [workflow1, workflow2] = await db
57
+ .insert(schema.workflow)
58
+ .values([
59
+ { organizationId: org1!.id, name: "Workflow 1" },
60
+ { organizationId: org2!.id, name: "Workflow 2" },
61
+ ])
62
+ .returning();
63
+
64
+ // Create forms for both organizations
65
+ const [form1, form2] = await db
66
+ .insert(schema.form)
67
+ .values([
68
+ {
69
+ workflowId: workflow1!.id,
70
+ organizationId: org1!.id,
71
+ conversationId: conversation1!.id,
72
+ name: "form 1",
73
+ },
74
+ {
75
+ workflowId: workflow2!.id,
76
+ organizationId: org2!.id,
77
+ conversationId: conversation2!.id,
78
+ name: "form 2",
79
+ },
80
+ ])
81
+ .returning();
82
+
83
+ // Create form groups for both organizations (multi=true for testing)
84
+ const [formGroup1, formGroup2] = await db
85
+ .insert(schema.formGroup)
86
+ .values([
87
+ {
88
+ formId: form1!.id,
89
+ name: "Group 1",
90
+ multi: true,
91
+ order: 0,
92
+ },
93
+ {
94
+ formId: form2!.id,
95
+ name: "Group 2",
96
+ multi: true,
97
+ order: 0,
98
+ },
99
+ ])
100
+ .returning();
101
+
102
+ // Create deals for both organizations
103
+ const [deal1, deal2] = await db
104
+ .insert(schema.deal)
105
+ .values([
106
+ { organizationId: org1!.id, name: "Deal 1" },
107
+ { organizationId: org2!.id, name: "Deal 2" },
108
+ ])
109
+ .returning();
110
+
111
+ // Create submissions for both organizations
112
+ const [submission1, submission2] = await db
113
+ .insert(schema.submission)
114
+ .values([
115
+ {
116
+ formId: form1!.id,
117
+ dealId: deal1!.id,
118
+ organizationId: org1!.id,
119
+ conversationId: conversation1!.id,
120
+ status: "draft",
121
+ },
122
+ {
123
+ formId: form2!.id,
124
+ dealId: deal2!.id,
125
+ organizationId: org2!.id,
126
+ conversationId: conversation2!.id,
127
+ status: "draft",
128
+ },
129
+ ])
130
+ .returning();
131
+
132
+ // Try to add a submission group row for org2's submission using member1
133
+ // This should fail because member1 doesn't have access to org2's formgroup
134
+ await expect(
135
+ addSubmissionGroupRow({
136
+ member: member1!,
137
+ submissionId: submission2!.id,
138
+ formGroupId: formGroup2!.id,
139
+ }),
140
+ ).rejects.toThrow();
141
+
142
+ // Verify no submission group was created for org2's submission
143
+ const org2SubmissionGroups = await db.query.submissionGroup.findMany({
144
+ where: eq(schema.submissionGroup.submissionId, submission2!.id),
145
+ });
146
+ expect(org2SubmissionGroups).toHaveLength(0);
147
+
148
+ // Now add a submission group row for org1's submission using member1 (should work)
149
+ const result = await addSubmissionGroupRow({
150
+ member: member1!,
151
+ submissionId: submission1!.id,
152
+ formGroupId: formGroup1!.id,
153
+ });
154
+
155
+ expect(result).toBeDefined();
156
+ expect(result.submissionId).toBe(submission1!.id);
157
+ expect(result.formGroupId).toBe(formGroup1!.id);
158
+
159
+ // Verify the submission group was created for org1's submission
160
+ const org1SubmissionGroups = await db.query.submissionGroup.findMany({
161
+ where: eq(schema.submissionGroup.submissionId, submission1!.id),
162
+ });
163
+ expect(org1SubmissionGroups).toHaveLength(1);
164
+ expect(org1SubmissionGroups[0]!.formGroupId).toBe(formGroup1!.id);
165
+ });
166
+ });
167
+
168
+ describe("dbtest: getSubmissionGroup", () => {
169
+ // TODO CLAUDE 2025-07-17: The function checks organizationId on the submission table to ensure proper access control. The submissionGroupId filter is applied within the `with` clause, which means it only returns groups that belong to the already organization-validated submission. This approach is secure as it leverages the relational constraint that submission groups belong to submissions.
170
+
171
+ beforeEach(async () => {
172
+ await resetTestDb();
173
+ });
174
+
175
+ it("prevents accessing submission groups across organizations", async () => {
176
+ // Create two organizations
177
+ const [org1, org2] = await db
178
+ .insert(schema.organization)
179
+ .values([{ name: "Org 1" }, { name: "Org 2" }])
180
+ .returning();
181
+
182
+ // Create users for both organizations
183
+ const [user1, user2] = await db
184
+ .insert(schema.user)
185
+ .values([
186
+ { name: "User 1", email: "user1-getsubmissiongroup@example.com", emailVerified: true },
187
+ { name: "User 2", email: "user2-getsubmissiongroup@example.com", emailVerified: true },
188
+ ])
189
+ .returning();
190
+
191
+ // Create members for both organizations
192
+ const [member1, _member2] = await db
193
+ .insert(schema.member)
194
+ .values([
195
+ { organizationId: org1!.id, userId: user1!.id, role: "member" },
196
+ { organizationId: org2!.id, userId: user2!.id, role: "member" },
197
+ ])
198
+ .returning();
199
+
200
+ // Create conversations for both organizations
201
+ const [conversation1, conversation2] = await db
202
+ .insert(schema.conversation)
203
+ .values([
204
+ { organizationId: org1!.id, model: "gpt-4.1" },
205
+ { organizationId: org2!.id, model: "gpt-4.1" },
206
+ ])
207
+ .returning();
208
+
209
+ // Create workflow for both organizations
210
+ const [workflow1, workflow2] = await db
211
+ .insert(schema.workflow)
212
+ .values([
213
+ { organizationId: org1!.id, name: "Workflow 1" },
214
+ { organizationId: org2!.id, name: "Workflow 2" },
215
+ ])
216
+ .returning();
217
+
218
+ // Create forms for both organizations
219
+ const [form1, form2] = await db
220
+ .insert(schema.form)
221
+ .values([
222
+ {
223
+ workflowId: workflow1!.id,
224
+ organizationId: org1!.id,
225
+ conversationId: conversation1!.id,
226
+ name: "form 1",
227
+ },
228
+ {
229
+ workflowId: workflow2!.id,
230
+ organizationId: org2!.id,
231
+ conversationId: conversation2!.id,
232
+ name: "form 2",
233
+ },
234
+ ])
235
+ .returning();
236
+
237
+ // Create form groups for both organizations
238
+ const [formGroup1, formGroup2] = await db
239
+ .insert(schema.formGroup)
240
+ .values([
241
+ {
242
+ formId: form1!.id,
243
+ name: "Group 1",
244
+ multi: false,
245
+ order: 0,
246
+ },
247
+ {
248
+ formId: form2!.id,
249
+ name: "Group 2",
250
+ multi: false,
251
+ order: 0,
252
+ },
253
+ ])
254
+ .returning();
255
+
256
+ // Create deals for both organizations
257
+ const [deal1, deal2] = await db
258
+ .insert(schema.deal)
259
+ .values([
260
+ { organizationId: org1!.id, name: "Deal 1" },
261
+ { organizationId: org2!.id, name: "Deal 2" },
262
+ ])
263
+ .returning();
264
+
265
+ // Create submissions for both organizations
266
+ const [submission1, submission2] = await db
267
+ .insert(schema.submission)
268
+ .values([
269
+ {
270
+ formId: form1!.id,
271
+ dealId: deal1!.id,
272
+ organizationId: org1!.id,
273
+ conversationId: conversation1!.id,
274
+ status: "draft",
275
+ },
276
+ {
277
+ formId: form2!.id,
278
+ dealId: deal2!.id,
279
+ organizationId: org2!.id,
280
+ conversationId: conversation2!.id,
281
+ status: "draft",
282
+ },
283
+ ])
284
+ .returning();
285
+
286
+ // Create submission groups for both organizations
287
+ const [submissionGroup1, submissionGroup2] = await db
288
+ .insert(schema.submissionGroup)
289
+ .values([
290
+ {
291
+ submissionId: submission1!.id,
292
+ formGroupId: formGroup1!.id,
293
+ order: 0,
294
+ },
295
+ {
296
+ submissionId: submission2!.id,
297
+ formGroupId: formGroup2!.id,
298
+ order: 0,
299
+ },
300
+ ])
301
+ .returning();
302
+
303
+ // Try to get org2's submission group using member1 (should fail)
304
+ await expect(
305
+ getSubmissionGroup({
306
+ member: member1!,
307
+ submissionId: submission2!.id,
308
+ submissionGroupId: submissionGroup2!.id,
309
+ }),
310
+ ).rejects.toThrow();
311
+
312
+ // Try to get org1's submission group with org2's submission ID using member1 (should fail)
313
+ await expect(
314
+ getSubmissionGroup({
315
+ member: member1!,
316
+ submissionId: submission2!.id,
317
+ submissionGroupId: submissionGroup1!.id,
318
+ }),
319
+ ).rejects.toThrow();
320
+
321
+ // Get org1's submission group using member1 (should work)
322
+ const result = await getSubmissionGroup({
323
+ member: member1!,
324
+ submissionId: submission1!.id,
325
+ submissionGroupId: submissionGroup1!.id,
326
+ });
327
+
328
+ expect(result).toBeDefined();
329
+ expect(result.id).toBe(submissionGroup1!.id);
330
+ expect(result.submissionId).toBe(submission1!.id);
331
+ expect(result.formGroupId).toBe(formGroup1!.id);
332
+ });
333
+ });
334
+
335
+ describe("dbtest: syncSubmissionSchema", () => {
336
+ // TODO CLAUDE 2025-07-17: The function checks organizationId on the submission table to ensure the member has access to the submission. However, there's a potential concern that the function creates new submissionGroup and submissionItem records without explicitly validating that these new records maintain proper organizational boundaries. The function relies on the existing submission's organizationId check and the fact that form groups and items are already associated with that organization through the schema hierarchy.
337
+
338
+ beforeEach(async () => {
339
+ await resetTestDb();
340
+ });
341
+
342
+ it("prevents syncing submission schema across organizations", async () => {
343
+ // Create two organizations
344
+ const [org1, org2] = await db
345
+ .insert(schema.organization)
346
+ .values([{ name: "Org 1" }, { name: "Org 2" }])
347
+ .returning();
348
+
349
+ // Create users for both organizations
350
+ const [user1, user2] = await db
351
+ .insert(schema.user)
352
+ .values([
353
+ { name: "User 1", email: "user1-syncsubmissionschema@example.com", emailVerified: true },
354
+ { name: "User 2", email: "user2-syncsubmissionschema@example.com", emailVerified: true },
355
+ ])
356
+ .returning();
357
+
358
+ // Create members for both organizations
359
+ const [member1, _member2] = await db
360
+ .insert(schema.member)
361
+ .values([
362
+ { organizationId: org1!.id, userId: user1!.id, role: "member" },
363
+ { organizationId: org2!.id, userId: user2!.id, role: "member" },
364
+ ])
365
+ .returning();
366
+
367
+ // Create conversations for both organizations
368
+ const [conversation1, conversation2] = await db
369
+ .insert(schema.conversation)
370
+ .values([
371
+ { organizationId: org1!.id, model: "gpt-4.1" },
372
+ { organizationId: org2!.id, model: "gpt-4.1" },
373
+ ])
374
+ .returning();
375
+
376
+ // Create workflow for both organizations
377
+ const [workflow1, workflow2] = await db
378
+ .insert(schema.workflow)
379
+ .values([
380
+ { organizationId: org1!.id, name: "Workflow 1" },
381
+ { organizationId: org2!.id, name: "Workflow 2" },
382
+ ])
383
+ .returning();
384
+
385
+ // Create forms for both organizations
386
+ const [form1, form2] = await db
387
+ .insert(schema.form)
388
+ .values([
389
+ {
390
+ workflowId: workflow1!.id,
391
+ organizationId: org1!.id,
392
+ conversationId: conversation1!.id,
393
+ name: "form 1",
394
+ },
395
+ {
396
+ workflowId: workflow2!.id,
397
+ organizationId: org2!.id,
398
+ conversationId: conversation2!.id,
399
+ name: "form 2",
400
+ },
401
+ ])
402
+ .returning();
403
+
404
+ // Create form groups for both organizations
405
+ const [formGroup1, formGroup2] = await db
406
+ .insert(schema.formGroup)
407
+ .values([
408
+ {
409
+ formId: form1!.id,
410
+ name: "Group 1",
411
+ multi: false,
412
+ order: 0,
413
+ },
414
+ {
415
+ formId: form2!.id,
416
+ name: "Group 2",
417
+ multi: false,
418
+ order: 0,
419
+ },
420
+ ])
421
+ .returning();
422
+
423
+ // Create form fields for both organizations
424
+ const [formField1, _formField2] = await db
425
+ .insert(schema.formField)
426
+ .values([
427
+ {
428
+ formGroupId: formGroup1!.id,
429
+ name: "Item 1",
430
+ type: "string",
431
+ order: 0,
432
+ },
433
+ {
434
+ formGroupId: formGroup2!.id,
435
+ name: "Item 2",
436
+ type: "string",
437
+ order: 0,
438
+ },
439
+ ])
440
+ .returning();
441
+
442
+ // Create deals for both organizations
443
+ const [deal1, deal2] = await db
444
+ .insert(schema.deal)
445
+ .values([
446
+ { organizationId: org1!.id, name: "Deal 1" },
447
+ { organizationId: org2!.id, name: "Deal 2" },
448
+ ])
449
+ .returning();
450
+
451
+ // Create submissions for both organizations
452
+ const [submission1, submission2] = await db
453
+ .insert(schema.submission)
454
+ .values([
455
+ {
456
+ formId: form1!.id,
457
+ dealId: deal1!.id,
458
+ organizationId: org1!.id,
459
+ conversationId: conversation1!.id,
460
+ status: "draft",
461
+ },
462
+ {
463
+ formId: form2!.id,
464
+ dealId: deal2!.id,
465
+ organizationId: org2!.id,
466
+ conversationId: conversation2!.id,
467
+ status: "draft",
468
+ },
469
+ ])
470
+ .returning();
471
+
472
+ // Try to sync submission schema for org2's submission using member1
473
+ // This should fail because member1 doesn't have access to org2's submission
474
+ await expect(
475
+ syncSubmissionToForm({
476
+ member: member1!,
477
+ submissionId: submission2!.id,
478
+ }),
479
+ ).rejects.toThrow();
480
+
481
+ // Verify no submission groups were created for org2's submission
482
+ const org2SubmissionGroups = await db.query.submissionGroup.findMany({
483
+ where: eq(schema.submissionGroup.submissionId, submission2!.id),
484
+ });
485
+ expect(org2SubmissionGroups).toHaveLength(0);
486
+
487
+ // Now sync submission schema for org1's submission using member1 (should work)
488
+ await syncSubmissionToForm({
489
+ member: member1!,
490
+ submissionId: submission1!.id,
491
+ });
492
+
493
+ // Verify the submission group was created for org1's submission
494
+ const org1SubmissionGroups = await db.query.submissionGroup.findMany({
495
+ where: eq(schema.submissionGroup.submissionId, submission1!.id),
496
+ });
497
+ expect(org1SubmissionGroups).toHaveLength(1);
498
+ expect(org1SubmissionGroups[0]!.formGroupId).toBe(formGroup1!.id);
499
+
500
+ // Verify the submission item was created for org1's submission
501
+ const org1SubmissionItems = await db.query.submissionItem.findMany({
502
+ where: eq(schema.submissionItem.submissionGroupId, org1SubmissionGroups[0]!.id),
503
+ });
504
+ expect(org1SubmissionItems).toHaveLength(1);
505
+ expect(org1SubmissionItems[0]!.formFieldId).toBe(formField1!.id);
506
+ });
507
+ });
508
+
509
+ describe("dbtest: getSubmission", () => {
510
+ beforeEach(async () => {
511
+ await resetTestDb();
512
+ });
513
+
514
+ it("prevents accessing submissions across organizations", async () => {
515
+ // Create two organizations
516
+ const [org1, org2] = await db
517
+ .insert(schema.organization)
518
+ .values([{ name: "Org 1" }, { name: "Org 2" }])
519
+ .returning();
520
+
521
+ // Create users for both organizations
522
+ const [user1, user2] = await db
523
+ .insert(schema.user)
524
+ .values([
525
+ { name: "User 1", email: "user1-getsubmission@example.com", emailVerified: true },
526
+ { name: "User 2", email: "user2-getsubmission@example.com", emailVerified: true },
527
+ ])
528
+ .returning();
529
+
530
+ // Create members for both organizations
531
+ const [member1, _member2] = await db
532
+ .insert(schema.member)
533
+ .values([
534
+ { organizationId: org1!.id, userId: user1!.id, role: "member" },
535
+ { organizationId: org2!.id, userId: user2!.id, role: "member" },
536
+ ])
537
+ .returning();
538
+
539
+ // Create conversations for both organizations
540
+ const [conversation1, conversation2] = await db
541
+ .insert(schema.conversation)
542
+ .values([
543
+ { organizationId: org1!.id, model: "gpt-4.1" },
544
+ { organizationId: org2!.id, model: "gpt-4.1" },
545
+ ])
546
+ .returning();
547
+
548
+ // Create workflow for both organizations
549
+ const [workflow1, workflow2] = await db
550
+ .insert(schema.workflow)
551
+ .values([
552
+ { organizationId: org1!.id, name: "Workflow 1" },
553
+ { organizationId: org2!.id, name: "Workflow 2" },
554
+ ])
555
+ .returning();
556
+
557
+ // Create forms for both organizations
558
+ const [form1, form2] = await db
559
+ .insert(schema.form)
560
+ .values([
561
+ {
562
+ workflowId: workflow1!.id,
563
+ organizationId: org1!.id,
564
+ conversationId: conversation1!.id,
565
+ name: "form 1",
566
+ },
567
+ {
568
+ workflowId: workflow2!.id,
569
+ organizationId: org2!.id,
570
+ conversationId: conversation2!.id,
571
+ name: "form 2",
572
+ },
573
+ ])
574
+ .returning();
575
+
576
+ // Create deals for both organizations
577
+ const [deal1, deal2] = await db
578
+ .insert(schema.deal)
579
+ .values([
580
+ { organizationId: org1!.id, name: "Deal 1" },
581
+ { organizationId: org2!.id, name: "Deal 2" },
582
+ ])
583
+ .returning();
584
+
585
+ // Create submissions for both organizations
586
+ const [submission1, submission2] = await db
587
+ .insert(schema.submission)
588
+ .values([
589
+ {
590
+ formId: form1!.id,
591
+ dealId: deal1!.id,
592
+ organizationId: org1!.id,
593
+ conversationId: conversation1!.id,
594
+ status: "draft",
595
+ },
596
+ {
597
+ formId: form2!.id,
598
+ dealId: deal2!.id,
599
+ organizationId: org2!.id,
600
+ conversationId: conversation2!.id,
601
+ status: "draft",
602
+ },
603
+ ])
604
+ .returning();
605
+
606
+ // Try to get org2's submission using member1 (should fail)
607
+ await expect(
608
+ getSubmission({
609
+ member: member1!,
610
+ submissionId: submission2!.id,
611
+ }),
612
+ ).rejects.toThrow();
613
+
614
+ // Get org1's submission using member1 (should work)
615
+ const result = await getSubmission({
616
+ member: member1!,
617
+ submissionId: submission1!.id,
618
+ });
619
+
620
+ expect(result).toBeDefined();
621
+ expect(result.id).toBe(submission1!.id);
622
+ expect(result.organizationId).toBe(org1!.id);
623
+ expect(result.formId).toBe(form1!.id);
624
+ expect(result.dealId).toBe(deal1!.id);
625
+ expect(result.conversationId).toBe(conversation1!.id);
626
+ expect(result.status).toBe("draft");
627
+ });
628
+ });
629
+
630
+ describe("dbtest: updateSubmissionValue", () => {
631
+ beforeEach(async () => {
632
+ await resetTestDb();
633
+ });
634
+
635
+ it("prevents updating submission values across organizations", async () => {
636
+ // Create two organizations
637
+ const [org1, org2] = await db
638
+ .insert(schema.organization)
639
+ .values([{ name: "Org 1" }, { name: "Org 2" }])
640
+ .returning();
641
+
642
+ // Create users for both organizations
643
+ const [user1, user2] = await db
644
+ .insert(schema.user)
645
+ .values([
646
+ { name: "User 1", email: "user1-updatesubmissionvalue@example.com", emailVerified: true },
647
+ { name: "User 2", email: "user2-updatesubmissionvalue@example.com", emailVerified: true },
648
+ ])
649
+ .returning();
650
+
651
+ // Create members for both organizations
652
+ const [member1, _member2] = await db
653
+ .insert(schema.member)
654
+ .values([
655
+ { organizationId: org1!.id, userId: user1!.id, role: "member" },
656
+ { organizationId: org2!.id, userId: user2!.id, role: "member" },
657
+ ])
658
+ .returning();
659
+
660
+ // Create conversations for both organizations
661
+ const [conversation1, conversation2] = await db
662
+ .insert(schema.conversation)
663
+ .values([
664
+ { organizationId: org1!.id, model: "gpt-4.1" },
665
+ { organizationId: org2!.id, model: "gpt-4.1" },
666
+ ])
667
+ .returning();
668
+
669
+ // Create workflow for both organizations
670
+ const [workflow1, workflow2] = await db
671
+ .insert(schema.workflow)
672
+ .values([
673
+ { organizationId: org1!.id, name: "Workflow 1" },
674
+ { organizationId: org2!.id, name: "Workflow 2" },
675
+ ])
676
+ .returning();
677
+
678
+ // Create forms for both organizations
679
+ const [form1, form2] = await db
680
+ .insert(schema.form)
681
+ .values([
682
+ {
683
+ workflowId: workflow1!.id,
684
+ organizationId: org1!.id,
685
+ conversationId: conversation1!.id,
686
+ name: "form 1",
687
+ },
688
+ {
689
+ workflowId: workflow2!.id,
690
+ organizationId: org2!.id,
691
+ conversationId: conversation2!.id,
692
+ name: "form 2",
693
+ },
694
+ ])
695
+ .returning();
696
+
697
+ // Create form groups for both organizations
698
+ const [formGroup1, formGroup2] = await db
699
+ .insert(schema.formGroup)
700
+ .values([
701
+ {
702
+ formId: form1!.id,
703
+ name: "Group 1",
704
+ multi: false,
705
+ order: 0,
706
+ },
707
+ {
708
+ formId: form2!.id,
709
+ name: "Group 2",
710
+ multi: false,
711
+ order: 0,
712
+ },
713
+ ])
714
+ .returning();
715
+
716
+ // Create form fields for both organizations
717
+ const [formField1, formField2] = await db
718
+ .insert(schema.formField)
719
+ .values([
720
+ {
721
+ formGroupId: formGroup1!.id,
722
+ name: "Item 1",
723
+ type: "string",
724
+ order: 0,
725
+ },
726
+ {
727
+ formGroupId: formGroup2!.id,
728
+ name: "Item 2",
729
+ type: "string",
730
+ order: 0,
731
+ },
732
+ ])
733
+ .returning();
734
+
735
+ // Create deals for both organizations
736
+ const [deal1, deal2] = await db
737
+ .insert(schema.deal)
738
+ .values([
739
+ { organizationId: org1!.id, name: "Deal 1" },
740
+ { organizationId: org2!.id, name: "Deal 2" },
741
+ ])
742
+ .returning();
743
+
744
+ // Create submissions for both organizations
745
+ const [submission1, submission2] = await db
746
+ .insert(schema.submission)
747
+ .values([
748
+ {
749
+ formId: form1!.id,
750
+ dealId: deal1!.id,
751
+ organizationId: org1!.id,
752
+ conversationId: conversation1!.id,
753
+ status: "draft",
754
+ },
755
+ {
756
+ formId: form2!.id,
757
+ dealId: deal2!.id,
758
+ organizationId: org2!.id,
759
+ conversationId: conversation2!.id,
760
+ status: "draft",
761
+ },
762
+ ])
763
+ .returning();
764
+
765
+ // Create submission groups for both organizations
766
+ const [submissionGroup1, submissionGroup2] = await db
767
+ .insert(schema.submissionGroup)
768
+ .values([
769
+ {
770
+ submissionId: submission1!.id,
771
+ formGroupId: formGroup1!.id,
772
+ order: 0,
773
+ },
774
+ {
775
+ submissionId: submission2!.id,
776
+ formGroupId: formGroup2!.id,
777
+ order: 0,
778
+ },
779
+ ])
780
+ .returning();
781
+
782
+ // Create submission items for both organizations
783
+ const [submissionItem1, submissionItem2] = await db
784
+ .insert(schema.submissionItem)
785
+ .values([
786
+ {
787
+ submissionGroupId: submissionGroup1!.id,
788
+ formFieldId: formField1!.id,
789
+ },
790
+ {
791
+ submissionGroupId: submissionGroup2!.id,
792
+ formFieldId: formField2!.id,
793
+ },
794
+ ])
795
+ .returning();
796
+
797
+ // Try to update org2's submission item using member1 (should fail)
798
+ await expect(
799
+ updateSubmissionValue({
800
+ member: member1!,
801
+ submissionItemId: submissionItem2!.id,
802
+ value: "unauthorized update",
803
+ }),
804
+ ).rejects.toThrow();
805
+
806
+ // Verify no version was created for org2's submission item
807
+ const org2ItemVersions = await db.query.submissionItemVersion.findMany({
808
+ where: eq(schema.submissionItemVersion.submissionItemId, submissionItem2!.id),
809
+ });
810
+ expect(org2ItemVersions).toHaveLength(0);
811
+
812
+ // Update org1's submission item using member1 (should work)
813
+ await updateSubmissionValue({
814
+ member: member1!,
815
+ submissionItemId: submissionItem1!.id,
816
+ value: "authorized update",
817
+ });
818
+
819
+ // Verify the version was created for org1's submission item
820
+ const org1ItemVersions = await db.query.submissionItemVersion.findMany({
821
+ where: eq(schema.submissionItemVersion.submissionItemId, submissionItem1!.id),
822
+ });
823
+ expect(org1ItemVersions).toHaveLength(1);
824
+ expect(org1ItemVersions[0]!.value).toBe("authorized update");
825
+ expect(org1ItemVersions[0]!.selected).toBe(true);
826
+ expect(org1ItemVersions[0]!.sourceType).toBe("manual");
827
+ });
828
+ });
829
+
830
+ describe("dbtest: resetSubmission", () => {
831
+ beforeEach(async () => {
832
+ await resetTestDb();
833
+ });
834
+
835
+ it("prevents resetting submissions across organizations", async () => {
836
+ // Create two organizations
837
+ const [org1, org2] = await db
838
+ .insert(schema.organization)
839
+ .values([{ name: "Org 1" }, { name: "Org 2" }])
840
+ .returning();
841
+
842
+ // Create users for both organizations
843
+ const [user1, user2] = await db
844
+ .insert(schema.user)
845
+ .values([
846
+ { name: "User 1", email: "user1-resetsubmission@example.com", emailVerified: true },
847
+ { name: "User 2", email: "user2-resetsubmission@example.com", emailVerified: true },
848
+ ])
849
+ .returning();
850
+
851
+ // Create members for both organizations
852
+ const [member1, _member2] = await db
853
+ .insert(schema.member)
854
+ .values([
855
+ { organizationId: org1!.id, userId: user1!.id, role: "member" },
856
+ { organizationId: org2!.id, userId: user2!.id, role: "member" },
857
+ ])
858
+ .returning();
859
+
860
+ // Create conversations for both organizations
861
+ const [conversation1, conversation2] = await db
862
+ .insert(schema.conversation)
863
+ .values([
864
+ { organizationId: org1!.id, model: "gpt-4.1" },
865
+ { organizationId: org2!.id, model: "gpt-4.1" },
866
+ ])
867
+ .returning();
868
+
869
+ // Create workflow for both organizations
870
+ const [workflow1, workflow2] = await db
871
+ .insert(schema.workflow)
872
+ .values([
873
+ { organizationId: org1!.id, name: "Workflow 1" },
874
+ { organizationId: org2!.id, name: "Workflow 2" },
875
+ ])
876
+ .returning();
877
+
878
+ // Create forms for both organizations
879
+ const [form1, form2] = await db
880
+ .insert(schema.form)
881
+ .values([
882
+ {
883
+ workflowId: workflow1!.id,
884
+ organizationId: org1!.id,
885
+ conversationId: conversation1!.id,
886
+ name: "form 1",
887
+ },
888
+ {
889
+ workflowId: workflow2!.id,
890
+ organizationId: org2!.id,
891
+ conversationId: conversation2!.id,
892
+ name: "form 2",
893
+ },
894
+ ])
895
+ .returning();
896
+
897
+ // Create form groups for both organizations (multi=true for testing)
898
+ const [formGroup1, formGroup2] = await db
899
+ .insert(schema.formGroup)
900
+ .values([
901
+ {
902
+ formId: form1!.id,
903
+ name: "Group 1",
904
+ multi: true,
905
+ order: 0,
906
+ },
907
+ {
908
+ formId: form2!.id,
909
+ name: "Group 2",
910
+ multi: true,
911
+ order: 0,
912
+ },
913
+ ])
914
+ .returning();
915
+
916
+ // Create form fields for both organizations
917
+ const [formField1, formField2] = await db
918
+ .insert(schema.formField)
919
+ .values([
920
+ {
921
+ formGroupId: formGroup1!.id,
922
+ name: "Item 1",
923
+ type: "string",
924
+ order: 0,
925
+ },
926
+ {
927
+ formGroupId: formGroup2!.id,
928
+ name: "Item 2",
929
+ type: "string",
930
+ order: 0,
931
+ },
932
+ ])
933
+ .returning();
934
+
935
+ // Create deals for both organizations
936
+ const [deal1, deal2] = await db
937
+ .insert(schema.deal)
938
+ .values([
939
+ { organizationId: org1!.id, name: "Deal 1" },
940
+ { organizationId: org2!.id, name: "Deal 2" },
941
+ ])
942
+ .returning();
943
+
944
+ // Create submissions for both organizations
945
+ const [submission1, submission2] = await db
946
+ .insert(schema.submission)
947
+ .values([
948
+ {
949
+ formId: form1!.id,
950
+ dealId: deal1!.id,
951
+ organizationId: org1!.id,
952
+ conversationId: conversation1!.id,
953
+ status: "draft",
954
+ },
955
+ {
956
+ formId: form2!.id,
957
+ dealId: deal2!.id,
958
+ organizationId: org2!.id,
959
+ conversationId: conversation2!.id,
960
+ status: "draft",
961
+ },
962
+ ])
963
+ .returning();
964
+
965
+ // Create submission groups for both organizations
966
+ const [submissionGroup1, submissionGroup2] = await db
967
+ .insert(schema.submissionGroup)
968
+ .values([
969
+ {
970
+ submissionId: submission1!.id,
971
+ formGroupId: formGroup1!.id,
972
+ order: 0,
973
+ },
974
+ {
975
+ submissionId: submission2!.id,
976
+ formGroupId: formGroup2!.id,
977
+ order: 0,
978
+ },
979
+ ])
980
+ .returning();
981
+
982
+ // Create submission items for both organizations
983
+ const [submissionItem1, submissionItem2] = await db
984
+ .insert(schema.submissionItem)
985
+ .values([
986
+ {
987
+ submissionGroupId: submissionGroup1!.id,
988
+ formFieldId: formField1!.id,
989
+ },
990
+ {
991
+ submissionGroupId: submissionGroup2!.id,
992
+ formFieldId: formField2!.id,
993
+ },
994
+ ])
995
+ .returning();
996
+
997
+ // Create submission item versions for both organizations
998
+ await db.insert(schema.submissionItemVersion).values([
999
+ {
1000
+ submissionItemId: submissionItem1!.id,
1001
+ sourceType: "manual",
1002
+ value: "test value 1",
1003
+ selected: true,
1004
+ },
1005
+ {
1006
+ submissionItemId: submissionItem2!.id,
1007
+ sourceType: "manual",
1008
+ value: "test value 2",
1009
+ selected: true,
1010
+ },
1011
+ ]);
1012
+
1013
+ // Verify initial state: both organizations have data
1014
+ const initialOrg1Versions = await db.query.submissionItemVersion.findMany({
1015
+ where: eq(schema.submissionItemVersion.submissionItemId, submissionItem1!.id),
1016
+ });
1017
+ const initialOrg2Versions = await db.query.submissionItemVersion.findMany({
1018
+ where: eq(schema.submissionItemVersion.submissionItemId, submissionItem2!.id),
1019
+ });
1020
+ const initialOrg1Groups = await db.query.submissionGroup.findMany({
1021
+ where: eq(schema.submissionGroup.submissionId, submission1!.id),
1022
+ });
1023
+ const initialOrg2Groups = await db.query.submissionGroup.findMany({
1024
+ where: eq(schema.submissionGroup.submissionId, submission2!.id),
1025
+ });
1026
+
1027
+ expect(initialOrg1Versions).toHaveLength(1);
1028
+ expect(initialOrg2Versions).toHaveLength(1);
1029
+ expect(initialOrg1Groups).toHaveLength(1);
1030
+ expect(initialOrg2Groups).toHaveLength(1);
1031
+
1032
+ // Try to reset org2's submission using member1 (should silently do nothing due to organization check)
1033
+ await resetSubmission({
1034
+ member: member1!,
1035
+ submissionId: submission2!.id,
1036
+ });
1037
+
1038
+ // Verify org2's data is unchanged
1039
+ const org2VersionsAfterReset = await db.query.submissionItemVersion.findMany({
1040
+ where: eq(schema.submissionItemVersion.submissionItemId, submissionItem2!.id),
1041
+ });
1042
+ const org2GroupsAfterReset = await db.query.submissionGroup.findMany({
1043
+ where: eq(schema.submissionGroup.submissionId, submission2!.id),
1044
+ });
1045
+
1046
+ expect(org2VersionsAfterReset).toHaveLength(1);
1047
+ expect(org2GroupsAfterReset).toHaveLength(1);
1048
+
1049
+ // Reset org1's submission using member1 (should work)
1050
+ await resetSubmission({
1051
+ member: member1!,
1052
+ submissionId: submission1!.id,
1053
+ });
1054
+
1055
+ // Verify org1's data is reset
1056
+ const org1VersionsAfterReset = await db.query.submissionItemVersion.findMany({
1057
+ where: eq(schema.submissionItemVersion.submissionItemId, submissionItem1!.id),
1058
+ });
1059
+ const org1GroupsAfterReset = await db.query.submissionGroup.findMany({
1060
+ where: eq(schema.submissionGroup.submissionId, submission1!.id),
1061
+ });
1062
+
1063
+ expect(org1VersionsAfterReset).toHaveLength(0);
1064
+ expect(org1GroupsAfterReset).toHaveLength(0);
1065
+
1066
+ // Verify org2's data is still unchanged
1067
+ const org2VersionsFinal = await db.query.submissionItemVersion.findMany({
1068
+ where: eq(schema.submissionItemVersion.submissionItemId, submissionItem2!.id),
1069
+ });
1070
+ const org2GroupsFinal = await db.query.submissionGroup.findMany({
1071
+ where: eq(schema.submissionGroup.submissionId, submission2!.id),
1072
+ });
1073
+
1074
+ expect(org2VersionsFinal).toHaveLength(1);
1075
+ expect(org2GroupsFinal).toHaveLength(1);
1076
+ });
1077
+ });
1078
+
1079
+ describe("dbtest: getDenormSubmission", () => {
1080
+ beforeEach(async () => {
1081
+ await resetTestDb();
1082
+ });
1083
+
1084
+ it("prevents accessing denormalized submissions across organizations", async () => {
1085
+ // Create two organizations
1086
+ const [org1, org2] = await db
1087
+ .insert(schema.organization)
1088
+ .values([{ name: "Org 1" }, { name: "Org 2" }])
1089
+ .returning();
1090
+
1091
+ // Create users for both organizations
1092
+ const [user1, user2] = await db
1093
+ .insert(schema.user)
1094
+ .values([
1095
+ { name: "User 1", email: "user1-getdenormsubmission@example.com", emailVerified: true },
1096
+ { name: "User 2", email: "user2-getdenormsubmission@example.com", emailVerified: true },
1097
+ ])
1098
+ .returning();
1099
+
1100
+ // Create members for both organizations
1101
+ const [member1, _member2] = await db
1102
+ .insert(schema.member)
1103
+ .values([
1104
+ { organizationId: org1!.id, userId: user1!.id, role: "member" },
1105
+ { organizationId: org2!.id, userId: user2!.id, role: "member" },
1106
+ ])
1107
+ .returning();
1108
+
1109
+ // Create conversations for both organizations
1110
+ const [conversation1, conversation2] = await db
1111
+ .insert(schema.conversation)
1112
+ .values([
1113
+ { organizationId: org1!.id, model: "gpt-4.1" },
1114
+ { organizationId: org2!.id, model: "gpt-4.1" },
1115
+ ])
1116
+ .returning();
1117
+
1118
+ // Create workflow for both organizations
1119
+ const [workflow1, workflow2] = await db
1120
+ .insert(schema.workflow)
1121
+ .values([
1122
+ { organizationId: org1!.id, name: "Workflow 1" },
1123
+ { organizationId: org2!.id, name: "Workflow 2" },
1124
+ ])
1125
+ .returning();
1126
+
1127
+ // Create forms for both organizations
1128
+ const [form1, form2] = await db
1129
+ .insert(schema.form)
1130
+ .values([
1131
+ {
1132
+ workflowId: workflow1!.id,
1133
+ organizationId: org1!.id,
1134
+ conversationId: conversation1!.id,
1135
+ name: "form 1",
1136
+ hint: "Test hint 1",
1137
+ },
1138
+ {
1139
+ workflowId: workflow2!.id,
1140
+ organizationId: org2!.id,
1141
+ conversationId: conversation2!.id,
1142
+ name: "form 2",
1143
+ hint: "Test hint 2",
1144
+ },
1145
+ ])
1146
+ .returning();
1147
+
1148
+ // Create form groups for both organizations
1149
+ const [formGroup1, formGroup2] = await db
1150
+ .insert(schema.formGroup)
1151
+ .values([
1152
+ {
1153
+ formId: form1!.id,
1154
+ name: "Group 1",
1155
+ multi: false,
1156
+ hint: "Group hint 1",
1157
+ order: 0,
1158
+ },
1159
+ {
1160
+ formId: form2!.id,
1161
+ name: "Group 2",
1162
+ multi: false,
1163
+ hint: "Group hint 2",
1164
+ order: 0,
1165
+ },
1166
+ ])
1167
+ .returning();
1168
+
1169
+ // Create form fields for both organizations
1170
+ const [formField1, formField2] = await db
1171
+ .insert(schema.formField)
1172
+ .values([
1173
+ {
1174
+ formGroupId: formGroup1!.id,
1175
+ name: "Item 1",
1176
+ type: "string",
1177
+ hint: "Item hint 1",
1178
+ order: 0,
1179
+ },
1180
+ {
1181
+ formGroupId: formGroup2!.id,
1182
+ name: "Item 2",
1183
+ type: "string",
1184
+ hint: "Item hint 2",
1185
+ order: 0,
1186
+ },
1187
+ ])
1188
+ .returning();
1189
+
1190
+ // Create deals for both organizations
1191
+ const [deal1, deal2] = await db
1192
+ .insert(schema.deal)
1193
+ .values([
1194
+ { organizationId: org1!.id, name: "Deal 1" },
1195
+ { organizationId: org2!.id, name: "Deal 2" },
1196
+ ])
1197
+ .returning();
1198
+
1199
+ // Create submissions for both organizations
1200
+ const [submission1, submission2] = await db
1201
+ .insert(schema.submission)
1202
+ .values([
1203
+ {
1204
+ formId: form1!.id,
1205
+ dealId: deal1!.id,
1206
+ organizationId: org1!.id,
1207
+ conversationId: conversation1!.id,
1208
+ name: "Submission 1",
1209
+ summary: "Summary 1",
1210
+ status: "draft",
1211
+ },
1212
+ {
1213
+ formId: form2!.id,
1214
+ dealId: deal2!.id,
1215
+ organizationId: org2!.id,
1216
+ conversationId: conversation2!.id,
1217
+ name: "Submission 2",
1218
+ summary: "Summary 2",
1219
+ status: "draft",
1220
+ },
1221
+ ])
1222
+ .returning();
1223
+
1224
+ // Create submission groups for both organizations
1225
+ const [submissionGroup1, submissionGroup2] = await db
1226
+ .insert(schema.submissionGroup)
1227
+ .values([
1228
+ {
1229
+ submissionId: submission1!.id,
1230
+ formGroupId: formGroup1!.id,
1231
+ order: 0,
1232
+ },
1233
+ {
1234
+ submissionId: submission2!.id,
1235
+ formGroupId: formGroup2!.id,
1236
+ order: 0,
1237
+ },
1238
+ ])
1239
+ .returning();
1240
+
1241
+ // Create submission items for both organizations
1242
+ const [submissionItem1, submissionItem2] = await db
1243
+ .insert(schema.submissionItem)
1244
+ .values([
1245
+ {
1246
+ submissionGroupId: submissionGroup1!.id,
1247
+ formFieldId: formField1!.id,
1248
+ },
1249
+ {
1250
+ submissionGroupId: submissionGroup2!.id,
1251
+ formFieldId: formField2!.id,
1252
+ },
1253
+ ])
1254
+ .returning();
1255
+
1256
+ // Create submission item versions for both organizations
1257
+ await db.insert(schema.submissionItemVersion).values([
1258
+ {
1259
+ submissionItemId: submissionItem1!.id,
1260
+ sourceType: "manual",
1261
+ value: "test value 1",
1262
+ selected: true,
1263
+ },
1264
+ {
1265
+ submissionItemId: submissionItem2!.id,
1266
+ sourceType: "manual",
1267
+ value: "test value 2",
1268
+ selected: true,
1269
+ },
1270
+ ]);
1271
+
1272
+ // Try to get org2's denormalized submission using member1 (should fail)
1273
+ await expect(
1274
+ getDenormSubmission({
1275
+ member: member1!,
1276
+ submissionId: submission2!.id,
1277
+ }),
1278
+ ).rejects.toThrow();
1279
+
1280
+ // Get org1's denormalized submission using member1 (should work)
1281
+ const result = await getDenormSubmission({
1282
+ member: member1!,
1283
+ submissionId: submission1!.id,
1284
+ });
1285
+
1286
+ expect(result).toBeDefined();
1287
+ expect(result.id).toBe(submission1!.id);
1288
+ expect(result.name).toBe("Submission 1");
1289
+ expect(result.summary).toBe("Summary 1");
1290
+ expect(result.formName).toBe("form 1");
1291
+ expect(result.hint).toBe("Test hint 1");
1292
+ expect(result.groups).toHaveLength(1);
1293
+ expect(result.groups[0]!.id).toBe(submissionGroup1!.id);
1294
+ expect(result.groups[0]!.name).toBe("Group 1");
1295
+ expect(result.groups[0]!.multi).toBe(false);
1296
+ expect(result.groups[0]!.hint).toBe("Group hint 1");
1297
+ expect(result.groups[0]!.items).toHaveLength(1);
1298
+ expect(result.groups[0]!.items[0]!.id).toBe(submissionItem1!.id);
1299
+ expect(result.groups[0]!.items[0]!.name).toBe("Item 1");
1300
+ expect(result.groups[0]!.items[0]!.type).toBe("string");
1301
+ expect(result.groups[0]!.items[0]!.hint).toBe("Item hint 1");
1302
+ expect(result.groups[0]!.items[0]!.value).toBe("test value 1");
1303
+ });
1304
+ });