agor-live 0.23.1 → 0.23.2

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 (469) hide show
  1. package/dist/core/claude/index.cjs +51 -27
  2. package/dist/core/claude/index.js +51 -27
  3. package/dist/core/claude-cli/index.cjs +13 -0
  4. package/dist/core/claude-cli/index.js +13 -0
  5. package/dist/core/claude-cli/pricing.d.ts.map +1 -1
  6. package/dist/core/client/index.cjs +17 -0
  7. package/dist/core/client/index.js +16 -0
  8. package/dist/core/db/index.cjs +618 -421
  9. package/dist/core/db/index.js +550 -353
  10. package/dist/core/db/repositories/boards.d.ts +27 -0
  11. package/dist/core/db/repositories/boards.d.ts.map +1 -1
  12. package/dist/core/db/repositories/branches.d.ts +11 -1
  13. package/dist/core/db/repositories/branches.d.ts.map +1 -1
  14. package/dist/core/db/repositories/gateway-channels.d.ts +9 -0
  15. package/dist/core/db/repositories/gateway-channels.d.ts.map +1 -1
  16. package/dist/core/db/repositories/sessions.d.ts +7 -0
  17. package/dist/core/db/repositories/sessions.d.ts.map +1 -1
  18. package/dist/core/environment/render-snapshot.cjs +6 -2
  19. package/dist/core/environment/render-snapshot.d.ts +2 -0
  20. package/dist/core/environment/render-snapshot.d.ts.map +1 -1
  21. package/dist/core/environment/render-snapshot.js +6 -2
  22. package/dist/core/environment/variable-resolver.cjs +3 -1
  23. package/dist/core/environment/variable-resolver.js +3 -1
  24. package/dist/core/index.cjs +684 -486
  25. package/dist/core/index.js +684 -486
  26. package/dist/core/lib/feathers-validation.cjs +3 -0
  27. package/dist/core/lib/feathers-validation.d.ts +1 -0
  28. package/dist/core/lib/feathers-validation.d.ts.map +1 -1
  29. package/dist/core/lib/feathers-validation.js +3 -0
  30. package/dist/core/local-actions/index.cjs +123 -56
  31. package/dist/core/local-actions/index.js +121 -54
  32. package/dist/core/mcp/index.cjs +21 -3
  33. package/dist/core/mcp/index.d.ts +1 -1
  34. package/dist/core/mcp/index.d.ts.map +1 -1
  35. package/dist/core/mcp/index.js +18 -3
  36. package/dist/core/mcp/template-patterns.d.ts +15 -0
  37. package/dist/core/mcp/template-patterns.d.ts.map +1 -0
  38. package/dist/core/mcp/template-resolver.d.ts +13 -0
  39. package/dist/core/mcp/template-resolver.d.ts.map +1 -1
  40. package/dist/core/models/browser.cjs +6 -0
  41. package/dist/core/models/browser.js +6 -0
  42. package/dist/core/models/claude.d.ts.map +1 -1
  43. package/dist/core/models/index.cjs +6 -0
  44. package/dist/core/models/index.js +6 -0
  45. package/dist/core/seed/index.cjs +360 -216
  46. package/dist/core/seed/index.js +329 -185
  47. package/dist/core/templates/handlebars-helpers.cjs +3 -1
  48. package/dist/core/templates/handlebars-helpers.d.ts +5 -0
  49. package/dist/core/templates/handlebars-helpers.d.ts.map +1 -1
  50. package/dist/core/templates/handlebars-helpers.js +3 -1
  51. package/dist/core/tools/mcp/auth-secrets.cjs +3460 -3
  52. package/dist/core/tools/mcp/auth-secrets.d.ts.map +1 -1
  53. package/dist/core/tools/mcp/auth-secrets.js +3477 -3
  54. package/dist/core/tools/mcp/http-headers.cjs +17 -1
  55. package/dist/core/tools/mcp/http-headers.d.ts.map +1 -1
  56. package/dist/core/tools/mcp/http-headers.js +15 -1
  57. package/dist/core/tools/mcp/oauth-refresh.cjs +67 -43
  58. package/dist/core/tools/mcp/oauth-refresh.js +65 -41
  59. package/dist/core/types/board.d.ts +12 -0
  60. package/dist/core/types/board.d.ts.map +1 -1
  61. package/dist/core/types/gateway.d.ts +14 -0
  62. package/dist/core/types/gateway.d.ts.map +1 -1
  63. package/dist/core/types/index.cjs +17 -0
  64. package/dist/core/types/index.js +16 -0
  65. package/dist/core/unix/index.cjs +67 -0
  66. package/dist/core/unix/index.js +67 -0
  67. package/dist/daemon/auth/executor-runtime-scope.d.ts.map +1 -1
  68. package/dist/daemon/auth/executor-runtime-scope.js +19 -5
  69. package/dist/daemon/auth/executor-session-token.d.ts +15 -0
  70. package/dist/daemon/auth/executor-session-token.d.ts.map +1 -0
  71. package/dist/daemon/auth/executor-session-token.js +17 -0
  72. package/dist/daemon/auth/issue-browser-tokens-hook.d.ts +24 -0
  73. package/dist/daemon/auth/issue-browser-tokens-hook.d.ts.map +1 -0
  74. package/dist/daemon/auth/issue-browser-tokens-hook.js +95 -0
  75. package/dist/daemon/auth/service-jwt-strategy.d.ts.map +1 -1
  76. package/dist/daemon/auth/service-jwt-strategy.js +14 -2
  77. package/dist/daemon/declarations.d.ts +1 -0
  78. package/dist/daemon/declarations.d.ts.map +1 -1
  79. package/dist/daemon/index.js +1365 -418
  80. package/dist/daemon/main.js +1365 -418
  81. package/dist/daemon/mcp/server.js +294 -31
  82. package/dist/daemon/mcp/tools/analytics.js +73 -24
  83. package/dist/daemon/mcp/tools/artifacts.js +73 -24
  84. package/dist/daemon/mcp/tools/boards.js +73 -24
  85. package/dist/daemon/mcp/tools/branches.js +73 -24
  86. package/dist/daemon/mcp/tools/card-types.js +73 -24
  87. package/dist/daemon/mcp/tools/cards.js +73 -24
  88. package/dist/daemon/mcp/tools/environment.js +73 -24
  89. package/dist/daemon/mcp/tools/gateway-channels.d.ts.map +1 -1
  90. package/dist/daemon/mcp/tools/gateway-channels.js +190 -38
  91. package/dist/daemon/mcp/tools/knowledge.js +73 -24
  92. package/dist/daemon/mcp/tools/mcp-servers.js +73 -24
  93. package/dist/daemon/mcp/tools/messages.js +73 -24
  94. package/dist/daemon/mcp/tools/proxies.js +73 -24
  95. package/dist/daemon/mcp/tools/repos.js +73 -24
  96. package/dist/daemon/mcp/tools/schedules.js +73 -24
  97. package/dist/daemon/mcp/tools/search.js +73 -24
  98. package/dist/daemon/mcp/tools/sessions.js +73 -24
  99. package/dist/daemon/mcp/tools/tasks.js +73 -24
  100. package/dist/daemon/mcp/tools/users.js +76 -27
  101. package/dist/daemon/mcp/tools/widgets.d.ts.map +1 -1
  102. package/dist/daemon/mcp/tools/widgets.js +257 -99
  103. package/dist/daemon/oauth-auth-helpers.d.ts +35 -0
  104. package/dist/daemon/oauth-auth-helpers.d.ts.map +1 -0
  105. package/dist/daemon/oauth-auth-helpers.js +14 -0
  106. package/dist/daemon/register-hooks.d.ts +1 -0
  107. package/dist/daemon/register-hooks.d.ts.map +1 -1
  108. package/dist/daemon/register-hooks.js +304 -53
  109. package/dist/daemon/register-routes.d.ts.map +1 -1
  110. package/dist/daemon/register-routes.js +738 -288
  111. package/dist/daemon/register-services.d.ts.map +1 -1
  112. package/dist/daemon/register-services.js +386 -155
  113. package/dist/daemon/services/boards.d.ts +5 -0
  114. package/dist/daemon/services/boards.d.ts.map +1 -1
  115. package/dist/daemon/services/boards.js +7 -0
  116. package/dist/daemon/services/branches.d.ts.map +1 -1
  117. package/dist/daemon/services/branches.js +31 -2
  118. package/dist/daemon/services/claude-models.d.ts.map +1 -1
  119. package/dist/daemon/services/claude-models.js +4 -1
  120. package/dist/daemon/services/gateway.d.ts +15 -0
  121. package/dist/daemon/services/gateway.d.ts.map +1 -1
  122. package/dist/daemon/services/gateway.js +34 -0
  123. package/dist/daemon/services/health-monitor.d.ts.map +1 -1
  124. package/dist/daemon/services/health-monitor.js +10 -7
  125. package/dist/daemon/services/session-streams.d.ts +29 -0
  126. package/dist/daemon/services/session-streams.d.ts.map +1 -0
  127. package/dist/daemon/services/session-streams.js +84 -0
  128. package/dist/daemon/services/session-token-service.d.ts.map +1 -1
  129. package/dist/daemon/services/session-token-service.js +8 -4
  130. package/dist/daemon/setup/index.js +43 -11
  131. package/dist/daemon/setup/socketio.d.ts.map +1 -1
  132. package/dist/daemon/setup/socketio.js +43 -11
  133. package/dist/daemon/startup.d.ts.map +1 -1
  134. package/dist/daemon/startup.js +37 -16
  135. package/dist/daemon/utils/authorization.js +19 -5
  136. package/dist/daemon/utils/emit-service-event.d.ts +56 -0
  137. package/dist/daemon/utils/emit-service-event.d.ts.map +1 -0
  138. package/dist/daemon/utils/emit-service-event.js +23 -0
  139. package/dist/daemon/utils/mcp-header-secrets.d.ts +3 -5
  140. package/dist/daemon/utils/mcp-header-secrets.d.ts.map +1 -1
  141. package/dist/daemon/utils/mcp-header-secrets.js +31 -2
  142. package/dist/daemon/utils/realtime-access-cache.d.ts +9 -0
  143. package/dist/daemon/utils/realtime-access-cache.d.ts.map +1 -1
  144. package/dist/daemon/utils/realtime-access-cache.js +24 -0
  145. package/dist/daemon/utils/realtime-publish.d.ts +24 -0
  146. package/dist/daemon/utils/realtime-publish.d.ts.map +1 -1
  147. package/dist/daemon/utils/realtime-publish.js +120 -2
  148. package/dist/daemon/utils/session-queue-tenant-scope.d.ts +24 -0
  149. package/dist/daemon/utils/session-queue-tenant-scope.d.ts.map +1 -0
  150. package/dist/daemon/utils/session-queue-tenant-scope.js +133 -0
  151. package/dist/daemon/widgets/gateway-token/index.d.ts +114 -0
  152. package/dist/daemon/widgets/gateway-token/index.d.ts.map +1 -0
  153. package/dist/daemon/widgets/gateway-token/index.js +14711 -0
  154. package/dist/daemon/widgets/index.d.ts.map +1 -1
  155. package/dist/daemon/widgets/index.js +190 -16
  156. package/dist/daemon/widgets/registry.d.ts +7 -0
  157. package/dist/daemon/widgets/registry.d.ts.map +1 -1
  158. package/dist/daemon/widgets/submissions.js +12 -9
  159. package/dist/executor/commands/git.d.ts.map +1 -1
  160. package/dist/executor/commands/git.js +2 -0
  161. package/dist/executor/db/feathers-repositories.d.ts +19 -1
  162. package/dist/executor/db/feathers-repositories.d.ts.map +1 -1
  163. package/dist/executor/db/feathers-repositories.js +31 -1
  164. package/dist/executor/handlers/sdk/claude.d.ts.map +1 -1
  165. package/dist/executor/handlers/sdk/claude.js +1 -1
  166. package/dist/executor/handlers/sdk/codex.d.ts.map +1 -1
  167. package/dist/executor/handlers/sdk/codex.js +1 -1
  168. package/dist/executor/handlers/sdk/copilot.d.ts.map +1 -1
  169. package/dist/executor/handlers/sdk/copilot.js +1 -1
  170. package/dist/executor/handlers/sdk/cursor.d.ts.map +1 -1
  171. package/dist/executor/handlers/sdk/cursor.js +1 -0
  172. package/dist/executor/handlers/sdk/gemini.d.ts.map +1 -1
  173. package/dist/executor/handlers/sdk/gemini.js +1 -1
  174. package/dist/executor/handlers/sdk/opencode.d.ts.map +1 -1
  175. package/dist/executor/handlers/sdk/opencode.js +1 -1
  176. package/dist/executor/payload-types.d.ts +5 -5
  177. package/dist/executor/sdk-handlers/base/mcp-scoping.d.ts +8 -1
  178. package/dist/executor/sdk-handlers/base/mcp-scoping.d.ts.map +1 -1
  179. package/dist/executor/sdk-handlers/base/mcp-scoping.js +58 -6
  180. package/dist/executor/sdk-handlers/claude/claude-tool.d.ts +2 -2
  181. package/dist/executor/sdk-handlers/claude/claude-tool.d.ts.map +1 -1
  182. package/dist/executor/sdk-handlers/claude/claude-tool.js +2 -2
  183. package/dist/executor/sdk-handlers/claude/prompt-service.d.ts +13 -3
  184. package/dist/executor/sdk-handlers/claude/prompt-service.d.ts.map +1 -1
  185. package/dist/executor/sdk-handlers/claude/prompt-service.js +16 -3
  186. package/dist/executor/sdk-handlers/claude/query-builder.d.ts +2 -1
  187. package/dist/executor/sdk-handlers/claude/query-builder.d.ts.map +1 -1
  188. package/dist/executor/sdk-handlers/claude/query-builder.js +2 -1
  189. package/dist/executor/sdk-handlers/codex/codex-tool.d.ts +2 -2
  190. package/dist/executor/sdk-handlers/codex/codex-tool.d.ts.map +1 -1
  191. package/dist/executor/sdk-handlers/codex/codex-tool.js +2 -2
  192. package/dist/executor/sdk-handlers/codex/prompt-service.d.ts +3 -2
  193. package/dist/executor/sdk-handlers/codex/prompt-service.d.ts.map +1 -1
  194. package/dist/executor/sdk-handlers/codex/prompt-service.js +70 -6
  195. package/dist/executor/sdk-handlers/copilot/copilot-tool.d.ts +2 -2
  196. package/dist/executor/sdk-handlers/copilot/copilot-tool.d.ts.map +1 -1
  197. package/dist/executor/sdk-handlers/copilot/copilot-tool.js +2 -2
  198. package/dist/executor/sdk-handlers/copilot/prompt-service.d.ts +3 -2
  199. package/dist/executor/sdk-handlers/copilot/prompt-service.d.ts.map +1 -1
  200. package/dist/executor/sdk-handlers/copilot/prompt-service.js +4 -1
  201. package/dist/executor/sdk-handlers/gemini/gemini-tool.d.ts +2 -2
  202. package/dist/executor/sdk-handlers/gemini/gemini-tool.d.ts.map +1 -1
  203. package/dist/executor/sdk-handlers/gemini/gemini-tool.js +2 -2
  204. package/dist/executor/sdk-handlers/gemini/prompt-service.d.ts +3 -2
  205. package/dist/executor/sdk-handlers/gemini/prompt-service.d.ts.map +1 -1
  206. package/dist/executor/sdk-handlers/gemini/prompt-service.js +4 -1
  207. package/dist/executor/sdk-handlers/opencode/opencode-tool.d.ts +3 -2
  208. package/dist/executor/sdk-handlers/opencode/opencode-tool.d.ts.map +1 -1
  209. package/dist/executor/sdk-handlers/opencode/opencode-tool.js +4 -1
  210. package/dist/executor/services/feathers-client.d.ts.map +1 -1
  211. package/dist/executor/services/feathers-client.js +119 -20
  212. package/dist/ui/assets/AgorEmojiPickerInner-leeNywMc.js +1 -0
  213. package/dist/ui/assets/App-Dpl4Cc0U.js +4 -0
  214. package/dist/ui/assets/App-Dpl4Cc0U.js.gz +0 -0
  215. package/dist/ui/assets/AppNode-wN3UZlFK.js +1 -0
  216. package/dist/ui/assets/AppNode-wN3UZlFK.js.gz +0 -0
  217. package/dist/ui/assets/{ArtifactConsentModal-oMMzRn8L.js → ArtifactConsentModal-DjzXcP_L.js} +1 -1
  218. package/dist/ui/assets/ArtifactConsentModal-DjzXcP_L.js.gz +0 -0
  219. package/dist/ui/assets/ArtifactFullscreenPage-B3b_EZ0F.js +9 -0
  220. package/dist/ui/assets/ArtifactFullscreenPage-B3b_EZ0F.js.gz +0 -0
  221. package/dist/ui/assets/ArtifactNode-DISy2T-6.js +9 -0
  222. package/dist/ui/assets/ArtifactNode-DISy2T-6.js.gz +0 -0
  223. package/dist/ui/assets/AutocompleteTextarea-DUpsoEGr.js +19 -0
  224. package/dist/ui/assets/AutocompleteTextarea-DUpsoEGr.js.gz +0 -0
  225. package/dist/ui/assets/BoardObjectNodes-BakeGpIX.js +34 -0
  226. package/dist/ui/assets/BoardObjectNodes-BakeGpIX.js.gz +0 -0
  227. package/dist/ui/assets/{CodeEditor.inner-Cuj6RuLL.js → CodeEditor.inner-HmSdTLW5.js} +1 -1
  228. package/dist/ui/assets/CodeEditor.inner-HmSdTLW5.js.gz +0 -0
  229. package/dist/ui/assets/ConversationView-mWaA-B1f.js +1 -0
  230. package/dist/ui/assets/ConversationView-mWaA-B1f.js.gz +0 -0
  231. package/dist/ui/assets/{EmbeddedTerminal-Lx5I9EOJ.js → EmbeddedTerminal-NNoyPA81.js} +1 -1
  232. package/dist/ui/assets/EmbeddedTerminal-NNoyPA81.js.gz +0 -0
  233. package/dist/ui/assets/KnowledgePage-CkxVnRvz.js +24 -0
  234. package/dist/ui/assets/KnowledgePage-CkxVnRvz.js.gz +0 -0
  235. package/dist/ui/assets/{MarketingScreenshotPage-CmDPBHOl.js → MarketingScreenshotPage-B86Gs8jx.js} +2 -2
  236. package/dist/ui/assets/MarketingScreenshotPage-B86Gs8jx.js.gz +0 -0
  237. package/dist/ui/assets/MobileApp-BPs-SXvz.js +1 -0
  238. package/dist/ui/assets/MobileApp-BPs-SXvz.js.gz +0 -0
  239. package/dist/ui/assets/SessionCanvas-xVfDoEtz.js +13 -0
  240. package/dist/ui/assets/SessionCanvas-xVfDoEtz.js.gz +0 -0
  241. package/dist/ui/assets/{StreamdownDemoPage-okKKR2QH.js → StreamdownDemoPage-CvWLzVsv.js} +2 -2
  242. package/dist/ui/assets/StreamdownDemoPage-CvWLzVsv.js.gz +0 -0
  243. package/dist/ui/assets/{TerminalModal-D9jMGZXv.js → TerminalModal-ExOgsuOP.js} +2 -2
  244. package/dist/ui/assets/TerminalModal-ExOgsuOP.js.gz +0 -0
  245. package/dist/ui/assets/ThemeSwitcher-Cgyp5ruu.js +1 -0
  246. package/dist/ui/assets/ThemeSwitcher-Cgyp5ruu.js.gz +0 -0
  247. package/dist/ui/assets/{ThemedSyntaxHighlighter.inner-C1FdIHn0.js → ThemedSyntaxHighlighter.inner-rpCN9S6K.js} +1 -1
  248. package/dist/ui/assets/{antd-DT5ackd0.js → antd-BCqimh1J.js} +5 -5
  249. package/dist/ui/assets/{antd-DT5ackd0.js.gz → antd-BCqimh1J.js.gz} +0 -0
  250. package/dist/ui/assets/architecture-U656AL7Q-BxSQIjrE.js +1 -0
  251. package/dist/ui/assets/{architectureDiagram-VXUJARFQ-DwTJGGoj.js → architectureDiagram-VXUJARFQ-pDpGHSqT.js} +1 -1
  252. package/dist/ui/assets/architectureDiagram-VXUJARFQ-pDpGHSqT.js.gz +0 -0
  253. package/dist/ui/assets/{blockDiagram-VD42YOAC-Dh1_TVW2.js → blockDiagram-VD42YOAC-uP8JTJpK.js} +1 -1
  254. package/dist/ui/assets/blockDiagram-VD42YOAC-uP8JTJpK.js.gz +0 -0
  255. package/dist/ui/assets/{c4Diagram-YG6GDRKO-B1e96AcB.js → c4Diagram-YG6GDRKO-qQe72Mm7.js} +1 -1
  256. package/dist/ui/assets/c4Diagram-YG6GDRKO-qQe72Mm7.js.gz +0 -0
  257. package/dist/ui/assets/channel-CoUBs6Zn.js +1 -0
  258. package/dist/ui/assets/{chunk-4BX2VUAB-BODpCjJx.js → chunk-4BX2VUAB-sz-YE8Nt.js} +1 -1
  259. package/dist/ui/assets/chunk-4ZMWKKQ3-3oKtfWXp.js +3 -0
  260. package/dist/ui/assets/chunk-4ZMWKKQ3-3oKtfWXp.js.gz +0 -0
  261. package/dist/ui/assets/chunk-55IACEB6-BS04dgKF.js +1 -0
  262. package/dist/ui/assets/{chunk-ABZYJK2D-DCTXWSzV.js → chunk-ABZYJK2D-t3Gkphds.js} +3 -3
  263. package/dist/ui/assets/chunk-ABZYJK2D-t3Gkphds.js.gz +0 -0
  264. package/dist/ui/assets/{chunk-AGHRB4JF-CbNphBjE.js → chunk-AGHRB4JF-D_QmWxbY.js} +1 -1
  265. package/dist/ui/assets/chunk-AGHRB4JF-D_QmWxbY.js.gz +0 -0
  266. package/dist/ui/assets/{chunk-ATLVNIR6-rWg3qxof.js → chunk-ATLVNIR6-Bmg7-Ufz.js} +1 -1
  267. package/dist/ui/assets/chunk-ATLVNIR6-Bmg7-Ufz.js.gz +0 -0
  268. package/dist/ui/assets/{chunk-B4BG7PRW-CgtLCbpE.js → chunk-B4BG7PRW-dnSEE1u-.js} +1 -1
  269. package/dist/ui/assets/chunk-B4BG7PRW-dnSEE1u-.js.gz +0 -0
  270. package/dist/ui/assets/{chunk-CVBHYZKI-DTL6Zgr0.js → chunk-CVBHYZKI-BStaYnF0.js} +1 -1
  271. package/dist/ui/assets/{chunk-DI55MBZ5-Dwvx2Kva.js → chunk-DI55MBZ5-28dvx6o3.js} +1 -1
  272. package/dist/ui/assets/chunk-DI55MBZ5-28dvx6o3.js.gz +0 -0
  273. package/dist/ui/assets/chunk-EXTU4WIE-X-FURkEh.js +1 -0
  274. package/dist/ui/assets/{chunk-FMBD7UC4-BogA_9CV.js → chunk-FMBD7UC4-C_63gC9S.js} +1 -1
  275. package/dist/ui/assets/{chunk-HN2XXSSU-2blQO3Gb.js → chunk-HN2XXSSU-UFD374KI.js} +1 -1
  276. package/dist/ui/assets/chunk-HN2XXSSU-UFD374KI.js.gz +0 -0
  277. package/dist/ui/assets/{chunk-JA3XYJ7Z-Cr1rmOui.js → chunk-JA3XYJ7Z-B60hLNeR.js} +1 -1
  278. package/dist/ui/assets/chunk-JA3XYJ7Z-B60hLNeR.js.gz +0 -0
  279. package/dist/ui/assets/{chunk-JZLCHNYA-BsgZ79Fa.js → chunk-JZLCHNYA-ButC6pwN.js} +1 -1
  280. package/dist/ui/assets/chunk-JZLCHNYA-ButC6pwN.js.gz +0 -0
  281. package/dist/ui/assets/{chunk-MI3HLSF2-dwYeUy5S.js → chunk-MI3HLSF2-BivYzoSV.js} +1 -1
  282. package/dist/ui/assets/chunk-MI3HLSF2-BivYzoSV.js.gz +0 -0
  283. package/dist/ui/assets/chunk-N4CR4FBY-mVWzo5wJ.js +2 -0
  284. package/dist/ui/assets/chunk-N4CR4FBY-mVWzo5wJ.js.gz +0 -0
  285. package/dist/ui/assets/{chunk-QN33PNHL-DxdIDCAa.js → chunk-QN33PNHL-tXtHZpaG.js} +1 -1
  286. package/dist/ui/assets/{chunk-QXUST7PY-BCK2V0i-.js → chunk-QXUST7PY-DATib_Vv.js} +1 -1
  287. package/dist/ui/assets/chunk-QXUST7PY-DATib_Vv.js.gz +0 -0
  288. package/dist/ui/assets/chunk-QZHKN3VN-y6l249e5.js +1 -0
  289. package/dist/ui/assets/{chunk-S3R3BYOJ-GP3zIxrB.js → chunk-S3R3BYOJ-BEtfmflI.js} +1 -1
  290. package/dist/ui/assets/chunk-S3R3BYOJ-BEtfmflI.js.gz +0 -0
  291. package/dist/ui/assets/{chunk-TZMSLE5B-dX5RaM6g.js → chunk-TZMSLE5B-BY1ZtogK.js} +1 -1
  292. package/dist/ui/assets/chunk-TZMSLE5B-BY1ZtogK.js.gz +0 -0
  293. package/dist/ui/assets/classDiagram-2ON5EDUG-BYvq-uPY.js +1 -0
  294. package/dist/ui/assets/classDiagram-v2-WZHVMYZB-BYvq-uPY.js +1 -0
  295. package/dist/ui/assets/constants-CYzQKfD1.js +1 -0
  296. package/dist/ui/assets/{cose-bilkent-S5V4N54A-Dx0BJVDl.js → cose-bilkent-S5V4N54A-DPvYrqGG.js} +1 -1
  297. package/dist/ui/assets/cose-bilkent-S5V4N54A-DPvYrqGG.js.gz +0 -0
  298. package/dist/ui/assets/{dagre-6UL2VRFP-DiQSUxqN.js → dagre-6UL2VRFP-D800J6qb.js} +1 -1
  299. package/dist/ui/assets/dagre-6UL2VRFP-D800J6qb.js.gz +0 -0
  300. package/dist/ui/assets/{dagre-Bekd9Vdj.js → dagre-TNc4wezg.js} +1 -1
  301. package/dist/ui/assets/dagre-TNc4wezg.js.gz +0 -0
  302. package/dist/ui/assets/{diagram-PSM6KHXK-DtJnDQjc.js → diagram-PSM6KHXK-CGdP9F-X.js} +1 -1
  303. package/dist/ui/assets/diagram-PSM6KHXK-CGdP9F-X.js.gz +0 -0
  304. package/dist/ui/assets/{diagram-QEK2KX5R-CobkCRdj.js → diagram-QEK2KX5R-BD5lOCe5.js} +1 -1
  305. package/dist/ui/assets/diagram-QEK2KX5R-BD5lOCe5.js.gz +0 -0
  306. package/dist/ui/assets/{diagram-S2PKOQOG-DHEZYivc.js → diagram-S2PKOQOG-cp3l22vN.js} +1 -1
  307. package/dist/ui/assets/diagram-S2PKOQOG-cp3l22vN.js.gz +0 -0
  308. package/dist/ui/assets/editor-Cr0W5BQI.js +39 -0
  309. package/dist/ui/assets/editor-Cr0W5BQI.js.gz +0 -0
  310. package/dist/ui/assets/{emoji-B0hLmSLZ.js → emoji-Bv3m24sO.js} +1 -1
  311. package/dist/ui/assets/emoji-Bv3m24sO.js.gz +0 -0
  312. package/dist/ui/assets/{erDiagram-Q2GNP2WA-BVNeTZPQ.js → erDiagram-Q2GNP2WA-CQSXRgqr.js} +1 -1
  313. package/dist/ui/assets/erDiagram-Q2GNP2WA-CQSXRgqr.js.gz +0 -0
  314. package/dist/ui/assets/{flowDiagram-NV44I4VS-C73VFdyk.js → flowDiagram-NV44I4VS-CKcKpkph.js} +1 -1
  315. package/dist/ui/assets/flowDiagram-NV44I4VS-CKcKpkph.js.gz +0 -0
  316. package/dist/ui/assets/{ganttDiagram-LVOFAZNH-B_RosuD1.js → ganttDiagram-LVOFAZNH-DlAHzXO5.js} +1 -1
  317. package/dist/ui/assets/ganttDiagram-LVOFAZNH-DlAHzXO5.js.gz +0 -0
  318. package/dist/ui/assets/{gitGraph-F6HP7TQM-DMFIqn4h.js → gitGraph-F6HP7TQM-DeuXy4B1.js} +1 -1
  319. package/dist/ui/assets/{gitGraphDiagram-NY62KEGX-hxbgwNA1.js → gitGraphDiagram-NY62KEGX-aB-AI4Vq.js} +1 -1
  320. package/dist/ui/assets/gitGraphDiagram-NY62KEGX-aB-AI4Vq.js.gz +0 -0
  321. package/dist/ui/assets/index-B-qHc0o5.js +63 -0
  322. package/dist/ui/assets/index-B-qHc0o5.js.gz +0 -0
  323. package/dist/ui/assets/{info-NVLQJR56-DZ3K-w48.js → info-NVLQJR56-B9PG7xsc.js} +1 -1
  324. package/dist/ui/assets/{infoDiagram-ER5ION4S-CxnBJQu6.js → infoDiagram-ER5ION4S-C5Wpoqim.js} +1 -1
  325. package/dist/ui/assets/{journeyDiagram-XKPGCS4Q-CHYNj-f8.js → journeyDiagram-XKPGCS4Q-CHLziqfS.js} +1 -1
  326. package/dist/ui/assets/journeyDiagram-XKPGCS4Q-CHLziqfS.js.gz +0 -0
  327. package/dist/ui/assets/{kanban-definition-3W4ZIXB7-DQPCCsj2.js → kanban-definition-3W4ZIXB7-Dq7GzQE_.js} +1 -1
  328. package/dist/ui/assets/kanban-definition-3W4ZIXB7-Dq7GzQE_.js.gz +0 -0
  329. package/dist/ui/assets/{line-DBRjKmfa.js → line-DHKNg83I.js} +1 -1
  330. package/dist/ui/assets/{linear-DFao5Wyp.js → linear-BvUfn0I8.js} +1 -1
  331. package/dist/ui/assets/linear-BvUfn0I8.js.gz +0 -0
  332. package/dist/ui/assets/{mermaid-parser.core-DYCfacHj.js → mermaid-parser.core-C6d9tKoo.js} +2 -2
  333. package/dist/ui/assets/mermaid-parser.core-C6d9tKoo.js.gz +0 -0
  334. package/dist/ui/assets/{mermaid.core-C6xGFSdE.js → mermaid.core-CxE5KezR.js} +3 -3
  335. package/dist/ui/assets/mermaid.core-CxE5KezR.js.gz +0 -0
  336. package/dist/ui/assets/{mindmap-definition-VGOIOE7T-L3Pw-YM7.js → mindmap-definition-VGOIOE7T-DmPoQ48w.js} +1 -1
  337. package/dist/ui/assets/mindmap-definition-VGOIOE7T-DmPoQ48w.js.gz +0 -0
  338. package/dist/ui/assets/{packet-BFZMPI3H-CpL6iNoa.js → packet-BFZMPI3H-JZEkVZxU.js} +1 -1
  339. package/dist/ui/assets/{particles-CT8hcJOA.js → particles-CxMmUw86.js} +1 -1
  340. package/dist/ui/assets/particles-CxMmUw86.js.gz +0 -0
  341. package/dist/ui/assets/{pie-7BOR55EZ-hTqChbTo.js → pie-7BOR55EZ-_1II5pYQ.js} +1 -1
  342. package/dist/ui/assets/{pieDiagram-ADFJNKIX-Bf4Nou75.js → pieDiagram-ADFJNKIX-DrNkH33i.js} +1 -1
  343. package/dist/ui/assets/pieDiagram-ADFJNKIX-DrNkH33i.js.gz +0 -0
  344. package/dist/ui/assets/{quadrantDiagram-AYHSOK5B-DpjUTLB1.js → quadrantDiagram-AYHSOK5B-DOpC-HEF.js} +1 -1
  345. package/dist/ui/assets/quadrantDiagram-AYHSOK5B-DOpC-HEF.js.gz +0 -0
  346. package/dist/ui/assets/{radar-NHE76QYJ-myy7OENC.js → radar-NHE76QYJ-DDmqhzEZ.js} +1 -1
  347. package/dist/ui/assets/{reactflow-Cubtnk8i.js → reactflow-D98uPOMq.js} +1 -1
  348. package/dist/ui/assets/reactflow-D98uPOMq.js.gz +0 -0
  349. package/dist/ui/assets/{requirementDiagram-UZGBJVZJ-Bfrfh-0-.js → requirementDiagram-UZGBJVZJ-Bzx0iEPP.js} +1 -1
  350. package/dist/ui/assets/requirementDiagram-UZGBJVZJ-Bzx0iEPP.js.gz +0 -0
  351. package/dist/ui/assets/{sandpack-C58bwfIS.js → sandpack-059Z4UWP.js} +1 -1
  352. package/dist/ui/assets/sandpack-059Z4UWP.js.gz +0 -0
  353. package/dist/ui/assets/sandpackDefaults-CPMNDsw7.js +1 -0
  354. package/dist/ui/assets/sandpackDefaults-CPMNDsw7.js.gz +0 -0
  355. package/dist/ui/assets/{sankeyDiagram-TZEHDZUN-ClZAZ6va.js → sankeyDiagram-TZEHDZUN-Do9pvfDv.js} +1 -1
  356. package/dist/ui/assets/sankeyDiagram-TZEHDZUN-Do9pvfDv.js.gz +0 -0
  357. package/dist/ui/assets/{sequenceDiagram-WL72ISMW-CNgly63p.js → sequenceDiagram-WL72ISMW-CN8neUTA.js} +1 -1
  358. package/dist/ui/assets/sequenceDiagram-WL72ISMW-CN8neUTA.js.gz +0 -0
  359. package/dist/ui/assets/{src-DAeyG22O.js → src-DEbsv3pp.js} +2 -2
  360. package/dist/ui/assets/src-DEbsv3pp.js.gz +0 -0
  361. package/dist/ui/assets/{stateDiagram-FKZM4ZOC-BrEAoDpE.js → stateDiagram-FKZM4ZOC-BluWJi8n.js} +1 -1
  362. package/dist/ui/assets/stateDiagram-FKZM4ZOC-BluWJi8n.js.gz +0 -0
  363. package/dist/ui/assets/stateDiagram-v2-4FDKWEC3-DeyqBMDR.js +1 -0
  364. package/dist/ui/assets/{streamdown-BdAVfkeF.js → streamdown-BT1twtFc.js} +5 -5
  365. package/dist/ui/assets/streamdown-BT1twtFc.js.gz +0 -0
  366. package/dist/ui/assets/{syntax-BOfTnQiy.js → syntax-CBu6nLfm.js} +1 -1
  367. package/dist/ui/assets/syntax-CBu6nLfm.js.gz +0 -0
  368. package/dist/ui/assets/{timeline-definition-IT6M3QCI-CaRH3k4l.js → timeline-definition-IT6M3QCI-WdUNkiRj.js} +1 -1
  369. package/dist/ui/assets/timeline-definition-IT6M3QCI-WdUNkiRj.js.gz +0 -0
  370. package/dist/ui/assets/{treemap-KMMF4GRG-CUaLOV_B.js → treemap-KMMF4GRG-CoriU4Jl.js} +1 -1
  371. package/dist/ui/assets/{useUserLocalStorage-C8sgXgXR.js → useUserLocalStorage-GidNiOPC.js} +1 -1
  372. package/dist/ui/assets/useUserLocalStorage-GidNiOPC.js.gz +0 -0
  373. package/dist/ui/assets/{xychartDiagram-PRI3JC2R-BlhkI9T_.js → xychartDiagram-PRI3JC2R-CgBAKNt2.js} +1 -1
  374. package/dist/ui/assets/xychartDiagram-PRI3JC2R-CgBAKNt2.js.gz +0 -0
  375. package/dist/ui/index.html +9 -8
  376. package/dist/ui/index.html.gz +0 -0
  377. package/package.json +2 -2
  378. package/dist/ui/assets/AgorEmojiPickerInner-DQjr8M3_.js +0 -1
  379. package/dist/ui/assets/App-hJtcOxHv.js +0 -5
  380. package/dist/ui/assets/App-hJtcOxHv.js.gz +0 -0
  381. package/dist/ui/assets/AppNode-BhuMpn8O.js +0 -1
  382. package/dist/ui/assets/AppNode-BhuMpn8O.js.gz +0 -0
  383. package/dist/ui/assets/ArtifactConsentModal-oMMzRn8L.js.gz +0 -0
  384. package/dist/ui/assets/ArtifactFullscreenPage-B3wT8t8f.js +0 -9
  385. package/dist/ui/assets/ArtifactFullscreenPage-B3wT8t8f.js.gz +0 -0
  386. package/dist/ui/assets/ArtifactNode-BzQcrwFS.js +0 -9
  387. package/dist/ui/assets/ArtifactNode-BzQcrwFS.js.gz +0 -0
  388. package/dist/ui/assets/AutocompleteTextarea-Dau-V_30.js +0 -19
  389. package/dist/ui/assets/AutocompleteTextarea-Dau-V_30.js.gz +0 -0
  390. package/dist/ui/assets/BoardObjectNodes-DdKWv_ZT.js +0 -34
  391. package/dist/ui/assets/BoardObjectNodes-DdKWv_ZT.js.gz +0 -0
  392. package/dist/ui/assets/CodeEditor.inner-Cuj6RuLL.js.gz +0 -0
  393. package/dist/ui/assets/ConversationView-9-3ma1u-.js +0 -1
  394. package/dist/ui/assets/ConversationView-9-3ma1u-.js.gz +0 -0
  395. package/dist/ui/assets/EmbeddedTerminal-Lx5I9EOJ.js.gz +0 -0
  396. package/dist/ui/assets/KnowledgePage-Dz8YAMYC.js +0 -24
  397. package/dist/ui/assets/KnowledgePage-Dz8YAMYC.js.gz +0 -0
  398. package/dist/ui/assets/MarketingScreenshotPage-CmDPBHOl.js.gz +0 -0
  399. package/dist/ui/assets/MobileApp-BpgSG_gz.js +0 -1
  400. package/dist/ui/assets/MobileApp-BpgSG_gz.js.gz +0 -0
  401. package/dist/ui/assets/SessionCanvas-B6_mtlxK.js +0 -13
  402. package/dist/ui/assets/SessionCanvas-B6_mtlxK.js.gz +0 -0
  403. package/dist/ui/assets/StreamdownDemoPage-okKKR2QH.js.gz +0 -0
  404. package/dist/ui/assets/TerminalModal-D9jMGZXv.js.gz +0 -0
  405. package/dist/ui/assets/ThemeSwitcher-D9HgT37l.js +0 -1
  406. package/dist/ui/assets/ThemeSwitcher-D9HgT37l.js.gz +0 -0
  407. package/dist/ui/assets/architecture-U656AL7Q-DMnxkQRZ.js +0 -1
  408. package/dist/ui/assets/architectureDiagram-VXUJARFQ-DwTJGGoj.js.gz +0 -0
  409. package/dist/ui/assets/blockDiagram-VD42YOAC-Dh1_TVW2.js.gz +0 -0
  410. package/dist/ui/assets/c4Diagram-YG6GDRKO-B1e96AcB.js.gz +0 -0
  411. package/dist/ui/assets/channel-Jv4dT4S5.js +0 -1
  412. package/dist/ui/assets/chunk-55IACEB6-lJXvUquf.js +0 -1
  413. package/dist/ui/assets/chunk-ABZYJK2D-DCTXWSzV.js.gz +0 -0
  414. package/dist/ui/assets/chunk-AGHRB4JF-CbNphBjE.js.gz +0 -0
  415. package/dist/ui/assets/chunk-ATLVNIR6-rWg3qxof.js.gz +0 -0
  416. package/dist/ui/assets/chunk-B4BG7PRW-CgtLCbpE.js.gz +0 -0
  417. package/dist/ui/assets/chunk-DI55MBZ5-Dwvx2Kva.js.gz +0 -0
  418. package/dist/ui/assets/chunk-EXTU4WIE-DHyaqTsP.js +0 -1
  419. package/dist/ui/assets/chunk-HN2XXSSU-2blQO3Gb.js.gz +0 -0
  420. package/dist/ui/assets/chunk-JA3XYJ7Z-Cr1rmOui.js.gz +0 -0
  421. package/dist/ui/assets/chunk-JZLCHNYA-BsgZ79Fa.js.gz +0 -0
  422. package/dist/ui/assets/chunk-MI3HLSF2-dwYeUy5S.js.gz +0 -0
  423. package/dist/ui/assets/chunk-N4CR4FBY-DEMgSRVe.js +0 -2
  424. package/dist/ui/assets/chunk-N4CR4FBY-DEMgSRVe.js.gz +0 -0
  425. package/dist/ui/assets/chunk-QXUST7PY-BCK2V0i-.js.gz +0 -0
  426. package/dist/ui/assets/chunk-QZHKN3VN-CALjGrEE.js +0 -1
  427. package/dist/ui/assets/chunk-S3R3BYOJ-GP3zIxrB.js.gz +0 -0
  428. package/dist/ui/assets/chunk-TZMSLE5B-dX5RaM6g.js.gz +0 -0
  429. package/dist/ui/assets/classDiagram-2ON5EDUG-C3_RVP70.js +0 -1
  430. package/dist/ui/assets/classDiagram-v2-WZHVMYZB-C3_RVP70.js +0 -1
  431. package/dist/ui/assets/constants-GjIDNVyt.js +0 -1
  432. package/dist/ui/assets/cose-bilkent-S5V4N54A-Dx0BJVDl.js.gz +0 -0
  433. package/dist/ui/assets/dagre-6UL2VRFP-DiQSUxqN.js.gz +0 -0
  434. package/dist/ui/assets/dagre-Bekd9Vdj.js.gz +0 -0
  435. package/dist/ui/assets/diagram-PSM6KHXK-DtJnDQjc.js.gz +0 -0
  436. package/dist/ui/assets/diagram-QEK2KX5R-CobkCRdj.js.gz +0 -0
  437. package/dist/ui/assets/diagram-S2PKOQOG-DHEZYivc.js.gz +0 -0
  438. package/dist/ui/assets/editor-DQIG-JYZ.js +0 -43
  439. package/dist/ui/assets/editor-DQIG-JYZ.js.gz +0 -0
  440. package/dist/ui/assets/emoji-B0hLmSLZ.js.gz +0 -0
  441. package/dist/ui/assets/erDiagram-Q2GNP2WA-BVNeTZPQ.js.gz +0 -0
  442. package/dist/ui/assets/flowDiagram-NV44I4VS-C73VFdyk.js.gz +0 -0
  443. package/dist/ui/assets/ganttDiagram-LVOFAZNH-B_RosuD1.js.gz +0 -0
  444. package/dist/ui/assets/gitGraphDiagram-NY62KEGX-hxbgwNA1.js.gz +0 -0
  445. package/dist/ui/assets/index-DTz1Dif6.js +0 -64
  446. package/dist/ui/assets/index-DTz1Dif6.js.gz +0 -0
  447. package/dist/ui/assets/journeyDiagram-XKPGCS4Q-CHYNj-f8.js.gz +0 -0
  448. package/dist/ui/assets/kanban-definition-3W4ZIXB7-DQPCCsj2.js.gz +0 -0
  449. package/dist/ui/assets/linear-DFao5Wyp.js.gz +0 -0
  450. package/dist/ui/assets/mermaid-parser.core-DYCfacHj.js.gz +0 -0
  451. package/dist/ui/assets/mermaid.core-C6xGFSdE.js.gz +0 -0
  452. package/dist/ui/assets/mindmap-definition-VGOIOE7T-L3Pw-YM7.js.gz +0 -0
  453. package/dist/ui/assets/particles-CT8hcJOA.js.gz +0 -0
  454. package/dist/ui/assets/pieDiagram-ADFJNKIX-Bf4Nou75.js.gz +0 -0
  455. package/dist/ui/assets/quadrantDiagram-AYHSOK5B-DpjUTLB1.js.gz +0 -0
  456. package/dist/ui/assets/reactflow-Cubtnk8i.js.gz +0 -0
  457. package/dist/ui/assets/requirementDiagram-UZGBJVZJ-Bfrfh-0-.js.gz +0 -0
  458. package/dist/ui/assets/sandpack-C58bwfIS.js.gz +0 -0
  459. package/dist/ui/assets/sandpackDefaults-Bkga8XAE.js +0 -1
  460. package/dist/ui/assets/sankeyDiagram-TZEHDZUN-ClZAZ6va.js.gz +0 -0
  461. package/dist/ui/assets/sequenceDiagram-WL72ISMW-CNgly63p.js.gz +0 -0
  462. package/dist/ui/assets/src-DAeyG22O.js.gz +0 -0
  463. package/dist/ui/assets/stateDiagram-FKZM4ZOC-BrEAoDpE.js.gz +0 -0
  464. package/dist/ui/assets/stateDiagram-v2-4FDKWEC3-BNL52_oN.js +0 -1
  465. package/dist/ui/assets/streamdown-BdAVfkeF.js.gz +0 -0
  466. package/dist/ui/assets/syntax-BOfTnQiy.js.gz +0 -0
  467. package/dist/ui/assets/timeline-definition-IT6M3QCI-CaRH3k4l.js.gz +0 -0
  468. package/dist/ui/assets/useUserLocalStorage-C8sgXgXR.js.gz +0 -0
  469. package/dist/ui/assets/xychartDiagram-PRI3JC2R-BlhkI9T_.js.gz +0 -0
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/tools/mcp/auth-secrets.ts
@@ -26,6 +36,3449 @@ __export(auth_secrets_exports, {
26
36
  });
27
37
  module.exports = __toCommonJS(auth_secrets_exports);
28
38
 
39
+ // src/config/env-resolver.ts
40
+ var import_drizzle_orm5 = require("drizzle-orm");
41
+
42
+ // src/db/database-wrapper.ts
43
+ var import_drizzle_orm = require("drizzle-orm");
44
+
45
+ // src/db/tenant-context.ts
46
+ var import_node_async_hooks = require("async_hooks");
47
+ var tenantDatabaseScope = new import_node_async_hooks.AsyncLocalStorage();
48
+
49
+ // src/db/encryption.ts
50
+ var import_node_crypto = require("crypto");
51
+
52
+ // src/db/repositories/session-env-selections.ts
53
+ var import_drizzle_orm4 = require("drizzle-orm");
54
+
55
+ // src/db/schema.postgres.ts
56
+ var schema_postgres_exports = {};
57
+ __export(schema_postgres_exports, {
58
+ appVariables: () => appVariables,
59
+ artifactTrustGrants: () => artifactTrustGrants,
60
+ artifacts: () => artifacts,
61
+ boardComments: () => boardComments,
62
+ boardGroupGrants: () => boardGroupGrants,
63
+ boardObjects: () => boardObjects,
64
+ boardOwners: () => boardOwners,
65
+ boards: () => boards,
66
+ branchGroupGrants: () => branchGroupGrants,
67
+ branchOwners: () => branchOwners,
68
+ branches: () => branches,
69
+ branchesRelations: () => branchesRelations,
70
+ cardTypes: () => cardTypes,
71
+ cards: () => cards,
72
+ gatewayChannels: () => gatewayChannels,
73
+ gatewayOutboundMessages: () => gatewayOutboundMessages,
74
+ groupMemberships: () => groupMemberships,
75
+ groups: () => groups,
76
+ kbDocumentUnits: () => kbDocumentUnits,
77
+ kbDocumentVersions: () => kbDocumentVersions,
78
+ kbDocuments: () => kbDocuments,
79
+ kbEmbeddingSpaces: () => kbEmbeddingSpaces,
80
+ kbGraphEdges: () => kbGraphEdges,
81
+ kbGraphNodes: () => kbGraphNodes,
82
+ kbNamespaceAcl: () => kbNamespaceAcl,
83
+ kbNamespaces: () => kbNamespaces,
84
+ mcpServers: () => mcpServers,
85
+ messages: () => messages,
86
+ repos: () => repos,
87
+ schedules: () => schedules,
88
+ schedulesRelations: () => schedulesRelations,
89
+ serializedSessions: () => serializedSessions,
90
+ sessionEnvSelections: () => sessionEnvSelections,
91
+ sessionMcpServers: () => sessionMcpServers,
92
+ sessionRelationships: () => sessionRelationships,
93
+ sessionRelationshipsRelations: () => sessionRelationshipsRelations,
94
+ sessions: () => sessions,
95
+ sessionsRelations: () => sessionsRelations,
96
+ tasks: () => tasks,
97
+ threadSessionMap: () => threadSessionMap,
98
+ userApiKeys: () => userApiKeys,
99
+ userMcpOauthTokens: () => userMcpOauthTokens,
100
+ users: () => users
101
+ });
102
+
103
+ // src/types/branch.ts
104
+ var BRANCH_PERMISSION_LEVELS = ["none", "view", "session", "prompt", "all"];
105
+
106
+ // src/types/session.ts
107
+ var SessionStatus = {
108
+ IDLE: "idle",
109
+ RUNNING: "running",
110
+ STOPPING: "stopping",
111
+ // Stop requested, waiting for task to stop
112
+ AWAITING_PERMISSION: "awaiting_permission",
113
+ AWAITING_INPUT: "awaiting_input",
114
+ // Legacy / pre-#1177: AskUserQuestion was disallowed at the SDK; new sessions never enter this state, kept for historical rows
115
+ TIMED_OUT: "timed_out",
116
+ // Permission/input request timed out, executor exited — user must re-prompt
117
+ COMPLETED: "completed",
118
+ FAILED: "failed"
119
+ };
120
+ var EXECUTING_SESSION_STATUSES = /* @__PURE__ */ new Set([
121
+ SessionStatus.RUNNING,
122
+ SessionStatus.STOPPING,
123
+ SessionStatus.AWAITING_PERMISSION,
124
+ SessionStatus.AWAITING_INPUT
125
+ ]);
126
+
127
+ // src/types/task.ts
128
+ var TaskStatus = {
129
+ QUEUED: "queued",
130
+ // Task created but not yet running (waiting for executor to drain queue)
131
+ CREATED: "created",
132
+ RUNNING: "running",
133
+ STOPPING: "stopping",
134
+ // Stop requested, waiting for SDK to halt
135
+ AWAITING_PERMISSION: "awaiting_permission",
136
+ AWAITING_INPUT: "awaiting_input",
137
+ // Legacy / pre-#1177: AskUserQuestion was disallowed at the SDK; new tasks never enter this state, kept for historical rows
138
+ TIMED_OUT: "timed_out",
139
+ // Permission/input request timed out, executor exited — user must re-prompt
140
+ COMPLETED: "completed",
141
+ FAILED: "failed",
142
+ STOPPED: "stopped"
143
+ // User-requested stop (distinct from failed)
144
+ };
145
+ var TERMINAL_TASK_STATUSES = /* @__PURE__ */ new Set([
146
+ TaskStatus.COMPLETED,
147
+ TaskStatus.FAILED,
148
+ TaskStatus.STOPPED,
149
+ TaskStatus.TIMED_OUT
150
+ ]);
151
+ var EXECUTING_TASK_STATUSES = /* @__PURE__ */ new Set([
152
+ TaskStatus.RUNNING,
153
+ TaskStatus.STOPPING,
154
+ TaskStatus.AWAITING_PERMISSION,
155
+ TaskStatus.AWAITING_INPUT
156
+ ]);
157
+
158
+ // src/types/user.ts
159
+ var ROLES = {
160
+ SUPERADMIN: "superadmin",
161
+ ADMIN: "admin",
162
+ MEMBER: "member",
163
+ VIEWER: "viewer"
164
+ };
165
+ var ROLE_OPTIONS = [
166
+ {
167
+ value: ROLES.SUPERADMIN,
168
+ label: "Superadmin",
169
+ description: "Full system access + branch RBAC bypass"
170
+ },
171
+ {
172
+ value: ROLES.ADMIN,
173
+ label: "Admin",
174
+ description: "Manage resources (users, MCP servers, config)"
175
+ },
176
+ { value: ROLES.MEMBER, label: "Member", description: "Standard user" },
177
+ { value: ROLES.VIEWER, label: "Viewer", description: "Read-only access" }
178
+ ];
179
+ var ROLE_RANK = {
180
+ [ROLES.VIEWER]: 0,
181
+ [ROLES.MEMBER]: 1,
182
+ [ROLES.ADMIN]: 2,
183
+ [ROLES.SUPERADMIN]: 3,
184
+ owner: 3
185
+ };
186
+
187
+ // src/db/schema.postgres.ts
188
+ var import_drizzle_orm2 = require("drizzle-orm");
189
+ var import_pg_core = require("drizzle-orm/pg-core");
190
+ var bytea = (0, import_pg_core.customType)({
191
+ dataType() {
192
+ return "bytea";
193
+ }
194
+ });
195
+ var t = {
196
+ timestamp: (name) => (0, import_pg_core.timestamp)(name, { mode: "date", withTimezone: true }),
197
+ bool: (name) => (0, import_pg_core.boolean)(name),
198
+ json: (name) => (0, import_pg_core.jsonb)(name).$type()
199
+ };
200
+ var sessions = (0, import_pg_core.pgTable)(
201
+ "sessions",
202
+ {
203
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
204
+ // Primary identity
205
+ session_id: (0, import_pg_core.varchar)("session_id", { length: 36 }).primaryKey(),
206
+ created_at: t.timestamp("created_at").notNull(),
207
+ updated_at: t.timestamp("updated_at"),
208
+ // User attribution
209
+ created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }).notNull(),
210
+ // Unix username for SDK impersonation (immutable once set)
211
+ // Set from creator's unix_username at session creation time
212
+ // NEVER changes, even if user's unix_username changes later
213
+ // This ensures SDK session data remains accessible in the original home directory
214
+ unix_username: (0, import_pg_core.text)("unix_username"),
215
+ // Materialized for filtering/joins (cross-DB compatible)
216
+ status: (0, import_pg_core.text)("status", {
217
+ enum: [
218
+ "idle",
219
+ "running",
220
+ "stopping",
221
+ "awaiting_permission",
222
+ "awaiting_input",
223
+ "timed_out",
224
+ "completed",
225
+ "failed"
226
+ ]
227
+ }).notNull(),
228
+ agentic_tool: (0, import_pg_core.text)("agentic_tool", {
229
+ enum: ["claude-code", "claude-code-cli", "codex", "gemini", "opencode", "copilot", "cursor"]
230
+ }).notNull(),
231
+ board_id: (0, import_pg_core.varchar)("board_id", { length: 36 }),
232
+ // NULL = no board
233
+ // Genealogy (materialized for tree queries)
234
+ parent_session_id: (0, import_pg_core.varchar)("parent_session_id", { length: 36 }),
235
+ forked_from_session_id: (0, import_pg_core.varchar)("forked_from_session_id", { length: 36 }),
236
+ // Branch reference (REQUIRED: all sessions must have a branch)
237
+ branch_id: (0, import_pg_core.varchar)("branch_id", { length: 36 }).notNull().references(() => branches.branch_id, {
238
+ onDelete: "cascade"
239
+ // Cascade delete sessions when branch is deleted
240
+ }),
241
+ // Scheduler tracking (materialized for deduplication and retention cleanup)
242
+ scheduled_run_at: (0, import_pg_core.bigint)("scheduled_run_at", { mode: "number" }),
243
+ // Unix timestamp (ms) - authoritative run ID - bigint to support dates beyond 2038
244
+ scheduled_from_branch: t.bool("scheduled_from_branch").notNull().default(false),
245
+ // FK to schedules.schedule_id, ON DELETE SET NULL. Defined here (not
246
+ // just in the migration) so drizzle-kit / db introspection sees the
247
+ // constraint and so future schema diffs don't lose it.
248
+ schedule_id: (0, import_pg_core.varchar)("schedule_id", { length: 36 }).references(
249
+ () => schedules.schedule_id,
250
+ { onDelete: "set null" }
251
+ ),
252
+ // UI state (materialized for efficient highlighting queries)
253
+ ready_for_prompt: t.bool("ready_for_prompt").notNull().default(false),
254
+ // Archive state (cascaded from branch archive)
255
+ archived: t.bool("archived").notNull().default(false),
256
+ archived_reason: (0, import_pg_core.text)("archived_reason", {
257
+ enum: ["branch_archived", "manual", "btw_completed"]
258
+ }),
259
+ // JSON blob for everything else (cross-DB via json() type)
260
+ data: t.json("data").$type().notNull()
261
+ },
262
+ (table) => ({
263
+ tenantIdx: (0, import_pg_core.index)("sessions_tenant_id_idx").on(table.tenant_id),
264
+ statusIdx: (0, import_pg_core.index)("sessions_status_idx").on(table.status),
265
+ statusReadyIdx: (0, import_pg_core.index)("sessions_status_ready_idx").on(table.status, table.ready_for_prompt),
266
+ agenticToolIdx: (0, import_pg_core.index)("sessions_agentic_tool_idx").on(table.agentic_tool),
267
+ boardIdx: (0, import_pg_core.index)("sessions_board_idx").on(table.board_id),
268
+ branchIdx: (0, import_pg_core.index)("sessions_branch_idx").on(table.branch_id),
269
+ createdIdx: (0, import_pg_core.index)("sessions_created_idx").on(table.created_at),
270
+ parentIdx: (0, import_pg_core.index)("sessions_parent_idx").on(table.parent_session_id),
271
+ forkedIdx: (0, import_pg_core.index)("sessions_forked_idx").on(table.forked_from_session_id),
272
+ // Scheduler indexes — including the partial unique index below.
273
+ scheduledFromBranchIdx: (0, import_pg_core.index)("sessions_scheduled_flag_idx").on(table.scheduled_from_branch),
274
+ // Partial unique index — covering for the scheduler's dedup lookup
275
+ // AND serves as the DB-level guard against check-then-create races
276
+ // in spawnScheduledSession.
277
+ scheduleRunUnique: (0, import_pg_core.uniqueIndex)("sessions_schedule_run_unique").on(table.tenant_id, table.schedule_id, table.scheduled_run_at).where(import_drizzle_orm2.sql`${table.schedule_id} IS NOT NULL AND ${table.scheduled_run_at} IS NOT NULL`)
278
+ })
279
+ );
280
+ var sessionRelationships = (0, import_pg_core.pgTable)(
281
+ "session_relationships",
282
+ {
283
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
284
+ relationship_id: (0, import_pg_core.varchar)("relationship_id", { length: 36 }).primaryKey(),
285
+ source_session_id: (0, import_pg_core.varchar)("source_session_id", { length: 36 }).notNull().references(() => sessions.session_id, { onDelete: "cascade" }),
286
+ target_session_id: (0, import_pg_core.varchar)("target_session_id", { length: 36 }).notNull().references(() => sessions.session_id, { onDelete: "cascade" }),
287
+ relationship_type: (0, import_pg_core.text)("relationship_type", { enum: ["remote_create"] }).notNull(),
288
+ created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }).notNull(),
289
+ created_at: t.timestamp("created_at").notNull(),
290
+ updated_at: t.timestamp("updated_at"),
291
+ callback_enabled: t.bool("callback_enabled").notNull().default(false),
292
+ callback_session_id: (0, import_pg_core.varchar)("callback_session_id", { length: 36 }).references(
293
+ () => sessions.session_id,
294
+ {
295
+ onDelete: "set null"
296
+ }
297
+ ),
298
+ data: t.json("data")
299
+ },
300
+ (table) => ({
301
+ tenantIdx: (0, import_pg_core.index)("session_relationships_tenant_id_idx").on(table.tenant_id),
302
+ sourceIdx: (0, import_pg_core.index)("session_relationships_source_idx").on(table.source_session_id),
303
+ targetIdx: (0, import_pg_core.index)("session_relationships_target_idx").on(table.target_session_id),
304
+ callbackIdx: (0, import_pg_core.index)("session_relationships_callback_idx").on(table.callback_session_id),
305
+ // Composite indexes so the OR predicate in dispatchCompletionCallbacks
306
+ // (WHERE source_session_id = $1 OR target_session_id = $2) uses BitmapOr
307
+ // over these instead of a full tenant table scan via tenant_id_idx.
308
+ tenantSourceIdx: (0, import_pg_core.index)("session_relationships_tenant_source_idx").on(
309
+ table.tenant_id,
310
+ table.source_session_id
311
+ ),
312
+ tenantTargetIdx: (0, import_pg_core.index)("session_relationships_tenant_target_idx").on(
313
+ table.tenant_id,
314
+ table.target_session_id
315
+ ),
316
+ sourceTargetTypeUnique: (0, import_pg_core.uniqueIndex)("session_relationships_source_target_type_unique").on(
317
+ table.tenant_id,
318
+ table.source_session_id,
319
+ table.target_session_id,
320
+ table.relationship_type
321
+ )
322
+ })
323
+ );
324
+ var tasks = (0, import_pg_core.pgTable)(
325
+ "tasks",
326
+ {
327
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
328
+ task_id: (0, import_pg_core.varchar)("task_id", { length: 36 }).primaryKey(),
329
+ session_id: (0, import_pg_core.varchar)("session_id", { length: 36 }).notNull().references(() => sessions.session_id, { onDelete: "cascade" }),
330
+ created_at: t.timestamp("created_at").notNull(),
331
+ started_at: t.timestamp("started_at"),
332
+ completed_at: t.timestamp("completed_at"),
333
+ last_executor_heartbeat_at: t.timestamp("last_executor_heartbeat_at"),
334
+ status: (0, import_pg_core.text)("status", {
335
+ enum: [
336
+ "queued",
337
+ "created",
338
+ "running",
339
+ "stopping",
340
+ "awaiting_permission",
341
+ "awaiting_input",
342
+ "timed_out",
343
+ "completed",
344
+ "failed",
345
+ "stopped"
346
+ ]
347
+ }).notNull(),
348
+ // Queue position (lower drains first); only populated for status='queued'
349
+ queue_position: (0, import_pg_core.integer)("queue_position"),
350
+ // User attribution
351
+ created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }).notNull(),
352
+ // MD5 of SDK session file at task completion (only populated when stateless_fs_mode is enabled)
353
+ session_md5: (0, import_pg_core.text)("session_md5"),
354
+ data: t.json("data").$type().notNull()
355
+ },
356
+ (table) => ({
357
+ tenantIdx: (0, import_pg_core.index)("tasks_tenant_id_idx").on(table.tenant_id),
358
+ sessionIdx: (0, import_pg_core.index)("tasks_session_idx").on(table.session_id),
359
+ statusIdx: (0, import_pg_core.index)("tasks_status_idx").on(table.status),
360
+ createdIdx: (0, import_pg_core.index)("tasks_created_idx").on(table.created_at),
361
+ // Composite for "latest task for session" queries (ORDER BY created_at DESC LIMIT 1).
362
+ sessionCreatedIdx: (0, import_pg_core.index)("tasks_session_created_idx").on(table.session_id, table.created_at),
363
+ queueIdx: (0, import_pg_core.index)("tasks_queue_idx").on(table.session_id, table.status, table.queue_position),
364
+ // Partial unique index — defense-in-depth for `tasks.createPending` race
365
+ // serialization. Only QUEUED rows are constrained; CREATED/RUNNING/done
366
+ // rows have NULL queue_position and are unaffected.
367
+ queuedPositionUnique: (0, import_pg_core.uniqueIndex)("tasks_queued_position_unique").on(table.tenant_id, table.session_id, table.queue_position).where(import_drizzle_orm2.sql`${table.status} = 'queued'`)
368
+ })
369
+ );
370
+ var serializedSessions = (0, import_pg_core.pgTable)(
371
+ "serialized_sessions",
372
+ {
373
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
374
+ id: (0, import_pg_core.varchar)("id", { length: 36 }).primaryKey(),
375
+ session_id: (0, import_pg_core.varchar)("session_id", { length: 36 }).notNull().references(() => sessions.session_id, { onDelete: "cascade" }),
376
+ branch_id: (0, import_pg_core.varchar)("branch_id", { length: 36 }).notNull().references(() => branches.branch_id, { onDelete: "cascade" }),
377
+ task_id: (0, import_pg_core.varchar)("task_id", { length: 36 }).references(() => tasks.task_id, {
378
+ onDelete: "set null"
379
+ }),
380
+ turn_index: (0, import_pg_core.integer)("turn_index").notNull().default(0),
381
+ created_at: t.timestamp("created_at").notNull(),
382
+ md5: (0, import_pg_core.text)("md5").notNull(),
383
+ status: (0, import_pg_core.text)("status").notNull(),
384
+ // 'processing' | 'done' — validated at app layer
385
+ payload: bytea("payload")
386
+ // gzipped; NULL while status='processing'
387
+ },
388
+ (table) => ({
389
+ tenantIdx: (0, import_pg_core.index)("serialized_sessions_tenant_id_idx").on(table.tenant_id),
390
+ sessionTurnIdx: (0, import_pg_core.index)("serialized_sessions_session_turn_idx").on(
391
+ table.session_id,
392
+ table.turn_index
393
+ ),
394
+ branchIdx: (0, import_pg_core.index)("serialized_sessions_branch_idx").on(table.branch_id)
395
+ })
396
+ );
397
+ var messages = (0, import_pg_core.pgTable)(
398
+ "messages",
399
+ {
400
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
401
+ // Primary identity
402
+ message_id: (0, import_pg_core.varchar)("message_id", { length: 36 }).primaryKey(),
403
+ created_at: t.timestamp("created_at").notNull(),
404
+ // Foreign keys (materialized for indexes)
405
+ session_id: (0, import_pg_core.varchar)("session_id", { length: 36 }).notNull().references(() => sessions.session_id, { onDelete: "cascade" }),
406
+ task_id: (0, import_pg_core.varchar)("task_id", { length: 36 }).references(() => tasks.task_id, {
407
+ onDelete: "set null"
408
+ }),
409
+ // Materialized for queries
410
+ type: (0, import_pg_core.text)("type", {
411
+ enum: [
412
+ "user",
413
+ "assistant",
414
+ "system",
415
+ "file-history-snapshot",
416
+ "permission_request",
417
+ "input_request",
418
+ "daemon_restart",
419
+ "daemon_crash",
420
+ "widget_request"
421
+ ]
422
+ }).notNull(),
423
+ role: (0, import_pg_core.text)("role", {
424
+ enum: ["user", "assistant", "system"]
425
+ }).notNull(),
426
+ index: (0, import_pg_core.integer)("index").notNull(),
427
+ // Position in conversation (0-based)
428
+ timestamp: t.timestamp("timestamp").notNull(),
429
+ content_preview: (0, import_pg_core.text)("content_preview"),
430
+ // First 200 chars for list views
431
+ // Parent tool use ID (for nested tool calls - e.g., Task tool spawning Read/Grep)
432
+ parent_tool_use_id: (0, import_pg_core.text)("parent_tool_use_id"),
433
+ // NOTE: queueing moved off `messages` and onto `tasks.status='queued'` as
434
+ // of migration sqlite/0040 (postgres/0030). The legacy `status` and
435
+ // `queue_position` columns are gone — see `tasks.queue_position` instead.
436
+ // Full data (JSON blob)
437
+ data: t.json("data").$type().notNull()
438
+ },
439
+ (table) => ({
440
+ tenantIdx: (0, import_pg_core.index)("messages_tenant_id_idx").on(table.tenant_id),
441
+ tenantTimestampIdx: (0, import_pg_core.index)("messages_tenant_timestamp_idx").on(table.tenant_id, table.timestamp),
442
+ // Indexes for efficient lookups
443
+ sessionIdx: (0, import_pg_core.index)("messages_session_id_idx").on(table.session_id),
444
+ taskIdx: (0, import_pg_core.index)("messages_task_id_idx").on(table.task_id),
445
+ sessionIndexIdx: (0, import_pg_core.index)("messages_session_index_idx").on(table.session_id, table.index),
446
+ timestampIdx: (0, import_pg_core.index)("messages_timestamp_idx").on(table.timestamp),
447
+ sessionTimestampIdx: (0, import_pg_core.index)("messages_session_timestamp_idx").on(
448
+ table.session_id,
449
+ table.timestamp
450
+ )
451
+ })
452
+ );
453
+ var boards = (0, import_pg_core.pgTable)(
454
+ "boards",
455
+ {
456
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
457
+ board_id: (0, import_pg_core.varchar)("board_id", { length: 36 }).primaryKey(),
458
+ created_at: t.timestamp("created_at").notNull(),
459
+ updated_at: t.timestamp("updated_at"),
460
+ // User attribution
461
+ created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }).notNull(),
462
+ // Materialized for lookups
463
+ name: (0, import_pg_core.text)("name").notNull(),
464
+ slug: (0, import_pg_core.text)("slug"),
465
+ primary_assistant_id: (0, import_pg_core.varchar)("primary_assistant_id", { length: 36 }).references(
466
+ () => branches.branch_id,
467
+ {
468
+ onDelete: "set null"
469
+ }
470
+ ),
471
+ // JSON blob for the rest
472
+ data: t.json("data").$type().notNull(),
473
+ // Archive state (for soft deletes)
474
+ archived: t.bool("archived").notNull().default(false),
475
+ archived_at: t.timestamp("archived_at"),
476
+ archived_by: (0, import_pg_core.varchar)("archived_by", { length: 36 })
477
+ },
478
+ (table) => ({
479
+ tenantIdx: (0, import_pg_core.index)("boards_tenant_id_idx").on(table.tenant_id),
480
+ nameIdx: (0, import_pg_core.index)("boards_name_idx").on(table.name),
481
+ slugIdx: (0, import_pg_core.index)("boards_slug_idx").on(table.slug),
482
+ slugTenantUnique: (0, import_pg_core.uniqueIndex)("boards_tenant_slug_unique").on(table.tenant_id, table.slug)
483
+ })
484
+ );
485
+ var repos = (0, import_pg_core.pgTable)(
486
+ "repos",
487
+ {
488
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
489
+ repo_id: (0, import_pg_core.varchar)("repo_id", { length: 36 }).primaryKey(),
490
+ created_at: t.timestamp("created_at").notNull(),
491
+ updated_at: t.timestamp("updated_at"),
492
+ // Materialized for querying
493
+ slug: (0, import_pg_core.text)("slug").notNull(),
494
+ repo_type: (0, import_pg_core.text)("repo_type", { enum: ["remote", "local"] }).notNull().default("remote"),
495
+ // Unix group for repo-level git access (agor_rp_<short-id>)
496
+ // Users who have access to ANY branch in this repo get added to this group.
497
+ // Applied to repo Unix-group-managed paths:
498
+ // - repo root (non-recursive) for traversal into .git/worktrees/<name>
499
+ // - .git (recursive) for shared git objects/refs and git operations
500
+ unix_group: (0, import_pg_core.text)("unix_group"),
501
+ data: t.json("data").$type().notNull()
502
+ },
503
+ (table) => ({
504
+ tenantIdx: (0, import_pg_core.index)("repos_tenant_id_idx").on(table.tenant_id),
505
+ slugIdx: (0, import_pg_core.index)("repos_slug_idx").on(table.slug),
506
+ slugTenantUnique: (0, import_pg_core.uniqueIndex)("repos_tenant_slug_unique").on(table.tenant_id, table.slug)
507
+ })
508
+ );
509
+ var branches = (0, import_pg_core.pgTable)(
510
+ "branches",
511
+ {
512
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
513
+ // Primary identity
514
+ branch_id: (0, import_pg_core.varchar)("branch_id", { length: 36 }).primaryKey(),
515
+ repo_id: (0, import_pg_core.varchar)("repo_id", { length: 36 }).notNull().references(() => repos.repo_id, { onDelete: "cascade" }),
516
+ created_at: t.timestamp("created_at").notNull(),
517
+ updated_at: t.timestamp("updated_at"),
518
+ // User attribution
519
+ created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }).notNull(),
520
+ // Materialized for queries
521
+ name: (0, import_pg_core.text)("name").notNull(),
522
+ // "feat-auth", "main"
523
+ ref: (0, import_pg_core.text)("ref").notNull(),
524
+ // Current branch/tag/commit
525
+ ref_type: (0, import_pg_core.text)("ref_type", { enum: ["branch", "tag"] }),
526
+ // Type of ref (branch or tag)
527
+ branch_unique_id: (0, import_pg_core.integer)("branch_unique_id").notNull(),
528
+ // Auto-assigned sequential ID for templates
529
+ // Environment configuration (static, initialized from templates, then user-editable)
530
+ start_command: (0, import_pg_core.text)("start_command"),
531
+ // Start command (initialized from repo's up_command template)
532
+ stop_command: (0, import_pg_core.text)("stop_command"),
533
+ // Stop command (initialized from repo's down_command template)
534
+ nuke_command: (0, import_pg_core.text)("nuke_command"),
535
+ // Nuke command (initialized from repo's nuke_command template)
536
+ health_check_url: (0, import_pg_core.text)("health_check_url"),
537
+ // Health check URL (initialized from repo's health_check.url_template)
538
+ app_url: (0, import_pg_core.text)("app_url"),
539
+ // Application URL (initialized from repo's app_url_template)
540
+ logs_command: (0, import_pg_core.text)("logs_command"),
541
+ // Logs command (initialized from repo's logs_command template)
542
+ // Name of the environment variant currently rendered into the command fields above.
543
+ // References a key under repo.environment.variants. Null for pre-v2 branches.
544
+ environment_variant: (0, import_pg_core.text)("environment_variant"),
545
+ // Board relationship (nullable - branches can exist without boards)
546
+ board_id: (0, import_pg_core.varchar)("board_id", { length: 36 }).references(() => boards.board_id, {
547
+ onDelete: "set null"
548
+ // If board is deleted, branch remains but loses board association
549
+ }),
550
+ // UI state (materialized for efficient highlighting queries)
551
+ needs_attention: t.bool("needs_attention").notNull().default(true),
552
+ // Default true for new branches
553
+ // Archive state (for soft deletes)
554
+ archived: t.bool("archived").notNull().default(false),
555
+ archived_at: t.timestamp("archived_at"),
556
+ archived_by: (0, import_pg_core.varchar)("archived_by", { length: 36 }),
557
+ filesystem_status: (0, import_pg_core.text)("filesystem_status", {
558
+ enum: ["creating", "ready", "failed", "preserved", "cleaned", "deleted"]
559
+ }),
560
+ // RBAC: App-layer permissions (rbac.md)
561
+ permission_source: (0, import_pg_core.text)("permission_source", { enum: ["board", "override"] }).$type().notNull().default("override"),
562
+ others_can: (0, import_pg_core.text)("others_can", {
563
+ enum: [...BRANCH_PERMISSION_LEVELS]
564
+ }).default("view"),
565
+ // RBAC: OS-layer permissions (unix-user-modes.md)
566
+ unix_group: (0, import_pg_core.text)("unix_group"),
567
+ // e.g., 'agor_wt_abc123'
568
+ others_fs_access: (0, import_pg_core.text)("others_fs_access", {
569
+ enum: ["none", "read", "write"]
570
+ }).$type().default("read"),
571
+ // Branch storage model — see context/explorations/clone-redesign.md.
572
+ // 'worktree' = native `git worktree add` (shared base .git/config — legacy default).
573
+ // 'clone' = self-standing `git clone` (own .git/ — closes cross-branch leak vectors).
574
+ //
575
+ // No DB-side CHECK: enum is validated at the Drizzle/TS/Zod/service
576
+ // layer to stay symmetric with the SQLite mirror (which can't easily
577
+ // alter CHECK constraints in place).
578
+ storage_mode: (0, import_pg_core.text)("storage_mode", { enum: ["worktree", "clone"] }).notNull().default("worktree"),
579
+ // Only meaningful when storage_mode='clone'. NULL = full clone, positive
580
+ // integer = `git clone --depth N` (shallow). The service layer rejects
581
+ // a non-null clone_depth on worktree-mode rows.
582
+ clone_depth: (0, import_pg_core.integer)("clone_depth"),
583
+ // JSON blob for everything else
584
+ data: t.json("data").$type().notNull()
585
+ },
586
+ (table) => ({
587
+ tenantIdx: (0, import_pg_core.index)("branches_tenant_id_idx").on(table.tenant_id),
588
+ repoIdx: (0, import_pg_core.index)("branches_repo_idx").on(table.repo_id),
589
+ nameIdx: (0, import_pg_core.index)("branches_name_idx").on(table.name),
590
+ refIdx: (0, import_pg_core.index)("branches_ref_idx").on(table.ref),
591
+ boardIdx: (0, import_pg_core.index)("branches_board_idx").on(table.board_id),
592
+ createdIdx: (0, import_pg_core.index)("branches_created_idx").on(table.created_at),
593
+ updatedIdx: (0, import_pg_core.index)("branches_updated_idx").on(table.updated_at),
594
+ // Composite unique constraint (repo + name)
595
+ uniqueRepoName: (0, import_pg_core.index)("branches_repo_name_unique").on(table.repo_id, table.name)
596
+ })
597
+ );
598
+ var branchOwners = (0, import_pg_core.pgTable)(
599
+ "branch_owners",
600
+ {
601
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
602
+ branch_id: (0, import_pg_core.varchar)("branch_id", { length: 36 }).notNull().references(() => branches.branch_id, { onDelete: "cascade" }),
603
+ user_id: (0, import_pg_core.varchar)("user_id", { length: 36 }).notNull().references(() => users.user_id, { onDelete: "cascade" }),
604
+ created_at: t.timestamp("created_at").defaultNow()
605
+ },
606
+ (table) => ({
607
+ tenantIdx: (0, import_pg_core.index)("branch_owners_tenant_id_idx").on(table.tenant_id),
608
+ pk: (0, import_pg_core.primaryKey)({ columns: [table.branch_id, table.user_id] })
609
+ })
610
+ );
611
+ var boardOwners = (0, import_pg_core.pgTable)(
612
+ "board_owners",
613
+ {
614
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
615
+ board_id: (0, import_pg_core.varchar)("board_id", { length: 36 }).notNull().references(() => boards.board_id, { onDelete: "cascade" }),
616
+ user_id: (0, import_pg_core.varchar)("user_id", { length: 36 }).notNull().references(() => users.user_id, { onDelete: "cascade" }),
617
+ created_at: t.timestamp("created_at")
618
+ },
619
+ (table) => ({
620
+ tenantIdx: (0, import_pg_core.index)("board_owners_tenant_id_idx").on(table.tenant_id),
621
+ pk: (0, import_pg_core.primaryKey)({ columns: [table.board_id, table.user_id] }),
622
+ userIdx: (0, import_pg_core.index)("board_owners_user_idx").on(table.user_id)
623
+ })
624
+ );
625
+ var schedules = (0, import_pg_core.pgTable)(
626
+ "schedules",
627
+ {
628
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
629
+ schedule_id: (0, import_pg_core.varchar)("schedule_id", { length: 36 }).primaryKey(),
630
+ branch_id: (0, import_pg_core.varchar)("branch_id", { length: 36 }).notNull().references(() => branches.branch_id, { onDelete: "cascade" }),
631
+ name: (0, import_pg_core.text)("name").notNull(),
632
+ description: (0, import_pg_core.text)("description"),
633
+ cron_expression: (0, import_pg_core.text)("cron_expression").notNull(),
634
+ timezone_mode: (0, import_pg_core.text)("timezone_mode", { enum: ["local", "utc"] }).notNull().default("local"),
635
+ timezone: (0, import_pg_core.text)("timezone"),
636
+ prompt: (0, import_pg_core.text)("prompt").notNull(),
637
+ agentic_tool_config: t.json("agentic_tool_config").notNull(),
638
+ enabled: t.bool("enabled").notNull().default(true),
639
+ allow_concurrent_runs: t.bool("allow_concurrent_runs").notNull().default(false),
640
+ retention: (0, import_pg_core.integer)("retention").notNull().default(5),
641
+ last_run_at: (0, import_pg_core.bigint)("last_run_at", { mode: "number" }),
642
+ last_run_session_id: (0, import_pg_core.varchar)("last_run_session_id", { length: 36 }).references(
643
+ () => sessions.session_id,
644
+ { onDelete: "set null" }
645
+ ),
646
+ next_run_at: (0, import_pg_core.bigint)("next_run_at", { mode: "number" }),
647
+ created_at: t.timestamp("created_at").notNull(),
648
+ updated_at: t.timestamp("updated_at").notNull(),
649
+ created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }).notNull().references(() => users.user_id)
650
+ },
651
+ (table) => ({
652
+ tenantIdx: (0, import_pg_core.index)("schedules_tenant_id_idx").on(table.tenant_id),
653
+ enabledNextRunIdx: (0, import_pg_core.index)("schedules_enabled_next_run_idx").on(table.enabled, table.next_run_at),
654
+ branchIdx: (0, import_pg_core.index)("schedules_branch_idx").on(table.branch_id),
655
+ createdByIdx: (0, import_pg_core.index)("schedules_created_by_idx").on(table.created_by)
656
+ })
657
+ );
658
+ var users = (0, import_pg_core.pgTable)(
659
+ "users",
660
+ {
661
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
662
+ // Primary identity
663
+ user_id: (0, import_pg_core.varchar)("user_id", { length: 36 }).primaryKey(),
664
+ created_at: t.timestamp("created_at").notNull(),
665
+ updated_at: t.timestamp("updated_at"),
666
+ // Materialized for auth lookups
667
+ email: (0, import_pg_core.text)("email").notNull(),
668
+ password: (0, import_pg_core.text)("password").notNull(),
669
+ // bcrypt hashed
670
+ // Basic profile (materialized for display)
671
+ name: (0, import_pg_core.text)("name"),
672
+ emoji: (0, import_pg_core.text)("emoji"),
673
+ role: (0, import_pg_core.text)("role", {
674
+ enum: ["superadmin", "admin", "member", "viewer"]
675
+ // 'owner' is deprecated alias for 'superadmin'
676
+ }).notNull().default("member"),
677
+ // Unix username for process impersonation (optional, app-enforced uniqueness)
678
+ unix_username: (0, import_pg_core.text)("unix_username"),
679
+ // Onboarding state
680
+ onboarding_completed: t.bool("onboarding_completed").notNull().default(false),
681
+ // Force password change flag (admin-settable, auto-cleared on password change)
682
+ must_change_password: t.bool("must_change_password").notNull().default(false),
683
+ // Auth invalidation marker. Password changes set this timestamp so any
684
+ // previously issued browser access or refresh token is rejected.
685
+ tokens_valid_after: t.timestamp("tokens_valid_after"),
686
+ // JSON blob for profile/preferences
687
+ data: t.json("data").$type().notNull()
688
+ },
689
+ (table) => ({
690
+ tenantIdx: (0, import_pg_core.index)("users_tenant_id_idx").on(table.tenant_id),
691
+ emailIdx: (0, import_pg_core.index)("users_email_idx").on(table.email),
692
+ emailTenantUnique: (0, import_pg_core.uniqueIndex)("users_tenant_email_unique").on(table.tenant_id, table.email)
693
+ })
694
+ );
695
+ var groups = (0, import_pg_core.pgTable)(
696
+ "groups",
697
+ {
698
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
699
+ group_id: (0, import_pg_core.varchar)("group_id", { length: 36 }).primaryKey(),
700
+ name: (0, import_pg_core.text)("name").notNull(),
701
+ slug: (0, import_pg_core.text)("slug").notNull(),
702
+ description: (0, import_pg_core.text)("description"),
703
+ archived: t.bool("archived").notNull().default(false),
704
+ created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }).references(() => users.user_id, {
705
+ onDelete: "set null"
706
+ }),
707
+ created_at: t.timestamp("created_at").notNull(),
708
+ updated_at: t.timestamp("updated_at")
709
+ },
710
+ (table) => ({
711
+ tenantIdx: (0, import_pg_core.index)("groups_tenant_id_idx").on(table.tenant_id),
712
+ slugIdx: (0, import_pg_core.uniqueIndex)("groups_tenant_slug_unique").on(table.tenant_id, table.slug),
713
+ archivedIdx: (0, import_pg_core.index)("groups_archived_idx").on(table.archived)
714
+ })
715
+ );
716
+ var groupMemberships = (0, import_pg_core.pgTable)(
717
+ "group_memberships",
718
+ {
719
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
720
+ group_id: (0, import_pg_core.varchar)("group_id", { length: 36 }).notNull().references(() => groups.group_id, { onDelete: "cascade" }),
721
+ user_id: (0, import_pg_core.varchar)("user_id", { length: 36 }).notNull().references(() => users.user_id, { onDelete: "cascade" }),
722
+ added_by: (0, import_pg_core.varchar)("added_by", { length: 36 }).references(() => users.user_id, {
723
+ onDelete: "set null"
724
+ }),
725
+ created_at: t.timestamp("created_at").notNull()
726
+ },
727
+ (table) => ({
728
+ tenantIdx: (0, import_pg_core.index)("group_memberships_tenant_id_idx").on(table.tenant_id),
729
+ pk: (0, import_pg_core.primaryKey)({ columns: [table.group_id, table.user_id] }),
730
+ userIdx: (0, import_pg_core.index)("group_memberships_user_idx").on(table.user_id)
731
+ })
732
+ );
733
+ var branchGroupGrants = (0, import_pg_core.pgTable)(
734
+ "branch_group_grants",
735
+ {
736
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
737
+ branch_id: (0, import_pg_core.varchar)("branch_id", { length: 36 }).notNull().references(() => branches.branch_id, { onDelete: "cascade" }),
738
+ group_id: (0, import_pg_core.varchar)("group_id", { length: 36 }).notNull().references(() => groups.group_id, { onDelete: "cascade" }),
739
+ can: (0, import_pg_core.text)("can", { enum: [...BRANCH_PERMISSION_LEVELS] }).notNull().default("view"),
740
+ fs_access: (0, import_pg_core.text)("fs_access", { enum: ["none", "read", "write"] }).$type(),
741
+ created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }).references(() => users.user_id, {
742
+ onDelete: "set null"
743
+ }),
744
+ created_at: t.timestamp("created_at").notNull(),
745
+ updated_at: t.timestamp("updated_at")
746
+ },
747
+ (table) => ({
748
+ tenantIdx: (0, import_pg_core.index)("branch_group_grants_tenant_id_idx").on(table.tenant_id),
749
+ pk: (0, import_pg_core.primaryKey)({ columns: [table.branch_id, table.group_id] }),
750
+ groupIdx: (0, import_pg_core.index)("branch_group_grants_group_idx").on(table.group_id)
751
+ })
752
+ );
753
+ var boardGroupGrants = (0, import_pg_core.pgTable)(
754
+ "board_group_grants",
755
+ {
756
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
757
+ board_id: (0, import_pg_core.varchar)("board_id", { length: 36 }).notNull().references(() => boards.board_id, { onDelete: "cascade" }),
758
+ group_id: (0, import_pg_core.varchar)("group_id", { length: 36 }).notNull().references(() => groups.group_id, { onDelete: "cascade" }),
759
+ can: (0, import_pg_core.text)("can", { enum: [...BRANCH_PERMISSION_LEVELS] }).notNull().default("view"),
760
+ fs_access: (0, import_pg_core.text)("fs_access", { enum: ["none", "read", "write"] }).$type(),
761
+ created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }).references(() => users.user_id, {
762
+ onDelete: "set null"
763
+ }),
764
+ created_at: t.timestamp("created_at").notNull(),
765
+ updated_at: t.timestamp("updated_at")
766
+ },
767
+ (table) => ({
768
+ tenantIdx: (0, import_pg_core.index)("board_group_grants_tenant_id_idx").on(table.tenant_id),
769
+ pk: (0, import_pg_core.primaryKey)({ columns: [table.board_id, table.group_id] }),
770
+ groupIdx: (0, import_pg_core.index)("board_group_grants_group_idx").on(table.group_id)
771
+ })
772
+ );
773
+ var appVariables = (0, import_pg_core.pgTable)(
774
+ "app_variables",
775
+ {
776
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
777
+ variable_id: (0, import_pg_core.varchar)("variable_id", { length: 36 }).primaryKey(),
778
+ namespace: (0, import_pg_core.text)("namespace").notNull(),
779
+ key: (0, import_pg_core.text)("key").notNull(),
780
+ value_text: (0, import_pg_core.text)("value_text"),
781
+ value_encrypted: (0, import_pg_core.text)("value_encrypted"),
782
+ is_encrypted: t.bool("is_encrypted").notNull().default(false),
783
+ content_type: (0, import_pg_core.text)("content_type").notNull().default("text/plain"),
784
+ metadata: t.json("metadata"),
785
+ updated_by: (0, import_pg_core.varchar)("updated_by", { length: 36 }).references(() => users.user_id, {
786
+ onDelete: "set null"
787
+ }),
788
+ created_at: t.timestamp("created_at").notNull(),
789
+ updated_at: t.timestamp("updated_at").notNull()
790
+ },
791
+ (table) => ({
792
+ tenantIdx: (0, import_pg_core.index)("app_variables_tenant_id_idx").on(table.tenant_id),
793
+ namespaceKeyIdx: (0, import_pg_core.uniqueIndex)("app_variables_tenant_namespace_key_unique").on(
794
+ table.tenant_id,
795
+ table.namespace,
796
+ table.key
797
+ ),
798
+ namespaceIdx: (0, import_pg_core.index)("app_variables_namespace_idx").on(table.namespace)
799
+ })
800
+ );
801
+ var userApiKeys = (0, import_pg_core.pgTable)(
802
+ "user_api_keys",
803
+ {
804
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
805
+ id: (0, import_pg_core.varchar)("id", { length: 36 }).primaryKey(),
806
+ user_id: (0, import_pg_core.varchar)("user_id", { length: 36 }).notNull().references(() => users.user_id, { onDelete: "cascade" }),
807
+ name: (0, import_pg_core.text)("name").notNull(),
808
+ prefix: (0, import_pg_core.text)("prefix").notNull(),
809
+ // first 12 chars: 'agor_sk_XXXX' for identification
810
+ key_hash: (0, import_pg_core.text)("key_hash").notNull(),
811
+ // bcrypt hash of full key
812
+ created_at: t.timestamp("created_at").notNull(),
813
+ last_used_at: t.timestamp("last_used_at")
814
+ },
815
+ (table) => ({
816
+ tenantIdx: (0, import_pg_core.index)("user_api_keys_tenant_id_idx").on(table.tenant_id),
817
+ userIdx: (0, import_pg_core.index)("user_api_keys_user_idx").on(table.user_id),
818
+ prefixIdx: (0, import_pg_core.index)("user_api_keys_prefix_idx").on(table.prefix)
819
+ })
820
+ );
821
+ var mcpServers = (0, import_pg_core.pgTable)(
822
+ "mcp_servers",
823
+ {
824
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
825
+ // Primary identity
826
+ mcp_server_id: (0, import_pg_core.varchar)("mcp_server_id", { length: 36 }).primaryKey(),
827
+ created_at: t.timestamp("created_at").notNull(),
828
+ updated_at: t.timestamp("updated_at"),
829
+ // Materialized for filtering
830
+ name: (0, import_pg_core.text)("name").notNull(),
831
+ // e.g., "filesystem", "sentry"
832
+ transport: (0, import_pg_core.text)("transport", {
833
+ enum: ["stdio", "http", "sse"]
834
+ }).notNull(),
835
+ scope: (0, import_pg_core.text)("scope", {
836
+ enum: ["global", "session"]
837
+ }).notNull(),
838
+ enabled: t.bool("enabled").notNull().default(true),
839
+ // Scope foreign key
840
+ // For 'global' scope: which user owns this server
841
+ // For 'session' scope: use session_mcp_servers junction table (many-to-many)
842
+ owner_user_id: (0, import_pg_core.varchar)("owner_user_id", { length: 36 }),
843
+ // Source tracking (materialized for queries)
844
+ source: (0, import_pg_core.text)("source", {
845
+ enum: ["user", "imported", "agor"]
846
+ }).notNull(),
847
+ // JSON blob for configuration and capabilities
848
+ data: t.json("data").$type().notNull()
849
+ },
850
+ (table) => ({
851
+ tenantIdx: (0, import_pg_core.index)("mcp_servers_tenant_id_idx").on(table.tenant_id),
852
+ nameIdx: (0, import_pg_core.index)("mcp_servers_name_idx").on(table.name),
853
+ scopeIdx: (0, import_pg_core.index)("mcp_servers_scope_idx").on(table.scope),
854
+ ownerIdx: (0, import_pg_core.index)("mcp_servers_owner_idx").on(table.owner_user_id),
855
+ enabledIdx: (0, import_pg_core.index)("mcp_servers_enabled_idx").on(table.enabled)
856
+ })
857
+ );
858
+ var cardTypes = (0, import_pg_core.pgTable)(
859
+ "card_types",
860
+ {
861
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
862
+ card_type_id: (0, import_pg_core.varchar)("card_type_id", { length: 36 }).primaryKey(),
863
+ name: (0, import_pg_core.text)("name").notNull(),
864
+ emoji: (0, import_pg_core.text)("emoji"),
865
+ color: (0, import_pg_core.text)("color"),
866
+ json_schema: (0, import_pg_core.text)("json_schema"),
867
+ // JSON string of JSON Schema
868
+ created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }),
869
+ created_at: t.timestamp("created_at").notNull(),
870
+ updated_at: t.timestamp("updated_at").notNull()
871
+ },
872
+ (table) => ({
873
+ tenantIdx: (0, import_pg_core.index)("card_types_tenant_id_idx").on(table.tenant_id),
874
+ nameIdx: (0, import_pg_core.index)("card_types_name_idx").on(table.name)
875
+ })
876
+ );
877
+ var cards = (0, import_pg_core.pgTable)(
878
+ "cards",
879
+ {
880
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
881
+ card_id: (0, import_pg_core.varchar)("card_id", { length: 36 }).primaryKey(),
882
+ board_id: (0, import_pg_core.varchar)("board_id", { length: 36 }).notNull().references(() => boards.board_id, { onDelete: "cascade" }),
883
+ card_type_id: (0, import_pg_core.varchar)("card_type_id", { length: 36 }).references(() => cardTypes.card_type_id, {
884
+ onDelete: "set null"
885
+ }),
886
+ title: (0, import_pg_core.text)("title").notNull(),
887
+ url: (0, import_pg_core.text)("url"),
888
+ description: (0, import_pg_core.text)("description"),
889
+ note: (0, import_pg_core.text)("note"),
890
+ data: (0, import_pg_core.text)("data"),
891
+ // JSON blob validated against CardType.json_schema if present
892
+ color_override: (0, import_pg_core.text)("color_override"),
893
+ emoji_override: (0, import_pg_core.text)("emoji_override"),
894
+ created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }),
895
+ created_at: t.timestamp("created_at").notNull(),
896
+ updated_at: t.timestamp("updated_at").notNull(),
897
+ archived: t.bool("archived").notNull().default(false),
898
+ archived_at: t.timestamp("archived_at")
899
+ },
900
+ (table) => ({
901
+ tenantIdx: (0, import_pg_core.index)("cards_tenant_id_idx").on(table.tenant_id),
902
+ boardIdx: (0, import_pg_core.index)("cards_board_idx").on(table.board_id),
903
+ cardTypeIdx: (0, import_pg_core.index)("cards_card_type_idx").on(table.card_type_id),
904
+ titleIdx: (0, import_pg_core.index)("cards_title_idx").on(table.title),
905
+ archivedIdx: (0, import_pg_core.index)("cards_archived_idx").on(table.archived),
906
+ createdIdx: (0, import_pg_core.index)("cards_created_idx").on(table.created_at)
907
+ })
908
+ );
909
+ var artifacts = (0, import_pg_core.pgTable)(
910
+ "artifacts",
911
+ {
912
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
913
+ artifact_id: (0, import_pg_core.varchar)("artifact_id", { length: 36 }).primaryKey(),
914
+ branch_id: (0, import_pg_core.varchar)("branch_id", { length: 36 }).references(() => branches.branch_id, {
915
+ onDelete: "set null"
916
+ }),
917
+ source_session_id: (0, import_pg_core.varchar)("source_session_id", { length: 36 }).references(
918
+ () => sessions.session_id,
919
+ {
920
+ onDelete: "set null"
921
+ }
922
+ ),
923
+ board_id: (0, import_pg_core.varchar)("board_id", { length: 36 }).notNull().references(() => boards.board_id, { onDelete: "cascade" }),
924
+ name: (0, import_pg_core.text)("name").notNull(),
925
+ description: (0, import_pg_core.text)("description"),
926
+ path: (0, import_pg_core.text)("path"),
927
+ // provenance only — where files were read from
928
+ template: (0, import_pg_core.text)("template").notNull().default("react"),
929
+ build_status: (0, import_pg_core.text)("build_status").notNull().default("unknown"),
930
+ build_errors: t.json("build_errors"),
931
+ content_hash: (0, import_pg_core.text)("content_hash"),
932
+ files: t.json("files"),
933
+ dependencies: t.json("dependencies"),
934
+ entry: (0, import_pg_core.text)("entry"),
935
+ // denormalized cache of the Sandpack entry file
936
+ sandpack_config: t.json("sandpack_config"),
937
+ required_env_vars: t.json("required_env_vars"),
938
+ agor_grants: t.json("agor_grants"),
939
+ agor_runtime: t.json("agor_runtime"),
940
+ public: t.bool("public").notNull().default(true),
941
+ created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }),
942
+ created_at: t.timestamp("created_at").notNull(),
943
+ updated_at: t.timestamp("updated_at").notNull(),
944
+ archived: t.bool("archived").notNull().default(false),
945
+ archived_at: t.timestamp("archived_at")
946
+ },
947
+ (table) => ({
948
+ tenantIdx: (0, import_pg_core.index)("artifacts_tenant_id_idx").on(table.tenant_id),
949
+ branchIdx: (0, import_pg_core.index)("artifacts_branch_idx").on(table.branch_id),
950
+ sourceSessionIdx: (0, import_pg_core.index)("artifacts_source_session_idx").on(table.source_session_id),
951
+ boardIdx: (0, import_pg_core.index)("artifacts_board_idx").on(table.board_id),
952
+ archivedIdx: (0, import_pg_core.index)("artifacts_archived_idx").on(table.archived),
953
+ publicIdx: (0, import_pg_core.index)("artifacts_public_idx").on(table.public)
954
+ })
955
+ );
956
+ var artifactTrustGrants = (0, import_pg_core.pgTable)(
957
+ "artifact_trust_grants",
958
+ {
959
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
960
+ grant_id: (0, import_pg_core.varchar)("grant_id", { length: 36 }).primaryKey(),
961
+ user_id: (0, import_pg_core.varchar)("user_id", { length: 36 }).notNull(),
962
+ scope_type: (0, import_pg_core.text)("scope_type").notNull(),
963
+ scope_value: (0, import_pg_core.text)("scope_value"),
964
+ env_vars_set: t.json("env_vars_set").notNull(),
965
+ agor_grants_set: t.json("agor_grants_set").notNull(),
966
+ granted_at: t.timestamp("granted_at").notNull(),
967
+ revoked_at: t.timestamp("revoked_at")
968
+ },
969
+ (table) => ({
970
+ tenantIdx: (0, import_pg_core.index)("artifact_trust_grants_tenant_id_idx").on(table.tenant_id),
971
+ userIdx: (0, import_pg_core.index)("artifact_trust_grants_user_idx").on(table.user_id),
972
+ scopeIdx: (0, import_pg_core.index)("artifact_trust_grants_scope_idx").on(table.scope_type, table.scope_value)
973
+ })
974
+ );
975
+ var boardObjects = (0, import_pg_core.pgTable)(
976
+ "board_objects",
977
+ {
978
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
979
+ // Primary identity
980
+ object_id: (0, import_pg_core.varchar)("object_id", { length: 36 }).primaryKey(),
981
+ board_id: (0, import_pg_core.varchar)("board_id", { length: 36 }).notNull().references(() => boards.board_id, { onDelete: "cascade" }),
982
+ created_at: t.timestamp("created_at").notNull(),
983
+ // Polymorphic entity reference (exactly one must be set)
984
+ branch_id: (0, import_pg_core.varchar)("branch_id", { length: 36 }).references(() => branches.branch_id, {
985
+ onDelete: "cascade"
986
+ }),
987
+ card_id: (0, import_pg_core.varchar)("card_id", { length: 36 }).references(() => cards.card_id, {
988
+ onDelete: "cascade"
989
+ }),
990
+ // Position data (JSON)
991
+ data: t.json("data").$type().notNull()
992
+ },
993
+ (table) => ({
994
+ tenantIdx: (0, import_pg_core.index)("board_objects_tenant_id_idx").on(table.tenant_id),
995
+ boardIdx: (0, import_pg_core.index)("board_objects_board_idx").on(table.board_id),
996
+ branchIdx: (0, import_pg_core.index)("board_objects_branch_idx").on(table.branch_id),
997
+ cardIdx: (0, import_pg_core.index)("board_objects_card_idx").on(table.card_id)
998
+ })
999
+ );
1000
+ var sessionMcpServers = (0, import_pg_core.pgTable)(
1001
+ "session_mcp_servers",
1002
+ {
1003
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1004
+ session_id: (0, import_pg_core.varchar)("session_id", { length: 36 }).notNull().references(() => sessions.session_id, { onDelete: "cascade" }),
1005
+ mcp_server_id: (0, import_pg_core.varchar)("mcp_server_id", { length: 36 }).notNull().references(() => mcpServers.mcp_server_id, { onDelete: "cascade" }),
1006
+ enabled: t.bool("enabled").notNull().default(true),
1007
+ added_at: t.timestamp("added_at").notNull()
1008
+ },
1009
+ (table) => ({
1010
+ tenantIdx: (0, import_pg_core.index)("session_mcp_servers_tenant_id_idx").on(table.tenant_id),
1011
+ // Composite primary key
1012
+ pk: (0, import_pg_core.index)("session_mcp_servers_pk").on(table.session_id, table.mcp_server_id),
1013
+ // Indexes for queries
1014
+ sessionIdx: (0, import_pg_core.index)("session_mcp_servers_session_idx").on(table.session_id),
1015
+ serverIdx: (0, import_pg_core.index)("session_mcp_servers_server_idx").on(table.mcp_server_id),
1016
+ enabledIdx: (0, import_pg_core.index)("session_mcp_servers_enabled_idx").on(table.session_id, table.enabled)
1017
+ })
1018
+ );
1019
+ var userMcpOauthTokens = (0, import_pg_core.pgTable)(
1020
+ "user_mcp_oauth_tokens",
1021
+ {
1022
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1023
+ // NULL = shared-mode token (one per mcp_server_id)
1024
+ user_id: (0, import_pg_core.varchar)("user_id", { length: 36 }).references(() => users.user_id, {
1025
+ onDelete: "cascade"
1026
+ }),
1027
+ mcp_server_id: (0, import_pg_core.varchar)("mcp_server_id", { length: 36 }).notNull().references(() => mcpServers.mcp_server_id, { onDelete: "cascade" }),
1028
+ oauth_access_token: (0, import_pg_core.text)("oauth_access_token").notNull(),
1029
+ oauth_token_expires_at: t.timestamp("oauth_token_expires_at"),
1030
+ // Unix timestamp in milliseconds
1031
+ oauth_refresh_token: (0, import_pg_core.text)("oauth_refresh_token"),
1032
+ // DCR / registered client credentials this grant was issued under.
1033
+ // Must be preserved across refreshes.
1034
+ oauth_client_id: (0, import_pg_core.text)("oauth_client_id"),
1035
+ oauth_client_secret: (0, import_pg_core.text)("oauth_client_secret"),
1036
+ created_at: t.timestamp("created_at").notNull(),
1037
+ updated_at: t.timestamp("updated_at")
1038
+ },
1039
+ (table) => ({
1040
+ tenantIdx: (0, import_pg_core.index)("user_mcp_oauth_tokens_tenant_id_idx").on(table.tenant_id),
1041
+ // Composite lookup indexes. Uniqueness enforced via partial unique indexes
1042
+ // created in the migration (one for per-user rows, one for the shared row).
1043
+ pk: (0, import_pg_core.index)("user_mcp_oauth_tokens_pk").on(table.user_id, table.mcp_server_id),
1044
+ userIdx: (0, import_pg_core.index)("user_mcp_oauth_tokens_user_idx").on(table.user_id),
1045
+ serverIdx: (0, import_pg_core.index)("user_mcp_oauth_tokens_server_idx").on(table.mcp_server_id)
1046
+ })
1047
+ );
1048
+ var boardComments = (0, import_pg_core.pgTable)(
1049
+ "board_comments",
1050
+ {
1051
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1052
+ // Primary identity
1053
+ comment_id: (0, import_pg_core.varchar)("comment_id", { length: 36 }).primaryKey(),
1054
+ created_at: t.timestamp("created_at").notNull(),
1055
+ updated_at: t.timestamp("updated_at"),
1056
+ // Scoping & authorship
1057
+ board_id: (0, import_pg_core.varchar)("board_id", { length: 36 }).notNull().references(() => boards.board_id, { onDelete: "cascade" }),
1058
+ created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }).notNull(),
1059
+ // FLEXIBLE ATTACHMENTS (all optional)
1060
+ // Phase 1: board-level only (all NULL)
1061
+ // Phase 2: object attachments (session, task, message, branch)
1062
+ // Phase 3: spatial positioning
1063
+ session_id: (0, import_pg_core.varchar)("session_id", { length: 36 }).references(() => sessions.session_id, {
1064
+ onDelete: "set null"
1065
+ }),
1066
+ task_id: (0, import_pg_core.varchar)("task_id", { length: 36 }).references(() => tasks.task_id, {
1067
+ onDelete: "set null"
1068
+ }),
1069
+ message_id: (0, import_pg_core.varchar)("message_id", { length: 36 }).references(() => messages.message_id, {
1070
+ onDelete: "set null"
1071
+ }),
1072
+ branch_id: (0, import_pg_core.varchar)("branch_id", { length: 36 }).references(() => branches.branch_id, {
1073
+ onDelete: "cascade"
1074
+ }),
1075
+ // Content (materialized for display)
1076
+ content: (0, import_pg_core.text)("content").notNull(),
1077
+ // Markdown-supported text
1078
+ content_preview: (0, import_pg_core.text)("content_preview").notNull(),
1079
+ // First 200 chars
1080
+ // Thread support (optional)
1081
+ parent_comment_id: (0, import_pg_core.varchar)("parent_comment_id", { length: 36 }),
1082
+ // Metadata (materialized for filtering)
1083
+ resolved: t.bool("resolved").notNull().default(false),
1084
+ edited: t.bool("edited").notNull().default(false),
1085
+ // Reactions (for BOTH thread roots and replies)
1086
+ // Stored as JSON array: [{ user_id: "abc", emoji: "👍" }, ...]
1087
+ // Display grouped by emoji: { "👍": ["alice", "bob"], "🎉": ["charlie"] }
1088
+ reactions: t.json("reactions").$type().notNull().default(import_drizzle_orm2.sql`'[]'`),
1089
+ // JSON blob for advanced features
1090
+ data: t.json("data").$type().notNull()
1091
+ },
1092
+ (table) => ({
1093
+ tenantIdx: (0, import_pg_core.index)("board_comments_tenant_id_idx").on(table.tenant_id),
1094
+ boardIdx: (0, import_pg_core.index)("board_comments_board_idx").on(table.board_id),
1095
+ sessionIdx: (0, import_pg_core.index)("board_comments_session_idx").on(table.session_id),
1096
+ taskIdx: (0, import_pg_core.index)("board_comments_task_idx").on(table.task_id),
1097
+ messageIdx: (0, import_pg_core.index)("board_comments_message_idx").on(table.message_id),
1098
+ branchIdx: (0, import_pg_core.index)("board_comments_branch_idx").on(table.branch_id),
1099
+ createdByIdx: (0, import_pg_core.index)("board_comments_created_by_idx").on(table.created_by),
1100
+ parentIdx: (0, import_pg_core.index)("board_comments_parent_idx").on(table.parent_comment_id),
1101
+ createdIdx: (0, import_pg_core.index)("board_comments_created_idx").on(table.created_at),
1102
+ resolvedIdx: (0, import_pg_core.index)("board_comments_resolved_idx").on(table.resolved)
1103
+ })
1104
+ );
1105
+ var gatewayChannels = (0, import_pg_core.pgTable)(
1106
+ "gateway_channels",
1107
+ {
1108
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1109
+ // Primary identity
1110
+ id: (0, import_pg_core.varchar)("id", { length: 36 }).primaryKey(),
1111
+ created_at: t.timestamp("created_at").notNull(),
1112
+ updated_at: t.timestamp("updated_at").notNull(),
1113
+ // User attribution
1114
+ created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }).notNull(),
1115
+ // Materialized for queries
1116
+ name: (0, import_pg_core.text)("name").notNull(),
1117
+ channel_type: (0, import_pg_core.text)("channel_type", {
1118
+ enum: ["slack", "discord", "whatsapp", "telegram", "github", "teams"]
1119
+ }).notNull(),
1120
+ target_branch_id: (0, import_pg_core.varchar)("target_branch_id", { length: 36 }).notNull().references(() => branches.branch_id, { onDelete: "cascade" }),
1121
+ agor_user_id: (0, import_pg_core.varchar)("agor_user_id", { length: 36 }).notNull(),
1122
+ channel_key: (0, import_pg_core.text)("channel_key").notNull(),
1123
+ enabled: t.bool("enabled").notNull().default(true),
1124
+ last_message_at: t.timestamp("last_message_at"),
1125
+ // JSON blob for platform credentials (encrypted at rest)
1126
+ config: t.json("config").notNull(),
1127
+ // JSON blob for agentic tool configuration (agent, model, permission mode, etc.)
1128
+ agentic_config: t.json("agentic_config")
1129
+ },
1130
+ (table) => ({
1131
+ tenantIdx: (0, import_pg_core.index)("gateway_channels_tenant_id_idx").on(table.tenant_id),
1132
+ channelKeyIdx: (0, import_pg_core.index)("idx_gateway_channel_key").on(table.channel_key),
1133
+ channelKeyTenantUnique: (0, import_pg_core.uniqueIndex)("gateway_channels_tenant_channel_key_unique").on(
1134
+ table.tenant_id,
1135
+ table.channel_key
1136
+ ),
1137
+ enabledTypeIdx: (0, import_pg_core.index)("idx_gateway_enabled_type").on(table.enabled, table.channel_type)
1138
+ })
1139
+ );
1140
+ var threadSessionMap = (0, import_pg_core.pgTable)(
1141
+ "thread_session_map",
1142
+ {
1143
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1144
+ // Primary identity
1145
+ id: (0, import_pg_core.varchar)("id", { length: 36 }).primaryKey(),
1146
+ created_at: t.timestamp("created_at").notNull(),
1147
+ last_message_at: t.timestamp("last_message_at").notNull(),
1148
+ // Foreign keys
1149
+ channel_id: (0, import_pg_core.varchar)("channel_id", { length: 36 }).notNull().references(() => gatewayChannels.id, { onDelete: "cascade" }),
1150
+ thread_id: (0, import_pg_core.text)("thread_id").notNull(),
1151
+ session_id: (0, import_pg_core.varchar)("session_id", { length: 36 }).notNull().references(() => sessions.session_id, { onDelete: "cascade" }),
1152
+ branch_id: (0, import_pg_core.varchar)("branch_id", { length: 36 }).notNull().references(() => branches.branch_id),
1153
+ // Materialized for queries
1154
+ status: (0, import_pg_core.text)("status", {
1155
+ enum: ["active", "archived", "paused"]
1156
+ }).notNull().default("active"),
1157
+ // JSON blob for extra metadata
1158
+ metadata: t.json("metadata")
1159
+ },
1160
+ (table) => ({
1161
+ tenantIdx: (0, import_pg_core.index)("thread_session_map_tenant_id_idx").on(table.tenant_id),
1162
+ uniqueChannelThread: (0, import_pg_core.uniqueIndex)("uniq_thread_map_tenant_channel_thread").on(
1163
+ table.tenant_id,
1164
+ table.channel_id,
1165
+ table.thread_id
1166
+ ),
1167
+ sessionIdx: (0, import_pg_core.index)("idx_thread_map_session_id").on(table.session_id),
1168
+ threadIdx: (0, import_pg_core.index)("idx_thread_map_thread_id").on(table.thread_id),
1169
+ channelStatusIdx: (0, import_pg_core.index)("idx_thread_map_channel_status").on(table.channel_id, table.status)
1170
+ })
1171
+ );
1172
+ var gatewayOutboundMessages = (0, import_pg_core.pgTable)(
1173
+ "gateway_outbound_messages",
1174
+ {
1175
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1176
+ id: (0, import_pg_core.varchar)("id", { length: 36 }).primaryKey(),
1177
+ created_at: t.timestamp("created_at").notNull(),
1178
+ updated_at: t.timestamp("updated_at").notNull(),
1179
+ gateway_channel_id: (0, import_pg_core.varchar)("gateway_channel_id", { length: 36 }).notNull().references(() => gatewayChannels.id, { onDelete: "cascade" }),
1180
+ channel_type: (0, import_pg_core.text)("channel_type", {
1181
+ enum: ["slack", "discord", "whatsapp", "telegram", "github", "teams"]
1182
+ }).notNull(),
1183
+ platform_channel_id: (0, import_pg_core.text)("platform_channel_id").notNull(),
1184
+ platform_message_id: (0, import_pg_core.text)("platform_message_id").notNull(),
1185
+ platform_thread_id: (0, import_pg_core.text)("platform_thread_id").notNull(),
1186
+ platform_permalink: (0, import_pg_core.text)("platform_permalink"),
1187
+ target_branch_id: (0, import_pg_core.varchar)("target_branch_id", { length: 36 }).notNull().references(() => branches.branch_id),
1188
+ emitted_by_user_id: (0, import_pg_core.varchar)("emitted_by_user_id", { length: 36 }).notNull().references(() => users.user_id),
1189
+ emitted_by_session_id: (0, import_pg_core.varchar)("emitted_by_session_id", { length: 36 }).references(
1190
+ () => sessions.session_id,
1191
+ {
1192
+ onDelete: "set null"
1193
+ }
1194
+ ),
1195
+ emitted_by_task_id: (0, import_pg_core.varchar)("emitted_by_task_id", { length: 36 }).references(
1196
+ () => tasks.task_id,
1197
+ {
1198
+ onDelete: "set null"
1199
+ }
1200
+ ),
1201
+ emitted_by_schedule_id: (0, import_pg_core.varchar)("emitted_by_schedule_id", { length: 36 }).references(
1202
+ () => schedules.schedule_id,
1203
+ {
1204
+ onDelete: "set null"
1205
+ }
1206
+ ),
1207
+ message_text: (0, import_pg_core.text)("message_text").notNull(),
1208
+ message_preview: (0, import_pg_core.text)("message_preview").notNull(),
1209
+ metadata: t.json("metadata"),
1210
+ consumed_by_session_id: (0, import_pg_core.varchar)("consumed_by_session_id", { length: 36 }).references(
1211
+ () => sessions.session_id,
1212
+ {
1213
+ onDelete: "set null"
1214
+ }
1215
+ ),
1216
+ consumed_at: t.timestamp("consumed_at")
1217
+ },
1218
+ (table) => ({
1219
+ tenantIdx: (0, import_pg_core.index)("gateway_outbound_messages_tenant_id_idx").on(table.tenant_id),
1220
+ uniqueChannelThread: (0, import_pg_core.uniqueIndex)("uniq_gateway_outbound_tenant_channel_thread").on(
1221
+ table.tenant_id,
1222
+ table.gateway_channel_id,
1223
+ table.platform_thread_id
1224
+ ),
1225
+ emittedSessionIdx: (0, import_pg_core.index)("idx_gateway_outbound_emitted_session").on(
1226
+ table.emitted_by_session_id
1227
+ ),
1228
+ emittedScheduleIdx: (0, import_pg_core.index)("idx_gateway_outbound_emitted_schedule").on(
1229
+ table.emitted_by_schedule_id
1230
+ ),
1231
+ targetBranchCreatedIdx: (0, import_pg_core.index)("idx_gateway_outbound_branch_created").on(
1232
+ table.target_branch_id,
1233
+ table.created_at
1234
+ ),
1235
+ consumedIdx: (0, import_pg_core.index)("idx_gateway_outbound_consumed").on(table.consumed_at)
1236
+ })
1237
+ );
1238
+ var sessionEnvSelections = (0, import_pg_core.pgTable)(
1239
+ "session_env_selections",
1240
+ {
1241
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1242
+ session_id: (0, import_pg_core.varchar)("session_id", { length: 36 }).notNull().references(() => sessions.session_id, { onDelete: "cascade" }),
1243
+ env_var_name: (0, import_pg_core.text)("env_var_name").notNull(),
1244
+ created_at: t.timestamp("created_at").notNull()
1245
+ },
1246
+ (table) => ({
1247
+ tenantIdx: (0, import_pg_core.index)("session_env_selections_tenant_id_idx").on(table.tenant_id),
1248
+ pk: (0, import_pg_core.primaryKey)({ columns: [table.session_id, table.env_var_name] }),
1249
+ sessionIdx: (0, import_pg_core.index)("session_env_selections_session_idx").on(table.session_id)
1250
+ })
1251
+ );
1252
+ var kbNamespaces = (0, import_pg_core.pgTable)(
1253
+ "kb_namespaces",
1254
+ {
1255
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1256
+ namespace_id: (0, import_pg_core.varchar)("namespace_id", { length: 36 }).primaryKey(),
1257
+ slug: (0, import_pg_core.text)("slug").notNull(),
1258
+ display_name: (0, import_pg_core.text)("display_name").notNull(),
1259
+ description: (0, import_pg_core.text)("description"),
1260
+ kind: (0, import_pg_core.text)("kind", { enum: ["system", "global", "user", "repo", "branch", "team"] }).notNull().default("global"),
1261
+ owner_user_id: (0, import_pg_core.varchar)("owner_user_id", { length: 36 }).references(() => users.user_id, {
1262
+ onDelete: "set null"
1263
+ }),
1264
+ repo_id: (0, import_pg_core.varchar)("repo_id", { length: 36 }).references(() => repos.repo_id, {
1265
+ onDelete: "set null"
1266
+ }),
1267
+ branch_id: (0, import_pg_core.varchar)("branch_id", { length: 36 }).references(() => branches.branch_id, {
1268
+ onDelete: "set null"
1269
+ }),
1270
+ visibility_default: (0, import_pg_core.text)("visibility_default", { enum: ["public", "private"] }).notNull().default("public"),
1271
+ others_can: (0, import_pg_core.text)("others_can", { enum: ["none", "read", "write"] }).notNull().default("write"),
1272
+ metadata: t.json("metadata"),
1273
+ created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }).references(() => users.user_id, {
1274
+ onDelete: "set null"
1275
+ }),
1276
+ created_at: t.timestamp("created_at").notNull(),
1277
+ updated_at: t.timestamp("updated_at"),
1278
+ archived: t.bool("archived").notNull().default(false),
1279
+ archived_at: t.timestamp("archived_at")
1280
+ },
1281
+ (table) => ({
1282
+ tenantIdx: (0, import_pg_core.index)("kb_namespaces_tenant_id_idx").on(table.tenant_id),
1283
+ slugIdx: (0, import_pg_core.uniqueIndex)("kb_namespaces_tenant_slug_unique").on(table.tenant_id, table.slug).where(import_drizzle_orm2.sql`${table.archived} = false`),
1284
+ kindIdx: (0, import_pg_core.index)("kb_namespaces_kind_idx").on(table.kind),
1285
+ ownerIdx: (0, import_pg_core.index)("kb_namespaces_owner_idx").on(table.owner_user_id),
1286
+ repoIdx: (0, import_pg_core.index)("kb_namespaces_repo_idx").on(table.repo_id),
1287
+ branchIdx: (0, import_pg_core.index)("kb_namespaces_branch_idx").on(table.branch_id),
1288
+ archivedIdx: (0, import_pg_core.index)("kb_namespaces_archived_idx").on(table.archived)
1289
+ })
1290
+ );
1291
+ var kbNamespaceAcl = (0, import_pg_core.pgTable)(
1292
+ "kb_namespace_acl",
1293
+ {
1294
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1295
+ namespace_acl_id: (0, import_pg_core.varchar)("namespace_acl_id", { length: 36 }).primaryKey(),
1296
+ namespace_id: (0, import_pg_core.varchar)("namespace_id", { length: 36 }).notNull().references(() => kbNamespaces.namespace_id, { onDelete: "cascade" }),
1297
+ subject_type: (0, import_pg_core.text)("subject_type", { enum: ["user", "group"] }).notNull(),
1298
+ subject_id: (0, import_pg_core.varchar)("subject_id", { length: 36 }).notNull(),
1299
+ permission: (0, import_pg_core.text)("permission", { enum: ["read", "write", "own"] }).notNull(),
1300
+ created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }).references(() => users.user_id, {
1301
+ onDelete: "set null"
1302
+ }),
1303
+ created_at: t.timestamp("created_at").notNull(),
1304
+ updated_at: t.timestamp("updated_at")
1305
+ },
1306
+ (table) => ({
1307
+ tenantIdx: (0, import_pg_core.index)("kb_namespace_acl_tenant_id_idx").on(table.tenant_id),
1308
+ namespaceIdx: (0, import_pg_core.index)("kb_namespace_acl_namespace_idx").on(table.namespace_id),
1309
+ subjectIdx: (0, import_pg_core.index)("kb_namespace_acl_subject_idx").on(table.subject_type, table.subject_id),
1310
+ namespaceSubjectIdx: (0, import_pg_core.uniqueIndex)("kb_namespace_acl_tenant_namespace_subject_unique").on(
1311
+ table.tenant_id,
1312
+ table.namespace_id,
1313
+ table.subject_type,
1314
+ table.subject_id
1315
+ )
1316
+ })
1317
+ );
1318
+ var kbDocuments = (0, import_pg_core.pgTable)(
1319
+ "kb_documents",
1320
+ {
1321
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1322
+ document_id: (0, import_pg_core.varchar)("document_id", { length: 36 }).primaryKey(),
1323
+ namespace_id: (0, import_pg_core.varchar)("namespace_id", { length: 36 }).notNull().references(() => kbNamespaces.namespace_id, { onDelete: "cascade" }),
1324
+ path: (0, import_pg_core.text)("path").notNull(),
1325
+ uri: (0, import_pg_core.text)("uri").notNull(),
1326
+ title: (0, import_pg_core.text)("title").notNull(),
1327
+ icon_emoji: (0, import_pg_core.text)("icon_emoji"),
1328
+ kind: (0, import_pg_core.text)("kind", {
1329
+ enum: ["doc", "memory", "skill", "prompt", "guide", "decision", "bundle", "external"]
1330
+ }).notNull().default("doc"),
1331
+ visibility: (0, import_pg_core.text)("visibility", { enum: ["public", "private"] }).notNull().default("public"),
1332
+ status: (0, import_pg_core.text)("status", { enum: ["draft", "published"] }).notNull().default("published"),
1333
+ edit_policy: (0, import_pg_core.text)("edit_policy", { enum: ["owner", "public", "admins"] }).notNull().default("owner"),
1334
+ // Application-maintained pointer. Avoids a circular FK with versions.
1335
+ current_version_id: (0, import_pg_core.varchar)("current_version_id", { length: 36 }),
1336
+ metadata: t.json("metadata"),
1337
+ created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }).references(() => users.user_id, {
1338
+ onDelete: "set null"
1339
+ }),
1340
+ created_at: t.timestamp("created_at").notNull(),
1341
+ updated_by: (0, import_pg_core.varchar)("updated_by", { length: 36 }).references(() => users.user_id, {
1342
+ onDelete: "set null"
1343
+ }),
1344
+ updated_at: t.timestamp("updated_at"),
1345
+ archived: t.bool("archived").notNull().default(false),
1346
+ archived_at: t.timestamp("archived_at")
1347
+ },
1348
+ (table) => ({
1349
+ tenantIdx: (0, import_pg_core.index)("kb_documents_tenant_id_idx").on(table.tenant_id),
1350
+ namespacePathIdx: (0, import_pg_core.uniqueIndex)("kb_documents_tenant_namespace_path_unique").on(table.tenant_id, table.namespace_id, table.path).where(import_drizzle_orm2.sql`${table.archived} = false`),
1351
+ uriIdx: (0, import_pg_core.uniqueIndex)("kb_documents_tenant_uri_unique").on(table.tenant_id, table.uri).where(import_drizzle_orm2.sql`${table.archived} = false`),
1352
+ namespaceIdx: (0, import_pg_core.index)("kb_documents_namespace_idx").on(table.namespace_id),
1353
+ kindIdx: (0, import_pg_core.index)("kb_documents_kind_idx").on(table.kind),
1354
+ visibilityIdx: (0, import_pg_core.index)("kb_documents_visibility_idx").on(table.visibility),
1355
+ statusIdx: (0, import_pg_core.index)("kb_documents_status_idx").on(table.status),
1356
+ createdByIdx: (0, import_pg_core.index)("kb_documents_created_by_idx").on(table.created_by),
1357
+ updatedAtIdx: (0, import_pg_core.index)("kb_documents_updated_at_idx").on(table.updated_at),
1358
+ archivedIdx: (0, import_pg_core.index)("kb_documents_archived_idx").on(table.archived)
1359
+ })
1360
+ );
1361
+ var kbDocumentVersions = (0, import_pg_core.pgTable)(
1362
+ "kb_document_versions",
1363
+ {
1364
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1365
+ version_id: (0, import_pg_core.varchar)("version_id", { length: 36 }).primaryKey(),
1366
+ document_id: (0, import_pg_core.varchar)("document_id", { length: 36 }).notNull().references(() => kbDocuments.document_id, { onDelete: "cascade" }),
1367
+ version_number: (0, import_pg_core.integer)("version_number").notNull(),
1368
+ content_text: (0, import_pg_core.text)("content_text"),
1369
+ content_blob: bytea("content_blob"),
1370
+ mime_type: (0, import_pg_core.text)("mime_type").notNull().default("text/markdown"),
1371
+ content_md5: (0, import_pg_core.text)("content_md5"),
1372
+ content_sha256: (0, import_pg_core.text)("content_sha256"),
1373
+ byte_length: (0, import_pg_core.integer)("byte_length"),
1374
+ char_length: (0, import_pg_core.integer)("char_length"),
1375
+ frontmatter: t.json("frontmatter"),
1376
+ metadata: t.json("metadata"),
1377
+ change_summary: (0, import_pg_core.text)("change_summary"),
1378
+ created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }).references(() => users.user_id, {
1379
+ onDelete: "set null"
1380
+ }),
1381
+ created_at: t.timestamp("created_at").notNull()
1382
+ },
1383
+ (table) => ({
1384
+ tenantIdx: (0, import_pg_core.index)("kb_document_versions_tenant_id_idx").on(table.tenant_id),
1385
+ documentVersionIdx: (0, import_pg_core.uniqueIndex)("kb_document_versions_tenant_document_version_unique").on(
1386
+ table.tenant_id,
1387
+ table.document_id,
1388
+ table.version_number
1389
+ ),
1390
+ documentIdx: (0, import_pg_core.index)("kb_document_versions_document_idx").on(table.document_id),
1391
+ createdIdx: (0, import_pg_core.index)("kb_document_versions_created_idx").on(table.created_at),
1392
+ md5Idx: (0, import_pg_core.index)("kb_document_versions_md5_idx").on(table.content_md5)
1393
+ })
1394
+ );
1395
+ var kbDocumentUnits = (0, import_pg_core.pgTable)(
1396
+ "kb_document_units",
1397
+ {
1398
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1399
+ unit_id: (0, import_pg_core.varchar)("unit_id", { length: 36 }).primaryKey(),
1400
+ document_id: (0, import_pg_core.varchar)("document_id", { length: 36 }).notNull().references(() => kbDocuments.document_id, { onDelete: "cascade" }),
1401
+ version_id: (0, import_pg_core.varchar)("version_id", { length: 36 }).notNull().references(() => kbDocumentVersions.version_id, { onDelete: "cascade" }),
1402
+ kind: (0, import_pg_core.text)("kind", { enum: ["document", "section", "file", "auto_split"] }).notNull().default("document"),
1403
+ ordinal: (0, import_pg_core.integer)("ordinal").notNull().default(0),
1404
+ path_anchor: (0, import_pg_core.text)("path_anchor"),
1405
+ heading_path: (0, import_pg_core.text)("heading_path"),
1406
+ source_path: (0, import_pg_core.text)("source_path"),
1407
+ content_text: (0, import_pg_core.text)("content_text"),
1408
+ content_md5: (0, import_pg_core.text)("content_md5"),
1409
+ start_offset: (0, import_pg_core.integer)("start_offset"),
1410
+ end_offset: (0, import_pg_core.integer)("end_offset"),
1411
+ embedding_status: (0, import_pg_core.text)("embedding_status", {
1412
+ enum: ["not_configured", "pending", "ready", "stale", "error"]
1413
+ }).notNull().default("not_configured"),
1414
+ embedding_model: (0, import_pg_core.text)("embedding_model"),
1415
+ embedding_dimensions: (0, import_pg_core.integer)("embedding_dimensions"),
1416
+ embedding_hash: (0, import_pg_core.text)("embedding_hash"),
1417
+ embedding_error: (0, import_pg_core.text)("embedding_error"),
1418
+ metadata: t.json("metadata"),
1419
+ created_at: t.timestamp("created_at").notNull(),
1420
+ updated_at: t.timestamp("updated_at")
1421
+ },
1422
+ (table) => ({
1423
+ tenantIdx: (0, import_pg_core.index)("kb_document_units_tenant_id_idx").on(table.tenant_id),
1424
+ documentIdx: (0, import_pg_core.index)("kb_document_units_document_idx").on(table.document_id),
1425
+ versionIdx: (0, import_pg_core.index)("kb_document_units_version_idx").on(table.version_id),
1426
+ versionOrdinalIdx: (0, import_pg_core.index)("kb_document_units_version_ordinal_idx").on(
1427
+ table.version_id,
1428
+ table.ordinal
1429
+ ),
1430
+ contentHashIdx: (0, import_pg_core.index)("kb_document_units_content_hash_idx").on(table.content_md5),
1431
+ embeddingStatusIdx: (0, import_pg_core.index)("kb_document_units_embedding_status_idx").on(table.embedding_status)
1432
+ })
1433
+ );
1434
+ var kbEmbeddingSpaces = (0, import_pg_core.pgTable)(
1435
+ "kb_embedding_spaces",
1436
+ {
1437
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1438
+ embedding_space_id: (0, import_pg_core.varchar)("embedding_space_id", { length: 36 }).primaryKey(),
1439
+ provider: (0, import_pg_core.text)("provider").notNull(),
1440
+ model: (0, import_pg_core.text)("model").notNull(),
1441
+ dimensions: (0, import_pg_core.integer)("dimensions").notNull(),
1442
+ storage_type: (0, import_pg_core.text)("storage_type").notNull().default("vector"),
1443
+ distance: (0, import_pg_core.text)("distance").notNull().default("cosine"),
1444
+ active: t.bool("active").notNull().default(true),
1445
+ metadata: t.json("metadata"),
1446
+ created_at: t.timestamp("created_at").notNull(),
1447
+ updated_at: t.timestamp("updated_at")
1448
+ },
1449
+ (table) => ({
1450
+ tenantIdx: (0, import_pg_core.index)("kb_embedding_spaces_tenant_id_idx").on(table.tenant_id),
1451
+ providerModelIdx: (0, import_pg_core.uniqueIndex)("kb_embedding_spaces_tenant_provider_model_unique").on(
1452
+ table.tenant_id,
1453
+ table.provider,
1454
+ table.model,
1455
+ table.dimensions,
1456
+ table.storage_type,
1457
+ table.distance
1458
+ ),
1459
+ activeIdx: (0, import_pg_core.index)("kb_embedding_spaces_active_idx").on(table.active)
1460
+ })
1461
+ );
1462
+ var kbGraphNodes = (0, import_pg_core.pgTable)(
1463
+ "kb_graph_nodes",
1464
+ {
1465
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1466
+ node_id: (0, import_pg_core.varchar)("node_id", { length: 36 }).primaryKey(),
1467
+ node_type: (0, import_pg_core.text)("node_type", {
1468
+ enum: [
1469
+ "namespace",
1470
+ "document",
1471
+ "document_unit",
1472
+ "branch",
1473
+ "session",
1474
+ "task",
1475
+ "message",
1476
+ "artifact",
1477
+ "repo",
1478
+ "board",
1479
+ "user",
1480
+ "tag",
1481
+ "external"
1482
+ ]
1483
+ }).notNull(),
1484
+ uri: (0, import_pg_core.text)("uri").notNull(),
1485
+ label: (0, import_pg_core.text)("label"),
1486
+ namespace_id: (0, import_pg_core.varchar)("namespace_id", { length: 36 }).references(
1487
+ () => kbNamespaces.namespace_id,
1488
+ { onDelete: "cascade" }
1489
+ ),
1490
+ document_id: (0, import_pg_core.varchar)("document_id", { length: 36 }).references(() => kbDocuments.document_id, {
1491
+ onDelete: "cascade"
1492
+ }),
1493
+ unit_id: (0, import_pg_core.varchar)("unit_id", { length: 36 }).references(() => kbDocumentUnits.unit_id, {
1494
+ onDelete: "cascade"
1495
+ }),
1496
+ branch_id: (0, import_pg_core.varchar)("branch_id", { length: 36 }).references(() => branches.branch_id, {
1497
+ onDelete: "cascade"
1498
+ }),
1499
+ session_id: (0, import_pg_core.varchar)("session_id", { length: 36 }).references(() => sessions.session_id, {
1500
+ onDelete: "cascade"
1501
+ }),
1502
+ task_id: (0, import_pg_core.varchar)("task_id", { length: 36 }).references(() => tasks.task_id, {
1503
+ onDelete: "cascade"
1504
+ }),
1505
+ message_id: (0, import_pg_core.varchar)("message_id", { length: 36 }).references(() => messages.message_id, {
1506
+ onDelete: "cascade"
1507
+ }),
1508
+ artifact_id: (0, import_pg_core.varchar)("artifact_id", { length: 36 }).references(() => artifacts.artifact_id, {
1509
+ onDelete: "cascade"
1510
+ }),
1511
+ repo_id: (0, import_pg_core.varchar)("repo_id", { length: 36 }).references(() => repos.repo_id, {
1512
+ onDelete: "cascade"
1513
+ }),
1514
+ board_id: (0, import_pg_core.varchar)("board_id", { length: 36 }).references(() => boards.board_id, {
1515
+ onDelete: "cascade"
1516
+ }),
1517
+ user_id: (0, import_pg_core.varchar)("user_id", { length: 36 }).references(() => users.user_id, {
1518
+ onDelete: "cascade"
1519
+ }),
1520
+ external_uri: (0, import_pg_core.text)("external_uri"),
1521
+ metadata: t.json("metadata"),
1522
+ created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }).references(() => users.user_id, {
1523
+ onDelete: "set null"
1524
+ }),
1525
+ created_at: t.timestamp("created_at").notNull(),
1526
+ updated_at: t.timestamp("updated_at"),
1527
+ archived: t.bool("archived").notNull().default(false),
1528
+ archived_at: t.timestamp("archived_at")
1529
+ },
1530
+ (table) => ({
1531
+ tenantIdx: (0, import_pg_core.index)("kb_graph_nodes_tenant_id_idx").on(table.tenant_id),
1532
+ uriIdx: (0, import_pg_core.uniqueIndex)("kb_graph_nodes_tenant_uri_unique").on(table.tenant_id, table.uri).where(import_drizzle_orm2.sql`${table.archived} = false`),
1533
+ typeIdx: (0, import_pg_core.index)("kb_graph_nodes_type_idx").on(table.node_type),
1534
+ namespaceIdx: (0, import_pg_core.index)("kb_graph_nodes_namespace_idx").on(table.namespace_id),
1535
+ documentIdx: (0, import_pg_core.index)("kb_graph_nodes_document_idx").on(table.document_id),
1536
+ unitIdx: (0, import_pg_core.index)("kb_graph_nodes_unit_idx").on(table.unit_id),
1537
+ branchIdx: (0, import_pg_core.index)("kb_graph_nodes_branch_idx").on(table.branch_id),
1538
+ sessionIdx: (0, import_pg_core.index)("kb_graph_nodes_session_idx").on(table.session_id),
1539
+ taskIdx: (0, import_pg_core.index)("kb_graph_nodes_task_idx").on(table.task_id),
1540
+ messageIdx: (0, import_pg_core.index)("kb_graph_nodes_message_idx").on(table.message_id),
1541
+ artifactIdx: (0, import_pg_core.index)("kb_graph_nodes_artifact_idx").on(table.artifact_id),
1542
+ repoIdx: (0, import_pg_core.index)("kb_graph_nodes_repo_idx").on(table.repo_id),
1543
+ boardIdx: (0, import_pg_core.index)("kb_graph_nodes_board_idx").on(table.board_id),
1544
+ userIdx: (0, import_pg_core.index)("kb_graph_nodes_user_idx").on(table.user_id),
1545
+ externalUriIdx: (0, import_pg_core.index)("kb_graph_nodes_external_uri_idx").on(table.external_uri),
1546
+ archivedIdx: (0, import_pg_core.index)("kb_graph_nodes_archived_idx").on(table.archived)
1547
+ })
1548
+ );
1549
+ var kbGraphEdges = (0, import_pg_core.pgTable)(
1550
+ "kb_graph_edges",
1551
+ {
1552
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1553
+ edge_id: (0, import_pg_core.varchar)("edge_id", { length: 36 }).primaryKey(),
1554
+ source_node_id: (0, import_pg_core.varchar)("source_node_id", { length: 36 }).notNull().references(() => kbGraphNodes.node_id, { onDelete: "cascade" }),
1555
+ target_node_id: (0, import_pg_core.varchar)("target_node_id", { length: 36 }).notNull().references(() => kbGraphNodes.node_id, { onDelete: "cascade" }),
1556
+ edge_type: (0, import_pg_core.text)("edge_type", {
1557
+ enum: [
1558
+ "contains",
1559
+ "references",
1560
+ "mentions",
1561
+ "implements",
1562
+ "depends_on",
1563
+ "supersedes",
1564
+ "derived_from",
1565
+ "tagged_with",
1566
+ "about",
1567
+ "parent_of",
1568
+ "related_to"
1569
+ ]
1570
+ }).notNull(),
1571
+ confidence: (0, import_pg_core.integer)("confidence"),
1572
+ properties: t.json("properties"),
1573
+ created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }).references(() => users.user_id, {
1574
+ onDelete: "set null"
1575
+ }),
1576
+ created_at: t.timestamp("created_at").notNull(),
1577
+ archived: t.bool("archived").notNull().default(false),
1578
+ archived_at: t.timestamp("archived_at")
1579
+ },
1580
+ (table) => ({
1581
+ tenantIdx: (0, import_pg_core.index)("kb_graph_edges_tenant_id_idx").on(table.tenant_id),
1582
+ sourceIdx: (0, import_pg_core.index)("kb_graph_edges_source_idx").on(table.source_node_id),
1583
+ targetIdx: (0, import_pg_core.index)("kb_graph_edges_target_idx").on(table.target_node_id),
1584
+ typeIdx: (0, import_pg_core.index)("kb_graph_edges_type_idx").on(table.edge_type),
1585
+ sourceTypeIdx: (0, import_pg_core.index)("kb_graph_edges_source_type_idx").on(
1586
+ table.source_node_id,
1587
+ table.edge_type
1588
+ ),
1589
+ targetTypeIdx: (0, import_pg_core.index)("kb_graph_edges_target_type_idx").on(
1590
+ table.target_node_id,
1591
+ table.edge_type
1592
+ ),
1593
+ sourceTargetTypeIdx: (0, import_pg_core.uniqueIndex)("kb_graph_edges_tenant_source_target_type_unique").on(table.tenant_id, table.source_node_id, table.target_node_id, table.edge_type).where(import_drizzle_orm2.sql`${table.archived} = false`),
1594
+ archivedIdx: (0, import_pg_core.index)("kb_graph_edges_archived_idx").on(table.archived)
1595
+ })
1596
+ );
1597
+ var sessionsRelations = (0, import_drizzle_orm2.relations)(sessions, ({ one, many }) => ({
1598
+ branch: one(branches, {
1599
+ fields: [sessions.branch_id],
1600
+ references: [branches.branch_id]
1601
+ }),
1602
+ schedule: one(schedules, {
1603
+ fields: [sessions.schedule_id],
1604
+ references: [schedules.schedule_id]
1605
+ }),
1606
+ outboundRelationships: many(sessionRelationships, { relationName: "relationshipSource" }),
1607
+ inboundRelationships: many(sessionRelationships, { relationName: "relationshipTarget" })
1608
+ }));
1609
+ var sessionRelationshipsRelations = (0, import_drizzle_orm2.relations)(sessionRelationships, ({ one }) => ({
1610
+ sourceSession: one(sessions, {
1611
+ fields: [sessionRelationships.source_session_id],
1612
+ references: [sessions.session_id],
1613
+ relationName: "relationshipSource"
1614
+ }),
1615
+ targetSession: one(sessions, {
1616
+ fields: [sessionRelationships.target_session_id],
1617
+ references: [sessions.session_id],
1618
+ relationName: "relationshipTarget"
1619
+ }),
1620
+ callbackSession: one(sessions, {
1621
+ fields: [sessionRelationships.callback_session_id],
1622
+ references: [sessions.session_id]
1623
+ })
1624
+ }));
1625
+ var branchesRelations = (0, import_drizzle_orm2.relations)(branches, ({ many }) => ({
1626
+ sessions: many(sessions),
1627
+ schedules: many(schedules)
1628
+ }));
1629
+ var schedulesRelations = (0, import_drizzle_orm2.relations)(schedules, ({ one, many }) => ({
1630
+ branch: one(branches, {
1631
+ fields: [schedules.branch_id],
1632
+ references: [branches.branch_id]
1633
+ }),
1634
+ sessions: many(sessions)
1635
+ }));
1636
+
1637
+ // src/db/schema.sqlite.ts
1638
+ var schema_sqlite_exports = {};
1639
+ __export(schema_sqlite_exports, {
1640
+ appVariables: () => appVariables2,
1641
+ artifactTrustGrants: () => artifactTrustGrants2,
1642
+ artifacts: () => artifacts2,
1643
+ boardComments: () => boardComments2,
1644
+ boardGroupGrants: () => boardGroupGrants2,
1645
+ boardObjects: () => boardObjects2,
1646
+ boardOwners: () => boardOwners2,
1647
+ boards: () => boards2,
1648
+ branchGroupGrants: () => branchGroupGrants2,
1649
+ branchOwners: () => branchOwners2,
1650
+ branches: () => branches2,
1651
+ branchesRelations: () => branchesRelations2,
1652
+ cardTypes: () => cardTypes2,
1653
+ cards: () => cards2,
1654
+ gatewayChannels: () => gatewayChannels2,
1655
+ gatewayOutboundMessages: () => gatewayOutboundMessages2,
1656
+ groupMemberships: () => groupMemberships2,
1657
+ groups: () => groups2,
1658
+ kbDocumentUnits: () => kbDocumentUnits2,
1659
+ kbDocumentVersions: () => kbDocumentVersions2,
1660
+ kbDocuments: () => kbDocuments2,
1661
+ kbEmbeddingSpaces: () => kbEmbeddingSpaces2,
1662
+ kbGraphEdges: () => kbGraphEdges2,
1663
+ kbGraphNodes: () => kbGraphNodes2,
1664
+ kbNamespaceAcl: () => kbNamespaceAcl2,
1665
+ kbNamespaces: () => kbNamespaces2,
1666
+ mcpServers: () => mcpServers2,
1667
+ messages: () => messages2,
1668
+ repos: () => repos2,
1669
+ schedules: () => schedules2,
1670
+ schedulesRelations: () => schedulesRelations2,
1671
+ serializedSessions: () => serializedSessions2,
1672
+ sessionEnvSelections: () => sessionEnvSelections2,
1673
+ sessionMcpServers: () => sessionMcpServers2,
1674
+ sessionRelationships: () => sessionRelationships2,
1675
+ sessionRelationshipsRelations: () => sessionRelationshipsRelations2,
1676
+ sessions: () => sessions2,
1677
+ sessionsRelations: () => sessionsRelations2,
1678
+ tasks: () => tasks2,
1679
+ threadSessionMap: () => threadSessionMap2,
1680
+ userApiKeys: () => userApiKeys2,
1681
+ userMcpOauthTokens: () => userMcpOauthTokens2,
1682
+ users: () => users2
1683
+ });
1684
+ var import_drizzle_orm3 = require("drizzle-orm");
1685
+ var import_sqlite_core = require("drizzle-orm/sqlite-core");
1686
+ var t2 = {
1687
+ timestamp: (name) => (0, import_sqlite_core.integer)(name, { mode: "timestamp_ms" }),
1688
+ bool: (name) => (0, import_sqlite_core.integer)(name, { mode: "boolean" }),
1689
+ json: (name) => (0, import_sqlite_core.text)(name, { mode: "json" }).$type()
1690
+ };
1691
+ var sessions2 = (0, import_sqlite_core.sqliteTable)(
1692
+ "sessions",
1693
+ {
1694
+ // Primary identity
1695
+ session_id: (0, import_sqlite_core.text)("session_id", { length: 36 }).primaryKey(),
1696
+ created_at: t2.timestamp("created_at").notNull(),
1697
+ updated_at: t2.timestamp("updated_at"),
1698
+ // User attribution
1699
+ created_by: (0, import_sqlite_core.text)("created_by", { length: 36 }).notNull(),
1700
+ // Unix username for SDK impersonation (immutable once set)
1701
+ // Set from creator's unix_username at session creation time
1702
+ // NEVER changes, even if user's unix_username changes later
1703
+ // This ensures SDK session data remains accessible in the original home directory
1704
+ unix_username: (0, import_sqlite_core.text)("unix_username"),
1705
+ // Materialized for filtering/joins (cross-DB compatible)
1706
+ status: (0, import_sqlite_core.text)("status", {
1707
+ enum: [
1708
+ "idle",
1709
+ "running",
1710
+ "stopping",
1711
+ "awaiting_permission",
1712
+ "awaiting_input",
1713
+ "timed_out",
1714
+ "completed",
1715
+ "failed"
1716
+ ]
1717
+ }).notNull(),
1718
+ agentic_tool: (0, import_sqlite_core.text)("agentic_tool", {
1719
+ enum: ["claude-code", "claude-code-cli", "codex", "gemini", "opencode", "copilot", "cursor"]
1720
+ }).notNull(),
1721
+ board_id: (0, import_sqlite_core.text)("board_id", { length: 36 }),
1722
+ // NULL = no board
1723
+ // Genealogy (materialized for tree queries)
1724
+ parent_session_id: (0, import_sqlite_core.text)("parent_session_id", { length: 36 }),
1725
+ forked_from_session_id: (0, import_sqlite_core.text)("forked_from_session_id", { length: 36 }),
1726
+ // Branch reference (REQUIRED: all sessions must have a branch)
1727
+ branch_id: (0, import_sqlite_core.text)("branch_id", { length: 36 }).notNull().references(() => branches2.branch_id, {
1728
+ onDelete: "cascade"
1729
+ // Cascade delete sessions when branch is deleted
1730
+ }),
1731
+ // Scheduler tracking (materialized for deduplication and retention cleanup)
1732
+ scheduled_run_at: (0, import_sqlite_core.integer)("scheduled_run_at"),
1733
+ // Unix timestamp (ms) - authoritative run ID
1734
+ scheduled_from_branch: t2.bool("scheduled_from_branch").notNull().default(false),
1735
+ // FK to schedules.schedule_id, ON DELETE SET NULL. Defined here (not
1736
+ // just in the migration) so drizzle-kit / db introspection sees the
1737
+ // constraint and so future schema diffs don't lose it.
1738
+ schedule_id: (0, import_sqlite_core.text)("schedule_id", { length: 36 }).references(
1739
+ () => schedules2.schedule_id,
1740
+ { onDelete: "set null" }
1741
+ ),
1742
+ // UI state (materialized for efficient highlighting queries)
1743
+ ready_for_prompt: t2.bool("ready_for_prompt").notNull().default(false),
1744
+ // Archive state (cascaded from branch archive)
1745
+ archived: t2.bool("archived").notNull().default(false),
1746
+ archived_reason: (0, import_sqlite_core.text)("archived_reason", {
1747
+ enum: ["branch_archived", "manual", "btw_completed"]
1748
+ }),
1749
+ // JSON blob for everything else (cross-DB via json() type)
1750
+ data: t2.json("data").$type().notNull()
1751
+ },
1752
+ (table) => ({
1753
+ statusIdx: (0, import_sqlite_core.index)("sessions_status_idx").on(table.status),
1754
+ statusReadyIdx: (0, import_sqlite_core.index)("sessions_status_ready_idx").on(table.status, table.ready_for_prompt),
1755
+ agenticToolIdx: (0, import_sqlite_core.index)("sessions_agentic_tool_idx").on(table.agentic_tool),
1756
+ boardIdx: (0, import_sqlite_core.index)("sessions_board_idx").on(table.board_id),
1757
+ branchIdx: (0, import_sqlite_core.index)("sessions_branch_idx").on(table.branch_id),
1758
+ createdIdx: (0, import_sqlite_core.index)("sessions_created_idx").on(table.created_at),
1759
+ parentIdx: (0, import_sqlite_core.index)("sessions_parent_idx").on(table.parent_session_id),
1760
+ forkedIdx: (0, import_sqlite_core.index)("sessions_forked_idx").on(table.forked_from_session_id),
1761
+ // Scheduler indexes — including the partial unique index below.
1762
+ scheduledFromBranchIdx: (0, import_sqlite_core.index)("sessions_scheduled_flag_idx").on(table.scheduled_from_branch),
1763
+ // Partial unique index — covering for the scheduler's dedup lookup
1764
+ // AND serves as the DB-level guard against check-then-create races
1765
+ // in spawnScheduledSession (cron tick vs manual run-now, or two
1766
+ // tick async paths). Partial because schedule_id is nullable: ad-hoc
1767
+ // sessions all have schedule_id NULL and must coexist.
1768
+ scheduleRunUnique: (0, import_sqlite_core.uniqueIndex)("sessions_schedule_run_unique").on(table.schedule_id, table.scheduled_run_at).where(import_drizzle_orm3.sql`${table.schedule_id} IS NOT NULL AND ${table.scheduled_run_at} IS NOT NULL`)
1769
+ })
1770
+ );
1771
+ var sessionRelationships2 = (0, import_sqlite_core.sqliteTable)(
1772
+ "session_relationships",
1773
+ {
1774
+ relationship_id: (0, import_sqlite_core.text)("relationship_id", { length: 36 }).primaryKey(),
1775
+ source_session_id: (0, import_sqlite_core.text)("source_session_id", { length: 36 }).notNull().references(() => sessions2.session_id, { onDelete: "cascade" }),
1776
+ target_session_id: (0, import_sqlite_core.text)("target_session_id", { length: 36 }).notNull().references(() => sessions2.session_id, { onDelete: "cascade" }),
1777
+ relationship_type: (0, import_sqlite_core.text)("relationship_type", { enum: ["remote_create"] }).notNull(),
1778
+ created_by: (0, import_sqlite_core.text)("created_by", { length: 36 }).notNull(),
1779
+ created_at: t2.timestamp("created_at").notNull(),
1780
+ updated_at: t2.timestamp("updated_at"),
1781
+ callback_enabled: t2.bool("callback_enabled").notNull().default(false),
1782
+ callback_session_id: (0, import_sqlite_core.text)("callback_session_id", { length: 36 }).references(
1783
+ () => sessions2.session_id,
1784
+ {
1785
+ onDelete: "set null"
1786
+ }
1787
+ ),
1788
+ data: t2.json("data")
1789
+ },
1790
+ (table) => ({
1791
+ sourceIdx: (0, import_sqlite_core.index)("session_relationships_source_idx").on(table.source_session_id),
1792
+ targetIdx: (0, import_sqlite_core.index)("session_relationships_target_idx").on(table.target_session_id),
1793
+ callbackIdx: (0, import_sqlite_core.index)("session_relationships_callback_idx").on(table.callback_session_id),
1794
+ // Note: no tenant_source/tenant_target composite indexes here — SQLite schema
1795
+ // has no tenant column on this table (RLS is Postgres-only). The standalone
1796
+ // source/target indexes above are sufficient for SQLite.
1797
+ sourceTargetTypeUnique: (0, import_sqlite_core.uniqueIndex)("session_relationships_source_target_type_unique").on(
1798
+ table.source_session_id,
1799
+ table.target_session_id,
1800
+ table.relationship_type
1801
+ )
1802
+ })
1803
+ );
1804
+ var tasks2 = (0, import_sqlite_core.sqliteTable)(
1805
+ "tasks",
1806
+ {
1807
+ task_id: (0, import_sqlite_core.text)("task_id", { length: 36 }).primaryKey(),
1808
+ session_id: (0, import_sqlite_core.text)("session_id", { length: 36 }).notNull().references(() => sessions2.session_id, { onDelete: "cascade" }),
1809
+ created_at: t2.timestamp("created_at").notNull(),
1810
+ started_at: t2.timestamp("started_at"),
1811
+ completed_at: t2.timestamp("completed_at"),
1812
+ last_executor_heartbeat_at: t2.timestamp("last_executor_heartbeat_at"),
1813
+ status: (0, import_sqlite_core.text)("status", {
1814
+ enum: [
1815
+ "queued",
1816
+ "created",
1817
+ "running",
1818
+ "stopping",
1819
+ "awaiting_permission",
1820
+ "awaiting_input",
1821
+ "timed_out",
1822
+ "completed",
1823
+ "failed",
1824
+ "stopped"
1825
+ ]
1826
+ }).notNull(),
1827
+ // Queue position (lower drains first); only populated for status='queued'
1828
+ queue_position: (0, import_sqlite_core.integer)("queue_position"),
1829
+ // User attribution
1830
+ created_by: (0, import_sqlite_core.text)("created_by", { length: 36 }).notNull(),
1831
+ // MD5 of SDK session file at task completion (only populated when stateless_fs_mode is enabled)
1832
+ session_md5: (0, import_sqlite_core.text)("session_md5"),
1833
+ data: t2.json("data").$type().notNull()
1834
+ },
1835
+ (table) => ({
1836
+ sessionIdx: (0, import_sqlite_core.index)("tasks_session_idx").on(table.session_id),
1837
+ statusIdx: (0, import_sqlite_core.index)("tasks_status_idx").on(table.status),
1838
+ createdIdx: (0, import_sqlite_core.index)("tasks_created_idx").on(table.created_at),
1839
+ queueIdx: (0, import_sqlite_core.index)("tasks_queue_idx").on(table.session_id, table.status, table.queue_position),
1840
+ // Partial unique index — defense-in-depth for `tasks.createPending` race
1841
+ // serialization. Only QUEUED rows are constrained; CREATED/RUNNING/done
1842
+ // rows have NULL queue_position and are unaffected.
1843
+ queuedPositionUnique: (0, import_sqlite_core.uniqueIndex)("tasks_queued_position_unique").on(table.session_id, table.queue_position).where(import_drizzle_orm3.sql`${table.status} = 'queued'`)
1844
+ })
1845
+ );
1846
+ var serializedSessions2 = (0, import_sqlite_core.sqliteTable)(
1847
+ "serialized_sessions",
1848
+ {
1849
+ id: (0, import_sqlite_core.text)("id", { length: 36 }).primaryKey(),
1850
+ session_id: (0, import_sqlite_core.text)("session_id", { length: 36 }).notNull().references(() => sessions2.session_id, { onDelete: "cascade" }),
1851
+ branch_id: (0, import_sqlite_core.text)("branch_id", { length: 36 }).notNull().references(() => branches2.branch_id, { onDelete: "cascade" }),
1852
+ task_id: (0, import_sqlite_core.text)("task_id", { length: 36 }).references(() => tasks2.task_id, {
1853
+ onDelete: "set null"
1854
+ }),
1855
+ turn_index: (0, import_sqlite_core.integer)("turn_index").notNull().default(0),
1856
+ created_at: t2.timestamp("created_at").notNull(),
1857
+ md5: (0, import_sqlite_core.text)("md5").notNull(),
1858
+ status: (0, import_sqlite_core.text)("status").notNull(),
1859
+ // 'processing' | 'done' — validated at app layer
1860
+ payload: (0, import_sqlite_core.blob)("payload", { mode: "buffer" })
1861
+ // gzipped; NULL while status='processing'
1862
+ },
1863
+ (table) => ({
1864
+ sessionTurnIdx: (0, import_sqlite_core.index)("serialized_sessions_session_turn_idx").on(
1865
+ table.session_id,
1866
+ table.turn_index
1867
+ ),
1868
+ branchIdx: (0, import_sqlite_core.index)("serialized_sessions_branch_idx").on(table.branch_id)
1869
+ })
1870
+ );
1871
+ var messages2 = (0, import_sqlite_core.sqliteTable)(
1872
+ "messages",
1873
+ {
1874
+ // Primary identity
1875
+ message_id: (0, import_sqlite_core.text)("message_id", { length: 36 }).primaryKey(),
1876
+ created_at: t2.timestamp("created_at").notNull(),
1877
+ // Foreign keys (materialized for indexes)
1878
+ session_id: (0, import_sqlite_core.text)("session_id", { length: 36 }).notNull().references(() => sessions2.session_id, { onDelete: "cascade" }),
1879
+ task_id: (0, import_sqlite_core.text)("task_id", { length: 36 }).references(() => tasks2.task_id, {
1880
+ onDelete: "set null"
1881
+ }),
1882
+ // Materialized for queries
1883
+ type: (0, import_sqlite_core.text)("type", {
1884
+ enum: [
1885
+ "user",
1886
+ "assistant",
1887
+ "system",
1888
+ "file-history-snapshot",
1889
+ "permission_request",
1890
+ "input_request",
1891
+ "daemon_restart",
1892
+ "daemon_crash",
1893
+ "widget_request"
1894
+ ]
1895
+ }).notNull(),
1896
+ role: (0, import_sqlite_core.text)("role", {
1897
+ enum: ["user", "assistant", "system"]
1898
+ }).notNull(),
1899
+ index: (0, import_sqlite_core.integer)("index").notNull(),
1900
+ // Position in conversation (0-based)
1901
+ timestamp: t2.timestamp("timestamp").notNull(),
1902
+ content_preview: (0, import_sqlite_core.text)("content_preview"),
1903
+ // First 200 chars for list views
1904
+ // Parent tool use ID (for nested tool calls - e.g., Task tool spawning Read/Grep)
1905
+ parent_tool_use_id: (0, import_sqlite_core.text)("parent_tool_use_id"),
1906
+ // NOTE: queueing moved off `messages` and onto `tasks.status='queued'` as
1907
+ // of migration sqlite/0040 (postgres/0030). The legacy `status` and
1908
+ // `queue_position` columns are gone — see `tasks.queue_position` instead.
1909
+ // Full data (JSON blob)
1910
+ data: t2.json("data").$type().notNull()
1911
+ },
1912
+ (table) => ({
1913
+ // Indexes for efficient lookups
1914
+ sessionIdx: (0, import_sqlite_core.index)("messages_session_id_idx").on(table.session_id),
1915
+ taskIdx: (0, import_sqlite_core.index)("messages_task_id_idx").on(table.task_id),
1916
+ sessionIndexIdx: (0, import_sqlite_core.index)("messages_session_index_idx").on(table.session_id, table.index),
1917
+ timestampIdx: (0, import_sqlite_core.index)("messages_timestamp_idx").on(table.timestamp),
1918
+ sessionTimestampIdx: (0, import_sqlite_core.index)("messages_session_timestamp_idx").on(
1919
+ table.session_id,
1920
+ table.timestamp
1921
+ )
1922
+ })
1923
+ );
1924
+ var boards2 = (0, import_sqlite_core.sqliteTable)(
1925
+ "boards",
1926
+ {
1927
+ board_id: (0, import_sqlite_core.text)("board_id", { length: 36 }).primaryKey(),
1928
+ created_at: t2.timestamp("created_at").notNull(),
1929
+ updated_at: t2.timestamp("updated_at"),
1930
+ // User attribution
1931
+ created_by: (0, import_sqlite_core.text)("created_by", { length: 36 }).notNull(),
1932
+ // Materialized for lookups
1933
+ name: (0, import_sqlite_core.text)("name").notNull(),
1934
+ slug: (0, import_sqlite_core.text)("slug").unique(),
1935
+ primary_assistant_id: (0, import_sqlite_core.text)("primary_assistant_id", { length: 36 }).references(
1936
+ () => branches2.branch_id,
1937
+ {
1938
+ onDelete: "set null"
1939
+ }
1940
+ ),
1941
+ // JSON blob for the rest
1942
+ data: t2.json("data").$type().notNull(),
1943
+ // Archive state (for soft deletes)
1944
+ archived: t2.bool("archived").notNull().default(false),
1945
+ archived_at: t2.timestamp("archived_at"),
1946
+ archived_by: (0, import_sqlite_core.text)("archived_by", { length: 36 })
1947
+ },
1948
+ (table) => ({
1949
+ nameIdx: (0, import_sqlite_core.index)("boards_name_idx").on(table.name),
1950
+ slugIdx: (0, import_sqlite_core.index)("boards_slug_idx").on(table.slug)
1951
+ })
1952
+ );
1953
+ var repos2 = (0, import_sqlite_core.sqliteTable)(
1954
+ "repos",
1955
+ {
1956
+ repo_id: (0, import_sqlite_core.text)("repo_id", { length: 36 }).primaryKey(),
1957
+ created_at: t2.timestamp("created_at").notNull(),
1958
+ updated_at: t2.timestamp("updated_at"),
1959
+ // Materialized for querying
1960
+ slug: (0, import_sqlite_core.text)("slug").notNull().unique(),
1961
+ repo_type: (0, import_sqlite_core.text)("repo_type", { enum: ["remote", "local"] }).notNull().default("remote"),
1962
+ // Unix group for repo-level git access (agor_rp_<short-id>)
1963
+ // Users who have access to ANY branch in this repo get added to this group.
1964
+ // Applied to repo Unix-group-managed paths:
1965
+ // - repo root (non-recursive) for traversal into .git/worktrees/<name>
1966
+ // - .git (recursive) for shared git objects/refs and git operations
1967
+ unix_group: (0, import_sqlite_core.text)("unix_group"),
1968
+ data: t2.json("data").$type().notNull()
1969
+ },
1970
+ (table) => ({
1971
+ slugIdx: (0, import_sqlite_core.index)("repos_slug_idx").on(table.slug)
1972
+ })
1973
+ );
1974
+ var branches2 = (0, import_sqlite_core.sqliteTable)(
1975
+ "branches",
1976
+ {
1977
+ // Primary identity
1978
+ branch_id: (0, import_sqlite_core.text)("branch_id", { length: 36 }).primaryKey(),
1979
+ repo_id: (0, import_sqlite_core.text)("repo_id", { length: 36 }).notNull().references(() => repos2.repo_id, { onDelete: "cascade" }),
1980
+ created_at: t2.timestamp("created_at").notNull(),
1981
+ updated_at: t2.timestamp("updated_at"),
1982
+ // User attribution
1983
+ created_by: (0, import_sqlite_core.text)("created_by", { length: 36 }).notNull(),
1984
+ // Materialized for queries
1985
+ name: (0, import_sqlite_core.text)("name").notNull(),
1986
+ // "feat-auth", "main"
1987
+ ref: (0, import_sqlite_core.text)("ref").notNull(),
1988
+ // Current branch/tag/commit
1989
+ ref_type: (0, import_sqlite_core.text)("ref_type", { enum: ["branch", "tag"] }),
1990
+ // Type of ref (branch or tag)
1991
+ branch_unique_id: (0, import_sqlite_core.integer)("branch_unique_id").notNull(),
1992
+ // Auto-assigned sequential ID for templates
1993
+ // Environment configuration (static, initialized from templates, then user-editable)
1994
+ start_command: (0, import_sqlite_core.text)("start_command"),
1995
+ // Start command (initialized from repo's up_command template)
1996
+ stop_command: (0, import_sqlite_core.text)("stop_command"),
1997
+ // Stop command (initialized from repo's down_command template)
1998
+ nuke_command: (0, import_sqlite_core.text)("nuke_command"),
1999
+ // Nuke command (initialized from repo's nuke_command template)
2000
+ health_check_url: (0, import_sqlite_core.text)("health_check_url"),
2001
+ // Health check URL (initialized from repo's health_check.url_template)
2002
+ app_url: (0, import_sqlite_core.text)("app_url"),
2003
+ // Application URL (initialized from repo's app_url_template)
2004
+ logs_command: (0, import_sqlite_core.text)("logs_command"),
2005
+ // Logs command (initialized from repo's logs_command template)
2006
+ // Name of the environment variant currently rendered into the command fields above.
2007
+ // References a key under repo.environment.variants. Null for pre-v2 branches.
2008
+ environment_variant: (0, import_sqlite_core.text)("environment_variant"),
2009
+ // Board relationship (nullable - branches can exist without boards)
2010
+ board_id: (0, import_sqlite_core.text)("board_id", { length: 36 }).references(() => boards2.board_id, {
2011
+ onDelete: "set null"
2012
+ // If board is deleted, branch remains but loses board association
2013
+ }),
2014
+ // UI state (materialized for efficient highlighting queries)
2015
+ needs_attention: t2.bool("needs_attention").notNull().default(true),
2016
+ // Default true for new branches
2017
+ // Archive state (for soft deletes)
2018
+ archived: t2.bool("archived").notNull().default(false),
2019
+ archived_at: t2.timestamp("archived_at"),
2020
+ archived_by: (0, import_sqlite_core.text)("archived_by", { length: 36 }),
2021
+ filesystem_status: (0, import_sqlite_core.text)("filesystem_status", {
2022
+ enum: ["creating", "ready", "failed", "preserved", "cleaned", "deleted"]
2023
+ }),
2024
+ // RBAC: App-layer permissions (rbac.md)
2025
+ permission_source: (0, import_sqlite_core.text)("permission_source", { enum: ["board", "override"] }).$type().notNull().default("override"),
2026
+ others_can: (0, import_sqlite_core.text)("others_can", {
2027
+ enum: [...BRANCH_PERMISSION_LEVELS]
2028
+ }).default("view"),
2029
+ // RBAC: OS-layer permissions (unix-user-modes.md)
2030
+ unix_group: (0, import_sqlite_core.text)("unix_group"),
2031
+ // e.g., 'agor_wt_abc123'
2032
+ others_fs_access: (0, import_sqlite_core.text)("others_fs_access", {
2033
+ enum: ["none", "read", "write"]
2034
+ }).$type().default("read"),
2035
+ // Branch storage model — see context/explorations/clone-redesign.md.
2036
+ // 'worktree' = native `git worktree add` (shared base .git/config — legacy default).
2037
+ // 'clone' = self-standing `git clone` (own .git/ — closes cross-branch leak vectors).
2038
+ //
2039
+ // Enum is validated at the Drizzle/TS/Zod/service layer (no DB-side
2040
+ // CHECK) per context/guides/creating-database-migrations.md so adding a
2041
+ // value later doesn't force a table-recreation migration on SQLite.
2042
+ storage_mode: (0, import_sqlite_core.text)("storage_mode", { enum: ["worktree", "clone"] }).notNull().default("worktree"),
2043
+ // Only meaningful when storage_mode='clone'. NULL = full clone, positive
2044
+ // integer = `git clone --depth N` (shallow). The service layer rejects
2045
+ // a non-null clone_depth on worktree-mode rows.
2046
+ clone_depth: (0, import_sqlite_core.integer)("clone_depth"),
2047
+ // JSON blob for everything else
2048
+ data: t2.json("data").$type().notNull()
2049
+ },
2050
+ (table) => ({
2051
+ repoIdx: (0, import_sqlite_core.index)("branches_repo_idx").on(table.repo_id),
2052
+ nameIdx: (0, import_sqlite_core.index)("branches_name_idx").on(table.name),
2053
+ refIdx: (0, import_sqlite_core.index)("branches_ref_idx").on(table.ref),
2054
+ boardIdx: (0, import_sqlite_core.index)("branches_board_idx").on(table.board_id),
2055
+ createdIdx: (0, import_sqlite_core.index)("branches_created_idx").on(table.created_at),
2056
+ updatedIdx: (0, import_sqlite_core.index)("branches_updated_idx").on(table.updated_at),
2057
+ // Composite unique constraint (repo + name)
2058
+ uniqueRepoName: (0, import_sqlite_core.index)("branches_repo_name_unique").on(table.repo_id, table.name)
2059
+ })
2060
+ );
2061
+ var branchOwners2 = (0, import_sqlite_core.sqliteTable)(
2062
+ "branch_owners",
2063
+ {
2064
+ branch_id: (0, import_sqlite_core.text)("branch_id", { length: 36 }).notNull().references(() => branches2.branch_id, { onDelete: "cascade" }),
2065
+ user_id: (0, import_sqlite_core.text)("user_id", { length: 36 }).notNull().references(() => users2.user_id, { onDelete: "cascade" }),
2066
+ created_at: t2.timestamp("created_at")
2067
+ },
2068
+ (table) => ({
2069
+ // Composite primary key matching migration 0016
2070
+ pk: (0, import_sqlite_core.primaryKey)({ columns: [table.branch_id, table.user_id] })
2071
+ })
2072
+ );
2073
+ var boardOwners2 = (0, import_sqlite_core.sqliteTable)(
2074
+ "board_owners",
2075
+ {
2076
+ board_id: (0, import_sqlite_core.text)("board_id", { length: 36 }).notNull().references(() => boards2.board_id, { onDelete: "cascade" }),
2077
+ user_id: (0, import_sqlite_core.text)("user_id", { length: 36 }).notNull().references(() => users2.user_id, { onDelete: "cascade" }),
2078
+ created_at: t2.timestamp("created_at")
2079
+ },
2080
+ (table) => ({
2081
+ pk: (0, import_sqlite_core.primaryKey)({ columns: [table.board_id, table.user_id] }),
2082
+ userIdx: (0, import_sqlite_core.index)("board_owners_user_idx").on(table.user_id)
2083
+ })
2084
+ );
2085
+ var schedules2 = (0, import_sqlite_core.sqliteTable)(
2086
+ "schedules",
2087
+ {
2088
+ schedule_id: (0, import_sqlite_core.text)("schedule_id", { length: 36 }).primaryKey(),
2089
+ branch_id: (0, import_sqlite_core.text)("branch_id", { length: 36 }).notNull().references(() => branches2.branch_id, { onDelete: "cascade" }),
2090
+ name: (0, import_sqlite_core.text)("name").notNull(),
2091
+ description: (0, import_sqlite_core.text)("description"),
2092
+ cron_expression: (0, import_sqlite_core.text)("cron_expression").notNull(),
2093
+ timezone_mode: (0, import_sqlite_core.text)("timezone_mode", { enum: ["local", "utc"] }).notNull().default("local"),
2094
+ timezone: (0, import_sqlite_core.text)("timezone"),
2095
+ // IANA, required when timezone_mode='local'
2096
+ prompt: (0, import_sqlite_core.text)("prompt").notNull(),
2097
+ // Handlebars template
2098
+ // jsonb on PG; mirrors BranchScheduleConfig minus promoted fields.
2099
+ agentic_tool_config: t2.json("agentic_tool_config").notNull(),
2100
+ enabled: t2.bool("enabled").notNull().default(true),
2101
+ allow_concurrent_runs: t2.bool("allow_concurrent_runs").notNull().default(false),
2102
+ retention: (0, import_sqlite_core.integer)("retention").notNull().default(5),
2103
+ // 0 = keep all
2104
+ last_run_at: (0, import_sqlite_core.integer)("last_run_at"),
2105
+ // Unix timestamp (ms)
2106
+ last_run_session_id: (0, import_sqlite_core.text)("last_run_session_id", { length: 36 }).references(
2107
+ () => sessions2.session_id,
2108
+ { onDelete: "set null" }
2109
+ ),
2110
+ next_run_at: (0, import_sqlite_core.integer)("next_run_at"),
2111
+ // Unix timestamp (ms), denormalized for scheduler
2112
+ created_at: t2.timestamp("created_at").notNull(),
2113
+ updated_at: t2.timestamp("updated_at").notNull(),
2114
+ created_by: (0, import_sqlite_core.text)("created_by", { length: 36 }).notNull().references(() => users2.user_id)
2115
+ },
2116
+ (table) => ({
2117
+ // Scheduler hot path: WHERE enabled = true AND next_run_at <= ?
2118
+ enabledNextRunIdx: (0, import_sqlite_core.index)("schedules_enabled_next_run_idx").on(table.enabled, table.next_run_at),
2119
+ branchIdx: (0, import_sqlite_core.index)("schedules_branch_idx").on(table.branch_id),
2120
+ createdByIdx: (0, import_sqlite_core.index)("schedules_created_by_idx").on(table.created_by)
2121
+ })
2122
+ );
2123
+ var users2 = (0, import_sqlite_core.sqliteTable)(
2124
+ "users",
2125
+ {
2126
+ // Primary identity
2127
+ user_id: (0, import_sqlite_core.text)("user_id", { length: 36 }).primaryKey(),
2128
+ created_at: t2.timestamp("created_at").notNull(),
2129
+ updated_at: t2.timestamp("updated_at"),
2130
+ // Materialized for auth lookups
2131
+ email: (0, import_sqlite_core.text)("email").unique().notNull(),
2132
+ password: (0, import_sqlite_core.text)("password").notNull(),
2133
+ // bcrypt hashed
2134
+ // Basic profile (materialized for display)
2135
+ name: (0, import_sqlite_core.text)("name"),
2136
+ emoji: (0, import_sqlite_core.text)("emoji"),
2137
+ role: (0, import_sqlite_core.text)("role", {
2138
+ enum: ["superadmin", "admin", "member", "viewer"]
2139
+ // 'owner' is deprecated alias for 'superadmin'
2140
+ }).notNull().default("member"),
2141
+ // Unix username for process impersonation (optional, app-enforced uniqueness)
2142
+ unix_username: (0, import_sqlite_core.text)("unix_username"),
2143
+ // Onboarding state
2144
+ onboarding_completed: t2.bool("onboarding_completed").notNull().default(false),
2145
+ // Force password change flag (admin-settable, auto-cleared on password change)
2146
+ must_change_password: t2.bool("must_change_password").notNull().default(false),
2147
+ // Auth invalidation marker. Password changes set this timestamp so any
2148
+ // previously issued browser access or refresh token is rejected.
2149
+ tokens_valid_after: t2.timestamp("tokens_valid_after"),
2150
+ // JSON blob for profile/preferences
2151
+ data: t2.json("data").$type().notNull()
2152
+ },
2153
+ (table) => ({
2154
+ emailIdx: (0, import_sqlite_core.index)("users_email_idx").on(table.email)
2155
+ })
2156
+ );
2157
+ var groups2 = (0, import_sqlite_core.sqliteTable)(
2158
+ "groups",
2159
+ {
2160
+ group_id: (0, import_sqlite_core.text)("group_id", { length: 36 }).primaryKey(),
2161
+ name: (0, import_sqlite_core.text)("name").notNull(),
2162
+ slug: (0, import_sqlite_core.text)("slug").notNull(),
2163
+ description: (0, import_sqlite_core.text)("description"),
2164
+ archived: t2.bool("archived").notNull().default(false),
2165
+ created_by: (0, import_sqlite_core.text)("created_by", { length: 36 }).references(() => users2.user_id, {
2166
+ onDelete: "set null"
2167
+ }),
2168
+ created_at: t2.timestamp("created_at").notNull(),
2169
+ updated_at: t2.timestamp("updated_at")
2170
+ },
2171
+ (table) => ({
2172
+ slugIdx: (0, import_sqlite_core.uniqueIndex)("groups_slug_idx").on(table.slug),
2173
+ archivedIdx: (0, import_sqlite_core.index)("groups_archived_idx").on(table.archived)
2174
+ })
2175
+ );
2176
+ var groupMemberships2 = (0, import_sqlite_core.sqliteTable)(
2177
+ "group_memberships",
2178
+ {
2179
+ group_id: (0, import_sqlite_core.text)("group_id", { length: 36 }).notNull().references(() => groups2.group_id, { onDelete: "cascade" }),
2180
+ user_id: (0, import_sqlite_core.text)("user_id", { length: 36 }).notNull().references(() => users2.user_id, { onDelete: "cascade" }),
2181
+ added_by: (0, import_sqlite_core.text)("added_by", { length: 36 }).references(() => users2.user_id, {
2182
+ onDelete: "set null"
2183
+ }),
2184
+ created_at: t2.timestamp("created_at").notNull()
2185
+ },
2186
+ (table) => ({
2187
+ pk: (0, import_sqlite_core.primaryKey)({ columns: [table.group_id, table.user_id] }),
2188
+ userIdx: (0, import_sqlite_core.index)("group_memberships_user_idx").on(table.user_id)
2189
+ })
2190
+ );
2191
+ var branchGroupGrants2 = (0, import_sqlite_core.sqliteTable)(
2192
+ "branch_group_grants",
2193
+ {
2194
+ branch_id: (0, import_sqlite_core.text)("branch_id", { length: 36 }).notNull().references(() => branches2.branch_id, { onDelete: "cascade" }),
2195
+ group_id: (0, import_sqlite_core.text)("group_id", { length: 36 }).notNull().references(() => groups2.group_id, { onDelete: "cascade" }),
2196
+ can: (0, import_sqlite_core.text)("can", { enum: [...BRANCH_PERMISSION_LEVELS] }).notNull().default("view"),
2197
+ fs_access: (0, import_sqlite_core.text)("fs_access", { enum: ["none", "read", "write"] }).$type(),
2198
+ created_by: (0, import_sqlite_core.text)("created_by", { length: 36 }).references(() => users2.user_id, {
2199
+ onDelete: "set null"
2200
+ }),
2201
+ created_at: t2.timestamp("created_at").notNull(),
2202
+ updated_at: t2.timestamp("updated_at")
2203
+ },
2204
+ (table) => ({
2205
+ pk: (0, import_sqlite_core.primaryKey)({ columns: [table.branch_id, table.group_id] }),
2206
+ groupIdx: (0, import_sqlite_core.index)("branch_group_grants_group_idx").on(table.group_id)
2207
+ })
2208
+ );
2209
+ var boardGroupGrants2 = (0, import_sqlite_core.sqliteTable)(
2210
+ "board_group_grants",
2211
+ {
2212
+ board_id: (0, import_sqlite_core.text)("board_id", { length: 36 }).notNull().references(() => boards2.board_id, { onDelete: "cascade" }),
2213
+ group_id: (0, import_sqlite_core.text)("group_id", { length: 36 }).notNull().references(() => groups2.group_id, { onDelete: "cascade" }),
2214
+ can: (0, import_sqlite_core.text)("can", { enum: [...BRANCH_PERMISSION_LEVELS] }).notNull().default("view"),
2215
+ fs_access: (0, import_sqlite_core.text)("fs_access", { enum: ["none", "read", "write"] }).$type(),
2216
+ created_by: (0, import_sqlite_core.text)("created_by", { length: 36 }).references(() => users2.user_id, {
2217
+ onDelete: "set null"
2218
+ }),
2219
+ created_at: t2.timestamp("created_at").notNull(),
2220
+ updated_at: t2.timestamp("updated_at")
2221
+ },
2222
+ (table) => ({
2223
+ pk: (0, import_sqlite_core.primaryKey)({ columns: [table.board_id, table.group_id] }),
2224
+ groupIdx: (0, import_sqlite_core.index)("board_group_grants_group_idx").on(table.group_id)
2225
+ })
2226
+ );
2227
+ var appVariables2 = (0, import_sqlite_core.sqliteTable)(
2228
+ "app_variables",
2229
+ {
2230
+ variable_id: (0, import_sqlite_core.text)("variable_id", { length: 36 }).primaryKey(),
2231
+ namespace: (0, import_sqlite_core.text)("namespace").notNull(),
2232
+ key: (0, import_sqlite_core.text)("key").notNull(),
2233
+ value_text: (0, import_sqlite_core.text)("value_text"),
2234
+ value_encrypted: (0, import_sqlite_core.text)("value_encrypted"),
2235
+ is_encrypted: t2.bool("is_encrypted").notNull().default(false),
2236
+ content_type: (0, import_sqlite_core.text)("content_type").notNull().default("text/plain"),
2237
+ metadata: t2.json("metadata"),
2238
+ updated_by: (0, import_sqlite_core.text)("updated_by", { length: 36 }).references(() => users2.user_id, {
2239
+ onDelete: "set null"
2240
+ }),
2241
+ created_at: t2.timestamp("created_at").notNull(),
2242
+ updated_at: t2.timestamp("updated_at").notNull()
2243
+ },
2244
+ (table) => ({
2245
+ namespaceKeyIdx: (0, import_sqlite_core.uniqueIndex)("app_variables_namespace_key_idx").on(table.namespace, table.key),
2246
+ namespaceIdx: (0, import_sqlite_core.index)("app_variables_namespace_idx").on(table.namespace)
2247
+ })
2248
+ );
2249
+ var userApiKeys2 = (0, import_sqlite_core.sqliteTable)(
2250
+ "user_api_keys",
2251
+ {
2252
+ id: (0, import_sqlite_core.text)("id", { length: 36 }).primaryKey(),
2253
+ user_id: (0, import_sqlite_core.text)("user_id", { length: 36 }).notNull().references(() => users2.user_id, { onDelete: "cascade" }),
2254
+ name: (0, import_sqlite_core.text)("name").notNull(),
2255
+ prefix: (0, import_sqlite_core.text)("prefix").notNull(),
2256
+ // first 12 chars: 'agor_sk_XXXX' for identification
2257
+ key_hash: (0, import_sqlite_core.text)("key_hash").notNull(),
2258
+ // bcrypt hash of full key
2259
+ created_at: t2.timestamp("created_at").notNull(),
2260
+ last_used_at: t2.timestamp("last_used_at")
2261
+ },
2262
+ (table) => ({
2263
+ userIdx: (0, import_sqlite_core.index)("user_api_keys_user_idx").on(table.user_id),
2264
+ prefixIdx: (0, import_sqlite_core.index)("user_api_keys_prefix_idx").on(table.prefix)
2265
+ })
2266
+ );
2267
+ var mcpServers2 = (0, import_sqlite_core.sqliteTable)(
2268
+ "mcp_servers",
2269
+ {
2270
+ // Primary identity
2271
+ mcp_server_id: (0, import_sqlite_core.text)("mcp_server_id", { length: 36 }).primaryKey(),
2272
+ created_at: t2.timestamp("created_at").notNull(),
2273
+ updated_at: t2.timestamp("updated_at"),
2274
+ // Materialized for filtering
2275
+ name: (0, import_sqlite_core.text)("name").notNull(),
2276
+ // e.g., "filesystem", "sentry"
2277
+ transport: (0, import_sqlite_core.text)("transport", {
2278
+ enum: ["stdio", "http", "sse"]
2279
+ }).notNull(),
2280
+ scope: (0, import_sqlite_core.text)("scope", {
2281
+ enum: ["global", "session"]
2282
+ }).notNull(),
2283
+ enabled: t2.bool("enabled").notNull().default(true),
2284
+ // Scope foreign key
2285
+ // For 'global' scope: which user owns this server
2286
+ // For 'session' scope: use session_mcp_servers junction table (many-to-many)
2287
+ owner_user_id: (0, import_sqlite_core.text)("owner_user_id", { length: 36 }),
2288
+ // Source tracking (materialized for queries)
2289
+ source: (0, import_sqlite_core.text)("source", {
2290
+ enum: ["user", "imported", "agor"]
2291
+ }).notNull(),
2292
+ // JSON blob for configuration and capabilities
2293
+ data: t2.json("data").$type().notNull()
2294
+ },
2295
+ (table) => ({
2296
+ nameIdx: (0, import_sqlite_core.index)("mcp_servers_name_idx").on(table.name),
2297
+ scopeIdx: (0, import_sqlite_core.index)("mcp_servers_scope_idx").on(table.scope),
2298
+ ownerIdx: (0, import_sqlite_core.index)("mcp_servers_owner_idx").on(table.owner_user_id),
2299
+ enabledIdx: (0, import_sqlite_core.index)("mcp_servers_enabled_idx").on(table.enabled)
2300
+ })
2301
+ );
2302
+ var cardTypes2 = (0, import_sqlite_core.sqliteTable)(
2303
+ "card_types",
2304
+ {
2305
+ card_type_id: (0, import_sqlite_core.text)("card_type_id", { length: 36 }).primaryKey(),
2306
+ name: (0, import_sqlite_core.text)("name").notNull(),
2307
+ emoji: (0, import_sqlite_core.text)("emoji"),
2308
+ color: (0, import_sqlite_core.text)("color"),
2309
+ json_schema: (0, import_sqlite_core.text)("json_schema"),
2310
+ // JSON string of JSON Schema
2311
+ created_by: (0, import_sqlite_core.text)("created_by", { length: 36 }),
2312
+ created_at: t2.timestamp("created_at").notNull(),
2313
+ updated_at: t2.timestamp("updated_at").notNull()
2314
+ },
2315
+ (table) => ({
2316
+ nameIdx: (0, import_sqlite_core.index)("card_types_name_idx").on(table.name)
2317
+ })
2318
+ );
2319
+ var cards2 = (0, import_sqlite_core.sqliteTable)(
2320
+ "cards",
2321
+ {
2322
+ card_id: (0, import_sqlite_core.text)("card_id", { length: 36 }).primaryKey(),
2323
+ board_id: (0, import_sqlite_core.text)("board_id", { length: 36 }).notNull().references(() => boards2.board_id, { onDelete: "cascade" }),
2324
+ card_type_id: (0, import_sqlite_core.text)("card_type_id", { length: 36 }).references(() => cardTypes2.card_type_id, {
2325
+ onDelete: "set null"
2326
+ }),
2327
+ title: (0, import_sqlite_core.text)("title").notNull(),
2328
+ url: (0, import_sqlite_core.text)("url"),
2329
+ description: (0, import_sqlite_core.text)("description"),
2330
+ note: (0, import_sqlite_core.text)("note"),
2331
+ data: (0, import_sqlite_core.text)("data"),
2332
+ // JSON blob validated against CardType.json_schema if present
2333
+ color_override: (0, import_sqlite_core.text)("color_override"),
2334
+ emoji_override: (0, import_sqlite_core.text)("emoji_override"),
2335
+ created_by: (0, import_sqlite_core.text)("created_by", { length: 36 }),
2336
+ created_at: t2.timestamp("created_at").notNull(),
2337
+ updated_at: t2.timestamp("updated_at").notNull(),
2338
+ archived: t2.bool("archived").notNull().default(false),
2339
+ archived_at: t2.timestamp("archived_at")
2340
+ },
2341
+ (table) => ({
2342
+ boardIdx: (0, import_sqlite_core.index)("cards_board_idx").on(table.board_id),
2343
+ cardTypeIdx: (0, import_sqlite_core.index)("cards_card_type_idx").on(table.card_type_id),
2344
+ titleIdx: (0, import_sqlite_core.index)("cards_title_idx").on(table.title),
2345
+ archivedIdx: (0, import_sqlite_core.index)("cards_archived_idx").on(table.archived),
2346
+ createdIdx: (0, import_sqlite_core.index)("cards_created_idx").on(table.created_at)
2347
+ })
2348
+ );
2349
+ var artifacts2 = (0, import_sqlite_core.sqliteTable)(
2350
+ "artifacts",
2351
+ {
2352
+ artifact_id: (0, import_sqlite_core.text)("artifact_id", { length: 36 }).primaryKey(),
2353
+ branch_id: (0, import_sqlite_core.text)("branch_id", { length: 36 }).references(() => branches2.branch_id, {
2354
+ onDelete: "set null"
2355
+ }),
2356
+ source_session_id: (0, import_sqlite_core.text)("source_session_id", { length: 36 }).references(
2357
+ () => sessions2.session_id,
2358
+ {
2359
+ onDelete: "set null"
2360
+ }
2361
+ ),
2362
+ board_id: (0, import_sqlite_core.text)("board_id", { length: 36 }).notNull().references(() => boards2.board_id, { onDelete: "cascade" }),
2363
+ name: (0, import_sqlite_core.text)("name").notNull(),
2364
+ description: (0, import_sqlite_core.text)("description"),
2365
+ path: (0, import_sqlite_core.text)("path"),
2366
+ // provenance only — where files were read from
2367
+ template: (0, import_sqlite_core.text)("template").notNull().default("react"),
2368
+ build_status: (0, import_sqlite_core.text)("build_status").notNull().default("unknown"),
2369
+ build_errors: t2.json("build_errors"),
2370
+ content_hash: (0, import_sqlite_core.text)("content_hash"),
2371
+ files: t2.json("files"),
2372
+ dependencies: t2.json("dependencies"),
2373
+ entry: (0, import_sqlite_core.text)("entry"),
2374
+ // denormalized cache of the Sandpack entry file
2375
+ sandpack_config: t2.json("sandpack_config"),
2376
+ required_env_vars: t2.json("required_env_vars"),
2377
+ agor_grants: t2.json("agor_grants"),
2378
+ agor_runtime: t2.json("agor_runtime"),
2379
+ public: t2.bool("public").notNull().default(true),
2380
+ created_by: (0, import_sqlite_core.text)("created_by", { length: 36 }),
2381
+ created_at: t2.timestamp("created_at").notNull(),
2382
+ updated_at: t2.timestamp("updated_at").notNull(),
2383
+ archived: t2.bool("archived").notNull().default(false),
2384
+ archived_at: t2.timestamp("archived_at")
2385
+ },
2386
+ (table) => ({
2387
+ branchIdx: (0, import_sqlite_core.index)("artifacts_branch_idx").on(table.branch_id),
2388
+ sourceSessionIdx: (0, import_sqlite_core.index)("artifacts_source_session_idx").on(table.source_session_id),
2389
+ boardIdx: (0, import_sqlite_core.index)("artifacts_board_idx").on(table.board_id),
2390
+ archivedIdx: (0, import_sqlite_core.index)("artifacts_archived_idx").on(table.archived),
2391
+ publicIdx: (0, import_sqlite_core.index)("artifacts_public_idx").on(table.public)
2392
+ })
2393
+ );
2394
+ var artifactTrustGrants2 = (0, import_sqlite_core.sqliteTable)(
2395
+ "artifact_trust_grants",
2396
+ {
2397
+ grant_id: (0, import_sqlite_core.text)("grant_id", { length: 36 }).primaryKey(),
2398
+ user_id: (0, import_sqlite_core.text)("user_id", { length: 36 }).notNull(),
2399
+ // CHECK constraint omitted — service-layer enforcement only, so adding new
2400
+ // scope_types in the future doesn't require a SQLite table-recreate.
2401
+ scope_type: (0, import_sqlite_core.text)("scope_type").notNull(),
2402
+ scope_value: (0, import_sqlite_core.text)("scope_value"),
2403
+ env_vars_set: t2.json("env_vars_set").notNull(),
2404
+ agor_grants_set: t2.json("agor_grants_set").notNull(),
2405
+ granted_at: t2.timestamp("granted_at").notNull(),
2406
+ revoked_at: t2.timestamp("revoked_at")
2407
+ },
2408
+ (table) => ({
2409
+ userIdx: (0, import_sqlite_core.index)("artifact_trust_grants_user_idx").on(table.user_id),
2410
+ scopeIdx: (0, import_sqlite_core.index)("artifact_trust_grants_scope_idx").on(table.scope_type, table.scope_value)
2411
+ })
2412
+ );
2413
+ var boardObjects2 = (0, import_sqlite_core.sqliteTable)(
2414
+ "board_objects",
2415
+ {
2416
+ // Primary identity
2417
+ object_id: (0, import_sqlite_core.text)("object_id", { length: 36 }).primaryKey(),
2418
+ board_id: (0, import_sqlite_core.text)("board_id", { length: 36 }).notNull().references(() => boards2.board_id, { onDelete: "cascade" }),
2419
+ created_at: t2.timestamp("created_at").notNull(),
2420
+ // Polymorphic entity reference (exactly one must be set)
2421
+ branch_id: (0, import_sqlite_core.text)("branch_id", { length: 36 }).references(() => branches2.branch_id, {
2422
+ onDelete: "cascade"
2423
+ }),
2424
+ card_id: (0, import_sqlite_core.text)("card_id", { length: 36 }).references(() => cards2.card_id, {
2425
+ onDelete: "cascade"
2426
+ }),
2427
+ // Position data (JSON)
2428
+ data: t2.json("data").$type().notNull()
2429
+ },
2430
+ (table) => ({
2431
+ boardIdx: (0, import_sqlite_core.index)("board_objects_board_idx").on(table.board_id),
2432
+ branchIdx: (0, import_sqlite_core.index)("board_objects_branch_idx").on(table.branch_id),
2433
+ cardIdx: (0, import_sqlite_core.index)("board_objects_card_idx").on(table.card_id)
2434
+ })
2435
+ );
2436
+ var sessionMcpServers2 = (0, import_sqlite_core.sqliteTable)(
2437
+ "session_mcp_servers",
2438
+ {
2439
+ session_id: (0, import_sqlite_core.text)("session_id", { length: 36 }).notNull().references(() => sessions2.session_id, { onDelete: "cascade" }),
2440
+ mcp_server_id: (0, import_sqlite_core.text)("mcp_server_id", { length: 36 }).notNull().references(() => mcpServers2.mcp_server_id, { onDelete: "cascade" }),
2441
+ enabled: t2.bool("enabled").notNull().default(true),
2442
+ added_at: t2.timestamp("added_at").notNull()
2443
+ },
2444
+ (table) => ({
2445
+ // Composite primary key
2446
+ pk: (0, import_sqlite_core.index)("session_mcp_servers_pk").on(table.session_id, table.mcp_server_id),
2447
+ // Indexes for queries
2448
+ sessionIdx: (0, import_sqlite_core.index)("session_mcp_servers_session_idx").on(table.session_id),
2449
+ serverIdx: (0, import_sqlite_core.index)("session_mcp_servers_server_idx").on(table.mcp_server_id),
2450
+ enabledIdx: (0, import_sqlite_core.index)("session_mcp_servers_enabled_idx").on(table.session_id, table.enabled)
2451
+ })
2452
+ );
2453
+ var userMcpOauthTokens2 = (0, import_sqlite_core.sqliteTable)(
2454
+ "user_mcp_oauth_tokens",
2455
+ {
2456
+ // NULL = shared-mode token (one per mcp_server_id)
2457
+ user_id: (0, import_sqlite_core.text)("user_id", { length: 36 }).references(() => users2.user_id, {
2458
+ onDelete: "cascade"
2459
+ }),
2460
+ mcp_server_id: (0, import_sqlite_core.text)("mcp_server_id", { length: 36 }).notNull().references(() => mcpServers2.mcp_server_id, { onDelete: "cascade" }),
2461
+ oauth_access_token: (0, import_sqlite_core.text)("oauth_access_token").notNull(),
2462
+ oauth_token_expires_at: t2.timestamp("oauth_token_expires_at"),
2463
+ // Unix timestamp in milliseconds
2464
+ oauth_refresh_token: (0, import_sqlite_core.text)("oauth_refresh_token"),
2465
+ // DCR / registered client credentials this grant was issued under.
2466
+ // Must be preserved across refreshes.
2467
+ oauth_client_id: (0, import_sqlite_core.text)("oauth_client_id"),
2468
+ oauth_client_secret: (0, import_sqlite_core.text)("oauth_client_secret"),
2469
+ created_at: t2.timestamp("created_at").notNull(),
2470
+ updated_at: t2.timestamp("updated_at")
2471
+ },
2472
+ (table) => ({
2473
+ // Composite lookup indexes. Uniqueness enforced via partial unique indexes
2474
+ // created in the migration (one for per-user rows, one for the shared row).
2475
+ pk: (0, import_sqlite_core.index)("user_mcp_oauth_tokens_pk").on(table.user_id, table.mcp_server_id),
2476
+ userIdx: (0, import_sqlite_core.index)("user_mcp_oauth_tokens_user_idx").on(table.user_id),
2477
+ serverIdx: (0, import_sqlite_core.index)("user_mcp_oauth_tokens_server_idx").on(table.mcp_server_id)
2478
+ })
2479
+ );
2480
+ var boardComments2 = (0, import_sqlite_core.sqliteTable)(
2481
+ "board_comments",
2482
+ {
2483
+ // Primary identity
2484
+ comment_id: (0, import_sqlite_core.text)("comment_id", { length: 36 }).primaryKey(),
2485
+ created_at: t2.timestamp("created_at").notNull(),
2486
+ updated_at: t2.timestamp("updated_at"),
2487
+ // Scoping & authorship
2488
+ board_id: (0, import_sqlite_core.text)("board_id", { length: 36 }).notNull().references(() => boards2.board_id, { onDelete: "cascade" }),
2489
+ created_by: (0, import_sqlite_core.text)("created_by", { length: 36 }).notNull(),
2490
+ // FLEXIBLE ATTACHMENTS (all optional)
2491
+ // Phase 1: board-level only (all NULL)
2492
+ // Phase 2: object attachments (session, task, message, branch)
2493
+ // Phase 3: spatial positioning
2494
+ session_id: (0, import_sqlite_core.text)("session_id", { length: 36 }).references(() => sessions2.session_id, {
2495
+ onDelete: "set null"
2496
+ }),
2497
+ task_id: (0, import_sqlite_core.text)("task_id", { length: 36 }).references(() => tasks2.task_id, {
2498
+ onDelete: "set null"
2499
+ }),
2500
+ message_id: (0, import_sqlite_core.text)("message_id", { length: 36 }).references(() => messages2.message_id, {
2501
+ onDelete: "set null"
2502
+ }),
2503
+ branch_id: (0, import_sqlite_core.text)("branch_id", { length: 36 }).references(() => branches2.branch_id, {
2504
+ onDelete: "cascade"
2505
+ }),
2506
+ // Content (materialized for display)
2507
+ content: (0, import_sqlite_core.text)("content").notNull(),
2508
+ // Markdown-supported text
2509
+ content_preview: (0, import_sqlite_core.text)("content_preview").notNull(),
2510
+ // First 200 chars
2511
+ // Thread support (optional)
2512
+ parent_comment_id: (0, import_sqlite_core.text)("parent_comment_id", { length: 36 }),
2513
+ // Metadata (materialized for filtering)
2514
+ resolved: t2.bool("resolved").notNull().default(false),
2515
+ edited: t2.bool("edited").notNull().default(false),
2516
+ // Reactions (for BOTH thread roots and replies)
2517
+ // Stored as JSON array: [{ user_id: "abc", emoji: "👍" }, ...]
2518
+ // Display grouped by emoji: { "👍": ["alice", "bob"], "🎉": ["charlie"] }
2519
+ reactions: t2.json("reactions").$type().notNull().default(import_drizzle_orm3.sql`'[]'`),
2520
+ // JSON blob for advanced features
2521
+ data: t2.json("data").$type().notNull()
2522
+ },
2523
+ (table) => ({
2524
+ boardIdx: (0, import_sqlite_core.index)("board_comments_board_idx").on(table.board_id),
2525
+ sessionIdx: (0, import_sqlite_core.index)("board_comments_session_idx").on(table.session_id),
2526
+ taskIdx: (0, import_sqlite_core.index)("board_comments_task_idx").on(table.task_id),
2527
+ messageIdx: (0, import_sqlite_core.index)("board_comments_message_idx").on(table.message_id),
2528
+ branchIdx: (0, import_sqlite_core.index)("board_comments_branch_idx").on(table.branch_id),
2529
+ createdByIdx: (0, import_sqlite_core.index)("board_comments_created_by_idx").on(table.created_by),
2530
+ parentIdx: (0, import_sqlite_core.index)("board_comments_parent_idx").on(table.parent_comment_id),
2531
+ createdIdx: (0, import_sqlite_core.index)("board_comments_created_idx").on(table.created_at),
2532
+ resolvedIdx: (0, import_sqlite_core.index)("board_comments_resolved_idx").on(table.resolved)
2533
+ })
2534
+ );
2535
+ var gatewayChannels2 = (0, import_sqlite_core.sqliteTable)(
2536
+ "gateway_channels",
2537
+ {
2538
+ // Primary identity
2539
+ id: (0, import_sqlite_core.text)("id", { length: 36 }).primaryKey(),
2540
+ created_at: t2.timestamp("created_at").notNull(),
2541
+ updated_at: t2.timestamp("updated_at").notNull(),
2542
+ // User attribution
2543
+ created_by: (0, import_sqlite_core.text)("created_by", { length: 36 }).notNull(),
2544
+ // Materialized for queries
2545
+ name: (0, import_sqlite_core.text)("name").notNull(),
2546
+ channel_type: (0, import_sqlite_core.text)("channel_type", {
2547
+ enum: ["slack", "discord", "whatsapp", "telegram", "github", "teams"]
2548
+ }).notNull(),
2549
+ target_branch_id: (0, import_sqlite_core.text)("target_branch_id", { length: 36 }).notNull().references(() => branches2.branch_id, { onDelete: "cascade" }),
2550
+ agor_user_id: (0, import_sqlite_core.text)("agor_user_id", { length: 36 }).notNull(),
2551
+ channel_key: (0, import_sqlite_core.text)("channel_key").notNull().unique(),
2552
+ enabled: t2.bool("enabled").notNull().default(true),
2553
+ last_message_at: t2.timestamp("last_message_at"),
2554
+ // JSON blob for platform credentials (encrypted at rest)
2555
+ config: t2.json("config").notNull(),
2556
+ // JSON blob for agentic tool configuration (agent, model, permission mode, etc.)
2557
+ agentic_config: t2.json("agentic_config")
2558
+ },
2559
+ (table) => ({
2560
+ channelKeyIdx: (0, import_sqlite_core.index)("idx_gateway_channel_key").on(table.channel_key),
2561
+ enabledTypeIdx: (0, import_sqlite_core.index)("idx_gateway_enabled_type").on(table.enabled, table.channel_type)
2562
+ })
2563
+ );
2564
+ var threadSessionMap2 = (0, import_sqlite_core.sqliteTable)(
2565
+ "thread_session_map",
2566
+ {
2567
+ // Primary identity
2568
+ id: (0, import_sqlite_core.text)("id", { length: 36 }).primaryKey(),
2569
+ created_at: t2.timestamp("created_at").notNull(),
2570
+ last_message_at: t2.timestamp("last_message_at").notNull(),
2571
+ // Foreign keys
2572
+ channel_id: (0, import_sqlite_core.text)("channel_id", { length: 36 }).notNull().references(() => gatewayChannels2.id, { onDelete: "cascade" }),
2573
+ thread_id: (0, import_sqlite_core.text)("thread_id").notNull(),
2574
+ session_id: (0, import_sqlite_core.text)("session_id", { length: 36 }).notNull().references(() => sessions2.session_id, { onDelete: "cascade" }),
2575
+ branch_id: (0, import_sqlite_core.text)("branch_id", { length: 36 }).notNull().references(() => branches2.branch_id),
2576
+ // Materialized for queries
2577
+ status: (0, import_sqlite_core.text)("status", {
2578
+ enum: ["active", "archived", "paused"]
2579
+ }).notNull().default("active"),
2580
+ // JSON blob for extra metadata
2581
+ metadata: t2.json("metadata")
2582
+ },
2583
+ (table) => ({
2584
+ uniqueChannelThread: (0, import_sqlite_core.uniqueIndex)("uniq_thread_map_channel_thread").on(
2585
+ table.channel_id,
2586
+ table.thread_id
2587
+ ),
2588
+ sessionIdx: (0, import_sqlite_core.index)("idx_thread_map_session_id").on(table.session_id),
2589
+ threadIdx: (0, import_sqlite_core.index)("idx_thread_map_thread_id").on(table.thread_id),
2590
+ channelStatusIdx: (0, import_sqlite_core.index)("idx_thread_map_channel_status").on(table.channel_id, table.status)
2591
+ })
2592
+ );
2593
+ var gatewayOutboundMessages2 = (0, import_sqlite_core.sqliteTable)(
2594
+ "gateway_outbound_messages",
2595
+ {
2596
+ id: (0, import_sqlite_core.text)("id", { length: 36 }).primaryKey(),
2597
+ created_at: t2.timestamp("created_at").notNull(),
2598
+ updated_at: t2.timestamp("updated_at").notNull(),
2599
+ gateway_channel_id: (0, import_sqlite_core.text)("gateway_channel_id", { length: 36 }).notNull().references(() => gatewayChannels2.id, { onDelete: "cascade" }),
2600
+ channel_type: (0, import_sqlite_core.text)("channel_type", {
2601
+ enum: ["slack", "discord", "whatsapp", "telegram", "github", "teams"]
2602
+ }).notNull(),
2603
+ platform_channel_id: (0, import_sqlite_core.text)("platform_channel_id").notNull(),
2604
+ platform_message_id: (0, import_sqlite_core.text)("platform_message_id").notNull(),
2605
+ platform_thread_id: (0, import_sqlite_core.text)("platform_thread_id").notNull(),
2606
+ platform_permalink: (0, import_sqlite_core.text)("platform_permalink"),
2607
+ target_branch_id: (0, import_sqlite_core.text)("target_branch_id", { length: 36 }).notNull().references(() => branches2.branch_id),
2608
+ emitted_by_user_id: (0, import_sqlite_core.text)("emitted_by_user_id", { length: 36 }).notNull().references(() => users2.user_id),
2609
+ emitted_by_session_id: (0, import_sqlite_core.text)("emitted_by_session_id", { length: 36 }).references(
2610
+ () => sessions2.session_id,
2611
+ {
2612
+ onDelete: "set null"
2613
+ }
2614
+ ),
2615
+ emitted_by_task_id: (0, import_sqlite_core.text)("emitted_by_task_id", { length: 36 }).references(() => tasks2.task_id, {
2616
+ onDelete: "set null"
2617
+ }),
2618
+ emitted_by_schedule_id: (0, import_sqlite_core.text)("emitted_by_schedule_id", { length: 36 }).references(
2619
+ () => schedules2.schedule_id,
2620
+ {
2621
+ onDelete: "set null"
2622
+ }
2623
+ ),
2624
+ message_text: (0, import_sqlite_core.text)("message_text").notNull(),
2625
+ message_preview: (0, import_sqlite_core.text)("message_preview").notNull(),
2626
+ metadata: t2.json("metadata"),
2627
+ consumed_by_session_id: (0, import_sqlite_core.text)("consumed_by_session_id", { length: 36 }).references(
2628
+ () => sessions2.session_id,
2629
+ {
2630
+ onDelete: "set null"
2631
+ }
2632
+ ),
2633
+ consumed_at: t2.timestamp("consumed_at")
2634
+ },
2635
+ (table) => ({
2636
+ uniqueChannelThread: (0, import_sqlite_core.uniqueIndex)("uniq_gateway_outbound_channel_thread").on(
2637
+ table.gateway_channel_id,
2638
+ table.platform_thread_id
2639
+ ),
2640
+ emittedSessionIdx: (0, import_sqlite_core.index)("idx_gateway_outbound_emitted_session").on(
2641
+ table.emitted_by_session_id
2642
+ ),
2643
+ emittedScheduleIdx: (0, import_sqlite_core.index)("idx_gateway_outbound_emitted_schedule").on(
2644
+ table.emitted_by_schedule_id
2645
+ ),
2646
+ targetBranchCreatedIdx: (0, import_sqlite_core.index)("idx_gateway_outbound_branch_created").on(
2647
+ table.target_branch_id,
2648
+ table.created_at
2649
+ ),
2650
+ consumedIdx: (0, import_sqlite_core.index)("idx_gateway_outbound_consumed").on(table.consumed_at)
2651
+ })
2652
+ );
2653
+ var sessionEnvSelections2 = (0, import_sqlite_core.sqliteTable)(
2654
+ "session_env_selections",
2655
+ {
2656
+ session_id: (0, import_sqlite_core.text)("session_id", { length: 36 }).notNull().references(() => sessions2.session_id, { onDelete: "cascade" }),
2657
+ env_var_name: (0, import_sqlite_core.text)("env_var_name").notNull(),
2658
+ created_at: t2.timestamp("created_at").notNull()
2659
+ },
2660
+ (table) => ({
2661
+ pk: (0, import_sqlite_core.primaryKey)({ columns: [table.session_id, table.env_var_name] }),
2662
+ sessionIdx: (0, import_sqlite_core.index)("session_env_selections_session_idx").on(table.session_id)
2663
+ })
2664
+ );
2665
+ var kbNamespaces2 = (0, import_sqlite_core.sqliteTable)(
2666
+ "kb_namespaces",
2667
+ {
2668
+ namespace_id: (0, import_sqlite_core.text)("namespace_id", { length: 36 }).primaryKey(),
2669
+ slug: (0, import_sqlite_core.text)("slug").notNull(),
2670
+ display_name: (0, import_sqlite_core.text)("display_name").notNull(),
2671
+ description: (0, import_sqlite_core.text)("description"),
2672
+ kind: (0, import_sqlite_core.text)("kind", { enum: ["system", "global", "user", "repo", "branch", "team"] }).notNull().default("global"),
2673
+ owner_user_id: (0, import_sqlite_core.text)("owner_user_id", { length: 36 }).references(() => users2.user_id, {
2674
+ onDelete: "set null"
2675
+ }),
2676
+ repo_id: (0, import_sqlite_core.text)("repo_id", { length: 36 }).references(() => repos2.repo_id, {
2677
+ onDelete: "set null"
2678
+ }),
2679
+ branch_id: (0, import_sqlite_core.text)("branch_id", { length: 36 }).references(() => branches2.branch_id, {
2680
+ onDelete: "set null"
2681
+ }),
2682
+ visibility_default: (0, import_sqlite_core.text)("visibility_default", { enum: ["public", "private"] }).notNull().default("public"),
2683
+ others_can: (0, import_sqlite_core.text)("others_can", { enum: ["none", "read", "write"] }).notNull().default("write"),
2684
+ metadata: t2.json("metadata"),
2685
+ created_by: (0, import_sqlite_core.text)("created_by", { length: 36 }).references(() => users2.user_id, {
2686
+ onDelete: "set null"
2687
+ }),
2688
+ created_at: t2.timestamp("created_at").notNull(),
2689
+ updated_at: t2.timestamp("updated_at"),
2690
+ archived: t2.bool("archived").notNull().default(false),
2691
+ archived_at: t2.timestamp("archived_at")
2692
+ },
2693
+ (table) => ({
2694
+ slugIdx: (0, import_sqlite_core.uniqueIndex)("kb_namespaces_slug_idx").on(table.slug).where(import_drizzle_orm3.sql`${table.archived} = false`),
2695
+ kindIdx: (0, import_sqlite_core.index)("kb_namespaces_kind_idx").on(table.kind),
2696
+ ownerIdx: (0, import_sqlite_core.index)("kb_namespaces_owner_idx").on(table.owner_user_id),
2697
+ repoIdx: (0, import_sqlite_core.index)("kb_namespaces_repo_idx").on(table.repo_id),
2698
+ branchIdx: (0, import_sqlite_core.index)("kb_namespaces_branch_idx").on(table.branch_id),
2699
+ archivedIdx: (0, import_sqlite_core.index)("kb_namespaces_archived_idx").on(table.archived)
2700
+ })
2701
+ );
2702
+ var kbNamespaceAcl2 = (0, import_sqlite_core.sqliteTable)(
2703
+ "kb_namespace_acl",
2704
+ {
2705
+ namespace_acl_id: (0, import_sqlite_core.text)("namespace_acl_id", { length: 36 }).primaryKey(),
2706
+ namespace_id: (0, import_sqlite_core.text)("namespace_id", { length: 36 }).notNull().references(() => kbNamespaces2.namespace_id, { onDelete: "cascade" }),
2707
+ subject_type: (0, import_sqlite_core.text)("subject_type", { enum: ["user", "group"] }).notNull(),
2708
+ subject_id: (0, import_sqlite_core.text)("subject_id", { length: 36 }).notNull(),
2709
+ permission: (0, import_sqlite_core.text)("permission", { enum: ["read", "write", "own"] }).notNull(),
2710
+ created_by: (0, import_sqlite_core.text)("created_by", { length: 36 }).references(() => users2.user_id, {
2711
+ onDelete: "set null"
2712
+ }),
2713
+ created_at: t2.timestamp("created_at").notNull(),
2714
+ updated_at: t2.timestamp("updated_at")
2715
+ },
2716
+ (table) => ({
2717
+ namespaceIdx: (0, import_sqlite_core.index)("kb_namespace_acl_namespace_idx").on(table.namespace_id),
2718
+ subjectIdx: (0, import_sqlite_core.index)("kb_namespace_acl_subject_idx").on(table.subject_type, table.subject_id),
2719
+ namespaceSubjectIdx: (0, import_sqlite_core.uniqueIndex)("kb_namespace_acl_namespace_subject_idx").on(
2720
+ table.namespace_id,
2721
+ table.subject_type,
2722
+ table.subject_id
2723
+ )
2724
+ })
2725
+ );
2726
+ var kbDocuments2 = (0, import_sqlite_core.sqliteTable)(
2727
+ "kb_documents",
2728
+ {
2729
+ document_id: (0, import_sqlite_core.text)("document_id", { length: 36 }).primaryKey(),
2730
+ namespace_id: (0, import_sqlite_core.text)("namespace_id", { length: 36 }).notNull().references(() => kbNamespaces2.namespace_id, { onDelete: "cascade" }),
2731
+ path: (0, import_sqlite_core.text)("path").notNull(),
2732
+ uri: (0, import_sqlite_core.text)("uri").notNull(),
2733
+ title: (0, import_sqlite_core.text)("title").notNull(),
2734
+ icon_emoji: (0, import_sqlite_core.text)("icon_emoji"),
2735
+ kind: (0, import_sqlite_core.text)("kind", {
2736
+ enum: ["doc", "memory", "skill", "prompt", "guide", "decision", "bundle", "external"]
2737
+ }).notNull().default("doc"),
2738
+ visibility: (0, import_sqlite_core.text)("visibility", { enum: ["public", "private"] }).notNull().default("public"),
2739
+ status: (0, import_sqlite_core.text)("status", { enum: ["draft", "published"] }).notNull().default("published"),
2740
+ edit_policy: (0, import_sqlite_core.text)("edit_policy", { enum: ["owner", "public", "admins"] }).notNull().default("owner"),
2741
+ // Application-maintained pointer. Avoids a circular FK with versions.
2742
+ current_version_id: (0, import_sqlite_core.text)("current_version_id", { length: 36 }),
2743
+ metadata: t2.json("metadata"),
2744
+ created_by: (0, import_sqlite_core.text)("created_by", { length: 36 }).references(() => users2.user_id, {
2745
+ onDelete: "set null"
2746
+ }),
2747
+ created_at: t2.timestamp("created_at").notNull(),
2748
+ updated_by: (0, import_sqlite_core.text)("updated_by", { length: 36 }).references(() => users2.user_id, {
2749
+ onDelete: "set null"
2750
+ }),
2751
+ updated_at: t2.timestamp("updated_at"),
2752
+ archived: t2.bool("archived").notNull().default(false),
2753
+ archived_at: t2.timestamp("archived_at")
2754
+ },
2755
+ (table) => ({
2756
+ namespacePathIdx: (0, import_sqlite_core.uniqueIndex)("kb_documents_namespace_path_idx").on(table.namespace_id, table.path).where(import_drizzle_orm3.sql`${table.archived} = false`),
2757
+ uriIdx: (0, import_sqlite_core.uniqueIndex)("kb_documents_uri_idx").on(table.uri).where(import_drizzle_orm3.sql`${table.archived} = false`),
2758
+ namespaceIdx: (0, import_sqlite_core.index)("kb_documents_namespace_idx").on(table.namespace_id),
2759
+ kindIdx: (0, import_sqlite_core.index)("kb_documents_kind_idx").on(table.kind),
2760
+ visibilityIdx: (0, import_sqlite_core.index)("kb_documents_visibility_idx").on(table.visibility),
2761
+ statusIdx: (0, import_sqlite_core.index)("kb_documents_status_idx").on(table.status),
2762
+ createdByIdx: (0, import_sqlite_core.index)("kb_documents_created_by_idx").on(table.created_by),
2763
+ updatedAtIdx: (0, import_sqlite_core.index)("kb_documents_updated_at_idx").on(table.updated_at),
2764
+ archivedIdx: (0, import_sqlite_core.index)("kb_documents_archived_idx").on(table.archived)
2765
+ })
2766
+ );
2767
+ var kbDocumentVersions2 = (0, import_sqlite_core.sqliteTable)(
2768
+ "kb_document_versions",
2769
+ {
2770
+ version_id: (0, import_sqlite_core.text)("version_id", { length: 36 }).primaryKey(),
2771
+ document_id: (0, import_sqlite_core.text)("document_id", { length: 36 }).notNull().references(() => kbDocuments2.document_id, { onDelete: "cascade" }),
2772
+ version_number: (0, import_sqlite_core.integer)("version_number").notNull(),
2773
+ content_text: (0, import_sqlite_core.text)("content_text"),
2774
+ content_blob: (0, import_sqlite_core.blob)("content_blob"),
2775
+ mime_type: (0, import_sqlite_core.text)("mime_type").notNull().default("text/markdown"),
2776
+ content_md5: (0, import_sqlite_core.text)("content_md5"),
2777
+ content_sha256: (0, import_sqlite_core.text)("content_sha256"),
2778
+ byte_length: (0, import_sqlite_core.integer)("byte_length"),
2779
+ char_length: (0, import_sqlite_core.integer)("char_length"),
2780
+ frontmatter: t2.json("frontmatter"),
2781
+ metadata: t2.json("metadata"),
2782
+ change_summary: (0, import_sqlite_core.text)("change_summary"),
2783
+ created_by: (0, import_sqlite_core.text)("created_by", { length: 36 }).references(() => users2.user_id, {
2784
+ onDelete: "set null"
2785
+ }),
2786
+ created_at: t2.timestamp("created_at").notNull()
2787
+ },
2788
+ (table) => ({
2789
+ documentVersionIdx: (0, import_sqlite_core.uniqueIndex)("kb_document_versions_document_version_idx").on(
2790
+ table.document_id,
2791
+ table.version_number
2792
+ ),
2793
+ documentIdx: (0, import_sqlite_core.index)("kb_document_versions_document_idx").on(table.document_id),
2794
+ createdIdx: (0, import_sqlite_core.index)("kb_document_versions_created_idx").on(table.created_at),
2795
+ md5Idx: (0, import_sqlite_core.index)("kb_document_versions_md5_idx").on(table.content_md5)
2796
+ })
2797
+ );
2798
+ var kbDocumentUnits2 = (0, import_sqlite_core.sqliteTable)(
2799
+ "kb_document_units",
2800
+ {
2801
+ unit_id: (0, import_sqlite_core.text)("unit_id", { length: 36 }).primaryKey(),
2802
+ document_id: (0, import_sqlite_core.text)("document_id", { length: 36 }).notNull().references(() => kbDocuments2.document_id, { onDelete: "cascade" }),
2803
+ version_id: (0, import_sqlite_core.text)("version_id", { length: 36 }).notNull().references(() => kbDocumentVersions2.version_id, { onDelete: "cascade" }),
2804
+ kind: (0, import_sqlite_core.text)("kind", { enum: ["document", "section", "file", "auto_split"] }).notNull().default("document"),
2805
+ ordinal: (0, import_sqlite_core.integer)("ordinal").notNull().default(0),
2806
+ path_anchor: (0, import_sqlite_core.text)("path_anchor"),
2807
+ heading_path: (0, import_sqlite_core.text)("heading_path"),
2808
+ source_path: (0, import_sqlite_core.text)("source_path"),
2809
+ content_text: (0, import_sqlite_core.text)("content_text"),
2810
+ content_md5: (0, import_sqlite_core.text)("content_md5"),
2811
+ start_offset: (0, import_sqlite_core.integer)("start_offset"),
2812
+ end_offset: (0, import_sqlite_core.integer)("end_offset"),
2813
+ embedding_status: (0, import_sqlite_core.text)("embedding_status", {
2814
+ enum: ["not_configured", "pending", "ready", "stale", "error"]
2815
+ }).notNull().default("not_configured"),
2816
+ embedding_model: (0, import_sqlite_core.text)("embedding_model"),
2817
+ embedding_dimensions: (0, import_sqlite_core.integer)("embedding_dimensions"),
2818
+ embedding_hash: (0, import_sqlite_core.text)("embedding_hash"),
2819
+ embedding_error: (0, import_sqlite_core.text)("embedding_error"),
2820
+ metadata: t2.json("metadata"),
2821
+ created_at: t2.timestamp("created_at").notNull(),
2822
+ updated_at: t2.timestamp("updated_at")
2823
+ },
2824
+ (table) => ({
2825
+ documentIdx: (0, import_sqlite_core.index)("kb_document_units_document_idx").on(table.document_id),
2826
+ versionIdx: (0, import_sqlite_core.index)("kb_document_units_version_idx").on(table.version_id),
2827
+ versionOrdinalIdx: (0, import_sqlite_core.index)("kb_document_units_version_ordinal_idx").on(
2828
+ table.version_id,
2829
+ table.ordinal
2830
+ ),
2831
+ contentHashIdx: (0, import_sqlite_core.index)("kb_document_units_content_hash_idx").on(table.content_md5),
2832
+ embeddingStatusIdx: (0, import_sqlite_core.index)("kb_document_units_embedding_status_idx").on(table.embedding_status)
2833
+ })
2834
+ );
2835
+ var kbEmbeddingSpaces2 = (0, import_sqlite_core.sqliteTable)(
2836
+ "kb_embedding_spaces",
2837
+ {
2838
+ embedding_space_id: (0, import_sqlite_core.text)("embedding_space_id", { length: 36 }).primaryKey(),
2839
+ provider: (0, import_sqlite_core.text)("provider").notNull(),
2840
+ model: (0, import_sqlite_core.text)("model").notNull(),
2841
+ dimensions: (0, import_sqlite_core.integer)("dimensions").notNull(),
2842
+ storage_type: (0, import_sqlite_core.text)("storage_type").notNull().default("vector"),
2843
+ distance: (0, import_sqlite_core.text)("distance").notNull().default("cosine"),
2844
+ active: t2.bool("active").notNull().default(true),
2845
+ metadata: t2.json("metadata"),
2846
+ created_at: t2.timestamp("created_at").notNull(),
2847
+ updated_at: t2.timestamp("updated_at")
2848
+ },
2849
+ (table) => ({
2850
+ providerModelIdx: (0, import_sqlite_core.uniqueIndex)("kb_embedding_spaces_provider_model_idx").on(
2851
+ table.provider,
2852
+ table.model,
2853
+ table.dimensions,
2854
+ table.storage_type,
2855
+ table.distance
2856
+ ),
2857
+ activeIdx: (0, import_sqlite_core.index)("kb_embedding_spaces_active_idx").on(table.active)
2858
+ })
2859
+ );
2860
+ var kbGraphNodes2 = (0, import_sqlite_core.sqliteTable)(
2861
+ "kb_graph_nodes",
2862
+ {
2863
+ node_id: (0, import_sqlite_core.text)("node_id", { length: 36 }).primaryKey(),
2864
+ node_type: (0, import_sqlite_core.text)("node_type", {
2865
+ enum: [
2866
+ "namespace",
2867
+ "document",
2868
+ "document_unit",
2869
+ "branch",
2870
+ "session",
2871
+ "task",
2872
+ "message",
2873
+ "artifact",
2874
+ "repo",
2875
+ "board",
2876
+ "user",
2877
+ "tag",
2878
+ "external"
2879
+ ]
2880
+ }).notNull(),
2881
+ uri: (0, import_sqlite_core.text)("uri").notNull(),
2882
+ label: (0, import_sqlite_core.text)("label"),
2883
+ namespace_id: (0, import_sqlite_core.text)("namespace_id", { length: 36 }).references(() => kbNamespaces2.namespace_id, {
2884
+ onDelete: "cascade"
2885
+ }),
2886
+ document_id: (0, import_sqlite_core.text)("document_id", { length: 36 }).references(() => kbDocuments2.document_id, {
2887
+ onDelete: "cascade"
2888
+ }),
2889
+ unit_id: (0, import_sqlite_core.text)("unit_id", { length: 36 }).references(() => kbDocumentUnits2.unit_id, {
2890
+ onDelete: "cascade"
2891
+ }),
2892
+ branch_id: (0, import_sqlite_core.text)("branch_id", { length: 36 }).references(() => branches2.branch_id, {
2893
+ onDelete: "cascade"
2894
+ }),
2895
+ session_id: (0, import_sqlite_core.text)("session_id", { length: 36 }).references(() => sessions2.session_id, {
2896
+ onDelete: "cascade"
2897
+ }),
2898
+ task_id: (0, import_sqlite_core.text)("task_id", { length: 36 }).references(() => tasks2.task_id, {
2899
+ onDelete: "cascade"
2900
+ }),
2901
+ message_id: (0, import_sqlite_core.text)("message_id", { length: 36 }).references(() => messages2.message_id, {
2902
+ onDelete: "cascade"
2903
+ }),
2904
+ artifact_id: (0, import_sqlite_core.text)("artifact_id", { length: 36 }).references(() => artifacts2.artifact_id, {
2905
+ onDelete: "cascade"
2906
+ }),
2907
+ repo_id: (0, import_sqlite_core.text)("repo_id", { length: 36 }).references(() => repos2.repo_id, {
2908
+ onDelete: "cascade"
2909
+ }),
2910
+ board_id: (0, import_sqlite_core.text)("board_id", { length: 36 }).references(() => boards2.board_id, {
2911
+ onDelete: "cascade"
2912
+ }),
2913
+ user_id: (0, import_sqlite_core.text)("user_id", { length: 36 }).references(() => users2.user_id, {
2914
+ onDelete: "cascade"
2915
+ }),
2916
+ external_uri: (0, import_sqlite_core.text)("external_uri"),
2917
+ metadata: t2.json("metadata"),
2918
+ created_by: (0, import_sqlite_core.text)("created_by", { length: 36 }).references(() => users2.user_id, {
2919
+ onDelete: "set null"
2920
+ }),
2921
+ created_at: t2.timestamp("created_at").notNull(),
2922
+ updated_at: t2.timestamp("updated_at"),
2923
+ archived: t2.bool("archived").notNull().default(false),
2924
+ archived_at: t2.timestamp("archived_at")
2925
+ },
2926
+ (table) => ({
2927
+ uriIdx: (0, import_sqlite_core.uniqueIndex)("kb_graph_nodes_uri_idx").on(table.uri).where(import_drizzle_orm3.sql`${table.archived} = false`),
2928
+ typeIdx: (0, import_sqlite_core.index)("kb_graph_nodes_type_idx").on(table.node_type),
2929
+ namespaceIdx: (0, import_sqlite_core.index)("kb_graph_nodes_namespace_idx").on(table.namespace_id),
2930
+ documentIdx: (0, import_sqlite_core.index)("kb_graph_nodes_document_idx").on(table.document_id),
2931
+ unitIdx: (0, import_sqlite_core.index)("kb_graph_nodes_unit_idx").on(table.unit_id),
2932
+ branchIdx: (0, import_sqlite_core.index)("kb_graph_nodes_branch_idx").on(table.branch_id),
2933
+ sessionIdx: (0, import_sqlite_core.index)("kb_graph_nodes_session_idx").on(table.session_id),
2934
+ taskIdx: (0, import_sqlite_core.index)("kb_graph_nodes_task_idx").on(table.task_id),
2935
+ messageIdx: (0, import_sqlite_core.index)("kb_graph_nodes_message_idx").on(table.message_id),
2936
+ artifactIdx: (0, import_sqlite_core.index)("kb_graph_nodes_artifact_idx").on(table.artifact_id),
2937
+ repoIdx: (0, import_sqlite_core.index)("kb_graph_nodes_repo_idx").on(table.repo_id),
2938
+ boardIdx: (0, import_sqlite_core.index)("kb_graph_nodes_board_idx").on(table.board_id),
2939
+ userIdx: (0, import_sqlite_core.index)("kb_graph_nodes_user_idx").on(table.user_id),
2940
+ externalUriIdx: (0, import_sqlite_core.index)("kb_graph_nodes_external_uri_idx").on(table.external_uri),
2941
+ archivedIdx: (0, import_sqlite_core.index)("kb_graph_nodes_archived_idx").on(table.archived)
2942
+ })
2943
+ );
2944
+ var kbGraphEdges2 = (0, import_sqlite_core.sqliteTable)(
2945
+ "kb_graph_edges",
2946
+ {
2947
+ edge_id: (0, import_sqlite_core.text)("edge_id", { length: 36 }).primaryKey(),
2948
+ source_node_id: (0, import_sqlite_core.text)("source_node_id", { length: 36 }).notNull().references(() => kbGraphNodes2.node_id, { onDelete: "cascade" }),
2949
+ target_node_id: (0, import_sqlite_core.text)("target_node_id", { length: 36 }).notNull().references(() => kbGraphNodes2.node_id, { onDelete: "cascade" }),
2950
+ edge_type: (0, import_sqlite_core.text)("edge_type", {
2951
+ enum: [
2952
+ "contains",
2953
+ "references",
2954
+ "mentions",
2955
+ "implements",
2956
+ "depends_on",
2957
+ "supersedes",
2958
+ "derived_from",
2959
+ "tagged_with",
2960
+ "about",
2961
+ "parent_of",
2962
+ "related_to"
2963
+ ]
2964
+ }).notNull(),
2965
+ confidence: (0, import_sqlite_core.integer)("confidence"),
2966
+ properties: t2.json("properties"),
2967
+ created_by: (0, import_sqlite_core.text)("created_by", { length: 36 }).references(() => users2.user_id, {
2968
+ onDelete: "set null"
2969
+ }),
2970
+ created_at: t2.timestamp("created_at").notNull(),
2971
+ archived: t2.bool("archived").notNull().default(false),
2972
+ archived_at: t2.timestamp("archived_at")
2973
+ },
2974
+ (table) => ({
2975
+ sourceIdx: (0, import_sqlite_core.index)("kb_graph_edges_source_idx").on(table.source_node_id),
2976
+ targetIdx: (0, import_sqlite_core.index)("kb_graph_edges_target_idx").on(table.target_node_id),
2977
+ typeIdx: (0, import_sqlite_core.index)("kb_graph_edges_type_idx").on(table.edge_type),
2978
+ sourceTypeIdx: (0, import_sqlite_core.index)("kb_graph_edges_source_type_idx").on(
2979
+ table.source_node_id,
2980
+ table.edge_type
2981
+ ),
2982
+ targetTypeIdx: (0, import_sqlite_core.index)("kb_graph_edges_target_type_idx").on(
2983
+ table.target_node_id,
2984
+ table.edge_type
2985
+ ),
2986
+ sourceTargetTypeIdx: (0, import_sqlite_core.uniqueIndex)("kb_graph_edges_source_target_type_idx").on(table.source_node_id, table.target_node_id, table.edge_type).where(import_drizzle_orm3.sql`${table.archived} = false`),
2987
+ archivedIdx: (0, import_sqlite_core.index)("kb_graph_edges_archived_idx").on(table.archived)
2988
+ })
2989
+ );
2990
+ var sessionsRelations2 = (0, import_drizzle_orm3.relations)(sessions2, ({ one, many }) => ({
2991
+ branch: one(branches2, {
2992
+ fields: [sessions2.branch_id],
2993
+ references: [branches2.branch_id]
2994
+ }),
2995
+ schedule: one(schedules2, {
2996
+ fields: [sessions2.schedule_id],
2997
+ references: [schedules2.schedule_id]
2998
+ }),
2999
+ outboundRelationships: many(sessionRelationships2, { relationName: "relationshipSource" }),
3000
+ inboundRelationships: many(sessionRelationships2, { relationName: "relationshipTarget" })
3001
+ }));
3002
+ var sessionRelationshipsRelations2 = (0, import_drizzle_orm3.relations)(sessionRelationships2, ({ one }) => ({
3003
+ sourceSession: one(sessions2, {
3004
+ fields: [sessionRelationships2.source_session_id],
3005
+ references: [sessions2.session_id],
3006
+ relationName: "relationshipSource"
3007
+ }),
3008
+ targetSession: one(sessions2, {
3009
+ fields: [sessionRelationships2.target_session_id],
3010
+ references: [sessions2.session_id],
3011
+ relationName: "relationshipTarget"
3012
+ }),
3013
+ callbackSession: one(sessions2, {
3014
+ fields: [sessionRelationships2.callback_session_id],
3015
+ references: [sessions2.session_id]
3016
+ })
3017
+ }));
3018
+ var branchesRelations2 = (0, import_drizzle_orm3.relations)(branches2, ({ many }) => ({
3019
+ sessions: many(sessions2),
3020
+ schedules: many(schedules2)
3021
+ }));
3022
+ var schedulesRelations2 = (0, import_drizzle_orm3.relations)(schedules2, ({ one, many }) => ({
3023
+ branch: one(branches2, {
3024
+ fields: [schedules2.branch_id],
3025
+ references: [branches2.branch_id]
3026
+ }),
3027
+ sessions: many(sessions2)
3028
+ }));
3029
+
3030
+ // src/config/config-manager.ts
3031
+ var import_node_fs = require("fs");
3032
+ var import_promises = __toESM(require("fs/promises"), 1);
3033
+ var import_node_os = __toESM(require("os"), 1);
3034
+ var import_node_path = __toESM(require("path"), 1);
3035
+ var yaml = __toESM(require("js-yaml"), 1);
3036
+
3037
+ // src/config/analytics-defaults.ts
3038
+ function getDefaultAnalyticsConfig() {
3039
+ return {
3040
+ enabled: false,
3041
+ client: {
3042
+ app: "agor-daemon",
3043
+ version: "dev",
3044
+ debug: false
3045
+ },
3046
+ filters: {
3047
+ exclude_events: []
3048
+ },
3049
+ plugins: [
3050
+ {
3051
+ type: "stdout",
3052
+ enabled: false,
3053
+ options: {
3054
+ pretty: false
3055
+ }
3056
+ },
3057
+ {
3058
+ type: "http_batch",
3059
+ enabled: false,
3060
+ options: {
3061
+ url: null,
3062
+ flush_interval_ms: 1e3,
3063
+ max_batch_size: 50,
3064
+ timeout_ms: 3e3,
3065
+ headers: {}
3066
+ }
3067
+ },
3068
+ {
3069
+ type: "module",
3070
+ enabled: false,
3071
+ options: {
3072
+ module_path: null,
3073
+ export_name: "createAnalyticsPlugin",
3074
+ plugin_options: {}
3075
+ }
3076
+ }
3077
+ ]
3078
+ };
3079
+ }
3080
+
3081
+ // src/config/constants.ts
3082
+ var DAEMON = {
3083
+ /**
3084
+ * Default daemon port
3085
+ */
3086
+ DEFAULT_PORT: 3030,
3087
+ /**
3088
+ * Default daemon host
3089
+ */
3090
+ DEFAULT_HOST: "localhost"
3091
+ };
3092
+ var MCP_TOKEN = {
3093
+ /**
3094
+ * Default lifetime for internal MCP session tokens in milliseconds.
3095
+ * Keep short to bound the blast radius of a leaked token — there is no
3096
+ * revocation mechanism; `exp` is the only backstop.
3097
+ */
3098
+ DEFAULT_EXPIRATION_MS: 24 * 60 * 60 * 1e3
3099
+ // 24 hours
3100
+ };
3101
+
3102
+ // src/config/executor-heartbeat.ts
3103
+ var EXECUTOR_HEARTBEAT_DEFAULT_INTERVAL_MS = 1e4;
3104
+ var EXECUTOR_HEARTBEAT_MIN_STALE_AFTER_MS = 3e4;
3105
+ var EXECUTOR_HEARTBEAT_DEFAULT_CALLBACK_TIMEOUT_MS = 3e3;
3106
+ function positiveIntegerOrDefault(value, fallback) {
3107
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
3108
+ }
3109
+ function resolveExecutorHeartbeatConfig(execution) {
3110
+ const raw = execution?.executor_heartbeat;
3111
+ const intervalMs = positiveIntegerOrDefault(
3112
+ raw?.interval_ms,
3113
+ EXECUTOR_HEARTBEAT_DEFAULT_INTERVAL_MS
3114
+ );
3115
+ const staleAfterMs = positiveIntegerOrDefault(
3116
+ raw?.stale_after_ms,
3117
+ Math.max(3 * intervalMs, EXECUTOR_HEARTBEAT_MIN_STALE_AFTER_MS)
3118
+ );
3119
+ const timeoutMs = positiveIntegerOrDefault(
3120
+ raw?.callback?.timeout_ms,
3121
+ EXECUTOR_HEARTBEAT_DEFAULT_CALLBACK_TIMEOUT_MS
3122
+ );
3123
+ return {
3124
+ // Default enabled: the heartbeat is a lightweight task-row timestamp patch,
3125
+ // and callback execution remains opt-in via command_template.
3126
+ enabled: raw?.enabled ?? true,
3127
+ interval_ms: intervalMs,
3128
+ stale_after_ms: staleAfterMs,
3129
+ callback: {
3130
+ command_template: raw?.callback?.command_template ?? null,
3131
+ timeout_ms: timeoutMs
3132
+ }
3133
+ };
3134
+ }
3135
+
3136
+ // src/config/multitenancy.ts
3137
+ var DEFAULT_STATIC_TENANT_ID = "default";
3138
+ var RESERVED_AUTH_CLAIMS = /* @__PURE__ */ new Set(["aud", "exp", "iat", "iss", "jti", "nbf", "sub", "type"]);
3139
+ function detectPostgresUrl(url) {
3140
+ if (!url) return false;
3141
+ const lower = url.toLowerCase();
3142
+ return lower.startsWith("postgresql://") || lower.startsWith("postgres://") || lower.startsWith("pg://");
3143
+ }
3144
+ function resolveMultiTenancyDatabaseDialect(config = {}) {
3145
+ if (process.env.AGOR_DB_DIALECT === "postgresql" || process.env.AGOR_DB_DIALECT === "sqlite") {
3146
+ return process.env.AGOR_DB_DIALECT;
3147
+ }
3148
+ if (detectPostgresUrl(process.env.DATABASE_URL)) return "postgresql";
3149
+ if (config.database?.dialect === "postgresql" || config.database?.dialect === "sqlite") {
3150
+ return config.database.dialect;
3151
+ }
3152
+ if (detectPostgresUrl(config.database?.postgresql?.url) || config.database?.postgresql?.host) {
3153
+ return "postgresql";
3154
+ }
3155
+ return "sqlite";
3156
+ }
3157
+ function resolveMultiTenancyConfig(config) {
3158
+ const raw = config.multi_tenancy ?? {};
3159
+ const mode = raw.mode ?? "static";
3160
+ return {
3161
+ mode,
3162
+ static_tenant_id: raw.static_tenant_id?.trim() || DEFAULT_STATIC_TENANT_ID,
3163
+ ...raw.auth_claim ? { auth_claim: raw.auth_claim } : {},
3164
+ ...raw.trusted_header ? { trusted_header: raw.trusted_header } : {}
3165
+ };
3166
+ }
3167
+ function assertValidMultiTenancyConfig(config) {
3168
+ const resolved = resolveMultiTenancyConfig(config);
3169
+ if (resolved.mode !== "static" && resolved.mode !== "required_from_auth") {
3170
+ throw new Error("Config error: multi_tenancy.mode must be one of: static, required_from_auth");
3171
+ }
3172
+ if (!resolved.static_tenant_id) {
3173
+ throw new Error("Config error: multi_tenancy.static_tenant_id must not be empty");
3174
+ }
3175
+ if (resolved.auth_claim && RESERVED_AUTH_CLAIMS.has(resolved.auth_claim)) {
3176
+ throw new Error(
3177
+ `Config error: multi_tenancy.auth_claim cannot be reserved JWT claim '${resolved.auth_claim}'`
3178
+ );
3179
+ }
3180
+ if (resolved.mode === "required_from_auth") {
3181
+ if (resolveMultiTenancyDatabaseDialect(config) !== "postgresql") {
3182
+ throw new Error(
3183
+ "Config error: multi_tenancy.required_from_auth requires database.dialect: postgresql"
3184
+ );
3185
+ }
3186
+ if (!resolved.auth_claim && !resolved.trusted_header) {
3187
+ throw new Error(
3188
+ "Config error: multi_tenancy.required_from_auth requires multi_tenancy.auth_claim or multi_tenancy.trusted_header"
3189
+ );
3190
+ }
3191
+ }
3192
+ }
3193
+
3194
+ // src/config/config-manager.ts
3195
+ var NO_FILE = -1;
3196
+ var NO_FILE_KEY = { mtimeMs: NO_FILE, size: 0 };
3197
+ var cachedEntry = null;
3198
+ function cacheKeyMatches(a, b) {
3199
+ return a.mtimeMs === b.mtimeMs && a.size === b.size;
3200
+ }
3201
+ function statCacheKey(configPath) {
3202
+ try {
3203
+ const stat = (0, import_node_fs.statSync)(configPath);
3204
+ return { mtimeMs: stat.mtimeMs, size: stat.size };
3205
+ } catch (error) {
3206
+ if (error.code === "ENOENT") {
3207
+ return NO_FILE_KEY;
3208
+ }
3209
+ return null;
3210
+ }
3211
+ }
3212
+ function readCachedConfig(configPath) {
3213
+ if (cachedEntry === null || cachedEntry.path !== configPath) {
3214
+ return null;
3215
+ }
3216
+ const currentKey = statCacheKey(configPath);
3217
+ if (currentKey === null || !cacheKeyMatches(currentKey, cachedEntry.key)) {
3218
+ return null;
3219
+ }
3220
+ return structuredClone(cachedEntry.config);
3221
+ }
3222
+ function writeCachedConfig(configPath, config, key) {
3223
+ cachedEntry = { path: configPath, config: structuredClone(config), key };
3224
+ }
3225
+ function parseAndValidateConfig(content) {
3226
+ if (content.trim() === "") {
3227
+ return {};
3228
+ }
3229
+ const parsed = yaml.load(content);
3230
+ const finalConfig = parsed || {};
3231
+ validateConfig(finalConfig);
3232
+ return finalConfig;
3233
+ }
3234
+ function getAgorHome() {
3235
+ return import_node_path.default.join(import_node_os.default.homedir(), ".agor");
3236
+ }
3237
+ function getConfigPath() {
3238
+ return import_node_path.default.join(getAgorHome(), "config.yaml");
3239
+ }
3240
+ function validateConfig(config) {
3241
+ const mode = config.execution?.unix_user_mode;
3242
+ if (mode === "opportunistic") {
3243
+ throw new Error(
3244
+ `Config error: 'opportunistic' unix_user_mode has been deprecated.
3245
+ Please update your config to use one of:
3246
+ - 'insulated': Filesystem isolation via Unix groups (recommended)
3247
+ - 'strict': Full process impersonation required
3248
+
3249
+ To update: agor config set execution.unix_user_mode insulated`
3250
+ );
3251
+ }
3252
+ const managedEnvExecutionMode = config.execution?.managed_envs_execution_mode;
3253
+ if (managedEnvExecutionMode !== void 0 && managedEnvExecutionMode !== "hybrid" && managedEnvExecutionMode !== "webhook-only") {
3254
+ throw new Error(
3255
+ `Config error: execution.managed_envs_execution_mode must be one of: hybrid, webhook-only`
3256
+ );
3257
+ }
3258
+ assertValidMultiTenancyConfig(config);
3259
+ validateOptionalHttpUrl(
3260
+ config.external_launch,
3261
+ "login_redirect_url",
3262
+ "external_launch.login_redirect_url"
3263
+ );
3264
+ }
3265
+ function validateOptionalHttpUrl(container, key, configPath) {
3266
+ if (!container || container[key] === void 0) return;
3267
+ const raw = container[key];
3268
+ if (typeof raw !== "string") {
3269
+ throw new Error(`Config error: ${configPath} must be an HTTP(S) URL string`);
3270
+ }
3271
+ container[key] = validateHttpUrlString(raw, configPath);
3272
+ }
3273
+ function validateHttpUrlString(url, label, options = {}) {
3274
+ const trimmed = options.stripTrailingSlash ? url.trim().replace(/\/$/, "") : url.trim();
3275
+ if (!trimmed.startsWith("http://") && !trimmed.startsWith("https://")) {
3276
+ throw new Error(`Invalid ${label}: "${url}". Must start with http:// or https://`);
3277
+ }
3278
+ let parsed;
3279
+ try {
3280
+ parsed = new URL(trimmed);
3281
+ } catch {
3282
+ throw new Error(`Invalid ${label} format: "${url}". Must be a valid HTTP(S) URL.`);
3283
+ }
3284
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
3285
+ throw new Error(`Invalid ${label}: "${url}". Must use http:// or https://`);
3286
+ }
3287
+ return trimmed;
3288
+ }
3289
+ function getDefaultConfig() {
3290
+ return {
3291
+ defaults: {
3292
+ board: "main",
3293
+ agent: "claude-code"
3294
+ },
3295
+ display: {
3296
+ tableStyle: "unicode",
3297
+ colorOutput: true
3298
+ },
3299
+ daemon: {
3300
+ port: DAEMON.DEFAULT_PORT,
3301
+ host: DAEMON.DEFAULT_HOST,
3302
+ mcpEnabled: true
3303
+ // Default: Enable built-in MCP server
3304
+ },
3305
+ ui: {
3306
+ port: 5173,
3307
+ host: "localhost"
3308
+ },
3309
+ execution: {
3310
+ session_token_expiration_ms: 864e5,
3311
+ // 24 hours
3312
+ session_token_max_uses: 1,
3313
+ // Single-use tokens
3314
+ mcp_token_expiration_ms: MCP_TOKEN.DEFAULT_EXPIRATION_MS,
3315
+ sync_unix_passwords: true,
3316
+ // Default: sync passwords to Unix
3317
+ executor_heartbeat: resolveExecutorHeartbeatConfig()
3318
+ },
3319
+ analytics: getDefaultAnalyticsConfig(),
3320
+ telemetry: {},
3321
+ multi_tenancy: {
3322
+ mode: "static",
3323
+ static_tenant_id: "default"
3324
+ }
3325
+ };
3326
+ }
3327
+ function loadConfigSync() {
3328
+ const configPath = getConfigPath();
3329
+ const cached = readCachedConfig(configPath);
3330
+ if (cached !== null) {
3331
+ return cached;
3332
+ }
3333
+ let beforeKey;
3334
+ let content;
3335
+ let afterKey;
3336
+ try {
3337
+ beforeKey = statCacheKey(configPath);
3338
+ if (beforeKey?.mtimeMs === NO_FILE) {
3339
+ const defaults = getDefaultConfig();
3340
+ writeCachedConfig(configPath, defaults, NO_FILE_KEY);
3341
+ return defaults;
3342
+ }
3343
+ content = (0, import_node_fs.readFileSync)(configPath, "utf-8");
3344
+ afterKey = statCacheKey(configPath);
3345
+ } catch (error) {
3346
+ if (error.code === "ENOENT") {
3347
+ const defaults = getDefaultConfig();
3348
+ writeCachedConfig(configPath, defaults, NO_FILE_KEY);
3349
+ return defaults;
3350
+ }
3351
+ throw new Error(
3352
+ `Failed to load config: ${error instanceof Error ? error.message : String(error)}`
3353
+ );
3354
+ }
3355
+ let finalConfig;
3356
+ try {
3357
+ finalConfig = parseAndValidateConfig(content);
3358
+ } catch (error) {
3359
+ throw new Error(
3360
+ `Failed to load config: ${error instanceof Error ? error.message : String(error)}`
3361
+ );
3362
+ }
3363
+ if (beforeKey !== null && afterKey !== null && cacheKeyMatches(beforeKey, afterKey)) {
3364
+ writeCachedConfig(configPath, finalConfig, beforeKey);
3365
+ }
3366
+ return finalConfig;
3367
+ }
3368
+
3369
+ // src/db/schema-factory.ts
3370
+ function detectDialectFromUrl(url) {
3371
+ if (!url) return null;
3372
+ const lowerUrl = url.toLowerCase();
3373
+ if (lowerUrl.startsWith("postgresql://") || lowerUrl.startsWith("postgres://") || lowerUrl.startsWith("pg://")) {
3374
+ return "postgresql";
3375
+ }
3376
+ if (lowerUrl.startsWith("file:") || lowerUrl.startsWith("libsql://") || lowerUrl.startsWith("http://") || lowerUrl.startsWith("https://")) {
3377
+ return "sqlite";
3378
+ }
3379
+ return null;
3380
+ }
3381
+ function getDatabaseDialect() {
3382
+ const envDialect = process.env.AGOR_DB_DIALECT;
3383
+ if (envDialect === "postgresql" || envDialect === "sqlite") {
3384
+ return envDialect;
3385
+ }
3386
+ const databaseUrl = process.env.DATABASE_URL;
3387
+ if (databaseUrl) {
3388
+ const detected = detectDialectFromUrl(databaseUrl);
3389
+ if (detected) {
3390
+ return detected;
3391
+ }
3392
+ }
3393
+ try {
3394
+ const config = loadConfigSync();
3395
+ if (config.database?.dialect === "postgresql" || config.database?.dialect === "sqlite") {
3396
+ return config.database.dialect;
3397
+ }
3398
+ if (config.database?.postgresql?.url) {
3399
+ const detected = detectDialectFromUrl(config.database.postgresql.url);
3400
+ if (detected) return detected;
3401
+ }
3402
+ } catch {
3403
+ }
3404
+ return "sqlite";
3405
+ }
3406
+
3407
+ // src/db/schema.ts
3408
+ var dialect = getDatabaseDialect();
3409
+ var schema = dialect === "postgresql" ? schema_postgres_exports : schema_sqlite_exports;
3410
+ var sessions3 = schema.sessions;
3411
+ var tasks3 = schema.tasks;
3412
+ var messages3 = schema.messages;
3413
+ var boards3 = schema.boards;
3414
+ var repos3 = schema.repos;
3415
+ var branches3 = schema.branches;
3416
+ var branchOwners3 = schema.branchOwners;
3417
+ var boardOwners3 = schema.boardOwners;
3418
+ var groups3 = schema.groups;
3419
+ var groupMemberships3 = schema.groupMemberships;
3420
+ var branchGroupGrants3 = schema.branchGroupGrants;
3421
+ var boardGroupGrants3 = schema.boardGroupGrants;
3422
+ var schedules3 = schema.schedules;
3423
+ var users3 = schema.users;
3424
+ var appVariables3 = schema.appVariables;
3425
+ var mcpServers3 = schema.mcpServers;
3426
+ var cardTypes3 = schema.cardTypes;
3427
+ var cards3 = schema.cards;
3428
+ var artifacts3 = schema.artifacts;
3429
+ var artifactTrustGrants3 = schema.artifactTrustGrants;
3430
+ var boardObjects3 = schema.boardObjects;
3431
+ var sessionMcpServers3 = schema.sessionMcpServers;
3432
+ var sessionRelationships3 = schema.sessionRelationships;
3433
+ var sessionEnvSelections3 = schema.sessionEnvSelections;
3434
+ var userMcpOauthTokens3 = schema.userMcpOauthTokens;
3435
+ var boardComments3 = schema.boardComments;
3436
+ var gatewayChannels3 = schema.gatewayChannels;
3437
+ var threadSessionMap3 = schema.threadSessionMap;
3438
+ var gatewayOutboundMessages3 = schema.gatewayOutboundMessages;
3439
+ var userApiKeys3 = schema.userApiKeys;
3440
+ var serializedSessions3 = schema.serializedSessions;
3441
+ var kbNamespaces3 = schema.kbNamespaces;
3442
+ var kbNamespaceAcl3 = schema.kbNamespaceAcl;
3443
+ var kbDocuments3 = schema.kbDocuments;
3444
+ var kbDocumentVersions3 = schema.kbDocumentVersions;
3445
+ var kbDocumentUnits3 = schema.kbDocumentUnits;
3446
+ var kbEmbeddingSpaces3 = schema.kbEmbeddingSpaces;
3447
+ var kbGraphNodes3 = schema.kbGraphNodes;
3448
+ var kbGraphEdges3 = schema.kbGraphEdges;
3449
+
3450
+ // src/lib/ids.ts
3451
+ var import_node_crypto2 = require("crypto");
3452
+ var import_uuid = require("uuid");
3453
+
3454
+ // src/config/env-blocklist.ts
3455
+ var BLOCKED_ENV_PATTERNS = Object.freeze([
3456
+ /^LD_/i,
3457
+ /^DYLD_/i,
3458
+ /^PYTHON(?!_AGOR_)/i
3459
+ ]);
3460
+
3461
+ // src/config/env-vars.ts
3462
+ var V05_SCOPES = ["global", "session"];
3463
+ var V05_SCOPE_SET = new Set(V05_SCOPES);
3464
+
3465
+ // src/templates/handlebars-helpers.ts
3466
+ var import_handlebars = __toESM(require("handlebars"), 1);
3467
+
3468
+ // src/mcp/template-patterns.ts
3469
+ var USER_ENV_PLACEHOLDER_RE = /^\{\{\s*user\.env\.[A-Za-z_][A-Za-z0-9_]*\s*\}\}$/;
3470
+ function isUserEnvPlaceholder(value) {
3471
+ return USER_ENV_PLACEHOLDER_RE.test(value.trim());
3472
+ }
3473
+
3474
+ // src/mcp/template-resolver.ts
3475
+ var TEMPLATE_RESOLVABLE_MCP_AUTH_SECRET_FIELDS = [
3476
+ "token",
3477
+ "api_token",
3478
+ "api_secret",
3479
+ "oauth_client_secret"
3480
+ ];
3481
+
29
3482
  // src/tools/mcp/http-headers.ts
30
3483
  var MCP_HEADER_REDACTED_SENTINEL = "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
31
3484
 
@@ -43,11 +3496,15 @@ function redactMCPAuthSecrets(auth) {
43
3496
  let changed = false;
44
3497
  const redacted = { ...auth };
45
3498
  const record = redacted;
3499
+ const templateResolvable = new Set(TEMPLATE_RESOLVABLE_MCP_AUTH_SECRET_FIELDS);
46
3500
  for (const field of MCP_AUTH_SECRET_FIELDS) {
47
- if (redacted[field] !== void 0) {
48
- record[field] = MCP_HEADER_REDACTED_SENTINEL;
49
- changed = true;
3501
+ const value = redacted[field];
3502
+ if (value === void 0) continue;
3503
+ if (templateResolvable.has(field) && typeof value === "string" && isUserEnvPlaceholder(value)) {
3504
+ continue;
50
3505
  }
3506
+ record[field] = MCP_HEADER_REDACTED_SENTINEL;
3507
+ changed = true;
51
3508
  }
52
3509
  return changed ? redacted : auth;
53
3510
  }