agor-live 0.21.2 → 0.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (974) hide show
  1. package/dist/cli/commands/admin/add-to-branch-group.d.ts +2 -13
  2. package/dist/cli/commands/admin/add-to-branch-group.d.ts.map +1 -1
  3. package/dist/cli/commands/admin/add-to-branch-group.js +133 -33
  4. package/dist/cli/commands/admin/create-branch-group.d.ts +2 -13
  5. package/dist/cli/commands/admin/create-branch-group.d.ts.map +1 -1
  6. package/dist/cli/commands/admin/create-branch-group.js +132 -38
  7. package/dist/cli/commands/admin/create-symlink.d.ts +2 -14
  8. package/dist/cli/commands/admin/create-symlink.d.ts.map +1 -1
  9. package/dist/cli/commands/admin/create-symlink.js +138 -61
  10. package/dist/cli/commands/admin/delete-branch-group.d.ts +2 -13
  11. package/dist/cli/commands/admin/delete-branch-group.d.ts.map +1 -1
  12. package/dist/cli/commands/admin/delete-branch-group.js +132 -28
  13. package/dist/cli/commands/admin/delete-user.d.ts +2 -13
  14. package/dist/cli/commands/admin/delete-user.d.ts.map +1 -1
  15. package/dist/cli/commands/admin/delete-user.js +132 -38
  16. package/dist/cli/commands/admin/ensure-user.d.ts +2 -14
  17. package/dist/cli/commands/admin/ensure-user.d.ts.map +1 -1
  18. package/dist/cli/commands/admin/ensure-user.js +131 -46
  19. package/dist/cli/commands/admin/remove-from-branch-group.d.ts +2 -13
  20. package/dist/cli/commands/admin/remove-from-branch-group.d.ts.map +1 -1
  21. package/dist/cli/commands/admin/remove-from-branch-group.js +133 -33
  22. package/dist/cli/commands/admin/remove-symlink.d.ts +2 -14
  23. package/dist/cli/commands/admin/remove-symlink.d.ts.map +1 -1
  24. package/dist/cli/commands/admin/remove-symlink.js +136 -49
  25. package/dist/cli/commands/admin/scrub-git-remotes.d.ts +2 -2
  26. package/dist/cli/commands/admin/scrub-git-remotes.d.ts.map +1 -1
  27. package/dist/cli/commands/admin/scrub-git-remotes.js +128 -86
  28. package/dist/cli/commands/admin/sync-user-symlinks.d.ts +2 -14
  29. package/dist/cli/commands/admin/sync-user-symlinks.d.ts.map +1 -1
  30. package/dist/cli/commands/admin/sync-user-symlinks.js +132 -43
  31. package/dist/cli/commands/auth/whoami.d.ts.map +1 -1
  32. package/dist/cli/commands/auth/whoami.js +2 -1
  33. package/dist/cli/commands/branch/env/request.test.d.ts +2 -0
  34. package/dist/cli/commands/branch/env/request.test.d.ts.map +1 -0
  35. package/dist/cli/commands/branch/env/request.test.js +17723 -0
  36. package/dist/cli/commands/branch/env/restart.d.ts.map +1 -1
  37. package/dist/cli/commands/branch/env/restart.js +8 -2
  38. package/dist/cli/commands/branch/env/start.d.ts.map +1 -1
  39. package/dist/cli/commands/branch/env/start.js +8 -2
  40. package/dist/cli/commands/branch/env/stop.d.ts.map +1 -1
  41. package/dist/cli/commands/branch/env/stop.js +8 -2
  42. package/dist/cli/commands/daemon/status.d.ts.map +1 -1
  43. package/dist/cli/commands/daemon/status.js +2 -1
  44. package/dist/cli/commands/init.d.ts +6 -0
  45. package/dist/cli/commands/init.d.ts.map +1 -1
  46. package/dist/cli/commands/init.js +140 -2
  47. package/dist/cli/commands/local/add-to-branch-group.d.ts +13 -0
  48. package/dist/cli/commands/local/add-to-branch-group.d.ts.map +1 -0
  49. package/dist/cli/commands/local/add-to-branch-group.js +37 -0
  50. package/dist/cli/commands/local/create-branch-group.d.ts +12 -0
  51. package/dist/cli/commands/local/create-branch-group.d.ts.map +1 -0
  52. package/dist/cli/commands/local/create-branch-group.js +35 -0
  53. package/dist/cli/commands/local/create-symlink.d.ts +14 -0
  54. package/dist/cli/commands/local/create-symlink.d.ts.map +1 -0
  55. package/dist/cli/commands/local/create-symlink.js +45 -0
  56. package/dist/cli/commands/{daemon → local/daemon}/sync.d.ts +1 -1
  57. package/dist/cli/commands/local/daemon/sync.d.ts.map +1 -0
  58. package/dist/cli/commands/{daemon → local/daemon}/sync.js +7 -6
  59. package/dist/cli/commands/local/delete-branch-group.d.ts +12 -0
  60. package/dist/cli/commands/local/delete-branch-group.d.ts.map +1 -0
  61. package/dist/cli/commands/local/delete-branch-group.js +35 -0
  62. package/dist/cli/commands/local/delete-user.d.ts +12 -0
  63. package/dist/cli/commands/local/delete-user.d.ts.map +1 -0
  64. package/dist/cli/commands/local/delete-user.js +36 -0
  65. package/dist/cli/commands/local/ensure-user.d.ts +12 -0
  66. package/dist/cli/commands/local/ensure-user.d.ts.map +1 -0
  67. package/dist/cli/commands/local/ensure-user.js +41 -0
  68. package/dist/cli/commands/local/remove-from-branch-group.d.ts +13 -0
  69. package/dist/cli/commands/local/remove-from-branch-group.d.ts.map +1 -0
  70. package/dist/cli/commands/local/remove-from-branch-group.js +37 -0
  71. package/dist/cli/commands/local/remove-symlink.d.ts +13 -0
  72. package/dist/cli/commands/local/remove-symlink.d.ts.map +1 -0
  73. package/dist/cli/commands/local/remove-symlink.js +39 -0
  74. package/dist/cli/commands/local/scrub-git-remotes.d.ts +9 -0
  75. package/dist/cli/commands/local/scrub-git-remotes.d.ts.map +1 -0
  76. package/dist/cli/commands/local/scrub-git-remotes.js +23 -0
  77. package/dist/cli/commands/{admin → local}/sync-unix.d.ts.map +1 -1
  78. package/dist/cli/commands/{admin → local}/sync-unix.js +3 -3
  79. package/dist/cli/commands/local/sync-user-symlinks.d.ts +12 -0
  80. package/dist/cli/commands/local/sync-user-symlinks.d.ts.map +1 -0
  81. package/dist/cli/commands/local/sync-user-symlinks.js +37 -0
  82. package/dist/cli/commands/telemetry/index.d.ts +7 -0
  83. package/dist/cli/commands/telemetry/index.d.ts.map +1 -0
  84. package/dist/cli/commands/telemetry/index.js +40 -0
  85. package/dist/cli/commands/telemetry/off.d.ts +6 -0
  86. package/dist/cli/commands/telemetry/off.d.ts.map +1 -0
  87. package/dist/cli/commands/telemetry/off.js +35 -0
  88. package/dist/cli/commands/telemetry/on.d.ts +6 -0
  89. package/dist/cli/commands/telemetry/on.d.ts.map +1 -0
  90. package/dist/cli/commands/telemetry/on.js +37 -0
  91. package/dist/cli/commands/telemetry/test.d.ts +6 -0
  92. package/dist/cli/commands/telemetry/test.d.ts.map +1 -0
  93. package/dist/cli/commands/telemetry/test.js +56 -0
  94. package/dist/cli/commands/user/create-admin.d.ts.map +1 -1
  95. package/dist/cli/commands/user/create-admin.js +81 -72
  96. package/dist/cli/commands/user/list.d.ts.map +1 -1
  97. package/dist/cli/commands/user/list.js +1 -0
  98. package/dist/cli/commands/whoami.js +2 -1
  99. package/dist/cli/lib/branch-environment-action.d.ts +21 -0
  100. package/dist/cli/lib/branch-environment-action.d.ts.map +1 -0
  101. package/dist/cli/lib/branch-environment-action.js +8 -0
  102. package/dist/core/api/index.cjs +12 -3
  103. package/dist/core/api/index.d.ts +16 -2
  104. package/dist/core/api/index.d.ts.map +1 -1
  105. package/dist/core/api/index.js +12 -3
  106. package/dist/core/claude/index.cjs +634 -81
  107. package/dist/core/claude/index.js +631 -80
  108. package/dist/core/claude-cli/index.cjs +11 -0
  109. package/dist/core/claude-cli/index.js +11 -0
  110. package/dist/core/claude-cli/pricing.d.ts.map +1 -1
  111. package/dist/core/client/index.cjs +78 -10
  112. package/dist/core/client/index.js +69 -10
  113. package/dist/core/config/browser.cjs +5 -7
  114. package/dist/core/config/browser.js +5 -7
  115. package/dist/core/config/config-manager.d.ts +33 -13
  116. package/dist/core/config/config-manager.d.ts.map +1 -1
  117. package/dist/core/config/constants.d.ts +1 -1
  118. package/dist/core/config/index.cjs +4277 -4391
  119. package/dist/core/config/index.d.ts +1 -0
  120. package/dist/core/config/index.d.ts.map +1 -1
  121. package/dist/core/config/index.js +4299 -4433
  122. package/dist/core/config/key-resolver.d.ts.map +1 -1
  123. package/dist/core/config/multitenancy.d.ts +33 -0
  124. package/dist/core/config/multitenancy.d.ts.map +1 -0
  125. package/dist/core/config/security-resolver.d.ts +1 -0
  126. package/dist/core/config/security-resolver.d.ts.map +1 -1
  127. package/dist/core/config/types.d.ts +75 -4
  128. package/dist/core/config/types.d.ts.map +1 -1
  129. package/dist/core/db/client.d.ts +34 -2
  130. package/dist/core/db/client.d.ts.map +1 -1
  131. package/dist/core/db/database-wrapper.d.ts.map +1 -1
  132. package/dist/core/db/first-run-bootstrap.d.ts.map +1 -1
  133. package/dist/core/db/index.cjs +2765 -1018
  134. package/dist/core/db/index.d.ts +2 -1
  135. package/dist/core/db/index.d.ts.map +1 -1
  136. package/dist/core/db/index.js +2612 -895
  137. package/dist/core/db/migrate.d.ts.map +1 -1
  138. package/dist/core/db/repositories/artifacts.d.ts +27 -2
  139. package/dist/core/db/repositories/artifacts.d.ts.map +1 -1
  140. package/dist/core/db/repositories/base.d.ts +18 -0
  141. package/dist/core/db/repositories/base.d.ts.map +1 -1
  142. package/dist/core/db/repositories/board-comments.d.ts +17 -1
  143. package/dist/core/db/repositories/board-comments.d.ts.map +1 -1
  144. package/dist/core/db/repositories/board-objects.d.ts.map +1 -1
  145. package/dist/core/db/repositories/boards.d.ts +28 -4
  146. package/dist/core/db/repositories/boards.d.ts.map +1 -1
  147. package/dist/core/db/repositories/branch-access.d.ts +32 -0
  148. package/dist/core/db/repositories/branch-access.d.ts.map +1 -1
  149. package/dist/core/db/repositories/branches.d.ts +54 -2
  150. package/dist/core/db/repositories/branches.d.ts.map +1 -1
  151. package/dist/core/db/repositories/cards.d.ts +15 -1
  152. package/dist/core/db/repositories/cards.d.ts.map +1 -1
  153. package/dist/core/db/repositories/gateway-channels.d.ts.map +1 -1
  154. package/dist/core/db/repositories/gateway-outbound-messages.d.ts +19 -0
  155. package/dist/core/db/repositories/gateway-outbound-messages.d.ts.map +1 -0
  156. package/dist/core/db/repositories/index.d.ts +3 -0
  157. package/dist/core/db/repositories/index.d.ts.map +1 -1
  158. package/dist/core/db/repositories/messages.d.ts +9 -2
  159. package/dist/core/db/repositories/messages.d.ts.map +1 -1
  160. package/dist/core/db/repositories/repos.d.ts.map +1 -1
  161. package/dist/core/db/repositories/schedules.d.ts +12 -1
  162. package/dist/core/db/repositories/schedules.d.ts.map +1 -1
  163. package/dist/core/db/repositories/session-relationships.d.ts +30 -0
  164. package/dist/core/db/repositories/session-relationships.d.ts.map +1 -0
  165. package/dist/core/db/repositories/sessions.d.ts +49 -5
  166. package/dist/core/db/repositories/sessions.d.ts.map +1 -1
  167. package/dist/core/db/repositories/tasks.d.ts +7 -2
  168. package/dist/core/db/repositories/tasks.d.ts.map +1 -1
  169. package/dist/core/db/repositories/user-api-keys.d.ts +10 -1
  170. package/dist/core/db/repositories/user-api-keys.d.ts.map +1 -1
  171. package/dist/core/db/repositories/users.d.ts +18 -7
  172. package/dist/core/db/repositories/users.d.ts.map +1 -1
  173. package/dist/core/db/schema.d.ts +2605 -766
  174. package/dist/core/db/schema.d.ts.map +1 -1
  175. package/dist/core/db/schema.postgres.d.ts +1318 -49
  176. package/dist/core/db/schema.postgres.d.ts.map +1 -1
  177. package/dist/core/db/schema.sqlite.d.ts +667 -45
  178. package/dist/core/db/schema.sqlite.d.ts.map +1 -1
  179. package/dist/core/db/tenant-context.d.ts +26 -0
  180. package/dist/core/db/tenant-context.d.ts.map +1 -0
  181. package/dist/core/db/tenant-scope.d.ts +31 -0
  182. package/dist/core/db/tenant-scope.d.ts.map +1 -0
  183. package/dist/core/db/user-utils.d.ts +2 -2
  184. package/dist/core/db/user-utils.d.ts.map +1 -1
  185. package/dist/core/drizzle/postgres/0050_artifact_source_session.sql +3 -0
  186. package/dist/core/drizzle/postgres/0051_session_relationships.sql +26 -0
  187. package/dist/core/drizzle/postgres/0052_gateway_outbound_messages.sql +45 -0
  188. package/dist/core/drizzle/postgres/0053_user_token_invalidation.sql +1 -0
  189. package/dist/core/drizzle/postgres/0054_app_level_multitenancy.sql +219 -0
  190. package/dist/core/drizzle/postgres/0055_app_level_multitenancy_rls.sql +411 -0
  191. package/dist/core/drizzle/postgres/0056_composite_indexes.sql +15 -0
  192. package/dist/core/drizzle/postgres/0057_message_timestamp_indexes.sql +3 -0
  193. package/dist/core/drizzle/postgres/meta/_journal.json +56 -0
  194. package/dist/core/drizzle/sqlite/0059_artifact_source_session.sql +2 -0
  195. package/dist/core/drizzle/sqlite/0060_session_relationships.sql +23 -0
  196. package/dist/core/drizzle/sqlite/0061_gateway_outbound_messages.sql +38 -0
  197. package/dist/core/drizzle/sqlite/0062_user_token_invalidation.sql +1 -0
  198. package/dist/core/drizzle/sqlite/0063_composite_indexes.sql +10 -0
  199. package/dist/core/drizzle/sqlite/0064_message_timestamp_indexes.sql +2 -0
  200. package/dist/core/drizzle/sqlite/meta/_journal.json +42 -0
  201. package/dist/core/environment/render-snapshot.cjs +1 -4
  202. package/dist/core/environment/render-snapshot.js +1 -4
  203. package/dist/core/environment/webhook.cjs +1 -4
  204. package/dist/core/environment/webhook.js +1 -4
  205. package/dist/core/gateway/connector-registry.d.ts.map +1 -1
  206. package/dist/core/gateway/connector.d.ts +32 -1
  207. package/dist/core/gateway/connector.d.ts.map +1 -1
  208. package/dist/core/gateway/connectors/slack-manifest.cjs +108 -0
  209. package/dist/core/gateway/connectors/slack-manifest.d.ts +85 -0
  210. package/dist/core/gateway/connectors/slack-manifest.d.ts.map +1 -0
  211. package/dist/core/gateway/connectors/slack-manifest.js +81 -0
  212. package/dist/core/gateway/connectors/slack.d.ts +136 -7
  213. package/dist/core/gateway/connectors/slack.d.ts.map +1 -1
  214. package/dist/core/gateway/connectors/teams.d.ts +107 -0
  215. package/dist/core/gateway/connectors/teams.d.ts.map +1 -0
  216. package/dist/core/gateway/context.d.ts.map +1 -1
  217. package/dist/core/gateway/index.cjs +1044 -78
  218. package/dist/core/gateway/index.d.ts +6 -2
  219. package/dist/core/gateway/index.d.ts.map +1 -1
  220. package/dist/core/gateway/index.js +1031 -77
  221. package/dist/core/gateway/system-message.d.ts +21 -0
  222. package/dist/core/gateway/system-message.d.ts.map +1 -1
  223. package/dist/core/git/exec.cjs +24 -0
  224. package/dist/core/git/exec.d.ts +6 -4
  225. package/dist/core/git/exec.d.ts.map +1 -1
  226. package/dist/core/git/exec.js +2 -0
  227. package/dist/core/git/index.cjs +3 -1363
  228. package/dist/core/git/index.d.ts +4 -614
  229. package/dist/core/git/index.d.ts.map +1 -1
  230. package/dist/core/git/index.js +1 -1304
  231. package/dist/core/git/pure.cjs +24 -0
  232. package/dist/core/git/pure.d.ts +2 -27
  233. package/dist/core/git/pure.d.ts.map +1 -1
  234. package/dist/core/git/pure.js +2 -0
  235. package/dist/core/index.cjs +11268 -10246
  236. package/dist/core/index.d.ts +2 -0
  237. package/dist/core/index.d.ts.map +1 -1
  238. package/dist/core/index.js +11703 -10179
  239. package/dist/core/lib/feathers-validation.cjs +6 -1
  240. package/dist/core/lib/feathers-validation.d.ts +1 -0
  241. package/dist/core/lib/feathers-validation.d.ts.map +1 -1
  242. package/dist/core/lib/feathers-validation.js +6 -1
  243. package/dist/core/local-actions/git-remotes.d.ts +7 -0
  244. package/dist/core/local-actions/git-remotes.d.ts.map +1 -0
  245. package/dist/core/local-actions/index.cjs +7941 -0
  246. package/dist/core/local-actions/index.d.ts +6 -0
  247. package/dist/core/local-actions/index.d.ts.map +1 -0
  248. package/dist/core/local-actions/index.js +7943 -0
  249. package/dist/core/local-actions/symlinks.d.ts +20 -0
  250. package/dist/core/local-actions/symlinks.d.ts.map +1 -0
  251. package/dist/core/local-actions/types.d.ts +14 -0
  252. package/dist/core/local-actions/types.d.ts.map +1 -0
  253. package/dist/core/local-actions/unix-groups.d.ts +16 -0
  254. package/dist/core/local-actions/unix-groups.d.ts.map +1 -0
  255. package/dist/core/local-actions/unix-users.d.ts +12 -0
  256. package/dist/core/local-actions/unix-users.d.ts.map +1 -0
  257. package/dist/core/mcp/index.cjs +498 -34
  258. package/dist/core/mcp/index.js +497 -33
  259. package/dist/core/mcp/template-resolver.d.ts.map +1 -1
  260. package/dist/core/models/browser.cjs +148 -25
  261. package/dist/core/models/browser.js +144 -25
  262. package/dist/core/models/claude.d.ts +2 -2
  263. package/dist/core/models/claude.d.ts.map +1 -1
  264. package/dist/core/models/codex.d.ts +205 -21
  265. package/dist/core/models/codex.d.ts.map +1 -1
  266. package/dist/core/models/index.cjs +148 -25
  267. package/dist/core/models/index.js +144 -25
  268. package/dist/core/package.json +24 -0
  269. package/dist/core/seed/demo-fixtures.d.ts +87 -0
  270. package/dist/core/seed/demo-fixtures.d.ts.map +1 -0
  271. package/dist/core/seed/dev-fixtures.d.ts.map +1 -1
  272. package/dist/core/seed/index.cjs +8785 -5563
  273. package/dist/core/seed/index.d.ts +1 -0
  274. package/dist/core/seed/index.d.ts.map +1 -1
  275. package/dist/core/seed/index.js +8787 -5570
  276. package/dist/core/sessions/index.cjs +129 -24
  277. package/dist/core/sessions/index.js +129 -24
  278. package/dist/core/telemetry/index.cjs +361 -0
  279. package/dist/core/telemetry/index.d.ts +5 -0
  280. package/dist/core/telemetry/index.d.ts.map +1 -0
  281. package/dist/core/telemetry/index.js +315 -0
  282. package/dist/core/telemetry/logger.d.ts +44 -0
  283. package/dist/core/telemetry/logger.d.ts.map +1 -0
  284. package/dist/core/telemetry/model-normalization.d.ts +3 -0
  285. package/dist/core/telemetry/model-normalization.d.ts.map +1 -0
  286. package/dist/core/telemetry/types.d.ts +47 -0
  287. package/dist/core/telemetry/types.d.ts.map +1 -0
  288. package/dist/core/telemetry/version.d.ts +9 -0
  289. package/dist/core/telemetry/version.d.ts.map +1 -0
  290. package/dist/core/templates/agor-system-prompt.md +22 -53
  291. package/dist/core/templates/session-context.cjs +2 -73
  292. package/dist/core/templates/session-context.d.ts +9 -53
  293. package/dist/core/templates/session-context.d.ts.map +1 -1
  294. package/dist/core/templates/session-context.js +2 -72
  295. package/dist/core/tools/mcp/jwt-auth.cjs +2 -20
  296. package/dist/core/tools/mcp/jwt-auth.d.ts.map +1 -1
  297. package/dist/core/tools/mcp/jwt-auth.js +2 -20
  298. package/dist/core/tools/mcp/oauth-mcp-transport.cjs +2 -15
  299. package/dist/core/tools/mcp/oauth-mcp-transport.d.ts.map +1 -1
  300. package/dist/core/tools/mcp/oauth-mcp-transport.js +2 -15
  301. package/dist/core/tools/mcp/oauth-refresh.cjs +684 -106
  302. package/dist/core/tools/mcp/oauth-refresh.js +682 -107
  303. package/dist/core/types/artifact.d.ts +5 -1
  304. package/dist/core/types/artifact.d.ts.map +1 -1
  305. package/dist/core/types/board.d.ts +2 -0
  306. package/dist/core/types/board.d.ts.map +1 -1
  307. package/dist/core/types/branch.d.ts +27 -0
  308. package/dist/core/types/branch.d.ts.map +1 -1
  309. package/dist/core/types/config-services.d.ts.map +1 -1
  310. package/dist/core/types/feathers.d.ts +6 -0
  311. package/dist/core/types/feathers.d.ts.map +1 -1
  312. package/dist/core/types/gateway.d.ts +77 -2
  313. package/dist/core/types/gateway.d.ts.map +1 -1
  314. package/dist/core/types/id.d.ts +1 -0
  315. package/dist/core/types/id.d.ts.map +1 -1
  316. package/dist/core/types/index.cjs +61 -0
  317. package/dist/core/types/index.d.ts +1 -0
  318. package/dist/core/types/index.d.ts.map +1 -1
  319. package/dist/core/types/index.js +52 -0
  320. package/dist/core/types/schedule.d.ts +4 -3
  321. package/dist/core/types/schedule.d.ts.map +1 -1
  322. package/dist/core/types/session.d.ts +72 -2
  323. package/dist/core/types/session.d.ts.map +1 -1
  324. package/dist/core/types/task.d.ts +9 -0
  325. package/dist/core/types/task.d.ts.map +1 -1
  326. package/dist/core/types/tenant.d.ts +15 -0
  327. package/dist/core/types/tenant.d.ts.map +1 -0
  328. package/dist/core/types/user.d.ts +61 -0
  329. package/dist/core/types/user.d.ts.map +1 -1
  330. package/dist/core/unix/index.cjs +1367 -669
  331. package/dist/core/unix/index.js +1330 -634
  332. package/dist/core/unix/unix-integration-service.d.ts +10 -7
  333. package/dist/core/unix/unix-integration-service.d.ts.map +1 -1
  334. package/dist/core/utils/emoji-shortcodes.d.ts +13 -0
  335. package/dist/core/utils/emoji-shortcodes.d.ts.map +1 -0
  336. package/dist/core/utils/permission-mode-mapper.cjs +19 -0
  337. package/dist/core/utils/permission-mode-mapper.js +19 -0
  338. package/dist/core/yaml/index.cjs +8 -8
  339. package/dist/core/yaml/index.d.ts +1 -1
  340. package/dist/core/yaml/index.d.ts.map +1 -1
  341. package/dist/core/yaml/index.js +7 -7
  342. package/dist/daemon/adapters/drizzle.d.ts +26 -4
  343. package/dist/daemon/adapters/drizzle.d.ts.map +1 -1
  344. package/dist/daemon/adapters/drizzle.js +68 -7
  345. package/dist/daemon/auth/api-key-strategy.js +1 -1
  346. package/dist/daemon/auth/executor-runtime-scope.d.ts.map +1 -1
  347. package/dist/daemon/auth/executor-runtime-scope.js +19 -5
  348. package/dist/daemon/auth/launch-auth.d.ts +5 -4
  349. package/dist/daemon/auth/launch-auth.d.ts.map +1 -1
  350. package/dist/daemon/auth/launch-auth.js +123 -39
  351. package/dist/daemon/auth/refresh-token-service.d.ts +22 -0
  352. package/dist/daemon/auth/refresh-token-service.d.ts.map +1 -0
  353. package/dist/daemon/auth/refresh-token-service.js +133 -0
  354. package/dist/daemon/auth/runtime-tokens.d.ts +3 -1
  355. package/dist/daemon/auth/runtime-tokens.d.ts.map +1 -1
  356. package/dist/daemon/auth/runtime-tokens.js +17 -4
  357. package/dist/daemon/auth/service-jwt-strategy.d.ts +2 -1
  358. package/dist/daemon/auth/service-jwt-strategy.d.ts.map +1 -1
  359. package/dist/daemon/auth/service-jwt-strategy.js +127 -1
  360. package/dist/daemon/auth/token-invalidation.d.ts +11 -0
  361. package/dist/daemon/auth/token-invalidation.d.ts.map +1 -0
  362. package/dist/daemon/auth/token-invalidation.js +38 -0
  363. package/dist/daemon/auth/user-redaction.d.ts +12 -0
  364. package/dist/daemon/auth/user-redaction.d.ts.map +1 -0
  365. package/dist/daemon/auth/user-redaction.js +13 -0
  366. package/dist/daemon/declarations.d.ts +8 -1
  367. package/dist/daemon/declarations.d.ts.map +1 -1
  368. package/dist/daemon/hooks/gateway-route.d.ts.map +1 -1
  369. package/dist/daemon/hooks/gateway-route.js +69 -7
  370. package/dist/daemon/index.d.ts.map +1 -1
  371. package/dist/daemon/index.js +10429 -4408
  372. package/dist/daemon/knowledge/pgvector.d.ts +3 -3
  373. package/dist/daemon/knowledge/pgvector.d.ts.map +1 -1
  374. package/dist/daemon/knowledge/pgvector.js +24 -0
  375. package/dist/daemon/knowledge/units.d.ts +2 -2
  376. package/dist/daemon/knowledge/units.d.ts.map +1 -1
  377. package/dist/daemon/main.js +10429 -4408
  378. package/dist/daemon/mcp/server.d.ts +3 -3
  379. package/dist/daemon/mcp/server.d.ts.map +1 -1
  380. package/dist/daemon/mcp/server.js +1621 -87
  381. package/dist/daemon/mcp/tokens.d.ts +2 -2
  382. package/dist/daemon/mcp/tokens.d.ts.map +1 -1
  383. package/dist/daemon/mcp/tokens.js +5 -1
  384. package/dist/daemon/mcp/tool-registry.d.ts.map +1 -1
  385. package/dist/daemon/mcp/tool-registry.js +1 -0
  386. package/dist/daemon/mcp/tools/analytics.d.ts.map +1 -1
  387. package/dist/daemon/mcp/tools/analytics.js +553 -29
  388. package/dist/daemon/mcp/tools/artifacts.d.ts.map +1 -1
  389. package/dist/daemon/mcp/tools/artifacts.js +516 -25
  390. package/dist/daemon/mcp/tools/boards.d.ts.map +1 -1
  391. package/dist/daemon/mcp/tools/boards.js +522 -26
  392. package/dist/daemon/mcp/tools/branches.d.ts.map +1 -1
  393. package/dist/daemon/mcp/tools/branches.js +579 -55
  394. package/dist/daemon/mcp/tools/card-types.js +513 -23
  395. package/dist/daemon/mcp/tools/cards.js +513 -23
  396. package/dist/daemon/mcp/tools/environment.d.ts.map +1 -1
  397. package/dist/daemon/mcp/tools/environment.js +534 -28
  398. package/dist/daemon/mcp/tools/gateway-channels.d.ts +4 -0
  399. package/dist/daemon/mcp/tools/gateway-channels.d.ts.map +1 -0
  400. package/dist/daemon/mcp/tools/gateway-channels.js +16035 -0
  401. package/dist/daemon/mcp/tools/knowledge.js +513 -23
  402. package/dist/daemon/mcp/tools/mcp-servers.d.ts.map +1 -1
  403. package/dist/daemon/mcp/tools/mcp-servers.js +848 -23
  404. package/dist/daemon/mcp/tools/messages.d.ts.map +1 -1
  405. package/dist/daemon/mcp/tools/messages.js +573 -37
  406. package/dist/daemon/mcp/tools/proxies.js +523 -25
  407. package/dist/daemon/mcp/tools/repos.js +513 -23
  408. package/dist/daemon/mcp/tools/schedules.d.ts.map +1 -1
  409. package/dist/daemon/mcp/tools/schedules.js +516 -24
  410. package/dist/daemon/mcp/tools/search.js +513 -23
  411. package/dist/daemon/mcp/tools/sessions.d.ts.map +1 -1
  412. package/dist/daemon/mcp/tools/sessions.js +660 -33
  413. package/dist/daemon/mcp/tools/tasks.js +513 -23
  414. package/dist/daemon/mcp/tools/users.d.ts.map +1 -1
  415. package/dist/daemon/mcp/tools/users.js +532 -28
  416. package/dist/daemon/mcp/tools/widgets.d.ts.map +1 -1
  417. package/dist/daemon/mcp/tools/widgets.js +542 -25
  418. package/dist/daemon/register-hooks.d.ts +8 -3
  419. package/dist/daemon/register-hooks.d.ts.map +1 -1
  420. package/dist/daemon/register-hooks.js +1146 -609
  421. package/dist/daemon/register-routes.d.ts +3 -2
  422. package/dist/daemon/register-routes.d.ts.map +1 -1
  423. package/dist/daemon/register-routes.js +2926 -829
  424. package/dist/daemon/register-services.d.ts +2 -2
  425. package/dist/daemon/register-services.d.ts.map +1 -1
  426. package/dist/daemon/register-services.js +4209 -1140
  427. package/dist/daemon/services/artifacts.d.ts +43 -6
  428. package/dist/daemon/services/artifacts.d.ts.map +1 -1
  429. package/dist/daemon/services/artifacts.js +134 -9
  430. package/dist/daemon/services/assistant-knowledge.d.ts +2 -2
  431. package/dist/daemon/services/assistant-knowledge.d.ts.map +1 -1
  432. package/dist/daemon/services/board-comments.d.ts +8 -5
  433. package/dist/daemon/services/board-comments.d.ts.map +1 -1
  434. package/dist/daemon/services/board-comments.js +78 -13
  435. package/dist/daemon/services/board-objects.d.ts +8 -5
  436. package/dist/daemon/services/board-objects.d.ts.map +1 -1
  437. package/dist/daemon/services/board-objects.js +14 -4
  438. package/dist/daemon/services/boards.d.ts +34 -5
  439. package/dist/daemon/services/boards.d.ts.map +1 -1
  440. package/dist/daemon/services/boards.js +116 -8
  441. package/dist/daemon/services/branch-owners.d.ts +3 -1
  442. package/dist/daemon/services/branch-owners.d.ts.map +1 -1
  443. package/dist/daemon/services/branch-owners.js +31 -4
  444. package/dist/daemon/services/branches.d.ts +39 -6
  445. package/dist/daemon/services/branches.d.ts.map +1 -1
  446. package/dist/daemon/services/branches.js +703 -210
  447. package/dist/daemon/services/card-types.d.ts +3 -3
  448. package/dist/daemon/services/card-types.d.ts.map +1 -1
  449. package/dist/daemon/services/card-types.js +68 -7
  450. package/dist/daemon/services/cards.d.ts +19 -4
  451. package/dist/daemon/services/cards.d.ts.map +1 -1
  452. package/dist/daemon/services/cards.js +92 -8
  453. package/dist/daemon/services/check-auth.d.ts +2 -2
  454. package/dist/daemon/services/check-auth.d.ts.map +1 -1
  455. package/dist/daemon/services/claude-cli-integration.d.ts +4 -1
  456. package/dist/daemon/services/claude-cli-integration.d.ts.map +1 -1
  457. package/dist/daemon/services/claude-cli-integration.js +117 -65
  458. package/dist/daemon/services/claude-models.d.ts +3 -3
  459. package/dist/daemon/services/claude-models.d.ts.map +1 -1
  460. package/dist/daemon/services/claude-models.js +1048 -397
  461. package/dist/daemon/services/config.d.ts +12 -4
  462. package/dist/daemon/services/config.d.ts.map +1 -1
  463. package/dist/daemon/services/config.js +39 -3
  464. package/dist/daemon/services/copilot-models.d.ts +3 -3
  465. package/dist/daemon/services/copilot-models.d.ts.map +1 -1
  466. package/dist/daemon/services/cursor-models.d.ts +3 -3
  467. package/dist/daemon/services/cursor-models.d.ts.map +1 -1
  468. package/dist/daemon/services/files.d.ts +3 -3
  469. package/dist/daemon/services/files.d.ts.map +1 -1
  470. package/dist/daemon/services/files.js +24 -5
  471. package/dist/daemon/services/gateway-channels-test.d.ts +24 -0
  472. package/dist/daemon/services/gateway-channels-test.d.ts.map +1 -0
  473. package/dist/daemon/services/gateway-channels-test.js +66 -0
  474. package/dist/daemon/services/gateway-channels.d.ts +3 -3
  475. package/dist/daemon/services/gateway-channels.d.ts.map +1 -1
  476. package/dist/daemon/services/gateway-channels.js +68 -7
  477. package/dist/daemon/services/gateway.d.ts +106 -5
  478. package/dist/daemon/services/gateway.d.ts.map +1 -1
  479. package/dist/daemon/services/gateway.js +1184 -95
  480. package/dist/daemon/services/github-app-setup.d.ts +3 -3
  481. package/dist/daemon/services/github-app-setup.d.ts.map +1 -1
  482. package/dist/daemon/services/groups.d.ts +7 -5
  483. package/dist/daemon/services/groups.d.ts.map +1 -1
  484. package/dist/daemon/services/groups.js +56 -0
  485. package/dist/daemon/services/health-monitor.d.ts +34 -2
  486. package/dist/daemon/services/health-monitor.d.ts.map +1 -1
  487. package/dist/daemon/services/health-monitor.js +145 -23
  488. package/dist/daemon/services/knowledge-document-edits.d.ts +3 -3
  489. package/dist/daemon/services/knowledge-document-edits.d.ts.map +1 -1
  490. package/dist/daemon/services/knowledge-documents.d.ts +3 -3
  491. package/dist/daemon/services/knowledge-documents.d.ts.map +1 -1
  492. package/dist/daemon/services/knowledge-documents.js +92 -7
  493. package/dist/daemon/services/knowledge-embedding-indexer.d.ts +7 -2
  494. package/dist/daemon/services/knowledge-embedding-indexer.d.ts.map +1 -1
  495. package/dist/daemon/services/knowledge-embedding-indexer.js +37 -3
  496. package/dist/daemon/services/knowledge-graph.d.ts +3 -3
  497. package/dist/daemon/services/knowledge-graph.d.ts.map +1 -1
  498. package/dist/daemon/services/knowledge-indexing.d.ts +3 -3
  499. package/dist/daemon/services/knowledge-indexing.d.ts.map +1 -1
  500. package/dist/daemon/services/knowledge-namespaces.d.ts +3 -3
  501. package/dist/daemon/services/knowledge-namespaces.d.ts.map +1 -1
  502. package/dist/daemon/services/knowledge-namespaces.js +72 -8
  503. package/dist/daemon/services/knowledge-reindex.d.ts +3 -3
  504. package/dist/daemon/services/knowledge-reindex.d.ts.map +1 -1
  505. package/dist/daemon/services/knowledge-reindex.js +28 -1
  506. package/dist/daemon/services/knowledge-search.d.ts +3 -3
  507. package/dist/daemon/services/knowledge-search.d.ts.map +1 -1
  508. package/dist/daemon/services/knowledge-settings.d.ts +3 -3
  509. package/dist/daemon/services/knowledge-settings.d.ts.map +1 -1
  510. package/dist/daemon/services/knowledge-settings.js +24 -0
  511. package/dist/daemon/services/knowledge-versions.d.ts +3 -3
  512. package/dist/daemon/services/knowledge-versions.d.ts.map +1 -1
  513. package/dist/daemon/services/knowledge-versions.js +68 -7
  514. package/dist/daemon/services/leaderboard.d.ts +14 -6
  515. package/dist/daemon/services/leaderboard.d.ts.map +1 -1
  516. package/dist/daemon/services/leaderboard.js +74 -15
  517. package/dist/daemon/services/local-actions.d.ts +13 -0
  518. package/dist/daemon/services/local-actions.d.ts.map +1 -0
  519. package/dist/daemon/services/local-actions.js +120 -0
  520. package/dist/daemon/services/mcp-servers.d.ts +3 -3
  521. package/dist/daemon/services/mcp-servers.d.ts.map +1 -1
  522. package/dist/daemon/services/mcp-servers.js +68 -13
  523. package/dist/daemon/services/messages.d.ts +10 -6
  524. package/dist/daemon/services/messages.d.ts.map +1 -1
  525. package/dist/daemon/services/messages.js +87 -7
  526. package/dist/daemon/services/repos.d.ts +6 -6
  527. package/dist/daemon/services/repos.d.ts.map +1 -1
  528. package/dist/daemon/services/repos.js +131 -32
  529. package/dist/daemon/services/scheduler.d.ts +23 -27
  530. package/dist/daemon/services/scheduler.d.ts.map +1 -1
  531. package/dist/daemon/services/scheduler.js +61 -30
  532. package/dist/daemon/services/schedules.d.ts +3 -3
  533. package/dist/daemon/services/schedules.d.ts.map +1 -1
  534. package/dist/daemon/services/schedules.js +68 -7
  535. package/dist/daemon/services/session-env-selections.d.ts +3 -3
  536. package/dist/daemon/services/session-env-selections.d.ts.map +1 -1
  537. package/dist/daemon/services/session-mcp-servers.d.ts +3 -3
  538. package/dist/daemon/services/session-mcp-servers.d.ts.map +1 -1
  539. package/dist/daemon/services/session-token-service.d.ts.map +1 -1
  540. package/dist/daemon/services/session-token-service.js +3 -0
  541. package/dist/daemon/services/sessions.d.ts +20 -8
  542. package/dist/daemon/services/sessions.d.ts.map +1 -1
  543. package/dist/daemon/services/sessions.js +211 -17
  544. package/dist/daemon/services/tasks.d.ts +24 -7
  545. package/dist/daemon/services/tasks.d.ts.map +1 -1
  546. package/dist/daemon/services/tasks.js +235 -59
  547. package/dist/daemon/services/terminals.d.ts +21 -3
  548. package/dist/daemon/services/terminals.d.ts.map +1 -1
  549. package/dist/daemon/services/terminals.js +81 -25
  550. package/dist/daemon/services/thread-session-map.d.ts +3 -3
  551. package/dist/daemon/services/thread-session-map.d.ts.map +1 -1
  552. package/dist/daemon/services/thread-session-map.js +68 -7
  553. package/dist/daemon/services/user-avatar-sync.d.ts +21 -0
  554. package/dist/daemon/services/user-avatar-sync.d.ts.map +1 -0
  555. package/dist/daemon/services/user-avatar-sync.js +267 -0
  556. package/dist/daemon/services/users.d.ts +29 -9
  557. package/dist/daemon/services/users.d.ts.map +1 -1
  558. package/dist/daemon/services/users.js +383 -30
  559. package/dist/daemon/services/zone-trigger.d.ts.map +1 -1
  560. package/dist/daemon/services/zone-trigger.js +17 -4
  561. package/dist/daemon/setup/build-info.d.ts +1 -1
  562. package/dist/daemon/setup/build-info.d.ts.map +1 -1
  563. package/dist/daemon/setup/build-info.js +5 -1
  564. package/dist/daemon/setup/database.d.ts +8 -3
  565. package/dist/daemon/setup/database.d.ts.map +1 -1
  566. package/dist/daemon/setup/database.js +26 -6
  567. package/dist/daemon/setup/first-run-admin.d.ts +2 -2
  568. package/dist/daemon/setup/first-run-admin.d.ts.map +1 -1
  569. package/dist/daemon/setup/index.js +97 -17
  570. package/dist/daemon/setup/socketio.d.ts +10 -1
  571. package/dist/daemon/setup/socketio.d.ts.map +1 -1
  572. package/dist/daemon/setup/socketio.js +68 -10
  573. package/dist/daemon/startup.d.ts +13 -2
  574. package/dist/daemon/startup.d.ts.map +1 -1
  575. package/dist/daemon/startup.js +354 -88
  576. package/dist/daemon/utils/append-system-message.d.ts +2 -2
  577. package/dist/daemon/utils/append-system-message.d.ts.map +1 -1
  578. package/dist/daemon/utils/apply-session-config-defaults.d.ts.map +1 -1
  579. package/dist/daemon/utils/apply-session-config-defaults.js +12 -1
  580. package/dist/daemon/utils/authorization.d.ts +3 -1
  581. package/dist/daemon/utils/authorization.d.ts.map +1 -1
  582. package/dist/daemon/utils/authorization.js +21 -6
  583. package/dist/daemon/utils/branch-authorization.d.ts +30 -0
  584. package/dist/daemon/utils/branch-authorization.d.ts.map +1 -1
  585. package/dist/daemon/utils/branch-authorization.js +63 -5
  586. package/dist/daemon/utils/branch-inspect.d.ts +1 -0
  587. package/dist/daemon/utils/branch-inspect.d.ts.map +1 -1
  588. package/dist/daemon/utils/branch-inspect.js +11 -3
  589. package/dist/daemon/utils/executor-read-impersonation.d.ts +2 -2
  590. package/dist/daemon/utils/executor-read-impersonation.d.ts.map +1 -1
  591. package/dist/daemon/utils/git-impersonation.d.ts +10 -10
  592. package/dist/daemon/utils/git-impersonation.d.ts.map +1 -1
  593. package/dist/daemon/utils/git-remote-credential-scan.d.ts +3 -3
  594. package/dist/daemon/utils/git-remote-credential-scan.d.ts.map +1 -1
  595. package/dist/daemon/utils/git-remote-credential-scan.js +6 -2
  596. package/dist/daemon/utils/mcp-token-authorization.d.ts +18 -13
  597. package/dist/daemon/utils/mcp-token-authorization.d.ts.map +1 -1
  598. package/dist/daemon/utils/mcp-token-authorization.js +11 -5
  599. package/dist/daemon/utils/open-source-telemetry-config.d.ts +6 -0
  600. package/dist/daemon/utils/open-source-telemetry-config.d.ts.map +1 -0
  601. package/dist/daemon/utils/open-source-telemetry-config.js +21 -0
  602. package/dist/daemon/utils/open-source-telemetry-heartbeat.d.ts +7 -0
  603. package/dist/daemon/utils/open-source-telemetry-heartbeat.d.ts.map +1 -0
  604. package/dist/daemon/utils/open-source-telemetry-heartbeat.js +15 -0
  605. package/dist/daemon/utils/open-source-telemetry-usage.d.ts +9 -0
  606. package/dist/daemon/utils/open-source-telemetry-usage.d.ts.map +1 -0
  607. package/dist/daemon/utils/open-source-telemetry-usage.js +121 -0
  608. package/dist/daemon/utils/realign-repo-origin.d.ts +3 -3
  609. package/dist/daemon/utils/realign-repo-origin.d.ts.map +1 -1
  610. package/dist/daemon/utils/realign-repo-origin.js +47 -16
  611. package/dist/daemon/utils/realtime-publish.d.ts +2 -0
  612. package/dist/daemon/utils/realtime-publish.d.ts.map +1 -1
  613. package/dist/daemon/utils/realtime-publish.js +51 -10
  614. package/dist/daemon/utils/session-state-hooks.d.ts +3 -3
  615. package/dist/daemon/utils/session-state-hooks.d.ts.map +1 -1
  616. package/dist/daemon/utils/session-stop.d.ts +43 -0
  617. package/dist/daemon/utils/session-stop.d.ts.map +1 -0
  618. package/dist/daemon/utils/session-stop.js +102 -0
  619. package/dist/daemon/utils/session-task-state.d.ts +7 -2
  620. package/dist/daemon/utils/session-task-state.d.ts.map +1 -1
  621. package/dist/daemon/utils/session-task-state.js +9 -3
  622. package/dist/daemon/utils/session-tasks.d.ts +4 -4
  623. package/dist/daemon/utils/session-tasks.d.ts.map +1 -1
  624. package/dist/daemon/utils/session-tasks.js +4 -8
  625. package/dist/daemon/utils/session-turn-lock.d.ts +8 -1
  626. package/dist/daemon/utils/session-turn-lock.d.ts.map +1 -1
  627. package/dist/daemon/utils/session-turn-lock.js +25 -2
  628. package/dist/daemon/utils/spawn-executor.d.ts +23 -1
  629. package/dist/daemon/utils/spawn-executor.d.ts.map +1 -1
  630. package/dist/daemon/utils/spawn-executor.js +34 -4
  631. package/dist/daemon/utils/tenant-db-scope.d.ts +20 -0
  632. package/dist/daemon/utils/tenant-db-scope.d.ts.map +1 -0
  633. package/dist/daemon/utils/tenant-db-scope.js +114 -0
  634. package/dist/daemon/utils/unix-group-init.d.ts +3 -3
  635. package/dist/daemon/utils/unix-group-init.d.ts.map +1 -1
  636. package/dist/daemon/utils/upload.d.ts +6 -9
  637. package/dist/daemon/utils/upload.d.ts.map +1 -1
  638. package/dist/daemon/utils/upload.js +30 -37
  639. package/dist/daemon/widgets/env-vars/index.d.ts +26 -1
  640. package/dist/daemon/widgets/env-vars/index.d.ts.map +1 -1
  641. package/dist/daemon/widgets/env-vars/index.js +145 -21
  642. package/dist/daemon/widgets/index.js +137 -21
  643. package/dist/executor/commands/environment.d.ts +13 -0
  644. package/dist/executor/commands/environment.d.ts.map +1 -0
  645. package/dist/executor/commands/environment.js +291 -0
  646. package/dist/executor/commands/git.js +1 -1
  647. package/dist/executor/commands/index.d.ts.map +1 -1
  648. package/dist/executor/commands/index.js +5 -1
  649. package/dist/executor/commands/unix.d.ts +8 -1
  650. package/dist/executor/commands/unix.d.ts.map +1 -1
  651. package/dist/executor/commands/unix.js +157 -2
  652. package/dist/executor/git/index.d.ts +8 -0
  653. package/dist/executor/git/index.d.ts.map +1 -0
  654. package/dist/executor/git/index.js +7 -0
  655. package/dist/executor/handlers/sdk/base-executor.d.ts.map +1 -1
  656. package/dist/executor/handlers/sdk/base-executor.js +4 -1
  657. package/dist/executor/handlers/sdk/git-safe-directory.d.ts.map +1 -1
  658. package/dist/executor/handlers/sdk/git-safe-directory.js +1 -1
  659. package/dist/executor/payload-types.d.ts +201 -5
  660. package/dist/executor/payload-types.d.ts.map +1 -1
  661. package/dist/executor/payload-types.js +98 -0
  662. package/dist/executor/sdk-handlers/base/diff-enrichment.js +1 -1
  663. package/dist/executor/sdk-handlers/base/mcp-scoping.d.ts.map +1 -1
  664. package/dist/executor/sdk-handlers/base/mcp-scoping.js +14 -0
  665. package/dist/executor/sdk-handlers/claude/message-processor.d.ts.map +1 -1
  666. package/dist/executor/sdk-handlers/claude/message-processor.js +0 -1
  667. package/dist/executor/sdk-handlers/claude/query-builder.d.ts +1 -0
  668. package/dist/executor/sdk-handlers/claude/query-builder.d.ts.map +1 -1
  669. package/dist/executor/sdk-handlers/claude/query-builder.js +91 -39
  670. package/dist/executor/sdk-handlers/codex/codex-tool.d.ts +6 -10
  671. package/dist/executor/sdk-handlers/codex/codex-tool.d.ts.map +1 -1
  672. package/dist/executor/sdk-handlers/codex/codex-tool.js +12 -15
  673. package/dist/executor/sdk-handlers/codex/normalizer.d.ts.map +1 -1
  674. package/dist/executor/sdk-handlers/codex/normalizer.js +11 -1
  675. package/dist/executor/sdk-handlers/codex/pricing/litellm-openai-model-prices.json +3663 -0
  676. package/dist/executor/sdk-handlers/codex/pricing/litellm-pricing.d.ts +31 -0
  677. package/dist/executor/sdk-handlers/codex/pricing/litellm-pricing.d.ts.map +1 -0
  678. package/dist/executor/sdk-handlers/codex/pricing/litellm-pricing.js +46 -0
  679. package/dist/executor/sdk-handlers/codex/prompt-service.d.ts +12 -5
  680. package/dist/executor/sdk-handlers/codex/prompt-service.d.ts.map +1 -1
  681. package/dist/executor/sdk-handlers/codex/prompt-service.js +133 -36
  682. package/dist/executor/sdk-handlers/codex/usage.d.ts +14 -23
  683. package/dist/executor/sdk-handlers/codex/usage.d.ts.map +1 -1
  684. package/dist/executor/sdk-handlers/codex/usage.js +18 -33
  685. package/dist/executor/sdk-handlers/copilot/prompt-service.d.ts +2 -4
  686. package/dist/executor/sdk-handlers/copilot/prompt-service.d.ts.map +1 -1
  687. package/dist/executor/sdk-handlers/copilot/prompt-service.js +4 -13
  688. package/dist/executor/sdk-handlers/gemini/prompt-service.d.ts +2 -4
  689. package/dist/executor/sdk-handlers/gemini/prompt-service.d.ts.map +1 -1
  690. package/dist/executor/sdk-handlers/gemini/prompt-service.js +4 -13
  691. package/dist/executor/services/feathers-client.js +5 -5
  692. package/dist/git/index.cjs +1101 -0
  693. package/dist/git/index.d.ts +533 -0
  694. package/dist/git/index.d.ts.map +1 -0
  695. package/dist/git/index.js +1022 -0
  696. package/dist/git/package.json +21 -0
  697. package/dist/git/pure.cjs +185 -0
  698. package/dist/git/pure.d.ts +39 -0
  699. package/dist/git/pure.d.ts.map +1 -0
  700. package/dist/git/pure.js +139 -0
  701. package/dist/ui/assets/AgorEmojiPickerInner-DQjr8M3_.js +1 -0
  702. package/dist/ui/assets/App-hJtcOxHv.js +5 -0
  703. package/dist/ui/assets/App-hJtcOxHv.js.gz +0 -0
  704. package/dist/ui/assets/AppNode-BhuMpn8O.js +1 -0
  705. package/dist/ui/assets/AppNode-BhuMpn8O.js.gz +0 -0
  706. package/dist/ui/assets/ArtifactConsentModal-oMMzRn8L.js +1 -0
  707. package/dist/ui/assets/ArtifactConsentModal-oMMzRn8L.js.gz +0 -0
  708. package/dist/ui/assets/ArtifactFullscreenPage-B3wT8t8f.js +9 -0
  709. package/dist/ui/assets/ArtifactFullscreenPage-B3wT8t8f.js.gz +0 -0
  710. package/dist/ui/assets/ArtifactNode-BzQcrwFS.js +9 -0
  711. package/dist/ui/assets/ArtifactNode-BzQcrwFS.js.gz +0 -0
  712. package/dist/ui/assets/AutocompleteTextarea-Dau-V_30.js +19 -0
  713. package/dist/ui/assets/AutocompleteTextarea-Dau-V_30.js.gz +0 -0
  714. package/dist/ui/assets/BoardObjectNodes-DdKWv_ZT.js +34 -0
  715. package/dist/ui/assets/BoardObjectNodes-DdKWv_ZT.js.gz +0 -0
  716. package/dist/ui/assets/CodeEditor.inner-Cuj6RuLL.js +7 -0
  717. package/dist/ui/assets/CodeEditor.inner-Cuj6RuLL.js.gz +0 -0
  718. package/dist/ui/assets/ConversationView-9-3ma1u-.js +1 -0
  719. package/dist/ui/assets/ConversationView-9-3ma1u-.js.gz +0 -0
  720. package/dist/ui/assets/EmbeddedTerminal-Lx5I9EOJ.js +2 -0
  721. package/dist/ui/assets/EmbeddedTerminal-Lx5I9EOJ.js.gz +0 -0
  722. package/dist/ui/assets/KnowledgePage-Dz8YAMYC.js +24 -0
  723. package/dist/ui/assets/KnowledgePage-Dz8YAMYC.js.gz +0 -0
  724. package/dist/ui/assets/MarketingScreenshotPage-9Qd7eZsm.css +1 -0
  725. package/dist/ui/assets/MarketingScreenshotPage-CmDPBHOl.js +143 -0
  726. package/dist/ui/assets/MarketingScreenshotPage-CmDPBHOl.js.gz +0 -0
  727. package/dist/ui/assets/MobileApp-BpgSG_gz.js +1 -0
  728. package/dist/ui/assets/MobileApp-BpgSG_gz.js.gz +0 -0
  729. package/dist/ui/assets/SessionCanvas-B6_mtlxK.js +13 -0
  730. package/dist/ui/assets/SessionCanvas-B6_mtlxK.js.gz +0 -0
  731. package/dist/ui/assets/SessionCanvas-Bh7Yg5dZ.css +1 -0
  732. package/dist/ui/assets/SessionCanvas-Bh7Yg5dZ.css.gz +0 -0
  733. package/dist/ui/assets/{StreamdownDemoPage-B9wbgp2s.js → StreamdownDemoPage-okKKR2QH.js} +2 -2
  734. package/dist/ui/assets/StreamdownDemoPage-okKKR2QH.js.gz +0 -0
  735. package/dist/ui/assets/TerminalModal-D9jMGZXv.js +2 -0
  736. package/dist/ui/assets/TerminalModal-D9jMGZXv.js.gz +0 -0
  737. package/dist/ui/assets/ThemeSwitcher-D9HgT37l.js +1 -0
  738. package/dist/ui/assets/ThemeSwitcher-D9HgT37l.js.gz +0 -0
  739. package/dist/ui/assets/ThemedSyntaxHighlighter.inner-C1FdIHn0.js +1 -0
  740. package/dist/ui/assets/antd-DT5ackd0.js +401 -0
  741. package/dist/ui/assets/antd-DT5ackd0.js.gz +0 -0
  742. package/dist/ui/assets/architecture-U656AL7Q-DMnxkQRZ.js +1 -0
  743. package/dist/ui/assets/architectureDiagram-VXUJARFQ-DwTJGGoj.js +36 -0
  744. package/dist/ui/assets/architectureDiagram-VXUJARFQ-DwTJGGoj.js.gz +0 -0
  745. package/dist/ui/assets/{blockDiagram-VD42YOAC-CzGHAHao.js → blockDiagram-VD42YOAC-Dh1_TVW2.js} +4 -4
  746. package/dist/ui/assets/blockDiagram-VD42YOAC-Dh1_TVW2.js.gz +0 -0
  747. package/dist/ui/assets/{c4Diagram-YG6GDRKO-DscJyaWN.js → c4Diagram-YG6GDRKO-B1e96AcB.js} +2 -2
  748. package/dist/ui/assets/c4Diagram-YG6GDRKO-B1e96AcB.js.gz +0 -0
  749. package/dist/ui/assets/channel-Jv4dT4S5.js +1 -0
  750. package/dist/ui/assets/{chunk-4BX2VUAB-DoWpTvP8.js → chunk-4BX2VUAB-BODpCjJx.js} +1 -1
  751. package/dist/ui/assets/chunk-55IACEB6-lJXvUquf.js +1 -0
  752. package/dist/ui/assets/{chunk-ABZYJK2D-RzDCrjE6.js → chunk-ABZYJK2D-DCTXWSzV.js} +3 -3
  753. package/dist/ui/assets/chunk-ABZYJK2D-DCTXWSzV.js.gz +0 -0
  754. package/dist/ui/assets/{chunk-AGHRB4JF-jidCS5Of.js → chunk-AGHRB4JF-CbNphBjE.js} +1 -1
  755. package/dist/ui/assets/chunk-AGHRB4JF-CbNphBjE.js.gz +0 -0
  756. package/dist/ui/assets/{chunk-ATLVNIR6-BEIIfJtC.js → chunk-ATLVNIR6-rWg3qxof.js} +1 -1
  757. package/dist/ui/assets/chunk-ATLVNIR6-rWg3qxof.js.gz +0 -0
  758. package/dist/ui/assets/{chunk-B4BG7PRW-B8b6dQQ2.js → chunk-B4BG7PRW-CgtLCbpE.js} +3 -3
  759. package/dist/ui/assets/chunk-B4BG7PRW-CgtLCbpE.js.gz +0 -0
  760. package/dist/ui/assets/{chunk-CVBHYZKI-D-mQAfrk.js → chunk-CVBHYZKI-DTL6Zgr0.js} +1 -1
  761. package/dist/ui/assets/{chunk-DI55MBZ5-BfATX3V8.js → chunk-DI55MBZ5-Dwvx2Kva.js} +1 -1
  762. package/dist/ui/assets/chunk-DI55MBZ5-Dwvx2Kva.js.gz +0 -0
  763. package/dist/ui/assets/chunk-EXTU4WIE-DHyaqTsP.js +1 -0
  764. package/dist/ui/assets/{chunk-FMBD7UC4-fqXscNvc.js → chunk-FMBD7UC4-BogA_9CV.js} +1 -1
  765. package/dist/ui/assets/{chunk-HN2XXSSU-BCHvD80g.js → chunk-HN2XXSSU-2blQO3Gb.js} +1 -1
  766. package/dist/ui/assets/chunk-HN2XXSSU-2blQO3Gb.js.gz +0 -0
  767. package/dist/ui/assets/chunk-JA3XYJ7Z-Cr1rmOui.js +11 -0
  768. package/dist/ui/assets/chunk-JA3XYJ7Z-Cr1rmOui.js.gz +0 -0
  769. package/dist/ui/assets/{chunk-JZLCHNYA-cKMooY3y.js → chunk-JZLCHNYA-BsgZ79Fa.js} +5 -5
  770. package/dist/ui/assets/chunk-JZLCHNYA-BsgZ79Fa.js.gz +0 -0
  771. package/dist/ui/assets/{chunk-MI3HLSF2-BlzO5wOE.js → chunk-MI3HLSF2-dwYeUy5S.js} +1 -1
  772. package/dist/ui/assets/chunk-MI3HLSF2-dwYeUy5S.js.gz +0 -0
  773. package/dist/ui/assets/chunk-N4CR4FBY-DEMgSRVe.js +2 -0
  774. package/dist/ui/assets/chunk-N4CR4FBY-DEMgSRVe.js.gz +0 -0
  775. package/dist/ui/assets/{chunk-QN33PNHL-DIHGQ_pd.js → chunk-QN33PNHL-DxdIDCAa.js} +1 -1
  776. package/dist/ui/assets/{chunk-QXUST7PY-C9l0muI0.js → chunk-QXUST7PY-BCK2V0i-.js} +2 -2
  777. package/dist/ui/assets/chunk-QXUST7PY-BCK2V0i-.js.gz +0 -0
  778. package/dist/ui/assets/chunk-QZHKN3VN-CALjGrEE.js +1 -0
  779. package/dist/ui/assets/chunk-S3R3BYOJ-GP3zIxrB.js +2 -0
  780. package/dist/ui/assets/chunk-S3R3BYOJ-GP3zIxrB.js.gz +0 -0
  781. package/dist/ui/assets/{chunk-TZMSLE5B-DZwI0C_2.js → chunk-TZMSLE5B-dX5RaM6g.js} +1 -1
  782. package/dist/ui/assets/chunk-TZMSLE5B-dX5RaM6g.js.gz +0 -0
  783. package/dist/ui/assets/classDiagram-2ON5EDUG-C3_RVP70.js +1 -0
  784. package/dist/ui/assets/classDiagram-v2-WZHVMYZB-C3_RVP70.js +1 -0
  785. package/dist/ui/assets/constants-GjIDNVyt.js +1 -0
  786. package/dist/ui/assets/{cose-bilkent-S5V4N54A-Ipik-oSD.js → cose-bilkent-S5V4N54A-Dx0BJVDl.js} +1 -1
  787. package/dist/ui/assets/cose-bilkent-S5V4N54A-Dx0BJVDl.js.gz +0 -0
  788. package/dist/ui/assets/cursor-QEb7m-rN.png +0 -0
  789. package/dist/ui/assets/{dagre-6UL2VRFP-BDpyWQnh.js → dagre-6UL2VRFP-DiQSUxqN.js} +1 -1
  790. package/dist/ui/assets/dagre-6UL2VRFP-DiQSUxqN.js.gz +0 -0
  791. package/dist/ui/assets/{dagre-CgA4KhUX.js → dagre-Bekd9Vdj.js} +1 -1
  792. package/dist/ui/assets/dagre-Bekd9Vdj.js.gz +0 -0
  793. package/dist/ui/assets/diagram-PSM6KHXK-DtJnDQjc.js +24 -0
  794. package/dist/ui/assets/diagram-PSM6KHXK-DtJnDQjc.js.gz +0 -0
  795. package/dist/ui/assets/{diagram-QEK2KX5R-BWPW28XI.js → diagram-QEK2KX5R-CobkCRdj.js} +1 -1
  796. package/dist/ui/assets/diagram-QEK2KX5R-CobkCRdj.js.gz +0 -0
  797. package/dist/ui/assets/{diagram-S2PKOQOG-BIHhcGoV.js → diagram-S2PKOQOG-DHEZYivc.js} +1 -1
  798. package/dist/ui/assets/diagram-S2PKOQOG-DHEZYivc.js.gz +0 -0
  799. package/dist/ui/assets/editor-DQIG-JYZ.js +43 -0
  800. package/dist/ui/assets/editor-DQIG-JYZ.js.gz +0 -0
  801. package/dist/ui/assets/emoji-B0hLmSLZ.js +3 -0
  802. package/dist/ui/assets/emoji-B0hLmSLZ.js.gz +0 -0
  803. package/dist/ui/assets/{erDiagram-Q2GNP2WA-ubTaAFcK.js → erDiagram-Q2GNP2WA-BVNeTZPQ.js} +2 -2
  804. package/dist/ui/assets/erDiagram-Q2GNP2WA-BVNeTZPQ.js.gz +0 -0
  805. package/dist/ui/assets/flowDiagram-NV44I4VS-C73VFdyk.js +162 -0
  806. package/dist/ui/assets/flowDiagram-NV44I4VS-C73VFdyk.js.gz +0 -0
  807. package/dist/ui/assets/ganttDiagram-LVOFAZNH-B_RosuD1.js +267 -0
  808. package/dist/ui/assets/ganttDiagram-LVOFAZNH-B_RosuD1.js.gz +0 -0
  809. package/dist/ui/assets/{gitGraph-F6HP7TQM-DghoobE6.js → gitGraph-F6HP7TQM-DMFIqn4h.js} +1 -1
  810. package/dist/ui/assets/gitGraphDiagram-NY62KEGX-hxbgwNA1.js +65 -0
  811. package/dist/ui/assets/gitGraphDiagram-NY62KEGX-hxbgwNA1.js.gz +0 -0
  812. package/dist/ui/assets/index-DTz1Dif6.js +64 -0
  813. package/dist/ui/assets/index-DTz1Dif6.js.gz +0 -0
  814. package/dist/ui/assets/index-qkT7Qqm2.css +1 -0
  815. package/dist/ui/assets/index-qkT7Qqm2.css.gz +0 -0
  816. package/dist/ui/assets/{info-NVLQJR56-0ZldEXPQ.js → info-NVLQJR56-DZ3K-w48.js} +1 -1
  817. package/dist/ui/assets/{infoDiagram-ER5ION4S-DMmPX-il.js → infoDiagram-ER5ION4S-CxnBJQu6.js} +1 -1
  818. package/dist/ui/assets/{journeyDiagram-XKPGCS4Q-CrVickA2.js → journeyDiagram-XKPGCS4Q-CHYNj-f8.js} +3 -3
  819. package/dist/ui/assets/journeyDiagram-XKPGCS4Q-CHYNj-f8.js.gz +0 -0
  820. package/dist/ui/assets/{kanban-definition-3W4ZIXB7-C_BsdHYL.js → kanban-definition-3W4ZIXB7-DQPCCsj2.js} +1 -1
  821. package/dist/ui/assets/kanban-definition-3W4ZIXB7-DQPCCsj2.js.gz +0 -0
  822. package/dist/ui/assets/{line-CfBP7Yic.js → line-DBRjKmfa.js} +1 -1
  823. package/dist/ui/assets/{linear-BsjageUB.js → linear-DFao5Wyp.js} +1 -1
  824. package/dist/ui/assets/linear-DFao5Wyp.js.gz +0 -0
  825. package/dist/ui/assets/{mermaid-parser.core-DZdP-NFq.js → mermaid-parser.core-DYCfacHj.js} +2 -2
  826. package/dist/ui/assets/mermaid-parser.core-DYCfacHj.js.gz +0 -0
  827. package/dist/ui/assets/mermaid.core-C6xGFSdE.js +11 -0
  828. package/dist/ui/assets/mermaid.core-C6xGFSdE.js.gz +0 -0
  829. package/dist/ui/assets/{mindmap-definition-VGOIOE7T-BbmaUjMY.js → mindmap-definition-VGOIOE7T-L3Pw-YM7.js} +1 -1
  830. package/dist/ui/assets/mindmap-definition-VGOIOE7T-L3Pw-YM7.js.gz +0 -0
  831. package/dist/ui/assets/{packet-BFZMPI3H-D_ZhkXuT.js → packet-BFZMPI3H-CpL6iNoa.js} +1 -1
  832. package/dist/ui/assets/{particles-Dv28pjOd.js → particles-CT8hcJOA.js} +1 -1
  833. package/dist/ui/assets/particles-CT8hcJOA.js.gz +0 -0
  834. package/dist/ui/assets/{pie-7BOR55EZ-Dn0Q3qNx.js → pie-7BOR55EZ-hTqChbTo.js} +1 -1
  835. package/dist/ui/assets/{pieDiagram-ADFJNKIX-BbyjfYu8.js → pieDiagram-ADFJNKIX-Bf4Nou75.js} +1 -1
  836. package/dist/ui/assets/pieDiagram-ADFJNKIX-Bf4Nou75.js.gz +0 -0
  837. package/dist/ui/assets/{quadrantDiagram-AYHSOK5B-Bc3GqMKz.js → quadrantDiagram-AYHSOK5B-DpjUTLB1.js} +3 -3
  838. package/dist/ui/assets/quadrantDiagram-AYHSOK5B-DpjUTLB1.js.gz +0 -0
  839. package/dist/ui/assets/{radar-NHE76QYJ-BHwoAy1q.js → radar-NHE76QYJ-myy7OENC.js} +1 -1
  840. package/dist/ui/assets/reactflow-Cubtnk8i.js +2 -0
  841. package/dist/ui/assets/reactflow-Cubtnk8i.js.gz +0 -0
  842. package/dist/ui/assets/{requirementDiagram-UZGBJVZJ-BQaKKL09.js → requirementDiagram-UZGBJVZJ-Bfrfh-0-.js} +1 -1
  843. package/dist/ui/assets/requirementDiagram-UZGBJVZJ-Bfrfh-0-.js.gz +0 -0
  844. package/dist/ui/assets/{sandpack-BQW_FQ7G.js → sandpack-C58bwfIS.js} +38 -38
  845. package/dist/ui/assets/sandpack-C58bwfIS.js.gz +0 -0
  846. package/dist/ui/assets/sandpackDefaults-Bkga8XAE.js +1 -0
  847. package/dist/ui/assets/sankeyDiagram-TZEHDZUN-ClZAZ6va.js +10 -0
  848. package/dist/ui/assets/sankeyDiagram-TZEHDZUN-ClZAZ6va.js.gz +0 -0
  849. package/dist/ui/assets/{sequenceDiagram-WL72ISMW-Dw32824o.js → sequenceDiagram-WL72ISMW-CNgly63p.js} +6 -6
  850. package/dist/ui/assets/sequenceDiagram-WL72ISMW-CNgly63p.js.gz +0 -0
  851. package/dist/ui/assets/src-DAeyG22O.js +34 -0
  852. package/dist/ui/assets/src-DAeyG22O.js.gz +0 -0
  853. package/dist/ui/assets/stateDiagram-FKZM4ZOC-BrEAoDpE.js +1 -0
  854. package/dist/ui/assets/stateDiagram-FKZM4ZOC-BrEAoDpE.js.gz +0 -0
  855. package/dist/ui/assets/stateDiagram-v2-4FDKWEC3-BNL52_oN.js +1 -0
  856. package/dist/ui/assets/streamdown-BdAVfkeF.js +521 -0
  857. package/dist/ui/assets/streamdown-BdAVfkeF.js.gz +0 -0
  858. package/dist/ui/assets/syntax-BOfTnQiy.js +9 -0
  859. package/dist/ui/assets/syntax-BOfTnQiy.js.gz +0 -0
  860. package/dist/ui/assets/{timeline-definition-IT6M3QCI-Jh_WZzXv.js → timeline-definition-IT6M3QCI-CaRH3k4l.js} +16 -16
  861. package/dist/ui/assets/timeline-definition-IT6M3QCI-CaRH3k4l.js.gz +0 -0
  862. package/dist/ui/assets/{treemap-KMMF4GRG-CPYIgjxE.js → treemap-KMMF4GRG-CUaLOV_B.js} +1 -1
  863. package/dist/ui/assets/{knowledgeRoutes-CivaUqha.js → useUserLocalStorage-C8sgXgXR.js} +1 -1
  864. package/dist/ui/assets/useUserLocalStorage-C8sgXgXR.js.gz +0 -0
  865. package/dist/ui/assets/{xychartDiagram-PRI3JC2R-CERc7Rdb.js → xychartDiagram-PRI3JC2R-BlhkI9T_.js} +1 -1
  866. package/dist/ui/assets/xychartDiagram-PRI3JC2R-BlhkI9T_.js.gz +0 -0
  867. package/dist/ui/index.html +13 -12
  868. package/dist/ui/index.html.gz +0 -0
  869. package/package.json +12 -10
  870. package/scripts/postinstall.js +27 -19
  871. package/dist/cli/commands/daemon/sync.d.ts.map +0 -1
  872. package/dist/ui/assets/App-9s2WHM6S.js +0 -22
  873. package/dist/ui/assets/App-9s2WHM6S.js.gz +0 -0
  874. package/dist/ui/assets/App-BAdBsEnV.css +0 -1
  875. package/dist/ui/assets/App-BAdBsEnV.css.gz +0 -0
  876. package/dist/ui/assets/ArtifactConsentModal-ParNk5kW.js +0 -1
  877. package/dist/ui/assets/ArtifactConsentModal-ParNk5kW.js.gz +0 -0
  878. package/dist/ui/assets/ArtifactFullscreenPage-VQxLMCiN.js +0 -9
  879. package/dist/ui/assets/ArtifactFullscreenPage-VQxLMCiN.js.gz +0 -0
  880. package/dist/ui/assets/AutocompleteTextarea-3RchrIgk.js +0 -18
  881. package/dist/ui/assets/AutocompleteTextarea-3RchrIgk.js.gz +0 -0
  882. package/dist/ui/assets/CodeEditor.inner-D51Z_CLQ.js +0 -8
  883. package/dist/ui/assets/CodeEditor.inner-D51Z_CLQ.js.gz +0 -0
  884. package/dist/ui/assets/ConversationView-Dyddw2b1.js +0 -34
  885. package/dist/ui/assets/ConversationView-Dyddw2b1.js.gz +0 -0
  886. package/dist/ui/assets/KnowledgePage-CdftslnF.js +0 -24
  887. package/dist/ui/assets/KnowledgePage-CdftslnF.js.gz +0 -0
  888. package/dist/ui/assets/MobileApp-BdBMpnJ1.js +0 -1
  889. package/dist/ui/assets/MobileApp-BdBMpnJ1.js.gz +0 -0
  890. package/dist/ui/assets/StreamdownDemoPage-B9wbgp2s.js.gz +0 -0
  891. package/dist/ui/assets/ThemeSwitcher-ubn6IOz9.js +0 -1
  892. package/dist/ui/assets/ThemeSwitcher-ubn6IOz9.js.gz +0 -0
  893. package/dist/ui/assets/antd-C-HfEC4E.js +0 -400
  894. package/dist/ui/assets/antd-C-HfEC4E.js.gz +0 -0
  895. package/dist/ui/assets/architecture-U656AL7Q-dkBewUpN.js +0 -1
  896. package/dist/ui/assets/architectureDiagram-VXUJARFQ-ChmZt3zk.js +0 -36
  897. package/dist/ui/assets/architectureDiagram-VXUJARFQ-ChmZt3zk.js.gz +0 -0
  898. package/dist/ui/assets/blockDiagram-VD42YOAC-CzGHAHao.js.gz +0 -0
  899. package/dist/ui/assets/c4Diagram-YG6GDRKO-DscJyaWN.js.gz +0 -0
  900. package/dist/ui/assets/channel-DvRQqEqC.js +0 -1
  901. package/dist/ui/assets/chunk-55IACEB6-DojF2pZN.js +0 -1
  902. package/dist/ui/assets/chunk-ABZYJK2D-RzDCrjE6.js.gz +0 -0
  903. package/dist/ui/assets/chunk-AGHRB4JF-jidCS5Of.js.gz +0 -0
  904. package/dist/ui/assets/chunk-ATLVNIR6-BEIIfJtC.js.gz +0 -0
  905. package/dist/ui/assets/chunk-B4BG7PRW-B8b6dQQ2.js.gz +0 -0
  906. package/dist/ui/assets/chunk-DI55MBZ5-BfATX3V8.js.gz +0 -0
  907. package/dist/ui/assets/chunk-EXTU4WIE-BKt6lPJM.js +0 -1
  908. package/dist/ui/assets/chunk-HN2XXSSU-BCHvD80g.js.gz +0 -0
  909. package/dist/ui/assets/chunk-JA3XYJ7Z-Cp6dqHnY.js +0 -11
  910. package/dist/ui/assets/chunk-JA3XYJ7Z-Cp6dqHnY.js.gz +0 -0
  911. package/dist/ui/assets/chunk-JZLCHNYA-cKMooY3y.js.gz +0 -0
  912. package/dist/ui/assets/chunk-MI3HLSF2-BlzO5wOE.js.gz +0 -0
  913. package/dist/ui/assets/chunk-N4CR4FBY-pASDorUx.js +0 -2
  914. package/dist/ui/assets/chunk-N4CR4FBY-pASDorUx.js.gz +0 -0
  915. package/dist/ui/assets/chunk-QXUST7PY-C9l0muI0.js.gz +0 -0
  916. package/dist/ui/assets/chunk-QZHKN3VN-CZskCFCf.js +0 -1
  917. package/dist/ui/assets/chunk-S3R3BYOJ-VJiLzt2o.js +0 -2
  918. package/dist/ui/assets/chunk-S3R3BYOJ-VJiLzt2o.js.gz +0 -0
  919. package/dist/ui/assets/chunk-TZMSLE5B-DZwI0C_2.js.gz +0 -0
  920. package/dist/ui/assets/classDiagram-2ON5EDUG-BFASUbmZ.js +0 -1
  921. package/dist/ui/assets/classDiagram-v2-WZHVMYZB-BFASUbmZ.js +0 -1
  922. package/dist/ui/assets/cose-bilkent-S5V4N54A-Ipik-oSD.js.gz +0 -0
  923. package/dist/ui/assets/dagre-6UL2VRFP-BDpyWQnh.js.gz +0 -0
  924. package/dist/ui/assets/dagre-CgA4KhUX.js.gz +0 -0
  925. package/dist/ui/assets/diagram-PSM6KHXK-B4GRzxLJ.js +0 -24
  926. package/dist/ui/assets/diagram-PSM6KHXK-B4GRzxLJ.js.gz +0 -0
  927. package/dist/ui/assets/diagram-QEK2KX5R-BWPW28XI.js.gz +0 -0
  928. package/dist/ui/assets/diagram-S2PKOQOG-BIHhcGoV.js.gz +0 -0
  929. package/dist/ui/assets/editor-C-HJ7Yw0.js +0 -39
  930. package/dist/ui/assets/editor-C-HJ7Yw0.js.gz +0 -0
  931. package/dist/ui/assets/emoji-D8F6B62m.js +0 -3
  932. package/dist/ui/assets/emoji-D8F6B62m.js.gz +0 -0
  933. package/dist/ui/assets/erDiagram-Q2GNP2WA-ubTaAFcK.js.gz +0 -0
  934. package/dist/ui/assets/flowDiagram-NV44I4VS-BHLCTYjI.js +0 -162
  935. package/dist/ui/assets/flowDiagram-NV44I4VS-BHLCTYjI.js.gz +0 -0
  936. package/dist/ui/assets/ganttDiagram-LVOFAZNH-ClC3pay1.js +0 -267
  937. package/dist/ui/assets/ganttDiagram-LVOFAZNH-ClC3pay1.js.gz +0 -0
  938. package/dist/ui/assets/gitGraphDiagram-NY62KEGX-Clqpiswu.js +0 -65
  939. package/dist/ui/assets/gitGraphDiagram-NY62KEGX-Clqpiswu.js.gz +0 -0
  940. package/dist/ui/assets/index-D9OElx9A.css +0 -1
  941. package/dist/ui/assets/index-D9OElx9A.css.gz +0 -0
  942. package/dist/ui/assets/index-DxPuzG7E.js +0 -350
  943. package/dist/ui/assets/index-DxPuzG7E.js.gz +0 -0
  944. package/dist/ui/assets/journeyDiagram-XKPGCS4Q-CrVickA2.js.gz +0 -0
  945. package/dist/ui/assets/kanban-definition-3W4ZIXB7-C_BsdHYL.js.gz +0 -0
  946. package/dist/ui/assets/katex-CamJ39w1.js +0 -257
  947. package/dist/ui/assets/katex-CamJ39w1.js.gz +0 -0
  948. package/dist/ui/assets/knowledgeRoutes-CivaUqha.js.gz +0 -0
  949. package/dist/ui/assets/linear-BsjageUB.js.gz +0 -0
  950. package/dist/ui/assets/mermaid-parser.core-DZdP-NFq.js.gz +0 -0
  951. package/dist/ui/assets/mermaid.core-TNrI0pHG.js +0 -11
  952. package/dist/ui/assets/mermaid.core-TNrI0pHG.js.gz +0 -0
  953. package/dist/ui/assets/message-BtWWJ9Af.js +0 -36
  954. package/dist/ui/assets/message-BtWWJ9Af.js.gz +0 -0
  955. package/dist/ui/assets/mindmap-definition-VGOIOE7T-BbmaUjMY.js.gz +0 -0
  956. package/dist/ui/assets/particles-Dv28pjOd.js.gz +0 -0
  957. package/dist/ui/assets/pieDiagram-ADFJNKIX-BbyjfYu8.js.gz +0 -0
  958. package/dist/ui/assets/quadrantDiagram-AYHSOK5B-Bc3GqMKz.js.gz +0 -0
  959. package/dist/ui/assets/reactflow-BVYPxNhc.js +0 -2
  960. package/dist/ui/assets/reactflow-BVYPxNhc.js.gz +0 -0
  961. package/dist/ui/assets/requirementDiagram-UZGBJVZJ-BQaKKL09.js.gz +0 -0
  962. package/dist/ui/assets/sandpack-BQW_FQ7G.js.gz +0 -0
  963. package/dist/ui/assets/sankeyDiagram-TZEHDZUN-DiJvDvhb.js +0 -10
  964. package/dist/ui/assets/sankeyDiagram-TZEHDZUN-DiJvDvhb.js.gz +0 -0
  965. package/dist/ui/assets/sequenceDiagram-WL72ISMW-Dw32824o.js.gz +0 -0
  966. package/dist/ui/assets/stateDiagram-FKZM4ZOC-BCOpNdHV.js +0 -1
  967. package/dist/ui/assets/stateDiagram-FKZM4ZOC-BCOpNdHV.js.gz +0 -0
  968. package/dist/ui/assets/stateDiagram-v2-4FDKWEC3-Cuqwvgfg.js +0 -1
  969. package/dist/ui/assets/syntax-VJrU5BEu.js +0 -10
  970. package/dist/ui/assets/syntax-VJrU5BEu.js.gz +0 -0
  971. package/dist/ui/assets/theme-DZtFA8b4.js +0 -1
  972. package/dist/ui/assets/timeline-definition-IT6M3QCI-Jh_WZzXv.js.gz +0 -0
  973. package/dist/ui/assets/xychartDiagram-PRI3JC2R-CERc7Rdb.js.gz +0 -0
  974. /package/dist/cli/commands/{admin → local}/sync-unix.d.ts +0 -0
@@ -12,14 +12,15 @@ var __export = (target, all) => {
12
12
  for (var name in all)
13
13
  __defProp(target, name, { get: all[name], enumerable: true });
14
14
  };
15
- var __copyProps = (to, from, except, desc7) => {
15
+ var __copyProps = (to, from, except, desc6) => {
16
16
  if (from && typeof from === "object" || typeof from === "function") {
17
17
  for (let key of __getOwnPropNames(from))
18
18
  if (!__hasOwnProp.call(to, key) && key !== except)
19
- __defProp(to, key, { get: () => from[key], enumerable: !(desc7 = __getOwnPropDesc(from, key)) || desc7.enumerable });
19
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc6 = __getOwnPropDesc(from, key)) || desc6.enumerable });
20
20
  }
21
21
  return to;
22
22
  };
23
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
23
24
  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
24
25
  // If the importer is in node compatibility mode or this is not an ESM
25
26
  // file that has been converted to a CommonJS file using a Babel-
@@ -31,9 +32,12 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
31
32
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
33
 
33
34
  // ../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.15_tsx@4.22.4_typescript@6.0.3_yaml@2.9.0/node_modules/tsup/assets/cjs_shims.js
35
+ var getImportMetaUrl, importMetaUrl;
34
36
  var init_cjs_shims = __esm({
35
37
  "../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.15_tsx@4.22.4_typescript@6.0.3_yaml@2.9.0/node_modules/tsup/assets/cjs_shims.js"() {
36
38
  "use strict";
39
+ getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
40
+ importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
37
41
  }
38
42
  });
39
43
 
@@ -156,6 +160,71 @@ var init_executor_heartbeat = __esm({
156
160
  }
157
161
  });
158
162
 
163
+ // src/config/multitenancy.ts
164
+ function detectPostgresUrl(url) {
165
+ if (!url) return false;
166
+ const lower = url.toLowerCase();
167
+ return lower.startsWith("postgresql://") || lower.startsWith("postgres://") || lower.startsWith("pg://");
168
+ }
169
+ function resolveMultiTenancyDatabaseDialect(config = {}) {
170
+ if (process.env.AGOR_DB_DIALECT === "postgresql" || process.env.AGOR_DB_DIALECT === "sqlite") {
171
+ return process.env.AGOR_DB_DIALECT;
172
+ }
173
+ if (detectPostgresUrl(process.env.DATABASE_URL)) return "postgresql";
174
+ if (config.database?.dialect === "postgresql" || config.database?.dialect === "sqlite") {
175
+ return config.database.dialect;
176
+ }
177
+ if (detectPostgresUrl(config.database?.postgresql?.url) || config.database?.postgresql?.host) {
178
+ return "postgresql";
179
+ }
180
+ return "sqlite";
181
+ }
182
+ function resolveMultiTenancyConfig(config) {
183
+ const raw = config.multi_tenancy ?? {};
184
+ const mode = raw.mode ?? "static";
185
+ return {
186
+ mode,
187
+ static_tenant_id: raw.static_tenant_id?.trim() || DEFAULT_STATIC_TENANT_ID,
188
+ ...raw.auth_claim ? { auth_claim: raw.auth_claim } : {},
189
+ ...raw.trusted_header ? { trusted_header: raw.trusted_header } : {}
190
+ };
191
+ }
192
+ function assertValidMultiTenancyConfig(config) {
193
+ const resolved = resolveMultiTenancyConfig(config);
194
+ if (resolved.mode !== "static" && resolved.mode !== "required_from_auth") {
195
+ throw new Error("Config error: multi_tenancy.mode must be one of: static, required_from_auth");
196
+ }
197
+ if (!resolved.static_tenant_id) {
198
+ throw new Error("Config error: multi_tenancy.static_tenant_id must not be empty");
199
+ }
200
+ if (resolved.auth_claim && RESERVED_AUTH_CLAIMS.has(resolved.auth_claim)) {
201
+ throw new Error(
202
+ `Config error: multi_tenancy.auth_claim cannot be reserved JWT claim '${resolved.auth_claim}'`
203
+ );
204
+ }
205
+ if (resolved.mode === "required_from_auth") {
206
+ if (resolveMultiTenancyDatabaseDialect(config) !== "postgresql") {
207
+ throw new Error(
208
+ "Config error: multi_tenancy.required_from_auth requires database.dialect: postgresql"
209
+ );
210
+ }
211
+ if (!resolved.auth_claim && !resolved.trusted_header) {
212
+ throw new Error(
213
+ "Config error: multi_tenancy.required_from_auth requires multi_tenancy.auth_claim or multi_tenancy.trusted_header"
214
+ );
215
+ }
216
+ }
217
+ }
218
+ var DEFAULT_STATIC_TENANT_ID, RESERVED_AUTH_CLAIMS;
219
+ var init_multitenancy = __esm({
220
+ "src/config/multitenancy.ts"() {
221
+ "use strict";
222
+ init_cjs_shims();
223
+ DEFAULT_STATIC_TENANT_ID = "default";
224
+ RESERVED_AUTH_CLAIMS = /* @__PURE__ */ new Set(["aud", "exp", "iat", "iss", "jti", "nbf", "sub", "type"]);
225
+ }
226
+ });
227
+
159
228
  // src/config/types.ts
160
229
  var BRANCH_STORAGE_MODES, DEFAULT_BRANCH_STORAGE_MODE;
161
230
  var init_types = __esm({
@@ -200,6 +269,7 @@ __export(config_manager_exports, {
200
269
  requireDaemonUser: () => requireDaemonUser,
201
270
  requirePublicBaseUrl: () => requirePublicBaseUrl,
202
271
  resolveBranchStorageConfig: () => resolveBranchStorageConfig,
272
+ resolveExecutionSecurityMode: () => resolveExecutionSecurityMode,
203
273
  saveConfig: () => saveConfig,
204
274
  setConfigValue: () => setConfigValue,
205
275
  unsetConfigValue: () => unsetConfigValue
@@ -209,8 +279,8 @@ function cacheKeyMatches(a, b) {
209
279
  }
210
280
  function statCacheKey(configPath) {
211
281
  try {
212
- const stat2 = (0, import_node_fs2.statSync)(configPath);
213
- return { mtimeMs: stat2.mtimeMs, size: stat2.size };
282
+ const stat = (0, import_node_fs2.statSync)(configPath);
283
+ return { mtimeMs: stat.mtimeMs, size: stat.size };
214
284
  } catch (error) {
215
285
  if (error.code === "ENOENT") {
216
286
  return NO_FILE_KEY;
@@ -238,7 +308,10 @@ function __resetConfigCacheForTests() {
238
308
  invalidateConfigCache();
239
309
  }
240
310
  function parseAndValidateConfig(content) {
241
- const parsed = import_js_yaml2.default.load(content);
311
+ if (content.trim() === "") {
312
+ return {};
313
+ }
314
+ const parsed = yaml2.load(content);
242
315
  const finalConfig = parsed || {};
243
316
  validateConfig(finalConfig);
244
317
  return finalConfig;
@@ -275,6 +348,7 @@ To update: agor config set execution.unix_user_mode insulated`
275
348
  `Config error: execution.managed_envs_execution_mode must be one of: hybrid, webhook-only`
276
349
  );
277
350
  }
351
+ assertValidMultiTenancyConfig(config);
278
352
  validateOptionalHttpUrl(
279
353
  config.external_launch,
280
354
  "login_redirect_url",
@@ -354,7 +428,7 @@ async function saveConfig(config) {
354
428
  validateConfig(config);
355
429
  await ensureAgorHome();
356
430
  const configPath = getConfigPath();
357
- const content = import_js_yaml2.default.dump(config, {
431
+ const content = yaml2.dump(config, {
358
432
  indent: 2,
359
433
  lineWidth: 120,
360
434
  noRefs: true
@@ -392,7 +466,12 @@ function getDefaultConfig() {
392
466
  // Default: sync passwords to Unix
393
467
  executor_heartbeat: resolveExecutorHeartbeatConfig()
394
468
  },
395
- analytics: getDefaultAnalyticsConfig()
469
+ analytics: getDefaultAnalyticsConfig(),
470
+ telemetry: {},
471
+ multi_tenancy: {
472
+ mode: "static",
473
+ static_tenant_id: "default"
474
+ }
396
475
  };
397
476
  }
398
477
  function expandHomePath(input) {
@@ -424,7 +503,8 @@ async function getConfigValue(key) {
424
503
  ui: { ...defaults.ui, ...config.ui },
425
504
  execution: { ...defaults.execution, ...config.execution },
426
505
  paths: { ...defaults.paths, ...config.paths },
427
- analytics: { ...defaults.analytics, ...config.analytics }
506
+ analytics: { ...defaults.analytics, ...config.analytics },
507
+ telemetry: { ...defaults.telemetry, ...config.telemetry }
428
508
  };
429
509
  const parts = key.split(".");
430
510
  let value = merged;
@@ -495,6 +575,9 @@ async function getBaseUrl() {
495
575
  if (config.daemon?.base_url) {
496
576
  return validateBaseUrl(config.daemon.base_url);
497
577
  }
578
+ if (config.ui?.base_url) {
579
+ return validateBaseUrl(config.ui.base_url);
580
+ }
498
581
  const defaults = getDefaultConfig();
499
582
  const envPort = process.env.PORT ? Number.parseInt(process.env.PORT, 10) : void 0;
500
583
  const port = envPort || config.daemon?.port || defaults.daemon?.port || DAEMON.DEFAULT_PORT;
@@ -509,8 +592,11 @@ async function requirePublicBaseUrl() {
509
592
  if (config.daemon?.base_url) {
510
593
  return validateBaseUrl(config.daemon.base_url);
511
594
  }
595
+ if (config.ui?.base_url) {
596
+ return validateBaseUrl(config.ui.base_url);
597
+ }
512
598
  throw new PublicBaseUrlNotConfiguredError(
513
- "No public base URL configured. Set the AGOR_BASE_URL environment variable or `daemon.base_url` in ~/.agor/config.yaml to the daemon's browser-reachable URL (e.g. https://agor.example.com). This is required so OAuth providers can redirect users back to a URL their browser can reach \u2014 the localhost fallback only works for browsers on the daemon machine."
599
+ "No public base URL configured. Set the AGOR_BASE_URL environment variable or `daemon.base_url` (preferred) / `ui.base_url` (legacy) in ~/.agor/config.yaml to the daemon's browser-reachable URL (e.g. https://agor.example.com). This is required so OAuth providers can redirect users back to a URL their browser can reach \u2014 the localhost fallback only works for browsers on the daemon machine."
514
600
  );
515
601
  }
516
602
  function loadConfigSync() {
@@ -580,10 +666,10 @@ function requireDaemonUser(config) {
580
666
  if (config.daemon?.unix_user) {
581
667
  return config.daemon.unix_user;
582
668
  }
583
- const unixIsolationEnabled = config.execution?.branch_rbac === true || config.execution?.unix_user_mode && config.execution.unix_user_mode !== "simple";
669
+ const unixIsolationEnabled = resolveExecutionSecurityMode(config).requiresDaemonUnixUser;
584
670
  if (unixIsolationEnabled) {
585
671
  throw new Error(
586
- "Unix isolation is enabled (branch_rbac or unix_user_mode) but daemon.unix_user is not configured.\nPlease set daemon.unix_user in ~/.agor/config.yaml to the user running the daemon.\nExample:\n daemon:\n unix_user: agor"
672
+ "Unix isolation is enabled (execution.unix_user_mode is insulated or strict) but daemon.unix_user is not configured.\nPlease set daemon.unix_user in ~/.agor/config.yaml to the user running the daemon.\nExample:\n daemon:\n unix_user: agor"
587
673
  );
588
674
  }
589
675
  const user = process.env.USER || import_node_os.default.userInfo().username;
@@ -594,19 +680,29 @@ function requireDaemonUser(config) {
594
680
  }
595
681
  return user;
596
682
  }
683
+ function resolveExecutionSecurityMode(config = loadConfigSync()) {
684
+ const unixUserMode = config.execution?.unix_user_mode ?? "simple";
685
+ const unixIsolationEnabled = unixUserMode !== "simple";
686
+ return {
687
+ appRbacEnabled: config.execution?.branch_rbac === true,
688
+ unixUserMode,
689
+ unixImpersonationEnabled: unixIsolationEnabled,
690
+ unixFsIsolationEnabled: unixIsolationEnabled,
691
+ unixGroupRefreshNeeded: unixIsolationEnabled,
692
+ requiresDaemonUnixUser: unixIsolationEnabled,
693
+ shouldInitUnixGroups: unixIsolationEnabled
694
+ };
695
+ }
597
696
  function isBranchRbacEnabled() {
598
697
  try {
599
- const config = loadConfigSync();
600
- return config.execution?.branch_rbac === true;
698
+ return resolveExecutionSecurityMode().appRbacEnabled;
601
699
  } catch {
602
700
  return false;
603
701
  }
604
702
  }
605
703
  function isUnixImpersonationEnabled() {
606
704
  try {
607
- const config = loadConfigSync();
608
- const mode = config.execution?.unix_user_mode;
609
- return mode !== void 0 && mode !== "simple";
705
+ return resolveExecutionSecurityMode().unixImpersonationEnabled;
610
706
  } catch {
611
707
  return false;
612
708
  }
@@ -632,7 +728,7 @@ function ensureBranchStorageModeAllowed(mode) {
632
728
  }
633
729
  }
634
730
  function isUnixGroupRefreshNeeded() {
635
- return isBranchRbacEnabled() || isUnixImpersonationEnabled();
731
+ return resolveExecutionSecurityMode().unixGroupRefreshNeeded;
636
732
  }
637
733
  function getDataHome() {
638
734
  if (process.env.AGOR_DATA_HOME) {
@@ -675,7 +771,7 @@ async function getReposDirAsync() {
675
771
  async function getBranchesDirAsync() {
676
772
  return import_node_path.default.join(await getDataHomeAsync(), "worktrees");
677
773
  }
678
- var import_node_fs2, import_promises, import_node_os, import_node_path, import_js_yaml2, NO_FILE, NO_FILE_KEY, cachedEntry, PublicBaseUrlNotConfiguredError, CONFIG_CREDENTIAL_KEYS;
774
+ var import_node_fs2, import_promises, import_node_os, import_node_path, yaml2, NO_FILE, NO_FILE_KEY, cachedEntry, PublicBaseUrlNotConfiguredError, CONFIG_CREDENTIAL_KEYS;
679
775
  var init_config_manager = __esm({
680
776
  "src/config/config-manager.ts"() {
681
777
  "use strict";
@@ -684,10 +780,11 @@ var init_config_manager = __esm({
684
780
  import_promises = __toESM(require("fs/promises"), 1);
685
781
  import_node_os = __toESM(require("os"), 1);
686
782
  import_node_path = __toESM(require("path"), 1);
687
- import_js_yaml2 = __toESM(require("js-yaml"), 1);
783
+ yaml2 = __toESM(require("js-yaml"), 1);
688
784
  init_analytics_defaults();
689
785
  init_constants();
690
786
  init_executor_heartbeat();
787
+ init_multitenancy();
691
788
  init_types();
692
789
  NO_FILE = -1;
693
790
  NO_FILE_KEY = { mtimeMs: NO_FILE, size: 0 };
@@ -710,6 +807,21 @@ var init_config_manager = __esm({
710
807
  }
711
808
  });
712
809
 
810
+ // src/db/tenant-context.ts
811
+ function getCurrentTenantId() {
812
+ const store = tenantDatabaseScope.getStore();
813
+ return store?.kind === "tenant" ? store.tenantId : void 0;
814
+ }
815
+ var import_node_async_hooks, tenantDatabaseScope;
816
+ var init_tenant_context = __esm({
817
+ "src/db/tenant-context.ts"() {
818
+ "use strict";
819
+ init_cjs_shims();
820
+ import_node_async_hooks = require("async_hooks");
821
+ tenantDatabaseScope = new import_node_async_hooks.AsyncLocalStorage();
822
+ }
823
+ });
824
+
713
825
  // src/db/database-wrapper.ts
714
826
  var database_wrapper_exports = {};
715
827
  __export(database_wrapper_exports, {
@@ -775,7 +887,7 @@ function dateTruncUtc(db, column, bucket) {
775
887
  }
776
888
  } else {
777
889
  return import_drizzle_orm.sql`to_char(
778
- date_trunc(${bucket}, ${column} AT TIME ZONE 'UTC'),
890
+ date_trunc(${import_drizzle_orm.sql.raw(`'${bucket}'`)}, ${column} AT TIME ZONE 'UTC'),
779
891
  'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"'
780
892
  )`;
781
893
  }
@@ -797,12 +909,12 @@ function advisoryLockKeyForUuid(uuid) {
797
909
  const FNV_OFFSET = 0xcbf29ce484222325n;
798
910
  const FNV_PRIME = 0x100000001b3n;
799
911
  const MASK_64 = 0xffffffffffffffffn;
800
- let hash2 = FNV_OFFSET;
912
+ let hash = FNV_OFFSET;
801
913
  for (let i = 0; i < uuid.length; i++) {
802
- hash2 ^= BigInt(uuid.charCodeAt(i));
803
- hash2 = hash2 * FNV_PRIME & MASK_64;
914
+ hash ^= BigInt(uuid.charCodeAt(i));
915
+ hash = hash * FNV_PRIME & MASK_64;
804
916
  }
805
- return hash2 > 0x7fffffffffffffffn ? hash2 - 0x10000000000000000n : hash2;
917
+ return hash > 0x7fffffffffffffffn ? hash - 0x10000000000000000n : hash;
806
918
  }
807
919
  async function executeRaw(db, query) {
808
920
  if (isSQLiteDatabase(db)) {
@@ -830,21 +942,36 @@ async function getOne(db, table, where) {
830
942
  }
831
943
  async function insertOne(db, table, values) {
832
944
  if (isSQLiteDatabase(db)) {
833
- const result = await db.insert(table).values(values).returning();
945
+ const result = await db.insert(table).values(withTenantInsertValues(values, table)).returning();
834
946
  return result;
835
947
  } else {
836
- const result = await db.insert(table).values(values).returning();
948
+ const result = await db.insert(table).values(withTenantInsertValues(values, table)).returning();
837
949
  return result[0];
838
950
  }
839
951
  }
840
- function wrapQuery(query, db) {
952
+ function tableHasTenantColumn(table) {
953
+ return Boolean(table && "tenant_id" in table);
954
+ }
955
+ function withTenantInsertValues(values, table) {
956
+ const tenantId = getCurrentTenantId();
957
+ if (!tenantId || !tableHasTenantColumn(table)) return values;
958
+ const stamp = (row) => {
959
+ if (!row || typeof row !== "object" || Array.isArray(row)) return row;
960
+ if ("tenant_id" in row) return row;
961
+ return { tenant_id: tenantId, ...row };
962
+ };
963
+ return Array.isArray(values) ? values.map(stamp) : stamp(values);
964
+ }
965
+ function wrapQuery(query, db, table) {
841
966
  return {
842
967
  ...query,
843
968
  one: async () => {
844
969
  if (isSQLiteDatabase(db)) {
845
970
  return await query.get();
846
971
  } else {
847
- const results = await query.limit(1);
972
+ const results = await query.limit(
973
+ 1
974
+ );
848
975
  return results[0] || null;
849
976
  }
850
977
  },
@@ -866,30 +993,55 @@ function wrapQuery(query, db) {
866
993
  return { rowsAffected: result.length || 0 };
867
994
  }
868
995
  },
869
- // biome-ignore lint/suspicious/noExplicitAny: Drizzle query builder types vary by dialect
870
996
  returning: () => wrapReturning(query.returning(), db),
871
997
  // Preserve chainable methods
872
- // biome-ignore lint/suspicious/noExplicitAny: These methods accept varying argument types from Drizzle
873
- where: (...args) => wrapQuery(query.where(...args), db),
874
- // biome-ignore lint/suspicious/noExplicitAny: These methods accept varying argument types from Drizzle
875
- limit: (...args) => wrapQuery(query.limit(...args), db),
876
- // biome-ignore lint/suspicious/noExplicitAny: These methods accept varying argument types from Drizzle
877
- offset: (...args) => wrapQuery(query.offset(...args), db),
878
- // biome-ignore lint/suspicious/noExplicitAny: These methods accept varying argument types from Drizzle
879
- orderBy: (...args) => wrapQuery(query.orderBy(...args), db),
880
- // biome-ignore lint/suspicious/noExplicitAny: These methods accept varying argument types from Drizzle
881
- groupBy: (...args) => wrapQuery(query.groupBy(...args), db),
882
- // biome-ignore lint/suspicious/noExplicitAny: These methods accept varying argument types from Drizzle
883
- set: (...args) => wrapQuery(query.set(...args), db),
884
- // biome-ignore lint/suspicious/noExplicitAny: These methods accept varying argument types from Drizzle
885
- values: (...args) => wrapQuery(query.values(...args), db),
886
- // biome-ignore lint/suspicious/noExplicitAny: These methods accept varying argument types from Drizzle
887
- innerJoin: (...args) => wrapQuery(query.innerJoin(...args), db),
888
- // biome-ignore lint/suspicious/noExplicitAny: These methods accept varying argument types from Drizzle
889
- leftJoin: (...args) => wrapQuery(query.leftJoin(...args), db),
890
- onConflictDoNothing: (...args) => (
891
- // biome-ignore lint/suspicious/noExplicitAny: Drizzle exposes onConflictDoNothing on both dialects after .values()
892
- wrapQuery(query.onConflictDoNothing(...args), db)
998
+ where: (...args) => wrapQuery(
999
+ query.where(...args),
1000
+ db,
1001
+ table
1002
+ ),
1003
+ limit: (...args) => wrapQuery(
1004
+ query.limit(...args),
1005
+ db,
1006
+ table
1007
+ ),
1008
+ offset: (...args) => wrapQuery(
1009
+ query.offset(...args),
1010
+ db,
1011
+ table
1012
+ ),
1013
+ orderBy: (...args) => wrapQuery(
1014
+ query.orderBy(...args),
1015
+ db,
1016
+ table
1017
+ ),
1018
+ groupBy: (...args) => wrapQuery(
1019
+ query.groupBy(...args),
1020
+ db,
1021
+ table
1022
+ ),
1023
+ set: (...args) => wrapQuery(query.set(...args), db, table),
1024
+ values: (...args) => wrapQuery(
1025
+ query.values(
1026
+ ...args.map((arg) => withTenantInsertValues(arg, table))
1027
+ ),
1028
+ db,
1029
+ table
1030
+ ),
1031
+ innerJoin: (...args) => wrapQuery(
1032
+ query.innerJoin(...args),
1033
+ db,
1034
+ table
1035
+ ),
1036
+ leftJoin: (...args) => wrapQuery(
1037
+ query.leftJoin(...args),
1038
+ db,
1039
+ table
1040
+ ),
1041
+ onConflictDoNothing: (...args) => wrapQuery(
1042
+ query.onConflictDoNothing(...args),
1043
+ db,
1044
+ table
893
1045
  )
894
1046
  };
895
1047
  }
@@ -922,7 +1074,7 @@ function select(db, columns) {
922
1074
  }
923
1075
  function insert(db, table) {
924
1076
  const query = db.insert(table);
925
- return wrapQuery(query, db);
1077
+ return wrapQuery(query, db, table);
926
1078
  }
927
1079
  function update(db, table) {
928
1080
  const query = db.update(table);
@@ -962,6 +1114,7 @@ var init_database_wrapper = __esm({
962
1114
  "use strict";
963
1115
  init_cjs_shims();
964
1116
  import_drizzle_orm = require("drizzle-orm");
1117
+ init_tenant_context();
965
1118
  }
966
1119
  });
967
1120
 
@@ -1166,15 +1319,35 @@ var init_schedule = __esm({
1166
1319
  });
1167
1320
 
1168
1321
  // src/types/session.ts
1322
+ var SessionStatus, EXECUTING_SESSION_STATUSES;
1169
1323
  var init_session = __esm({
1170
1324
  "src/types/session.ts"() {
1171
1325
  "use strict";
1172
1326
  init_cjs_shims();
1327
+ SessionStatus = {
1328
+ IDLE: "idle",
1329
+ RUNNING: "running",
1330
+ STOPPING: "stopping",
1331
+ // Stop requested, waiting for task to stop
1332
+ AWAITING_PERMISSION: "awaiting_permission",
1333
+ AWAITING_INPUT: "awaiting_input",
1334
+ // Legacy / pre-#1177: AskUserQuestion was disallowed at the SDK; new sessions never enter this state, kept for historical rows
1335
+ TIMED_OUT: "timed_out",
1336
+ // Permission/input request timed out, executor exited — user must re-prompt
1337
+ COMPLETED: "completed",
1338
+ FAILED: "failed"
1339
+ };
1340
+ EXECUTING_SESSION_STATUSES = /* @__PURE__ */ new Set([
1341
+ SessionStatus.RUNNING,
1342
+ SessionStatus.STOPPING,
1343
+ SessionStatus.AWAITING_PERMISSION,
1344
+ SessionStatus.AWAITING_INPUT
1345
+ ]);
1173
1346
  }
1174
1347
  });
1175
1348
 
1176
1349
  // src/types/task.ts
1177
- var TaskStatus, TERMINAL_TASK_STATUSES;
1350
+ var TaskStatus, TERMINAL_TASK_STATUSES, EXECUTING_TASK_STATUSES;
1178
1351
  var init_task = __esm({
1179
1352
  "src/types/task.ts"() {
1180
1353
  "use strict";
@@ -1202,6 +1375,12 @@ var init_task = __esm({
1202
1375
  TaskStatus.STOPPED,
1203
1376
  TaskStatus.TIMED_OUT
1204
1377
  ]);
1378
+ EXECUTING_TASK_STATUSES = /* @__PURE__ */ new Set([
1379
+ TaskStatus.RUNNING,
1380
+ TaskStatus.STOPPING,
1381
+ TaskStatus.AWAITING_PERMISSION,
1382
+ TaskStatus.AWAITING_INPUT
1383
+ ]);
1205
1384
  }
1206
1385
  });
1207
1386
 
@@ -1213,6 +1392,14 @@ var init_template = __esm({
1213
1392
  }
1214
1393
  });
1215
1394
 
1395
+ // src/types/tenant.ts
1396
+ var init_tenant = __esm({
1397
+ "src/types/tenant.ts"() {
1398
+ "use strict";
1399
+ init_cjs_shims();
1400
+ }
1401
+ });
1402
+
1216
1403
  // src/types/ui.ts
1217
1404
  var init_ui = __esm({
1218
1405
  "src/types/ui.ts"() {
@@ -1318,6 +1505,7 @@ var init_types2 = __esm({
1318
1505
  init_session();
1319
1506
  init_task();
1320
1507
  init_template();
1508
+ init_tenant();
1321
1509
  init_ui();
1322
1510
  init_user();
1323
1511
  init_utils();
@@ -1343,6 +1531,7 @@ __export(schema_postgres_exports, {
1343
1531
  cardTypes: () => cardTypes,
1344
1532
  cards: () => cards,
1345
1533
  gatewayChannels: () => gatewayChannels,
1534
+ gatewayOutboundMessages: () => gatewayOutboundMessages,
1346
1535
  groupMemberships: () => groupMemberships,
1347
1536
  groups: () => groups,
1348
1537
  kbDocumentUnits: () => kbDocumentUnits,
@@ -1361,6 +1550,8 @@ __export(schema_postgres_exports, {
1361
1550
  serializedSessions: () => serializedSessions,
1362
1551
  sessionEnvSelections: () => sessionEnvSelections,
1363
1552
  sessionMcpServers: () => sessionMcpServers,
1553
+ sessionRelationships: () => sessionRelationships,
1554
+ sessionRelationshipsRelations: () => sessionRelationshipsRelations,
1364
1555
  sessions: () => sessions,
1365
1556
  sessionsRelations: () => sessionsRelations,
1366
1557
  tasks: () => tasks,
@@ -1369,7 +1560,7 @@ __export(schema_postgres_exports, {
1369
1560
  userMcpOauthTokens: () => userMcpOauthTokens,
1370
1561
  users: () => users
1371
1562
  });
1372
- var import_drizzle_orm2, import_pg_core, bytea, t, sessions, tasks, serializedSessions, messages, boards, repos, branches, branchOwners, boardOwners, schedules, users, groups, groupMemberships, branchGroupGrants, boardGroupGrants, appVariables, userApiKeys, mcpServers, cardTypes, cards, artifacts, artifactTrustGrants, boardObjects, sessionMcpServers, userMcpOauthTokens, boardComments, gatewayChannels, threadSessionMap, sessionEnvSelections, kbNamespaces, kbNamespaceAcl, kbDocuments, kbDocumentVersions, kbDocumentUnits, kbEmbeddingSpaces, kbGraphNodes, kbGraphEdges, sessionsRelations, branchesRelations, schedulesRelations;
1563
+ var import_drizzle_orm2, import_pg_core, bytea, t, sessions, sessionRelationships, tasks, serializedSessions, messages, boards, repos, branches, branchOwners, boardOwners, schedules, users, groups, groupMemberships, branchGroupGrants, boardGroupGrants, appVariables, userApiKeys, mcpServers, cardTypes, cards, artifacts, artifactTrustGrants, boardObjects, sessionMcpServers, userMcpOauthTokens, boardComments, gatewayChannels, threadSessionMap, gatewayOutboundMessages, sessionEnvSelections, kbNamespaces, kbNamespaceAcl, kbDocuments, kbDocumentVersions, kbDocumentUnits, kbEmbeddingSpaces, kbGraphNodes, kbGraphEdges, sessionsRelations, sessionRelationshipsRelations, branchesRelations, schedulesRelations;
1373
1564
  var init_schema_postgres = __esm({
1374
1565
  "src/db/schema.postgres.ts"() {
1375
1566
  "use strict";
@@ -1390,6 +1581,7 @@ var init_schema_postgres = __esm({
1390
1581
  sessions = (0, import_pg_core.pgTable)(
1391
1582
  "sessions",
1392
1583
  {
1584
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1393
1585
  // Primary identity
1394
1586
  session_id: (0, import_pg_core.varchar)("session_id", { length: 36 }).primaryKey(),
1395
1587
  created_at: t.timestamp("created_at").notNull(),
@@ -1449,7 +1641,9 @@ var init_schema_postgres = __esm({
1449
1641
  data: t.json("data").$type().notNull()
1450
1642
  },
1451
1643
  (table) => ({
1644
+ tenantIdx: (0, import_pg_core.index)("sessions_tenant_id_idx").on(table.tenant_id),
1452
1645
  statusIdx: (0, import_pg_core.index)("sessions_status_idx").on(table.status),
1646
+ statusReadyIdx: (0, import_pg_core.index)("sessions_status_ready_idx").on(table.status, table.ready_for_prompt),
1453
1647
  agenticToolIdx: (0, import_pg_core.index)("sessions_agentic_tool_idx").on(table.agentic_tool),
1454
1648
  boardIdx: (0, import_pg_core.index)("sessions_board_idx").on(table.board_id),
1455
1649
  branchIdx: (0, import_pg_core.index)("sessions_branch_idx").on(table.branch_id),
@@ -1461,12 +1655,57 @@ var init_schema_postgres = __esm({
1461
1655
  // Partial unique index — covering for the scheduler's dedup lookup
1462
1656
  // AND serves as the DB-level guard against check-then-create races
1463
1657
  // in spawnScheduledSession.
1464
- scheduleRunUnique: (0, import_pg_core.uniqueIndex)("sessions_schedule_run_unique").on(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`)
1658
+ 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`)
1659
+ })
1660
+ );
1661
+ sessionRelationships = (0, import_pg_core.pgTable)(
1662
+ "session_relationships",
1663
+ {
1664
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1665
+ relationship_id: (0, import_pg_core.varchar)("relationship_id", { length: 36 }).primaryKey(),
1666
+ source_session_id: (0, import_pg_core.varchar)("source_session_id", { length: 36 }).notNull().references(() => sessions.session_id, { onDelete: "cascade" }),
1667
+ target_session_id: (0, import_pg_core.varchar)("target_session_id", { length: 36 }).notNull().references(() => sessions.session_id, { onDelete: "cascade" }),
1668
+ relationship_type: (0, import_pg_core.text)("relationship_type", { enum: ["remote_create"] }).notNull(),
1669
+ created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }).notNull(),
1670
+ created_at: t.timestamp("created_at").notNull(),
1671
+ updated_at: t.timestamp("updated_at"),
1672
+ callback_enabled: t.bool("callback_enabled").notNull().default(false),
1673
+ callback_session_id: (0, import_pg_core.varchar)("callback_session_id", { length: 36 }).references(
1674
+ () => sessions.session_id,
1675
+ {
1676
+ onDelete: "set null"
1677
+ }
1678
+ ),
1679
+ data: t.json("data")
1680
+ },
1681
+ (table) => ({
1682
+ tenantIdx: (0, import_pg_core.index)("session_relationships_tenant_id_idx").on(table.tenant_id),
1683
+ sourceIdx: (0, import_pg_core.index)("session_relationships_source_idx").on(table.source_session_id),
1684
+ targetIdx: (0, import_pg_core.index)("session_relationships_target_idx").on(table.target_session_id),
1685
+ callbackIdx: (0, import_pg_core.index)("session_relationships_callback_idx").on(table.callback_session_id),
1686
+ // Composite indexes so the OR predicate in dispatchCompletionCallbacks
1687
+ // (WHERE source_session_id = $1 OR target_session_id = $2) uses BitmapOr
1688
+ // over these instead of a full tenant table scan via tenant_id_idx.
1689
+ tenantSourceIdx: (0, import_pg_core.index)("session_relationships_tenant_source_idx").on(
1690
+ table.tenant_id,
1691
+ table.source_session_id
1692
+ ),
1693
+ tenantTargetIdx: (0, import_pg_core.index)("session_relationships_tenant_target_idx").on(
1694
+ table.tenant_id,
1695
+ table.target_session_id
1696
+ ),
1697
+ sourceTargetTypeUnique: (0, import_pg_core.uniqueIndex)("session_relationships_source_target_type_unique").on(
1698
+ table.tenant_id,
1699
+ table.source_session_id,
1700
+ table.target_session_id,
1701
+ table.relationship_type
1702
+ )
1465
1703
  })
1466
1704
  );
1467
1705
  tasks = (0, import_pg_core.pgTable)(
1468
1706
  "tasks",
1469
1707
  {
1708
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1470
1709
  task_id: (0, import_pg_core.varchar)("task_id", { length: 36 }).primaryKey(),
1471
1710
  session_id: (0, import_pg_core.varchar)("session_id", { length: 36 }).notNull().references(() => sessions.session_id, { onDelete: "cascade" }),
1472
1711
  created_at: t.timestamp("created_at").notNull(),
@@ -1496,19 +1735,23 @@ var init_schema_postgres = __esm({
1496
1735
  data: t.json("data").$type().notNull()
1497
1736
  },
1498
1737
  (table) => ({
1738
+ tenantIdx: (0, import_pg_core.index)("tasks_tenant_id_idx").on(table.tenant_id),
1499
1739
  sessionIdx: (0, import_pg_core.index)("tasks_session_idx").on(table.session_id),
1500
1740
  statusIdx: (0, import_pg_core.index)("tasks_status_idx").on(table.status),
1501
1741
  createdIdx: (0, import_pg_core.index)("tasks_created_idx").on(table.created_at),
1742
+ // Composite for "latest task for session" queries (ORDER BY created_at DESC LIMIT 1).
1743
+ sessionCreatedIdx: (0, import_pg_core.index)("tasks_session_created_idx").on(table.session_id, table.created_at),
1502
1744
  queueIdx: (0, import_pg_core.index)("tasks_queue_idx").on(table.session_id, table.status, table.queue_position),
1503
1745
  // Partial unique index — defense-in-depth for `tasks.createPending` race
1504
1746
  // serialization. Only QUEUED rows are constrained; CREATED/RUNNING/done
1505
1747
  // rows have NULL queue_position and are unaffected.
1506
- queuedPositionUnique: (0, import_pg_core.uniqueIndex)("tasks_queued_position_unique").on(table.session_id, table.queue_position).where(import_drizzle_orm2.sql`${table.status} = 'queued'`)
1748
+ 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'`)
1507
1749
  })
1508
1750
  );
1509
1751
  serializedSessions = (0, import_pg_core.pgTable)(
1510
1752
  "serialized_sessions",
1511
1753
  {
1754
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1512
1755
  id: (0, import_pg_core.varchar)("id", { length: 36 }).primaryKey(),
1513
1756
  session_id: (0, import_pg_core.varchar)("session_id", { length: 36 }).notNull().references(() => sessions.session_id, { onDelete: "cascade" }),
1514
1757
  branch_id: (0, import_pg_core.varchar)("branch_id", { length: 36 }).notNull().references(() => branches.branch_id, { onDelete: "cascade" }),
@@ -1524,6 +1767,7 @@ var init_schema_postgres = __esm({
1524
1767
  // gzipped; NULL while status='processing'
1525
1768
  },
1526
1769
  (table) => ({
1770
+ tenantIdx: (0, import_pg_core.index)("serialized_sessions_tenant_id_idx").on(table.tenant_id),
1527
1771
  sessionTurnIdx: (0, import_pg_core.index)("serialized_sessions_session_turn_idx").on(
1528
1772
  table.session_id,
1529
1773
  table.turn_index
@@ -1534,6 +1778,7 @@ var init_schema_postgres = __esm({
1534
1778
  messages = (0, import_pg_core.pgTable)(
1535
1779
  "messages",
1536
1780
  {
1781
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1537
1782
  // Primary identity
1538
1783
  message_id: (0, import_pg_core.varchar)("message_id", { length: 36 }).primaryKey(),
1539
1784
  created_at: t.timestamp("created_at").notNull(),
@@ -1573,15 +1818,23 @@ var init_schema_postgres = __esm({
1573
1818
  data: t.json("data").$type().notNull()
1574
1819
  },
1575
1820
  (table) => ({
1821
+ tenantIdx: (0, import_pg_core.index)("messages_tenant_id_idx").on(table.tenant_id),
1822
+ tenantTimestampIdx: (0, import_pg_core.index)("messages_tenant_timestamp_idx").on(table.tenant_id, table.timestamp),
1576
1823
  // Indexes for efficient lookups
1577
1824
  sessionIdx: (0, import_pg_core.index)("messages_session_id_idx").on(table.session_id),
1578
1825
  taskIdx: (0, import_pg_core.index)("messages_task_id_idx").on(table.task_id),
1579
- sessionIndexIdx: (0, import_pg_core.index)("messages_session_index_idx").on(table.session_id, table.index)
1826
+ sessionIndexIdx: (0, import_pg_core.index)("messages_session_index_idx").on(table.session_id, table.index),
1827
+ timestampIdx: (0, import_pg_core.index)("messages_timestamp_idx").on(table.timestamp),
1828
+ sessionTimestampIdx: (0, import_pg_core.index)("messages_session_timestamp_idx").on(
1829
+ table.session_id,
1830
+ table.timestamp
1831
+ )
1580
1832
  })
1581
1833
  );
1582
1834
  boards = (0, import_pg_core.pgTable)(
1583
1835
  "boards",
1584
1836
  {
1837
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1585
1838
  board_id: (0, import_pg_core.varchar)("board_id", { length: 36 }).primaryKey(),
1586
1839
  created_at: t.timestamp("created_at").notNull(),
1587
1840
  updated_at: t.timestamp("updated_at"),
@@ -1589,7 +1842,7 @@ var init_schema_postgres = __esm({
1589
1842
  created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }).notNull(),
1590
1843
  // Materialized for lookups
1591
1844
  name: (0, import_pg_core.text)("name").notNull(),
1592
- slug: (0, import_pg_core.text)("slug").unique(),
1845
+ slug: (0, import_pg_core.text)("slug"),
1593
1846
  primary_assistant_id: (0, import_pg_core.varchar)("primary_assistant_id", { length: 36 }).references(
1594
1847
  () => branches.branch_id,
1595
1848
  {
@@ -1604,18 +1857,21 @@ var init_schema_postgres = __esm({
1604
1857
  archived_by: (0, import_pg_core.varchar)("archived_by", { length: 36 })
1605
1858
  },
1606
1859
  (table) => ({
1860
+ tenantIdx: (0, import_pg_core.index)("boards_tenant_id_idx").on(table.tenant_id),
1607
1861
  nameIdx: (0, import_pg_core.index)("boards_name_idx").on(table.name),
1608
- slugIdx: (0, import_pg_core.index)("boards_slug_idx").on(table.slug)
1862
+ slugIdx: (0, import_pg_core.index)("boards_slug_idx").on(table.slug),
1863
+ slugTenantUnique: (0, import_pg_core.uniqueIndex)("boards_tenant_slug_unique").on(table.tenant_id, table.slug)
1609
1864
  })
1610
1865
  );
1611
1866
  repos = (0, import_pg_core.pgTable)(
1612
1867
  "repos",
1613
1868
  {
1869
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1614
1870
  repo_id: (0, import_pg_core.varchar)("repo_id", { length: 36 }).primaryKey(),
1615
1871
  created_at: t.timestamp("created_at").notNull(),
1616
1872
  updated_at: t.timestamp("updated_at"),
1617
1873
  // Materialized for querying
1618
- slug: (0, import_pg_core.text)("slug").notNull().unique(),
1874
+ slug: (0, import_pg_core.text)("slug").notNull(),
1619
1875
  repo_type: (0, import_pg_core.text)("repo_type", { enum: ["remote", "local"] }).notNull().default("remote"),
1620
1876
  // Unix group for repo-level git access (agor_rp_<short-id>)
1621
1877
  // Users who have access to ANY branch in this repo get added to this group.
@@ -1626,12 +1882,15 @@ var init_schema_postgres = __esm({
1626
1882
  data: t.json("data").$type().notNull()
1627
1883
  },
1628
1884
  (table) => ({
1629
- slugIdx: (0, import_pg_core.index)("repos_slug_idx").on(table.slug)
1885
+ tenantIdx: (0, import_pg_core.index)("repos_tenant_id_idx").on(table.tenant_id),
1886
+ slugIdx: (0, import_pg_core.index)("repos_slug_idx").on(table.slug),
1887
+ slugTenantUnique: (0, import_pg_core.uniqueIndex)("repos_tenant_slug_unique").on(table.tenant_id, table.slug)
1630
1888
  })
1631
1889
  );
1632
1890
  branches = (0, import_pg_core.pgTable)(
1633
1891
  "branches",
1634
1892
  {
1893
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1635
1894
  // Primary identity
1636
1895
  branch_id: (0, import_pg_core.varchar)("branch_id", { length: 36 }).primaryKey(),
1637
1896
  repo_id: (0, import_pg_core.varchar)("repo_id", { length: 36 }).notNull().references(() => repos.repo_id, { onDelete: "cascade" }),
@@ -1706,6 +1965,7 @@ var init_schema_postgres = __esm({
1706
1965
  data: t.json("data").$type().notNull()
1707
1966
  },
1708
1967
  (table) => ({
1968
+ tenantIdx: (0, import_pg_core.index)("branches_tenant_id_idx").on(table.tenant_id),
1709
1969
  repoIdx: (0, import_pg_core.index)("branches_repo_idx").on(table.repo_id),
1710
1970
  nameIdx: (0, import_pg_core.index)("branches_name_idx").on(table.name),
1711
1971
  refIdx: (0, import_pg_core.index)("branches_ref_idx").on(table.ref),
@@ -1719,22 +1979,26 @@ var init_schema_postgres = __esm({
1719
1979
  branchOwners = (0, import_pg_core.pgTable)(
1720
1980
  "branch_owners",
1721
1981
  {
1982
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1722
1983
  branch_id: (0, import_pg_core.varchar)("branch_id", { length: 36 }).notNull().references(() => branches.branch_id, { onDelete: "cascade" }),
1723
1984
  user_id: (0, import_pg_core.varchar)("user_id", { length: 36 }).notNull().references(() => users.user_id, { onDelete: "cascade" }),
1724
1985
  created_at: t.timestamp("created_at").defaultNow()
1725
1986
  },
1726
1987
  (table) => ({
1988
+ tenantIdx: (0, import_pg_core.index)("branch_owners_tenant_id_idx").on(table.tenant_id),
1727
1989
  pk: (0, import_pg_core.primaryKey)({ columns: [table.branch_id, table.user_id] })
1728
1990
  })
1729
1991
  );
1730
1992
  boardOwners = (0, import_pg_core.pgTable)(
1731
1993
  "board_owners",
1732
1994
  {
1995
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1733
1996
  board_id: (0, import_pg_core.varchar)("board_id", { length: 36 }).notNull().references(() => boards.board_id, { onDelete: "cascade" }),
1734
1997
  user_id: (0, import_pg_core.varchar)("user_id", { length: 36 }).notNull().references(() => users.user_id, { onDelete: "cascade" }),
1735
1998
  created_at: t.timestamp("created_at")
1736
1999
  },
1737
2000
  (table) => ({
2001
+ tenantIdx: (0, import_pg_core.index)("board_owners_tenant_id_idx").on(table.tenant_id),
1738
2002
  pk: (0, import_pg_core.primaryKey)({ columns: [table.board_id, table.user_id] }),
1739
2003
  userIdx: (0, import_pg_core.index)("board_owners_user_idx").on(table.user_id)
1740
2004
  })
@@ -1742,6 +2006,7 @@ var init_schema_postgres = __esm({
1742
2006
  schedules = (0, import_pg_core.pgTable)(
1743
2007
  "schedules",
1744
2008
  {
2009
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1745
2010
  schedule_id: (0, import_pg_core.varchar)("schedule_id", { length: 36 }).primaryKey(),
1746
2011
  branch_id: (0, import_pg_core.varchar)("branch_id", { length: 36 }).notNull().references(() => branches.branch_id, { onDelete: "cascade" }),
1747
2012
  name: (0, import_pg_core.text)("name").notNull(),
@@ -1765,6 +2030,7 @@ var init_schema_postgres = __esm({
1765
2030
  created_by: (0, import_pg_core.varchar)("created_by", { length: 36 }).notNull().references(() => users.user_id)
1766
2031
  },
1767
2032
  (table) => ({
2033
+ tenantIdx: (0, import_pg_core.index)("schedules_tenant_id_idx").on(table.tenant_id),
1768
2034
  enabledNextRunIdx: (0, import_pg_core.index)("schedules_enabled_next_run_idx").on(table.enabled, table.next_run_at),
1769
2035
  branchIdx: (0, import_pg_core.index)("schedules_branch_idx").on(table.branch_id),
1770
2036
  createdByIdx: (0, import_pg_core.index)("schedules_created_by_idx").on(table.created_by)
@@ -1773,12 +2039,13 @@ var init_schema_postgres = __esm({
1773
2039
  users = (0, import_pg_core.pgTable)(
1774
2040
  "users",
1775
2041
  {
2042
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1776
2043
  // Primary identity
1777
2044
  user_id: (0, import_pg_core.varchar)("user_id", { length: 36 }).primaryKey(),
1778
2045
  created_at: t.timestamp("created_at").notNull(),
1779
2046
  updated_at: t.timestamp("updated_at"),
1780
2047
  // Materialized for auth lookups
1781
- email: (0, import_pg_core.text)("email").unique().notNull(),
2048
+ email: (0, import_pg_core.text)("email").notNull(),
1782
2049
  password: (0, import_pg_core.text)("password").notNull(),
1783
2050
  // bcrypt hashed
1784
2051
  // Basic profile (materialized for display)
@@ -1794,16 +2061,22 @@ var init_schema_postgres = __esm({
1794
2061
  onboarding_completed: t.bool("onboarding_completed").notNull().default(false),
1795
2062
  // Force password change flag (admin-settable, auto-cleared on password change)
1796
2063
  must_change_password: t.bool("must_change_password").notNull().default(false),
2064
+ // Auth invalidation marker. Password changes set this timestamp so any
2065
+ // previously issued browser access or refresh token is rejected.
2066
+ tokens_valid_after: t.timestamp("tokens_valid_after"),
1797
2067
  // JSON blob for profile/preferences
1798
2068
  data: t.json("data").$type().notNull()
1799
2069
  },
1800
2070
  (table) => ({
1801
- emailIdx: (0, import_pg_core.index)("users_email_idx").on(table.email)
2071
+ tenantIdx: (0, import_pg_core.index)("users_tenant_id_idx").on(table.tenant_id),
2072
+ emailIdx: (0, import_pg_core.index)("users_email_idx").on(table.email),
2073
+ emailTenantUnique: (0, import_pg_core.uniqueIndex)("users_tenant_email_unique").on(table.tenant_id, table.email)
1802
2074
  })
1803
2075
  );
1804
2076
  groups = (0, import_pg_core.pgTable)(
1805
2077
  "groups",
1806
2078
  {
2079
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1807
2080
  group_id: (0, import_pg_core.varchar)("group_id", { length: 36 }).primaryKey(),
1808
2081
  name: (0, import_pg_core.text)("name").notNull(),
1809
2082
  slug: (0, import_pg_core.text)("slug").notNull(),
@@ -1816,13 +2089,15 @@ var init_schema_postgres = __esm({
1816
2089
  updated_at: t.timestamp("updated_at")
1817
2090
  },
1818
2091
  (table) => ({
1819
- slugIdx: (0, import_pg_core.uniqueIndex)("groups_slug_idx").on(table.slug),
2092
+ tenantIdx: (0, import_pg_core.index)("groups_tenant_id_idx").on(table.tenant_id),
2093
+ slugIdx: (0, import_pg_core.uniqueIndex)("groups_tenant_slug_unique").on(table.tenant_id, table.slug),
1820
2094
  archivedIdx: (0, import_pg_core.index)("groups_archived_idx").on(table.archived)
1821
2095
  })
1822
2096
  );
1823
2097
  groupMemberships = (0, import_pg_core.pgTable)(
1824
2098
  "group_memberships",
1825
2099
  {
2100
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1826
2101
  group_id: (0, import_pg_core.varchar)("group_id", { length: 36 }).notNull().references(() => groups.group_id, { onDelete: "cascade" }),
1827
2102
  user_id: (0, import_pg_core.varchar)("user_id", { length: 36 }).notNull().references(() => users.user_id, { onDelete: "cascade" }),
1828
2103
  added_by: (0, import_pg_core.varchar)("added_by", { length: 36 }).references(() => users.user_id, {
@@ -1831,6 +2106,7 @@ var init_schema_postgres = __esm({
1831
2106
  created_at: t.timestamp("created_at").notNull()
1832
2107
  },
1833
2108
  (table) => ({
2109
+ tenantIdx: (0, import_pg_core.index)("group_memberships_tenant_id_idx").on(table.tenant_id),
1834
2110
  pk: (0, import_pg_core.primaryKey)({ columns: [table.group_id, table.user_id] }),
1835
2111
  userIdx: (0, import_pg_core.index)("group_memberships_user_idx").on(table.user_id)
1836
2112
  })
@@ -1838,6 +2114,7 @@ var init_schema_postgres = __esm({
1838
2114
  branchGroupGrants = (0, import_pg_core.pgTable)(
1839
2115
  "branch_group_grants",
1840
2116
  {
2117
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1841
2118
  branch_id: (0, import_pg_core.varchar)("branch_id", { length: 36 }).notNull().references(() => branches.branch_id, { onDelete: "cascade" }),
1842
2119
  group_id: (0, import_pg_core.varchar)("group_id", { length: 36 }).notNull().references(() => groups.group_id, { onDelete: "cascade" }),
1843
2120
  can: (0, import_pg_core.text)("can", { enum: [...BRANCH_PERMISSION_LEVELS] }).notNull().default("view"),
@@ -1849,6 +2126,7 @@ var init_schema_postgres = __esm({
1849
2126
  updated_at: t.timestamp("updated_at")
1850
2127
  },
1851
2128
  (table) => ({
2129
+ tenantIdx: (0, import_pg_core.index)("branch_group_grants_tenant_id_idx").on(table.tenant_id),
1852
2130
  pk: (0, import_pg_core.primaryKey)({ columns: [table.branch_id, table.group_id] }),
1853
2131
  groupIdx: (0, import_pg_core.index)("branch_group_grants_group_idx").on(table.group_id)
1854
2132
  })
@@ -1856,6 +2134,7 @@ var init_schema_postgres = __esm({
1856
2134
  boardGroupGrants = (0, import_pg_core.pgTable)(
1857
2135
  "board_group_grants",
1858
2136
  {
2137
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1859
2138
  board_id: (0, import_pg_core.varchar)("board_id", { length: 36 }).notNull().references(() => boards.board_id, { onDelete: "cascade" }),
1860
2139
  group_id: (0, import_pg_core.varchar)("group_id", { length: 36 }).notNull().references(() => groups.group_id, { onDelete: "cascade" }),
1861
2140
  can: (0, import_pg_core.text)("can", { enum: [...BRANCH_PERMISSION_LEVELS] }).notNull().default("view"),
@@ -1867,6 +2146,7 @@ var init_schema_postgres = __esm({
1867
2146
  updated_at: t.timestamp("updated_at")
1868
2147
  },
1869
2148
  (table) => ({
2149
+ tenantIdx: (0, import_pg_core.index)("board_group_grants_tenant_id_idx").on(table.tenant_id),
1870
2150
  pk: (0, import_pg_core.primaryKey)({ columns: [table.board_id, table.group_id] }),
1871
2151
  groupIdx: (0, import_pg_core.index)("board_group_grants_group_idx").on(table.group_id)
1872
2152
  })
@@ -1874,6 +2154,7 @@ var init_schema_postgres = __esm({
1874
2154
  appVariables = (0, import_pg_core.pgTable)(
1875
2155
  "app_variables",
1876
2156
  {
2157
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1877
2158
  variable_id: (0, import_pg_core.varchar)("variable_id", { length: 36 }).primaryKey(),
1878
2159
  namespace: (0, import_pg_core.text)("namespace").notNull(),
1879
2160
  key: (0, import_pg_core.text)("key").notNull(),
@@ -1889,13 +2170,19 @@ var init_schema_postgres = __esm({
1889
2170
  updated_at: t.timestamp("updated_at").notNull()
1890
2171
  },
1891
2172
  (table) => ({
1892
- namespaceKeyIdx: (0, import_pg_core.uniqueIndex)("app_variables_namespace_key_idx").on(table.namespace, table.key),
2173
+ tenantIdx: (0, import_pg_core.index)("app_variables_tenant_id_idx").on(table.tenant_id),
2174
+ namespaceKeyIdx: (0, import_pg_core.uniqueIndex)("app_variables_tenant_namespace_key_unique").on(
2175
+ table.tenant_id,
2176
+ table.namespace,
2177
+ table.key
2178
+ ),
1893
2179
  namespaceIdx: (0, import_pg_core.index)("app_variables_namespace_idx").on(table.namespace)
1894
2180
  })
1895
2181
  );
1896
2182
  userApiKeys = (0, import_pg_core.pgTable)(
1897
2183
  "user_api_keys",
1898
2184
  {
2185
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1899
2186
  id: (0, import_pg_core.varchar)("id", { length: 36 }).primaryKey(),
1900
2187
  user_id: (0, import_pg_core.varchar)("user_id", { length: 36 }).notNull().references(() => users.user_id, { onDelete: "cascade" }),
1901
2188
  name: (0, import_pg_core.text)("name").notNull(),
@@ -1907,6 +2194,7 @@ var init_schema_postgres = __esm({
1907
2194
  last_used_at: t.timestamp("last_used_at")
1908
2195
  },
1909
2196
  (table) => ({
2197
+ tenantIdx: (0, import_pg_core.index)("user_api_keys_tenant_id_idx").on(table.tenant_id),
1910
2198
  userIdx: (0, import_pg_core.index)("user_api_keys_user_idx").on(table.user_id),
1911
2199
  prefixIdx: (0, import_pg_core.index)("user_api_keys_prefix_idx").on(table.prefix)
1912
2200
  })
@@ -1914,6 +2202,7 @@ var init_schema_postgres = __esm({
1914
2202
  mcpServers = (0, import_pg_core.pgTable)(
1915
2203
  "mcp_servers",
1916
2204
  {
2205
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1917
2206
  // Primary identity
1918
2207
  mcp_server_id: (0, import_pg_core.varchar)("mcp_server_id", { length: 36 }).primaryKey(),
1919
2208
  created_at: t.timestamp("created_at").notNull(),
@@ -1940,6 +2229,7 @@ var init_schema_postgres = __esm({
1940
2229
  data: t.json("data").$type().notNull()
1941
2230
  },
1942
2231
  (table) => ({
2232
+ tenantIdx: (0, import_pg_core.index)("mcp_servers_tenant_id_idx").on(table.tenant_id),
1943
2233
  nameIdx: (0, import_pg_core.index)("mcp_servers_name_idx").on(table.name),
1944
2234
  scopeIdx: (0, import_pg_core.index)("mcp_servers_scope_idx").on(table.scope),
1945
2235
  ownerIdx: (0, import_pg_core.index)("mcp_servers_owner_idx").on(table.owner_user_id),
@@ -1949,6 +2239,7 @@ var init_schema_postgres = __esm({
1949
2239
  cardTypes = (0, import_pg_core.pgTable)(
1950
2240
  "card_types",
1951
2241
  {
2242
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1952
2243
  card_type_id: (0, import_pg_core.varchar)("card_type_id", { length: 36 }).primaryKey(),
1953
2244
  name: (0, import_pg_core.text)("name").notNull(),
1954
2245
  emoji: (0, import_pg_core.text)("emoji"),
@@ -1960,12 +2251,14 @@ var init_schema_postgres = __esm({
1960
2251
  updated_at: t.timestamp("updated_at").notNull()
1961
2252
  },
1962
2253
  (table) => ({
2254
+ tenantIdx: (0, import_pg_core.index)("card_types_tenant_id_idx").on(table.tenant_id),
1963
2255
  nameIdx: (0, import_pg_core.index)("card_types_name_idx").on(table.name)
1964
2256
  })
1965
2257
  );
1966
2258
  cards = (0, import_pg_core.pgTable)(
1967
2259
  "cards",
1968
2260
  {
2261
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1969
2262
  card_id: (0, import_pg_core.varchar)("card_id", { length: 36 }).primaryKey(),
1970
2263
  board_id: (0, import_pg_core.varchar)("board_id", { length: 36 }).notNull().references(() => boards.board_id, { onDelete: "cascade" }),
1971
2264
  card_type_id: (0, import_pg_core.varchar)("card_type_id", { length: 36 }).references(() => cardTypes.card_type_id, {
@@ -1986,6 +2279,7 @@ var init_schema_postgres = __esm({
1986
2279
  archived_at: t.timestamp("archived_at")
1987
2280
  },
1988
2281
  (table) => ({
2282
+ tenantIdx: (0, import_pg_core.index)("cards_tenant_id_idx").on(table.tenant_id),
1989
2283
  boardIdx: (0, import_pg_core.index)("cards_board_idx").on(table.board_id),
1990
2284
  cardTypeIdx: (0, import_pg_core.index)("cards_card_type_idx").on(table.card_type_id),
1991
2285
  titleIdx: (0, import_pg_core.index)("cards_title_idx").on(table.title),
@@ -1996,10 +2290,17 @@ var init_schema_postgres = __esm({
1996
2290
  artifacts = (0, import_pg_core.pgTable)(
1997
2291
  "artifacts",
1998
2292
  {
2293
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
1999
2294
  artifact_id: (0, import_pg_core.varchar)("artifact_id", { length: 36 }).primaryKey(),
2000
2295
  branch_id: (0, import_pg_core.varchar)("branch_id", { length: 36 }).references(() => branches.branch_id, {
2001
2296
  onDelete: "set null"
2002
2297
  }),
2298
+ source_session_id: (0, import_pg_core.varchar)("source_session_id", { length: 36 }).references(
2299
+ () => sessions.session_id,
2300
+ {
2301
+ onDelete: "set null"
2302
+ }
2303
+ ),
2003
2304
  board_id: (0, import_pg_core.varchar)("board_id", { length: 36 }).notNull().references(() => boards.board_id, { onDelete: "cascade" }),
2004
2305
  name: (0, import_pg_core.text)("name").notNull(),
2005
2306
  description: (0, import_pg_core.text)("description"),
@@ -2025,7 +2326,9 @@ var init_schema_postgres = __esm({
2025
2326
  archived_at: t.timestamp("archived_at")
2026
2327
  },
2027
2328
  (table) => ({
2329
+ tenantIdx: (0, import_pg_core.index)("artifacts_tenant_id_idx").on(table.tenant_id),
2028
2330
  branchIdx: (0, import_pg_core.index)("artifacts_branch_idx").on(table.branch_id),
2331
+ sourceSessionIdx: (0, import_pg_core.index)("artifacts_source_session_idx").on(table.source_session_id),
2029
2332
  boardIdx: (0, import_pg_core.index)("artifacts_board_idx").on(table.board_id),
2030
2333
  archivedIdx: (0, import_pg_core.index)("artifacts_archived_idx").on(table.archived),
2031
2334
  publicIdx: (0, import_pg_core.index)("artifacts_public_idx").on(table.public)
@@ -2034,6 +2337,7 @@ var init_schema_postgres = __esm({
2034
2337
  artifactTrustGrants = (0, import_pg_core.pgTable)(
2035
2338
  "artifact_trust_grants",
2036
2339
  {
2340
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
2037
2341
  grant_id: (0, import_pg_core.varchar)("grant_id", { length: 36 }).primaryKey(),
2038
2342
  user_id: (0, import_pg_core.varchar)("user_id", { length: 36 }).notNull(),
2039
2343
  scope_type: (0, import_pg_core.text)("scope_type").notNull(),
@@ -2044,6 +2348,7 @@ var init_schema_postgres = __esm({
2044
2348
  revoked_at: t.timestamp("revoked_at")
2045
2349
  },
2046
2350
  (table) => ({
2351
+ tenantIdx: (0, import_pg_core.index)("artifact_trust_grants_tenant_id_idx").on(table.tenant_id),
2047
2352
  userIdx: (0, import_pg_core.index)("artifact_trust_grants_user_idx").on(table.user_id),
2048
2353
  scopeIdx: (0, import_pg_core.index)("artifact_trust_grants_scope_idx").on(table.scope_type, table.scope_value)
2049
2354
  })
@@ -2051,6 +2356,7 @@ var init_schema_postgres = __esm({
2051
2356
  boardObjects = (0, import_pg_core.pgTable)(
2052
2357
  "board_objects",
2053
2358
  {
2359
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
2054
2360
  // Primary identity
2055
2361
  object_id: (0, import_pg_core.varchar)("object_id", { length: 36 }).primaryKey(),
2056
2362
  board_id: (0, import_pg_core.varchar)("board_id", { length: 36 }).notNull().references(() => boards.board_id, { onDelete: "cascade" }),
@@ -2066,6 +2372,7 @@ var init_schema_postgres = __esm({
2066
2372
  data: t.json("data").$type().notNull()
2067
2373
  },
2068
2374
  (table) => ({
2375
+ tenantIdx: (0, import_pg_core.index)("board_objects_tenant_id_idx").on(table.tenant_id),
2069
2376
  boardIdx: (0, import_pg_core.index)("board_objects_board_idx").on(table.board_id),
2070
2377
  branchIdx: (0, import_pg_core.index)("board_objects_branch_idx").on(table.branch_id),
2071
2378
  cardIdx: (0, import_pg_core.index)("board_objects_card_idx").on(table.card_id)
@@ -2074,12 +2381,14 @@ var init_schema_postgres = __esm({
2074
2381
  sessionMcpServers = (0, import_pg_core.pgTable)(
2075
2382
  "session_mcp_servers",
2076
2383
  {
2384
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
2077
2385
  session_id: (0, import_pg_core.varchar)("session_id", { length: 36 }).notNull().references(() => sessions.session_id, { onDelete: "cascade" }),
2078
2386
  mcp_server_id: (0, import_pg_core.varchar)("mcp_server_id", { length: 36 }).notNull().references(() => mcpServers.mcp_server_id, { onDelete: "cascade" }),
2079
2387
  enabled: t.bool("enabled").notNull().default(true),
2080
2388
  added_at: t.timestamp("added_at").notNull()
2081
2389
  },
2082
2390
  (table) => ({
2391
+ tenantIdx: (0, import_pg_core.index)("session_mcp_servers_tenant_id_idx").on(table.tenant_id),
2083
2392
  // Composite primary key
2084
2393
  pk: (0, import_pg_core.index)("session_mcp_servers_pk").on(table.session_id, table.mcp_server_id),
2085
2394
  // Indexes for queries
@@ -2091,6 +2400,7 @@ var init_schema_postgres = __esm({
2091
2400
  userMcpOauthTokens = (0, import_pg_core.pgTable)(
2092
2401
  "user_mcp_oauth_tokens",
2093
2402
  {
2403
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
2094
2404
  // NULL = shared-mode token (one per mcp_server_id)
2095
2405
  user_id: (0, import_pg_core.varchar)("user_id", { length: 36 }).references(() => users.user_id, {
2096
2406
  onDelete: "cascade"
@@ -2108,6 +2418,7 @@ var init_schema_postgres = __esm({
2108
2418
  updated_at: t.timestamp("updated_at")
2109
2419
  },
2110
2420
  (table) => ({
2421
+ tenantIdx: (0, import_pg_core.index)("user_mcp_oauth_tokens_tenant_id_idx").on(table.tenant_id),
2111
2422
  // Composite lookup indexes. Uniqueness enforced via partial unique indexes
2112
2423
  // created in the migration (one for per-user rows, one for the shared row).
2113
2424
  pk: (0, import_pg_core.index)("user_mcp_oauth_tokens_pk").on(table.user_id, table.mcp_server_id),
@@ -2118,6 +2429,7 @@ var init_schema_postgres = __esm({
2118
2429
  boardComments = (0, import_pg_core.pgTable)(
2119
2430
  "board_comments",
2120
2431
  {
2432
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
2121
2433
  // Primary identity
2122
2434
  comment_id: (0, import_pg_core.varchar)("comment_id", { length: 36 }).primaryKey(),
2123
2435
  created_at: t.timestamp("created_at").notNull(),
@@ -2159,6 +2471,7 @@ var init_schema_postgres = __esm({
2159
2471
  data: t.json("data").$type().notNull()
2160
2472
  },
2161
2473
  (table) => ({
2474
+ tenantIdx: (0, import_pg_core.index)("board_comments_tenant_id_idx").on(table.tenant_id),
2162
2475
  boardIdx: (0, import_pg_core.index)("board_comments_board_idx").on(table.board_id),
2163
2476
  sessionIdx: (0, import_pg_core.index)("board_comments_session_idx").on(table.session_id),
2164
2477
  taskIdx: (0, import_pg_core.index)("board_comments_task_idx").on(table.task_id),
@@ -2173,6 +2486,7 @@ var init_schema_postgres = __esm({
2173
2486
  gatewayChannels = (0, import_pg_core.pgTable)(
2174
2487
  "gateway_channels",
2175
2488
  {
2489
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
2176
2490
  // Primary identity
2177
2491
  id: (0, import_pg_core.varchar)("id", { length: 36 }).primaryKey(),
2178
2492
  created_at: t.timestamp("created_at").notNull(),
@@ -2182,11 +2496,11 @@ var init_schema_postgres = __esm({
2182
2496
  // Materialized for queries
2183
2497
  name: (0, import_pg_core.text)("name").notNull(),
2184
2498
  channel_type: (0, import_pg_core.text)("channel_type", {
2185
- enum: ["slack", "discord", "whatsapp", "telegram", "github"]
2499
+ enum: ["slack", "discord", "whatsapp", "telegram", "github", "teams"]
2186
2500
  }).notNull(),
2187
2501
  target_branch_id: (0, import_pg_core.varchar)("target_branch_id", { length: 36 }).notNull().references(() => branches.branch_id, { onDelete: "cascade" }),
2188
2502
  agor_user_id: (0, import_pg_core.varchar)("agor_user_id", { length: 36 }).notNull(),
2189
- channel_key: (0, import_pg_core.text)("channel_key").notNull().unique(),
2503
+ channel_key: (0, import_pg_core.text)("channel_key").notNull(),
2190
2504
  enabled: t.bool("enabled").notNull().default(true),
2191
2505
  last_message_at: t.timestamp("last_message_at"),
2192
2506
  // JSON blob for platform credentials (encrypted at rest)
@@ -2195,13 +2509,19 @@ var init_schema_postgres = __esm({
2195
2509
  agentic_config: t.json("agentic_config")
2196
2510
  },
2197
2511
  (table) => ({
2512
+ tenantIdx: (0, import_pg_core.index)("gateway_channels_tenant_id_idx").on(table.tenant_id),
2198
2513
  channelKeyIdx: (0, import_pg_core.index)("idx_gateway_channel_key").on(table.channel_key),
2514
+ channelKeyTenantUnique: (0, import_pg_core.uniqueIndex)("gateway_channels_tenant_channel_key_unique").on(
2515
+ table.tenant_id,
2516
+ table.channel_key
2517
+ ),
2199
2518
  enabledTypeIdx: (0, import_pg_core.index)("idx_gateway_enabled_type").on(table.enabled, table.channel_type)
2200
2519
  })
2201
2520
  );
2202
2521
  threadSessionMap = (0, import_pg_core.pgTable)(
2203
2522
  "thread_session_map",
2204
2523
  {
2524
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
2205
2525
  // Primary identity
2206
2526
  id: (0, import_pg_core.varchar)("id", { length: 36 }).primaryKey(),
2207
2527
  created_at: t.timestamp("created_at").notNull(),
@@ -2219,7 +2539,9 @@ var init_schema_postgres = __esm({
2219
2539
  metadata: t.json("metadata")
2220
2540
  },
2221
2541
  (table) => ({
2222
- uniqueChannelThread: (0, import_pg_core.uniqueIndex)("uniq_thread_map_channel_thread").on(
2542
+ tenantIdx: (0, import_pg_core.index)("thread_session_map_tenant_id_idx").on(table.tenant_id),
2543
+ uniqueChannelThread: (0, import_pg_core.uniqueIndex)("uniq_thread_map_tenant_channel_thread").on(
2544
+ table.tenant_id,
2223
2545
  table.channel_id,
2224
2546
  table.thread_id
2225
2547
  ),
@@ -2228,14 +2550,82 @@ var init_schema_postgres = __esm({
2228
2550
  channelStatusIdx: (0, import_pg_core.index)("idx_thread_map_channel_status").on(table.channel_id, table.status)
2229
2551
  })
2230
2552
  );
2553
+ gatewayOutboundMessages = (0, import_pg_core.pgTable)(
2554
+ "gateway_outbound_messages",
2555
+ {
2556
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
2557
+ id: (0, import_pg_core.varchar)("id", { length: 36 }).primaryKey(),
2558
+ created_at: t.timestamp("created_at").notNull(),
2559
+ updated_at: t.timestamp("updated_at").notNull(),
2560
+ gateway_channel_id: (0, import_pg_core.varchar)("gateway_channel_id", { length: 36 }).notNull().references(() => gatewayChannels.id, { onDelete: "cascade" }),
2561
+ channel_type: (0, import_pg_core.text)("channel_type", {
2562
+ enum: ["slack", "discord", "whatsapp", "telegram", "github", "teams"]
2563
+ }).notNull(),
2564
+ platform_channel_id: (0, import_pg_core.text)("platform_channel_id").notNull(),
2565
+ platform_message_id: (0, import_pg_core.text)("platform_message_id").notNull(),
2566
+ platform_thread_id: (0, import_pg_core.text)("platform_thread_id").notNull(),
2567
+ platform_permalink: (0, import_pg_core.text)("platform_permalink"),
2568
+ target_branch_id: (0, import_pg_core.varchar)("target_branch_id", { length: 36 }).notNull().references(() => branches.branch_id),
2569
+ emitted_by_user_id: (0, import_pg_core.varchar)("emitted_by_user_id", { length: 36 }).notNull().references(() => users.user_id),
2570
+ emitted_by_session_id: (0, import_pg_core.varchar)("emitted_by_session_id", { length: 36 }).references(
2571
+ () => sessions.session_id,
2572
+ {
2573
+ onDelete: "set null"
2574
+ }
2575
+ ),
2576
+ emitted_by_task_id: (0, import_pg_core.varchar)("emitted_by_task_id", { length: 36 }).references(
2577
+ () => tasks.task_id,
2578
+ {
2579
+ onDelete: "set null"
2580
+ }
2581
+ ),
2582
+ emitted_by_schedule_id: (0, import_pg_core.varchar)("emitted_by_schedule_id", { length: 36 }).references(
2583
+ () => schedules.schedule_id,
2584
+ {
2585
+ onDelete: "set null"
2586
+ }
2587
+ ),
2588
+ message_text: (0, import_pg_core.text)("message_text").notNull(),
2589
+ message_preview: (0, import_pg_core.text)("message_preview").notNull(),
2590
+ metadata: t.json("metadata"),
2591
+ consumed_by_session_id: (0, import_pg_core.varchar)("consumed_by_session_id", { length: 36 }).references(
2592
+ () => sessions.session_id,
2593
+ {
2594
+ onDelete: "set null"
2595
+ }
2596
+ ),
2597
+ consumed_at: t.timestamp("consumed_at")
2598
+ },
2599
+ (table) => ({
2600
+ tenantIdx: (0, import_pg_core.index)("gateway_outbound_messages_tenant_id_idx").on(table.tenant_id),
2601
+ uniqueChannelThread: (0, import_pg_core.uniqueIndex)("uniq_gateway_outbound_tenant_channel_thread").on(
2602
+ table.tenant_id,
2603
+ table.gateway_channel_id,
2604
+ table.platform_thread_id
2605
+ ),
2606
+ emittedSessionIdx: (0, import_pg_core.index)("idx_gateway_outbound_emitted_session").on(
2607
+ table.emitted_by_session_id
2608
+ ),
2609
+ emittedScheduleIdx: (0, import_pg_core.index)("idx_gateway_outbound_emitted_schedule").on(
2610
+ table.emitted_by_schedule_id
2611
+ ),
2612
+ targetBranchCreatedIdx: (0, import_pg_core.index)("idx_gateway_outbound_branch_created").on(
2613
+ table.target_branch_id,
2614
+ table.created_at
2615
+ ),
2616
+ consumedIdx: (0, import_pg_core.index)("idx_gateway_outbound_consumed").on(table.consumed_at)
2617
+ })
2618
+ );
2231
2619
  sessionEnvSelections = (0, import_pg_core.pgTable)(
2232
2620
  "session_env_selections",
2233
2621
  {
2622
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
2234
2623
  session_id: (0, import_pg_core.varchar)("session_id", { length: 36 }).notNull().references(() => sessions.session_id, { onDelete: "cascade" }),
2235
2624
  env_var_name: (0, import_pg_core.text)("env_var_name").notNull(),
2236
2625
  created_at: t.timestamp("created_at").notNull()
2237
2626
  },
2238
2627
  (table) => ({
2628
+ tenantIdx: (0, import_pg_core.index)("session_env_selections_tenant_id_idx").on(table.tenant_id),
2239
2629
  pk: (0, import_pg_core.primaryKey)({ columns: [table.session_id, table.env_var_name] }),
2240
2630
  sessionIdx: (0, import_pg_core.index)("session_env_selections_session_idx").on(table.session_id)
2241
2631
  })
@@ -2243,6 +2633,7 @@ var init_schema_postgres = __esm({
2243
2633
  kbNamespaces = (0, import_pg_core.pgTable)(
2244
2634
  "kb_namespaces",
2245
2635
  {
2636
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
2246
2637
  namespace_id: (0, import_pg_core.varchar)("namespace_id", { length: 36 }).primaryKey(),
2247
2638
  slug: (0, import_pg_core.text)("slug").notNull(),
2248
2639
  display_name: (0, import_pg_core.text)("display_name").notNull(),
@@ -2269,7 +2660,8 @@ var init_schema_postgres = __esm({
2269
2660
  archived_at: t.timestamp("archived_at")
2270
2661
  },
2271
2662
  (table) => ({
2272
- slugIdx: (0, import_pg_core.uniqueIndex)("kb_namespaces_slug_idx").on(table.slug).where(import_drizzle_orm2.sql`${table.archived} = false`),
2663
+ tenantIdx: (0, import_pg_core.index)("kb_namespaces_tenant_id_idx").on(table.tenant_id),
2664
+ 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`),
2273
2665
  kindIdx: (0, import_pg_core.index)("kb_namespaces_kind_idx").on(table.kind),
2274
2666
  ownerIdx: (0, import_pg_core.index)("kb_namespaces_owner_idx").on(table.owner_user_id),
2275
2667
  repoIdx: (0, import_pg_core.index)("kb_namespaces_repo_idx").on(table.repo_id),
@@ -2280,6 +2672,7 @@ var init_schema_postgres = __esm({
2280
2672
  kbNamespaceAcl = (0, import_pg_core.pgTable)(
2281
2673
  "kb_namespace_acl",
2282
2674
  {
2675
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
2283
2676
  namespace_acl_id: (0, import_pg_core.varchar)("namespace_acl_id", { length: 36 }).primaryKey(),
2284
2677
  namespace_id: (0, import_pg_core.varchar)("namespace_id", { length: 36 }).notNull().references(() => kbNamespaces.namespace_id, { onDelete: "cascade" }),
2285
2678
  subject_type: (0, import_pg_core.text)("subject_type", { enum: ["user", "group"] }).notNull(),
@@ -2292,9 +2685,11 @@ var init_schema_postgres = __esm({
2292
2685
  updated_at: t.timestamp("updated_at")
2293
2686
  },
2294
2687
  (table) => ({
2688
+ tenantIdx: (0, import_pg_core.index)("kb_namespace_acl_tenant_id_idx").on(table.tenant_id),
2295
2689
  namespaceIdx: (0, import_pg_core.index)("kb_namespace_acl_namespace_idx").on(table.namespace_id),
2296
2690
  subjectIdx: (0, import_pg_core.index)("kb_namespace_acl_subject_idx").on(table.subject_type, table.subject_id),
2297
- namespaceSubjectIdx: (0, import_pg_core.uniqueIndex)("kb_namespace_acl_namespace_subject_idx").on(
2691
+ namespaceSubjectIdx: (0, import_pg_core.uniqueIndex)("kb_namespace_acl_tenant_namespace_subject_unique").on(
2692
+ table.tenant_id,
2298
2693
  table.namespace_id,
2299
2694
  table.subject_type,
2300
2695
  table.subject_id
@@ -2304,6 +2699,7 @@ var init_schema_postgres = __esm({
2304
2699
  kbDocuments = (0, import_pg_core.pgTable)(
2305
2700
  "kb_documents",
2306
2701
  {
2702
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
2307
2703
  document_id: (0, import_pg_core.varchar)("document_id", { length: 36 }).primaryKey(),
2308
2704
  namespace_id: (0, import_pg_core.varchar)("namespace_id", { length: 36 }).notNull().references(() => kbNamespaces.namespace_id, { onDelete: "cascade" }),
2309
2705
  path: (0, import_pg_core.text)("path").notNull(),
@@ -2331,8 +2727,9 @@ var init_schema_postgres = __esm({
2331
2727
  archived_at: t.timestamp("archived_at")
2332
2728
  },
2333
2729
  (table) => ({
2334
- namespacePathIdx: (0, import_pg_core.uniqueIndex)("kb_documents_namespace_path_idx").on(table.namespace_id, table.path).where(import_drizzle_orm2.sql`${table.archived} = false`),
2335
- uriIdx: (0, import_pg_core.uniqueIndex)("kb_documents_uri_idx").on(table.uri).where(import_drizzle_orm2.sql`${table.archived} = false`),
2730
+ tenantIdx: (0, import_pg_core.index)("kb_documents_tenant_id_idx").on(table.tenant_id),
2731
+ 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`),
2732
+ 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`),
2336
2733
  namespaceIdx: (0, import_pg_core.index)("kb_documents_namespace_idx").on(table.namespace_id),
2337
2734
  kindIdx: (0, import_pg_core.index)("kb_documents_kind_idx").on(table.kind),
2338
2735
  visibilityIdx: (0, import_pg_core.index)("kb_documents_visibility_idx").on(table.visibility),
@@ -2345,6 +2742,7 @@ var init_schema_postgres = __esm({
2345
2742
  kbDocumentVersions = (0, import_pg_core.pgTable)(
2346
2743
  "kb_document_versions",
2347
2744
  {
2745
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
2348
2746
  version_id: (0, import_pg_core.varchar)("version_id", { length: 36 }).primaryKey(),
2349
2747
  document_id: (0, import_pg_core.varchar)("document_id", { length: 36 }).notNull().references(() => kbDocuments.document_id, { onDelete: "cascade" }),
2350
2748
  version_number: (0, import_pg_core.integer)("version_number").notNull(),
@@ -2364,7 +2762,9 @@ var init_schema_postgres = __esm({
2364
2762
  created_at: t.timestamp("created_at").notNull()
2365
2763
  },
2366
2764
  (table) => ({
2367
- documentVersionIdx: (0, import_pg_core.uniqueIndex)("kb_document_versions_document_version_idx").on(
2765
+ tenantIdx: (0, import_pg_core.index)("kb_document_versions_tenant_id_idx").on(table.tenant_id),
2766
+ documentVersionIdx: (0, import_pg_core.uniqueIndex)("kb_document_versions_tenant_document_version_unique").on(
2767
+ table.tenant_id,
2368
2768
  table.document_id,
2369
2769
  table.version_number
2370
2770
  ),
@@ -2376,6 +2776,7 @@ var init_schema_postgres = __esm({
2376
2776
  kbDocumentUnits = (0, import_pg_core.pgTable)(
2377
2777
  "kb_document_units",
2378
2778
  {
2779
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
2379
2780
  unit_id: (0, import_pg_core.varchar)("unit_id", { length: 36 }).primaryKey(),
2380
2781
  document_id: (0, import_pg_core.varchar)("document_id", { length: 36 }).notNull().references(() => kbDocuments.document_id, { onDelete: "cascade" }),
2381
2782
  version_id: (0, import_pg_core.varchar)("version_id", { length: 36 }).notNull().references(() => kbDocumentVersions.version_id, { onDelete: "cascade" }),
@@ -2400,6 +2801,7 @@ var init_schema_postgres = __esm({
2400
2801
  updated_at: t.timestamp("updated_at")
2401
2802
  },
2402
2803
  (table) => ({
2804
+ tenantIdx: (0, import_pg_core.index)("kb_document_units_tenant_id_idx").on(table.tenant_id),
2403
2805
  documentIdx: (0, import_pg_core.index)("kb_document_units_document_idx").on(table.document_id),
2404
2806
  versionIdx: (0, import_pg_core.index)("kb_document_units_version_idx").on(table.version_id),
2405
2807
  versionOrdinalIdx: (0, import_pg_core.index)("kb_document_units_version_ordinal_idx").on(
@@ -2413,6 +2815,7 @@ var init_schema_postgres = __esm({
2413
2815
  kbEmbeddingSpaces = (0, import_pg_core.pgTable)(
2414
2816
  "kb_embedding_spaces",
2415
2817
  {
2818
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
2416
2819
  embedding_space_id: (0, import_pg_core.varchar)("embedding_space_id", { length: 36 }).primaryKey(),
2417
2820
  provider: (0, import_pg_core.text)("provider").notNull(),
2418
2821
  model: (0, import_pg_core.text)("model").notNull(),
@@ -2425,7 +2828,9 @@ var init_schema_postgres = __esm({
2425
2828
  updated_at: t.timestamp("updated_at")
2426
2829
  },
2427
2830
  (table) => ({
2428
- providerModelIdx: (0, import_pg_core.uniqueIndex)("kb_embedding_spaces_provider_model_idx").on(
2831
+ tenantIdx: (0, import_pg_core.index)("kb_embedding_spaces_tenant_id_idx").on(table.tenant_id),
2832
+ providerModelIdx: (0, import_pg_core.uniqueIndex)("kb_embedding_spaces_tenant_provider_model_unique").on(
2833
+ table.tenant_id,
2429
2834
  table.provider,
2430
2835
  table.model,
2431
2836
  table.dimensions,
@@ -2438,6 +2843,7 @@ var init_schema_postgres = __esm({
2438
2843
  kbGraphNodes = (0, import_pg_core.pgTable)(
2439
2844
  "kb_graph_nodes",
2440
2845
  {
2846
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
2441
2847
  node_id: (0, import_pg_core.varchar)("node_id", { length: 36 }).primaryKey(),
2442
2848
  node_type: (0, import_pg_core.text)("node_type", {
2443
2849
  enum: [
@@ -2503,7 +2909,8 @@ var init_schema_postgres = __esm({
2503
2909
  archived_at: t.timestamp("archived_at")
2504
2910
  },
2505
2911
  (table) => ({
2506
- uriIdx: (0, import_pg_core.uniqueIndex)("kb_graph_nodes_uri_idx").on(table.uri).where(import_drizzle_orm2.sql`${table.archived} = false`),
2912
+ tenantIdx: (0, import_pg_core.index)("kb_graph_nodes_tenant_id_idx").on(table.tenant_id),
2913
+ 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`),
2507
2914
  typeIdx: (0, import_pg_core.index)("kb_graph_nodes_type_idx").on(table.node_type),
2508
2915
  namespaceIdx: (0, import_pg_core.index)("kb_graph_nodes_namespace_idx").on(table.namespace_id),
2509
2916
  documentIdx: (0, import_pg_core.index)("kb_graph_nodes_document_idx").on(table.document_id),
@@ -2523,6 +2930,7 @@ var init_schema_postgres = __esm({
2523
2930
  kbGraphEdges = (0, import_pg_core.pgTable)(
2524
2931
  "kb_graph_edges",
2525
2932
  {
2933
+ tenant_id: (0, import_pg_core.text)("tenant_id").notNull().default("default"),
2526
2934
  edge_id: (0, import_pg_core.varchar)("edge_id", { length: 36 }).primaryKey(),
2527
2935
  source_node_id: (0, import_pg_core.varchar)("source_node_id", { length: 36 }).notNull().references(() => kbGraphNodes.node_id, { onDelete: "cascade" }),
2528
2936
  target_node_id: (0, import_pg_core.varchar)("target_node_id", { length: 36 }).notNull().references(() => kbGraphNodes.node_id, { onDelete: "cascade" }),
@@ -2551,6 +2959,7 @@ var init_schema_postgres = __esm({
2551
2959
  archived_at: t.timestamp("archived_at")
2552
2960
  },
2553
2961
  (table) => ({
2962
+ tenantIdx: (0, import_pg_core.index)("kb_graph_edges_tenant_id_idx").on(table.tenant_id),
2554
2963
  sourceIdx: (0, import_pg_core.index)("kb_graph_edges_source_idx").on(table.source_node_id),
2555
2964
  targetIdx: (0, import_pg_core.index)("kb_graph_edges_target_idx").on(table.target_node_id),
2556
2965
  typeIdx: (0, import_pg_core.index)("kb_graph_edges_type_idx").on(table.edge_type),
@@ -2562,11 +2971,11 @@ var init_schema_postgres = __esm({
2562
2971
  table.target_node_id,
2563
2972
  table.edge_type
2564
2973
  ),
2565
- sourceTargetTypeIdx: (0, import_pg_core.uniqueIndex)("kb_graph_edges_source_target_type_idx").on(table.source_node_id, table.target_node_id, table.edge_type).where(import_drizzle_orm2.sql`${table.archived} = false`),
2974
+ 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`),
2566
2975
  archivedIdx: (0, import_pg_core.index)("kb_graph_edges_archived_idx").on(table.archived)
2567
2976
  })
2568
2977
  );
2569
- sessionsRelations = (0, import_drizzle_orm2.relations)(sessions, ({ one }) => ({
2978
+ sessionsRelations = (0, import_drizzle_orm2.relations)(sessions, ({ one, many }) => ({
2570
2979
  branch: one(branches, {
2571
2980
  fields: [sessions.branch_id],
2572
2981
  references: [branches.branch_id]
@@ -2574,6 +2983,24 @@ var init_schema_postgres = __esm({
2574
2983
  schedule: one(schedules, {
2575
2984
  fields: [sessions.schedule_id],
2576
2985
  references: [schedules.schedule_id]
2986
+ }),
2987
+ outboundRelationships: many(sessionRelationships, { relationName: "relationshipSource" }),
2988
+ inboundRelationships: many(sessionRelationships, { relationName: "relationshipTarget" })
2989
+ }));
2990
+ sessionRelationshipsRelations = (0, import_drizzle_orm2.relations)(sessionRelationships, ({ one }) => ({
2991
+ sourceSession: one(sessions, {
2992
+ fields: [sessionRelationships.source_session_id],
2993
+ references: [sessions.session_id],
2994
+ relationName: "relationshipSource"
2995
+ }),
2996
+ targetSession: one(sessions, {
2997
+ fields: [sessionRelationships.target_session_id],
2998
+ references: [sessions.session_id],
2999
+ relationName: "relationshipTarget"
3000
+ }),
3001
+ callbackSession: one(sessions, {
3002
+ fields: [sessionRelationships.callback_session_id],
3003
+ references: [sessions.session_id]
2577
3004
  })
2578
3005
  }));
2579
3006
  branchesRelations = (0, import_drizzle_orm2.relations)(branches, ({ many }) => ({
@@ -2608,6 +3035,7 @@ __export(schema_sqlite_exports, {
2608
3035
  cardTypes: () => cardTypes2,
2609
3036
  cards: () => cards2,
2610
3037
  gatewayChannels: () => gatewayChannels2,
3038
+ gatewayOutboundMessages: () => gatewayOutboundMessages2,
2611
3039
  groupMemberships: () => groupMemberships2,
2612
3040
  groups: () => groups2,
2613
3041
  kbDocumentUnits: () => kbDocumentUnits2,
@@ -2626,6 +3054,8 @@ __export(schema_sqlite_exports, {
2626
3054
  serializedSessions: () => serializedSessions2,
2627
3055
  sessionEnvSelections: () => sessionEnvSelections2,
2628
3056
  sessionMcpServers: () => sessionMcpServers2,
3057
+ sessionRelationships: () => sessionRelationships2,
3058
+ sessionRelationshipsRelations: () => sessionRelationshipsRelations2,
2629
3059
  sessions: () => sessions2,
2630
3060
  sessionsRelations: () => sessionsRelations2,
2631
3061
  tasks: () => tasks2,
@@ -2634,7 +3064,7 @@ __export(schema_sqlite_exports, {
2634
3064
  userMcpOauthTokens: () => userMcpOauthTokens2,
2635
3065
  users: () => users2
2636
3066
  });
2637
- var import_drizzle_orm3, import_sqlite_core, t2, sessions2, tasks2, serializedSessions2, messages2, boards2, repos2, branches2, branchOwners2, boardOwners2, schedules2, users2, groups2, groupMemberships2, branchGroupGrants2, boardGroupGrants2, appVariables2, userApiKeys2, mcpServers2, cardTypes2, cards2, artifacts2, artifactTrustGrants2, boardObjects2, sessionMcpServers2, userMcpOauthTokens2, boardComments2, gatewayChannels2, threadSessionMap2, sessionEnvSelections2, kbNamespaces2, kbNamespaceAcl2, kbDocuments2, kbDocumentVersions2, kbDocumentUnits2, kbEmbeddingSpaces2, kbGraphNodes2, kbGraphEdges2, sessionsRelations2, branchesRelations2, schedulesRelations2;
3067
+ var import_drizzle_orm3, import_sqlite_core, t2, sessions2, sessionRelationships2, tasks2, serializedSessions2, messages2, boards2, repos2, branches2, branchOwners2, boardOwners2, schedules2, users2, groups2, groupMemberships2, branchGroupGrants2, boardGroupGrants2, appVariables2, userApiKeys2, mcpServers2, cardTypes2, cards2, artifacts2, artifactTrustGrants2, boardObjects2, sessionMcpServers2, userMcpOauthTokens2, boardComments2, gatewayChannels2, threadSessionMap2, gatewayOutboundMessages2, sessionEnvSelections2, kbNamespaces2, kbNamespaceAcl2, kbDocuments2, kbDocumentVersions2, kbDocumentUnits2, kbEmbeddingSpaces2, kbGraphNodes2, kbGraphEdges2, sessionsRelations2, sessionRelationshipsRelations2, branchesRelations2, schedulesRelations2;
2638
3068
  var init_schema_sqlite = __esm({
2639
3069
  "src/db/schema.sqlite.ts"() {
2640
3070
  "use strict";
@@ -2710,6 +3140,7 @@ var init_schema_sqlite = __esm({
2710
3140
  },
2711
3141
  (table) => ({
2712
3142
  statusIdx: (0, import_sqlite_core.index)("sessions_status_idx").on(table.status),
3143
+ statusReadyIdx: (0, import_sqlite_core.index)("sessions_status_ready_idx").on(table.status, table.ready_for_prompt),
2713
3144
  agenticToolIdx: (0, import_sqlite_core.index)("sessions_agentic_tool_idx").on(table.agentic_tool),
2714
3145
  boardIdx: (0, import_sqlite_core.index)("sessions_board_idx").on(table.board_id),
2715
3146
  branchIdx: (0, import_sqlite_core.index)("sessions_branch_idx").on(table.branch_id),
@@ -2726,6 +3157,39 @@ var init_schema_sqlite = __esm({
2726
3157
  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`)
2727
3158
  })
2728
3159
  );
3160
+ sessionRelationships2 = (0, import_sqlite_core.sqliteTable)(
3161
+ "session_relationships",
3162
+ {
3163
+ relationship_id: (0, import_sqlite_core.text)("relationship_id", { length: 36 }).primaryKey(),
3164
+ source_session_id: (0, import_sqlite_core.text)("source_session_id", { length: 36 }).notNull().references(() => sessions2.session_id, { onDelete: "cascade" }),
3165
+ target_session_id: (0, import_sqlite_core.text)("target_session_id", { length: 36 }).notNull().references(() => sessions2.session_id, { onDelete: "cascade" }),
3166
+ relationship_type: (0, import_sqlite_core.text)("relationship_type", { enum: ["remote_create"] }).notNull(),
3167
+ created_by: (0, import_sqlite_core.text)("created_by", { length: 36 }).notNull(),
3168
+ created_at: t2.timestamp("created_at").notNull(),
3169
+ updated_at: t2.timestamp("updated_at"),
3170
+ callback_enabled: t2.bool("callback_enabled").notNull().default(false),
3171
+ callback_session_id: (0, import_sqlite_core.text)("callback_session_id", { length: 36 }).references(
3172
+ () => sessions2.session_id,
3173
+ {
3174
+ onDelete: "set null"
3175
+ }
3176
+ ),
3177
+ data: t2.json("data")
3178
+ },
3179
+ (table) => ({
3180
+ sourceIdx: (0, import_sqlite_core.index)("session_relationships_source_idx").on(table.source_session_id),
3181
+ targetIdx: (0, import_sqlite_core.index)("session_relationships_target_idx").on(table.target_session_id),
3182
+ callbackIdx: (0, import_sqlite_core.index)("session_relationships_callback_idx").on(table.callback_session_id),
3183
+ // Note: no tenant_source/tenant_target composite indexes here — SQLite schema
3184
+ // has no tenant column on this table (RLS is Postgres-only). The standalone
3185
+ // source/target indexes above are sufficient for SQLite.
3186
+ sourceTargetTypeUnique: (0, import_sqlite_core.uniqueIndex)("session_relationships_source_target_type_unique").on(
3187
+ table.source_session_id,
3188
+ table.target_session_id,
3189
+ table.relationship_type
3190
+ )
3191
+ })
3192
+ );
2729
3193
  tasks2 = (0, import_sqlite_core.sqliteTable)(
2730
3194
  "tasks",
2731
3195
  {
@@ -2838,7 +3302,12 @@ var init_schema_sqlite = __esm({
2838
3302
  // Indexes for efficient lookups
2839
3303
  sessionIdx: (0, import_sqlite_core.index)("messages_session_id_idx").on(table.session_id),
2840
3304
  taskIdx: (0, import_sqlite_core.index)("messages_task_id_idx").on(table.task_id),
2841
- sessionIndexIdx: (0, import_sqlite_core.index)("messages_session_index_idx").on(table.session_id, table.index)
3305
+ sessionIndexIdx: (0, import_sqlite_core.index)("messages_session_index_idx").on(table.session_id, table.index),
3306
+ timestampIdx: (0, import_sqlite_core.index)("messages_timestamp_idx").on(table.timestamp),
3307
+ sessionTimestampIdx: (0, import_sqlite_core.index)("messages_session_timestamp_idx").on(
3308
+ table.session_id,
3309
+ table.timestamp
3310
+ )
2842
3311
  })
2843
3312
  );
2844
3313
  boards2 = (0, import_sqlite_core.sqliteTable)(
@@ -3064,6 +3533,9 @@ var init_schema_sqlite = __esm({
3064
3533
  onboarding_completed: t2.bool("onboarding_completed").notNull().default(false),
3065
3534
  // Force password change flag (admin-settable, auto-cleared on password change)
3066
3535
  must_change_password: t2.bool("must_change_password").notNull().default(false),
3536
+ // Auth invalidation marker. Password changes set this timestamp so any
3537
+ // previously issued browser access or refresh token is rejected.
3538
+ tokens_valid_after: t2.timestamp("tokens_valid_after"),
3067
3539
  // JSON blob for profile/preferences
3068
3540
  data: t2.json("data").$type().notNull()
3069
3541
  },
@@ -3270,6 +3742,12 @@ var init_schema_sqlite = __esm({
3270
3742
  branch_id: (0, import_sqlite_core.text)("branch_id", { length: 36 }).references(() => branches2.branch_id, {
3271
3743
  onDelete: "set null"
3272
3744
  }),
3745
+ source_session_id: (0, import_sqlite_core.text)("source_session_id", { length: 36 }).references(
3746
+ () => sessions2.session_id,
3747
+ {
3748
+ onDelete: "set null"
3749
+ }
3750
+ ),
3273
3751
  board_id: (0, import_sqlite_core.text)("board_id", { length: 36 }).notNull().references(() => boards2.board_id, { onDelete: "cascade" }),
3274
3752
  name: (0, import_sqlite_core.text)("name").notNull(),
3275
3753
  description: (0, import_sqlite_core.text)("description"),
@@ -3296,6 +3774,7 @@ var init_schema_sqlite = __esm({
3296
3774
  },
3297
3775
  (table) => ({
3298
3776
  branchIdx: (0, import_sqlite_core.index)("artifacts_branch_idx").on(table.branch_id),
3777
+ sourceSessionIdx: (0, import_sqlite_core.index)("artifacts_source_session_idx").on(table.source_session_id),
3299
3778
  boardIdx: (0, import_sqlite_core.index)("artifacts_board_idx").on(table.board_id),
3300
3779
  archivedIdx: (0, import_sqlite_core.index)("artifacts_archived_idx").on(table.archived),
3301
3780
  publicIdx: (0, import_sqlite_core.index)("artifacts_public_idx").on(table.public)
@@ -3454,7 +3933,7 @@ var init_schema_sqlite = __esm({
3454
3933
  // Materialized for queries
3455
3934
  name: (0, import_sqlite_core.text)("name").notNull(),
3456
3935
  channel_type: (0, import_sqlite_core.text)("channel_type", {
3457
- enum: ["slack", "discord", "whatsapp", "telegram", "github"]
3936
+ enum: ["slack", "discord", "whatsapp", "telegram", "github", "teams"]
3458
3937
  }).notNull(),
3459
3938
  target_branch_id: (0, import_sqlite_core.text)("target_branch_id", { length: 36 }).notNull().references(() => branches2.branch_id, { onDelete: "cascade" }),
3460
3939
  agor_user_id: (0, import_sqlite_core.text)("agor_user_id", { length: 36 }).notNull(),
@@ -3500,6 +3979,66 @@ var init_schema_sqlite = __esm({
3500
3979
  channelStatusIdx: (0, import_sqlite_core.index)("idx_thread_map_channel_status").on(table.channel_id, table.status)
3501
3980
  })
3502
3981
  );
3982
+ gatewayOutboundMessages2 = (0, import_sqlite_core.sqliteTable)(
3983
+ "gateway_outbound_messages",
3984
+ {
3985
+ id: (0, import_sqlite_core.text)("id", { length: 36 }).primaryKey(),
3986
+ created_at: t2.timestamp("created_at").notNull(),
3987
+ updated_at: t2.timestamp("updated_at").notNull(),
3988
+ gateway_channel_id: (0, import_sqlite_core.text)("gateway_channel_id", { length: 36 }).notNull().references(() => gatewayChannels2.id, { onDelete: "cascade" }),
3989
+ channel_type: (0, import_sqlite_core.text)("channel_type", {
3990
+ enum: ["slack", "discord", "whatsapp", "telegram", "github", "teams"]
3991
+ }).notNull(),
3992
+ platform_channel_id: (0, import_sqlite_core.text)("platform_channel_id").notNull(),
3993
+ platform_message_id: (0, import_sqlite_core.text)("platform_message_id").notNull(),
3994
+ platform_thread_id: (0, import_sqlite_core.text)("platform_thread_id").notNull(),
3995
+ platform_permalink: (0, import_sqlite_core.text)("platform_permalink"),
3996
+ target_branch_id: (0, import_sqlite_core.text)("target_branch_id", { length: 36 }).notNull().references(() => branches2.branch_id),
3997
+ emitted_by_user_id: (0, import_sqlite_core.text)("emitted_by_user_id", { length: 36 }).notNull().references(() => users2.user_id),
3998
+ emitted_by_session_id: (0, import_sqlite_core.text)("emitted_by_session_id", { length: 36 }).references(
3999
+ () => sessions2.session_id,
4000
+ {
4001
+ onDelete: "set null"
4002
+ }
4003
+ ),
4004
+ emitted_by_task_id: (0, import_sqlite_core.text)("emitted_by_task_id", { length: 36 }).references(() => tasks2.task_id, {
4005
+ onDelete: "set null"
4006
+ }),
4007
+ emitted_by_schedule_id: (0, import_sqlite_core.text)("emitted_by_schedule_id", { length: 36 }).references(
4008
+ () => schedules2.schedule_id,
4009
+ {
4010
+ onDelete: "set null"
4011
+ }
4012
+ ),
4013
+ message_text: (0, import_sqlite_core.text)("message_text").notNull(),
4014
+ message_preview: (0, import_sqlite_core.text)("message_preview").notNull(),
4015
+ metadata: t2.json("metadata"),
4016
+ consumed_by_session_id: (0, import_sqlite_core.text)("consumed_by_session_id", { length: 36 }).references(
4017
+ () => sessions2.session_id,
4018
+ {
4019
+ onDelete: "set null"
4020
+ }
4021
+ ),
4022
+ consumed_at: t2.timestamp("consumed_at")
4023
+ },
4024
+ (table) => ({
4025
+ uniqueChannelThread: (0, import_sqlite_core.uniqueIndex)("uniq_gateway_outbound_channel_thread").on(
4026
+ table.gateway_channel_id,
4027
+ table.platform_thread_id
4028
+ ),
4029
+ emittedSessionIdx: (0, import_sqlite_core.index)("idx_gateway_outbound_emitted_session").on(
4030
+ table.emitted_by_session_id
4031
+ ),
4032
+ emittedScheduleIdx: (0, import_sqlite_core.index)("idx_gateway_outbound_emitted_schedule").on(
4033
+ table.emitted_by_schedule_id
4034
+ ),
4035
+ targetBranchCreatedIdx: (0, import_sqlite_core.index)("idx_gateway_outbound_branch_created").on(
4036
+ table.target_branch_id,
4037
+ table.created_at
4038
+ ),
4039
+ consumedIdx: (0, import_sqlite_core.index)("idx_gateway_outbound_consumed").on(table.consumed_at)
4040
+ })
4041
+ );
3503
4042
  sessionEnvSelections2 = (0, import_sqlite_core.sqliteTable)(
3504
4043
  "session_env_selections",
3505
4044
  {
@@ -3837,7 +4376,7 @@ var init_schema_sqlite = __esm({
3837
4376
  archivedIdx: (0, import_sqlite_core.index)("kb_graph_edges_archived_idx").on(table.archived)
3838
4377
  })
3839
4378
  );
3840
- sessionsRelations2 = (0, import_drizzle_orm3.relations)(sessions2, ({ one }) => ({
4379
+ sessionsRelations2 = (0, import_drizzle_orm3.relations)(sessions2, ({ one, many }) => ({
3841
4380
  branch: one(branches2, {
3842
4381
  fields: [sessions2.branch_id],
3843
4382
  references: [branches2.branch_id]
@@ -3845,6 +4384,24 @@ var init_schema_sqlite = __esm({
3845
4384
  schedule: one(schedules2, {
3846
4385
  fields: [sessions2.schedule_id],
3847
4386
  references: [schedules2.schedule_id]
4387
+ }),
4388
+ outboundRelationships: many(sessionRelationships2, { relationName: "relationshipSource" }),
4389
+ inboundRelationships: many(sessionRelationships2, { relationName: "relationshipTarget" })
4390
+ }));
4391
+ sessionRelationshipsRelations2 = (0, import_drizzle_orm3.relations)(sessionRelationships2, ({ one }) => ({
4392
+ sourceSession: one(sessions2, {
4393
+ fields: [sessionRelationships2.source_session_id],
4394
+ references: [sessions2.session_id],
4395
+ relationName: "relationshipSource"
4396
+ }),
4397
+ targetSession: one(sessions2, {
4398
+ fields: [sessionRelationships2.target_session_id],
4399
+ references: [sessions2.session_id],
4400
+ relationName: "relationshipTarget"
4401
+ }),
4402
+ callbackSession: one(sessions2, {
4403
+ fields: [sessionRelationships2.callback_session_id],
4404
+ references: [sessions2.session_id]
3848
4405
  })
3849
4406
  }));
3850
4407
  branchesRelations2 = (0, import_drizzle_orm3.relations)(branches2, ({ many }) => ({
@@ -3923,6 +4480,7 @@ __export(schema_exports, {
3923
4480
  cardTypes: () => cardTypes3,
3924
4481
  cards: () => cards3,
3925
4482
  gatewayChannels: () => gatewayChannels3,
4483
+ gatewayOutboundMessages: () => gatewayOutboundMessages3,
3926
4484
  groupMemberships: () => groupMemberships3,
3927
4485
  groups: () => groups3,
3928
4486
  kbDocumentUnits: () => kbDocumentUnits3,
@@ -3940,6 +4498,7 @@ __export(schema_exports, {
3940
4498
  serializedSessions: () => serializedSessions3,
3941
4499
  sessionEnvSelections: () => sessionEnvSelections3,
3942
4500
  sessionMcpServers: () => sessionMcpServers3,
4501
+ sessionRelationships: () => sessionRelationships3,
3943
4502
  sessions: () => sessions3,
3944
4503
  tasks: () => tasks3,
3945
4504
  threadSessionMap: () => threadSessionMap3,
@@ -3947,7 +4506,7 @@ __export(schema_exports, {
3947
4506
  userMcpOauthTokens: () => userMcpOauthTokens3,
3948
4507
  users: () => users3
3949
4508
  });
3950
- var dialect, schema, sessions3, tasks3, messages3, boards3, repos3, branches3, branchOwners3, boardOwners3, groups3, groupMemberships3, branchGroupGrants3, boardGroupGrants3, schedules3, users3, appVariables3, mcpServers3, cardTypes3, cards3, artifacts3, artifactTrustGrants3, boardObjects3, sessionMcpServers3, sessionEnvSelections3, userMcpOauthTokens3, boardComments3, gatewayChannels3, threadSessionMap3, userApiKeys3, serializedSessions3, kbNamespaces3, kbNamespaceAcl3, kbDocuments3, kbDocumentVersions3, kbDocumentUnits3, kbEmbeddingSpaces3, kbGraphNodes3, kbGraphEdges3;
4509
+ var dialect, schema, sessions3, tasks3, messages3, boards3, repos3, branches3, branchOwners3, boardOwners3, groups3, groupMemberships3, branchGroupGrants3, boardGroupGrants3, schedules3, users3, appVariables3, mcpServers3, cardTypes3, cards3, artifacts3, artifactTrustGrants3, boardObjects3, sessionMcpServers3, sessionRelationships3, sessionEnvSelections3, userMcpOauthTokens3, boardComments3, gatewayChannels3, threadSessionMap3, gatewayOutboundMessages3, userApiKeys3, serializedSessions3, kbNamespaces3, kbNamespaceAcl3, kbDocuments3, kbDocumentVersions3, kbDocumentUnits3, kbEmbeddingSpaces3, kbGraphNodes3, kbGraphEdges3;
3951
4510
  var init_schema = __esm({
3952
4511
  "src/db/schema.ts"() {
3953
4512
  "use strict";
@@ -3979,11 +4538,13 @@ var init_schema = __esm({
3979
4538
  artifactTrustGrants3 = schema.artifactTrustGrants;
3980
4539
  boardObjects3 = schema.boardObjects;
3981
4540
  sessionMcpServers3 = schema.sessionMcpServers;
4541
+ sessionRelationships3 = schema.sessionRelationships;
3982
4542
  sessionEnvSelections3 = schema.sessionEnvSelections;
3983
4543
  userMcpOauthTokens3 = schema.userMcpOauthTokens;
3984
4544
  boardComments3 = schema.boardComments;
3985
4545
  gatewayChannels3 = schema.gatewayChannels;
3986
4546
  threadSessionMap3 = schema.threadSessionMap;
4547
+ gatewayOutboundMessages3 = schema.gatewayOutboundMessages;
3987
4548
  userApiKeys3 = schema.userApiKeys;
3988
4549
  serializedSessions3 = schema.serializedSessions;
3989
4550
  kbNamespaces3 = schema.kbNamespaces;
@@ -4016,35 +4577,6 @@ var init_ids = __esm({
4016
4577
  }
4017
4578
  });
4018
4579
 
4019
- // src/db/user-utils.ts
4020
- var import_bcryptjs, import_drizzle_orm6;
4021
- var init_user_utils = __esm({
4022
- "src/db/user-utils.ts"() {
4023
- "use strict";
4024
- init_cjs_shims();
4025
- import_bcryptjs = __toESM(require("bcryptjs"), 1);
4026
- import_drizzle_orm6 = require("drizzle-orm");
4027
- init_ids();
4028
- init_user();
4029
- init_database_wrapper();
4030
- init_schema();
4031
- }
4032
- });
4033
-
4034
- // src/db/first-run-bootstrap.ts
4035
- var import_node_crypto3, import_drizzle_orm7;
4036
- var init_first_run_bootstrap = __esm({
4037
- "src/db/first-run-bootstrap.ts"() {
4038
- "use strict";
4039
- init_cjs_shims();
4040
- import_node_crypto3 = require("crypto");
4041
- import_drizzle_orm7 = require("drizzle-orm");
4042
- init_database_wrapper();
4043
- init_schema();
4044
- init_user_utils();
4045
- }
4046
- });
4047
-
4048
4580
  // src/unix/index.ts
4049
4581
  var unix_exports = {};
4050
4582
  __export(unix_exports, {
@@ -4129,7 +4661,7 @@ var import_node_child_process = require("child_process");
4129
4661
  var import_node_util = require("util");
4130
4662
  var execAsync = (0, import_node_util.promisify)(import_node_child_process.exec);
4131
4663
  function spawnWithInput(cmd, args, input) {
4132
- return new Promise((resolve2, reject) => {
4664
+ return new Promise((resolve, reject) => {
4133
4665
  const child = (0, import_node_child_process.spawn)(cmd, args, {
4134
4666
  stdio: ["pipe", "pipe", "pipe"]
4135
4667
  });
@@ -4143,7 +4675,7 @@ function spawnWithInput(cmd, args, input) {
4143
4675
  });
4144
4676
  child.on("error", reject);
4145
4677
  child.on("close", (code) => {
4146
- resolve2({
4678
+ resolve({
4147
4679
  stdout,
4148
4680
  stderr,
4149
4681
  exitCode: code ?? 1
@@ -4627,10 +5159,7 @@ var import_node_fs = __toESM(require("fs"), 1);
4627
5159
 
4628
5160
  // src/yaml/index.ts
4629
5161
  init_cjs_shims();
4630
- var import_js_yaml = __toESM(require("js-yaml"), 1);
4631
- var load = import_js_yaml.default.load;
4632
- var dump = import_js_yaml.default.dump;
4633
- var YAMLException = import_js_yaml.default.YAMLException;
5162
+ var yaml = __toESM(require("js-yaml"), 1);
4634
5163
 
4635
5164
  // src/config/variant-resolver.ts
4636
5165
  init_cjs_shims();
@@ -4822,6 +5351,7 @@ init_schema();
4822
5351
  init_cjs_shims();
4823
5352
  init_ids();
4824
5353
  init_id();
5354
+ init_tenant_context();
4825
5355
  var RepositoryError = class extends Error {
4826
5356
  constructor(message, cause) {
4827
5357
  super(message);
@@ -4863,6 +5393,21 @@ async function resolveByShortIdPrefix(id, entityType, fetchMatches) {
4863
5393
  return matches[0];
4864
5394
  }
4865
5395
  var RESOLVE_SHORT_ID_FETCH_LIMIT = 11;
5396
+ function getHiddenTenantId(row) {
5397
+ const tenantId = row?.tenant_id;
5398
+ return typeof tenantId === "string" && tenantId.length > 0 ? tenantId : void 0;
5399
+ }
5400
+ function attachHiddenTenant(dto, row) {
5401
+ const tenantId = getHiddenTenantId(row);
5402
+ if (tenantId) {
5403
+ Object.defineProperty(dto, "tenant_id", {
5404
+ value: tenantId,
5405
+ enumerable: false,
5406
+ configurable: true
5407
+ });
5408
+ }
5409
+ return dto;
5410
+ }
4866
5411
 
4867
5412
  // src/db/repositories/session-env-selections.ts
4868
5413
  var SessionEnvSelectionRepository = class {
@@ -5250,71 +5795,103 @@ init_executor_heartbeat();
5250
5795
 
5251
5796
  // src/config/key-resolver.ts
5252
5797
  init_cjs_shims();
5253
-
5254
- // src/db/index.ts
5255
- init_cjs_shims();
5256
- var import_drizzle_orm34 = require("drizzle-orm");
5257
- var import_bcryptjs3 = __toESM(require("bcryptjs"), 1);
5798
+ var import_drizzle_orm6 = require("drizzle-orm");
5799
+ init_database_wrapper();
5800
+ init_schema();
5258
5801
  init_ids();
5259
-
5260
- // src/lib/slugs.ts
5261
- init_cjs_shims();
5262
-
5263
- // src/db/client.ts
5264
- init_cjs_shims();
5265
- var import_client = require("@libsql/client");
5266
- var import_libsql = require("drizzle-orm/libsql");
5267
- var import_postgres_js = require("drizzle-orm/postgres-js");
5268
- var import_postgres = __toESM(require("postgres"), 1);
5269
5802
  init_config_manager();
5270
- init_schema_postgres();
5271
- init_schema_sqlite();
5272
- init_schema_factory();
5273
-
5274
- // src/utils/path.ts
5275
- init_cjs_shims();
5276
- var import_node_os2 = require("os");
5277
- var import_node_path2 = require("path");
5803
+ var DEBUG_KEY_RESOLUTION = process.env.AGOR_DEBUG_KEY_RESOLUTION === "1" || process.env.DEBUG?.includes("key-resolution");
5278
5804
 
5279
- // src/db/index.ts
5280
- init_database_wrapper();
5281
- init_first_run_bootstrap();
5805
+ // src/config/index.ts
5806
+ init_multitenancy();
5282
5807
 
5283
- // src/db/migrate.ts
5808
+ // src/config/proxies-resolver.ts
5284
5809
  init_cjs_shims();
5285
- var import_node_path3 = require("path");
5286
- var import_node_url = require("url");
5287
- var import_drizzle_orm8 = require("drizzle-orm");
5288
- var import_migrator = require("drizzle-orm/libsql/migrator");
5289
- var import_migrator2 = require("drizzle-orm/postgres-js/migrator");
5290
- init_database_wrapper();
5291
- init_schema();
5292
5810
 
5293
- // src/db/pending-migrations.ts
5811
+ // src/config/repo-list.ts
5294
5812
  init_cjs_shims();
5295
5813
 
5296
- // src/db/repositories/index.ts
5814
+ // src/config/repo-reference.ts
5297
5815
  init_cjs_shims();
5816
+ var REPO_SLUG_PATTERN = /^[a-zA-Z0-9._-]+\/[a-zA-Z0-9._-]+$/;
5298
5817
 
5299
- // src/db/repositories/app-variables.ts
5818
+ // src/config/resolved-config-slice.ts
5300
5819
  init_cjs_shims();
5301
- var import_drizzle_orm9 = require("drizzle-orm");
5302
- init_ids();
5303
- init_database_wrapper();
5304
- init_schema();
5820
+ var import_zod = require("zod");
5821
+ var ResolvedConfigSliceSchema = import_zod.z.object({
5822
+ /** From `config.execution.*` */
5823
+ execution: import_zod.z.object({
5824
+ permission_timeout_ms: import_zod.z.number().int().nonnegative().optional(),
5825
+ executor_heartbeat: import_zod.z.object({
5826
+ enabled: import_zod.z.boolean(),
5827
+ interval_ms: import_zod.z.number().int().positive()
5828
+ }).optional()
5829
+ }).optional(),
5830
+ /** From `config.opencode.*` */
5831
+ opencode: import_zod.z.object({
5832
+ serverUrl: import_zod.z.string().optional()
5833
+ }).optional(),
5834
+ /** From `config.daemon.*` (selected fields only) */
5835
+ daemon: import_zod.z.object({
5836
+ host_ip_address: import_zod.z.string().optional()
5837
+ }).optional()
5838
+ });
5305
5839
 
5306
- // src/db/repositories/artifact-trust.ts
5840
+ // src/config/resource-schemas.ts
5307
5841
  init_cjs_shims();
5308
- var import_drizzle_orm10 = require("drizzle-orm");
5309
- init_ids();
5310
- init_database_wrapper();
5311
- init_schema();
5312
-
5313
- // src/db/repositories/artifacts.ts
5842
+ var import_zod2 = require("zod");
5843
+ var uuidSchema = import_zod2.z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, "Must be a valid UUID");
5844
+ var repoSlugSchema = import_zod2.z.string().regex(
5845
+ REPO_SLUG_PATTERN,
5846
+ 'Must be org/name format with alphanumeric, hyphens, underscores, or dots (e.g., "my-org/my-repo")'
5847
+ );
5848
+ var enforcedAgentConfigSchema = import_zod2.z.object({
5849
+ agentic_tool: import_zod2.z.enum(["claude-code", "claude-code-cli", "codex", "gemini", "opencode", "copilot", "cursor"]).optional(),
5850
+ permission_mode: import_zod2.z.string().optional(),
5851
+ model: import_zod2.z.string().optional(),
5852
+ mcp_server_ids: import_zod2.z.array(import_zod2.z.string()).optional()
5853
+ });
5854
+ var resourceRepoConfigSchema = import_zod2.z.object({
5855
+ repo_id: uuidSchema,
5856
+ slug: repoSlugSchema,
5857
+ remote_url: import_zod2.z.string().optional(),
5858
+ repo_type: import_zod2.z.enum(["remote", "local"]).default("remote"),
5859
+ default_branch: import_zod2.z.string().optional(),
5860
+ shallow: import_zod2.z.boolean().optional()
5861
+ }).refine((data) => data.repo_type !== "remote" || data.remote_url, {
5862
+ message: 'remote_url is required when repo_type is "remote"',
5863
+ path: ["remote_url"]
5864
+ });
5865
+ var resourceBranchConfigSchema = import_zod2.z.object({
5866
+ branch_id: uuidSchema,
5867
+ name: import_zod2.z.string().min(1, "Branch name is required"),
5868
+ ref: import_zod2.z.string().min(1, "Git ref is required"),
5869
+ ref_type: import_zod2.z.enum(["branch", "tag"]).optional(),
5870
+ others_can: import_zod2.z.enum(["none", "view", "session", "prompt", "all"]).optional(),
5871
+ mcp_server_ids: import_zod2.z.array(import_zod2.z.string()).optional(),
5872
+ repo: repoSlugSchema,
5873
+ readonly: import_zod2.z.boolean().optional(),
5874
+ agent: enforcedAgentConfigSchema.optional()
5875
+ });
5876
+ var resourceUserConfigSchema = import_zod2.z.object({
5877
+ user_id: uuidSchema,
5878
+ email: import_zod2.z.string().email("Must be a valid email address"),
5879
+ name: import_zod2.z.string().optional(),
5880
+ role: import_zod2.z.enum(["superadmin", "admin", "member", "viewer"]).default("member"),
5881
+ unix_username: import_zod2.z.string().optional(),
5882
+ password: import_zod2.z.string().optional()
5883
+ });
5884
+ var daemonResourcesConfigSchema = import_zod2.z.object({
5885
+ repos: import_zod2.z.array(resourceRepoConfigSchema).optional(),
5886
+ branches: import_zod2.z.array(resourceBranchConfigSchema).optional(),
5887
+ users: import_zod2.z.array(resourceUserConfigSchema).optional()
5888
+ });
5889
+
5890
+ // src/config/resource-sync.ts
5891
+ init_cjs_shims();
5892
+
5893
+ // src/config/security-resolver.ts
5314
5894
  init_cjs_shims();
5315
- var import_drizzle_orm11 = require("drizzle-orm");
5316
- init_config_manager();
5317
- init_ids();
5318
5895
 
5319
5896
  // src/utils/url.ts
5320
5897
  init_cjs_shims();
@@ -5366,99 +5943,113 @@ function stripHttpUrlUserinfo(rawUrl) {
5366
5943
  }
5367
5944
  }
5368
5945
 
5369
- // src/db/repositories/artifacts.ts
5370
- init_database_wrapper();
5371
- init_schema();
5946
+ // src/config/security-resolver.ts
5947
+ var DEFAULT_GIT_CONFIG_PARAMETERS = Object.freeze([
5948
+ "transfer.credentialsInUrl=die",
5949
+ "protocol.file.allow=user",
5950
+ "protocol.ext.allow=never",
5951
+ "core.protectHFS=true",
5952
+ "core.protectNTFS=true"
5953
+ ]);
5372
5954
 
5373
- // src/db/repositories/board-comments.ts
5955
+ // src/config/index.ts
5956
+ init_types();
5957
+
5958
+ // src/db/repositories/index.ts
5374
5959
  init_cjs_shims();
5375
- var import_drizzle_orm12 = require("drizzle-orm");
5960
+
5961
+ // src/db/repositories/app-variables.ts
5962
+ init_cjs_shims();
5963
+ var import_drizzle_orm7 = require("drizzle-orm");
5376
5964
  init_ids();
5377
5965
  init_database_wrapper();
5378
5966
  init_schema();
5379
5967
 
5380
- // src/db/repositories/board-objects.ts
5968
+ // src/db/repositories/artifact-trust.ts
5381
5969
  init_cjs_shims();
5382
- var import_drizzle_orm14 = require("drizzle-orm");
5970
+ var import_drizzle_orm8 = require("drizzle-orm");
5383
5971
  init_ids();
5972
+ init_database_wrapper();
5973
+ init_schema();
5384
5974
 
5385
- // src/utils/board-placement.ts
5975
+ // src/db/repositories/artifacts.ts
5386
5976
  init_cjs_shims();
5387
-
5388
- // src/db/repositories/board-objects.ts
5977
+ var import_drizzle_orm10 = require("drizzle-orm");
5978
+ init_config_manager();
5979
+ init_ids();
5389
5980
  init_database_wrapper();
5390
5981
  init_schema();
5391
5982
 
5392
5983
  // src/db/repositories/branch-access.ts
5393
5984
  init_cjs_shims();
5394
5985
  init_types2();
5395
- var import_drizzle_orm13 = require("drizzle-orm");
5986
+ var import_drizzle_orm9 = require("drizzle-orm");
5396
5987
  init_database_wrapper();
5397
5988
  init_schema();
5398
5989
  var VISIBLE_BRANCH_PERMISSION_LEVELS = BRANCH_PERMISSION_LEVELS.filter(
5399
5990
  (level) => level !== "none"
5400
5991
  );
5401
5992
  function activeGroupGrantAccessExists(db, userId) {
5402
- return (0, import_drizzle_orm13.exists)(
5993
+ return (0, import_drizzle_orm9.exists)(
5403
5994
  // biome-ignore lint/suspicious/noExplicitAny: Drizzle select has complex cross-dialect overloads
5404
- db.select({ _: import_drizzle_orm13.sql`1` }).from(branchGroupGrants3).innerJoin(
5995
+ db.select({ _: import_drizzle_orm9.sql`1` }).from(branchGroupGrants3).innerJoin(
5405
5996
  groupMemberships3,
5406
- (0, import_drizzle_orm13.and)(
5407
- (0, import_drizzle_orm13.eq)(groupMemberships3.group_id, branchGroupGrants3.group_id),
5408
- (0, import_drizzle_orm13.eq)(groupMemberships3.user_id, userId)
5997
+ (0, import_drizzle_orm9.and)(
5998
+ (0, import_drizzle_orm9.eq)(groupMemberships3.group_id, branchGroupGrants3.group_id),
5999
+ (0, import_drizzle_orm9.eq)(groupMemberships3.user_id, userId)
5409
6000
  )
5410
6001
  ).innerJoin(
5411
6002
  groups3,
5412
- (0, import_drizzle_orm13.and)((0, import_drizzle_orm13.eq)(groups3.group_id, branchGroupGrants3.group_id), (0, import_drizzle_orm13.eq)(groups3.archived, false))
6003
+ (0, import_drizzle_orm9.and)((0, import_drizzle_orm9.eq)(groups3.group_id, branchGroupGrants3.group_id), (0, import_drizzle_orm9.eq)(groups3.archived, false))
5413
6004
  ).where(
5414
- (0, import_drizzle_orm13.and)(
5415
- (0, import_drizzle_orm13.eq)(branchGroupGrants3.branch_id, branches3.branch_id),
5416
- (0, import_drizzle_orm13.inArray)(branchGroupGrants3.can, VISIBLE_BRANCH_PERMISSION_LEVELS)
6005
+ (0, import_drizzle_orm9.and)(
6006
+ (0, import_drizzle_orm9.eq)(branchGroupGrants3.branch_id, branches3.branch_id),
6007
+ (0, import_drizzle_orm9.inArray)(branchGroupGrants3.can, VISIBLE_BRANCH_PERMISSION_LEVELS)
5417
6008
  )
5418
6009
  )
5419
6010
  );
5420
6011
  }
5421
6012
  function activeBoardGroupGrantAccessExists(db, userId) {
5422
- return (0, import_drizzle_orm13.exists)(
6013
+ return (0, import_drizzle_orm9.exists)(
5423
6014
  // biome-ignore lint/suspicious/noExplicitAny: Drizzle select has complex cross-dialect overloads
5424
- db.select({ _: import_drizzle_orm13.sql`1` }).from(boardGroupGrants3).innerJoin(
6015
+ db.select({ _: import_drizzle_orm9.sql`1` }).from(boardGroupGrants3).innerJoin(
5425
6016
  groupMemberships3,
5426
- (0, import_drizzle_orm13.and)(
5427
- (0, import_drizzle_orm13.eq)(groupMemberships3.group_id, boardGroupGrants3.group_id),
5428
- (0, import_drizzle_orm13.eq)(groupMemberships3.user_id, userId)
6017
+ (0, import_drizzle_orm9.and)(
6018
+ (0, import_drizzle_orm9.eq)(groupMemberships3.group_id, boardGroupGrants3.group_id),
6019
+ (0, import_drizzle_orm9.eq)(groupMemberships3.user_id, userId)
5429
6020
  )
5430
6021
  ).innerJoin(
5431
6022
  groups3,
5432
- (0, import_drizzle_orm13.and)((0, import_drizzle_orm13.eq)(groups3.group_id, boardGroupGrants3.group_id), (0, import_drizzle_orm13.eq)(groups3.archived, false))
6023
+ (0, import_drizzle_orm9.and)((0, import_drizzle_orm9.eq)(groups3.group_id, boardGroupGrants3.group_id), (0, import_drizzle_orm9.eq)(groups3.archived, false))
5433
6024
  ).innerJoin(
5434
6025
  boards3,
5435
- (0, import_drizzle_orm13.and)(
5436
- (0, import_drizzle_orm13.eq)(boards3.board_id, boardGroupGrants3.board_id),
5437
- (0, import_drizzle_orm13.eq)(import_drizzle_orm13.sql`coalesce(${jsonExtract(db, boards3.data, "access_mode")}, 'shared')`, "shared")
6026
+ (0, import_drizzle_orm9.and)(
6027
+ (0, import_drizzle_orm9.eq)(boards3.board_id, boardGroupGrants3.board_id),
6028
+ (0, import_drizzle_orm9.eq)(import_drizzle_orm9.sql`coalesce(${jsonExtract(db, boards3.data, "access_mode")}, 'shared')`, "shared")
5438
6029
  )
5439
6030
  ).where(
5440
- (0, import_drizzle_orm13.and)(
5441
- (0, import_drizzle_orm13.eq)(boardGroupGrants3.board_id, branches3.board_id),
5442
- (0, import_drizzle_orm13.inArray)(boardGroupGrants3.can, VISIBLE_BRANCH_PERMISSION_LEVELS)
6031
+ (0, import_drizzle_orm9.and)(
6032
+ (0, import_drizzle_orm9.eq)(boardGroupGrants3.board_id, branches3.board_id),
6033
+ (0, import_drizzle_orm9.inArray)(boardGroupGrants3.can, VISIBLE_BRANCH_PERMISSION_LEVELS)
5443
6034
  )
5444
6035
  )
5445
6036
  );
5446
6037
  }
5447
6038
  function activeBoardOwnerAccessExists(db, userId) {
5448
- return (0, import_drizzle_orm13.exists)(
6039
+ return (0, import_drizzle_orm9.exists)(
5449
6040
  // biome-ignore lint/suspicious/noExplicitAny: Drizzle select has complex cross-dialect overloads
5450
- db.select({ _: import_drizzle_orm13.sql`1` }).from(boardOwners3).where((0, import_drizzle_orm13.and)((0, import_drizzle_orm13.eq)(boardOwners3.board_id, branches3.board_id), (0, import_drizzle_orm13.eq)(boardOwners3.user_id, userId)))
6041
+ db.select({ _: import_drizzle_orm9.sql`1` }).from(boardOwners3).where((0, import_drizzle_orm9.and)((0, import_drizzle_orm9.eq)(boardOwners3.board_id, branches3.board_id), (0, import_drizzle_orm9.eq)(boardOwners3.user_id, userId)))
5451
6042
  );
5452
6043
  }
5453
6044
  function alignedBoardDefaultVisible(db) {
5454
- return (0, import_drizzle_orm13.exists)(
6045
+ return (0, import_drizzle_orm9.exists)(
5455
6046
  // biome-ignore lint/suspicious/noExplicitAny: Drizzle select has complex cross-dialect overloads
5456
- db.select({ _: import_drizzle_orm13.sql`1` }).from(boards3).where(
5457
- (0, import_drizzle_orm13.and)(
5458
- (0, import_drizzle_orm13.eq)(boards3.board_id, branches3.board_id),
5459
- (0, import_drizzle_orm13.eq)(import_drizzle_orm13.sql`coalesce(${jsonExtract(db, boards3.data, "access_mode")}, 'shared')`, "shared"),
5460
- (0, import_drizzle_orm13.inArray)(
5461
- import_drizzle_orm13.sql`coalesce(${jsonExtract(db, boards3.data, "default_others_can")}, 'session')`,
6047
+ db.select({ _: import_drizzle_orm9.sql`1` }).from(boards3).where(
6048
+ (0, import_drizzle_orm9.and)(
6049
+ (0, import_drizzle_orm9.eq)(boards3.board_id, branches3.board_id),
6050
+ (0, import_drizzle_orm9.eq)(import_drizzle_orm9.sql`coalesce(${jsonExtract(db, boards3.data, "access_mode")}, 'shared')`, "shared"),
6051
+ (0, import_drizzle_orm9.inArray)(
6052
+ import_drizzle_orm9.sql`coalesce(${jsonExtract(db, boards3.data, "default_others_can")}, 'session')`,
5462
6053
  VISIBLE_BRANCH_PERMISSION_LEVELS
5463
6054
  )
5464
6055
  )
@@ -5466,33 +6057,81 @@ function alignedBoardDefaultVisible(db) {
5466
6057
  );
5467
6058
  }
5468
6059
  function visibleBranchAccessCondition(db, userId) {
5469
- return (0, import_drizzle_orm13.or)(
5470
- (0, import_drizzle_orm13.isNotNull)(branchOwners3.user_id),
6060
+ return (0, import_drizzle_orm9.or)(
6061
+ (0, import_drizzle_orm9.isNotNull)(branchOwners3.user_id),
5471
6062
  activeGroupGrantAccessExists(db, userId),
5472
- (0, import_drizzle_orm13.and)((0, import_drizzle_orm13.eq)(branches3.permission_source, "board"), activeBoardOwnerAccessExists(db, userId)),
5473
- (0, import_drizzle_orm13.and)((0, import_drizzle_orm13.eq)(branches3.permission_source, "board"), activeBoardGroupGrantAccessExists(db, userId)),
5474
- (0, import_drizzle_orm13.and)((0, import_drizzle_orm13.eq)(branches3.permission_source, "board"), alignedBoardDefaultVisible(db)),
5475
- (0, import_drizzle_orm13.and)(
5476
- (0, import_drizzle_orm13.eq)(branches3.permission_source, "override"),
5477
- (0, import_drizzle_orm13.inArray)(branches3.others_can, VISIBLE_BRANCH_PERMISSION_LEVELS)
6063
+ (0, import_drizzle_orm9.and)((0, import_drizzle_orm9.eq)(branches3.permission_source, "board"), activeBoardOwnerAccessExists(db, userId)),
6064
+ (0, import_drizzle_orm9.and)((0, import_drizzle_orm9.eq)(branches3.permission_source, "board"), activeBoardGroupGrantAccessExists(db, userId)),
6065
+ (0, import_drizzle_orm9.and)((0, import_drizzle_orm9.eq)(branches3.permission_source, "board"), alignedBoardDefaultVisible(db)),
6066
+ (0, import_drizzle_orm9.and)(
6067
+ (0, import_drizzle_orm9.eq)(branches3.permission_source, "override"),
6068
+ (0, import_drizzle_orm9.inArray)(branches3.others_can, VISIBLE_BRANCH_PERMISSION_LEVELS)
5478
6069
  )
5479
- ) ?? import_drizzle_orm13.sql`false`;
6070
+ ) ?? import_drizzle_orm9.sql`false`;
5480
6071
  }
5481
6072
 
6073
+ // src/db/repositories/board-comments.ts
6074
+ init_cjs_shims();
6075
+ var import_drizzle_orm11 = require("drizzle-orm");
6076
+ init_ids();
6077
+ init_database_wrapper();
6078
+ init_schema();
6079
+
6080
+ // src/db/repositories/board-objects.ts
6081
+ init_cjs_shims();
6082
+ var import_drizzle_orm12 = require("drizzle-orm");
6083
+ init_ids();
6084
+
6085
+ // src/utils/board-placement.ts
6086
+ init_cjs_shims();
6087
+
6088
+ // src/db/repositories/board-objects.ts
6089
+ init_database_wrapper();
6090
+ init_schema();
6091
+
5482
6092
  // src/db/repositories/boards.ts
5483
6093
  init_cjs_shims();
5484
6094
  init_types2();
5485
- var import_drizzle_orm17 = require("drizzle-orm");
6095
+ var import_drizzle_orm15 = require("drizzle-orm");
5486
6096
  var yaml3 = __toESM(require("js-yaml"), 1);
5487
6097
  init_config_manager();
5488
6098
  init_ids();
6099
+
6100
+ // src/lib/slugs.ts
6101
+ init_cjs_shims();
6102
+
6103
+ // src/utils/emoji-shortcodes.ts
6104
+ init_cjs_shims();
6105
+ var import_node_module = require("module");
6106
+ var requireJson = (0, import_node_module.createRequire)(importMetaUrl);
6107
+ var emojiData = requireJson("emojibase-data/en/compact.json");
6108
+ var shortcodes = requireJson(
6109
+ "emojibase-data/en/shortcodes/emojibase.json"
6110
+ );
6111
+ var emojiByHexcode = /* @__PURE__ */ new Map();
6112
+ for (const emoji of emojiData) {
6113
+ if (emoji.unicode) {
6114
+ emojiByHexcode.set(emoji.hexcode, emoji.unicode);
6115
+ }
6116
+ }
6117
+ var emojiByShortcode = /* @__PURE__ */ new Map();
6118
+ for (const [hexcode, codes] of Object.entries(shortcodes)) {
6119
+ const emoji = emojiByHexcode.get(hexcode);
6120
+ if (!emoji) continue;
6121
+ const codeList = Array.isArray(codes) ? codes : [codes];
6122
+ for (const code of codeList) {
6123
+ emojiByShortcode.set(code.toLowerCase(), emoji);
6124
+ }
6125
+ }
6126
+
6127
+ // src/db/repositories/boards.ts
5489
6128
  init_database_wrapper();
5490
6129
  init_schema();
5491
6130
 
5492
6131
  // src/db/repositories/branches.ts
5493
6132
  init_cjs_shims();
5494
6133
  init_types2();
5495
- var import_drizzle_orm16 = require("drizzle-orm");
6134
+ var import_drizzle_orm14 = require("drizzle-orm");
5496
6135
  init_config_manager();
5497
6136
  init_ids();
5498
6137
  init_database_wrapper();
@@ -5500,7 +6139,7 @@ init_schema();
5500
6139
 
5501
6140
  // src/db/repositories/groups.ts
5502
6141
  init_cjs_shims();
5503
- var import_drizzle_orm15 = require("drizzle-orm");
6142
+ var import_drizzle_orm13 = require("drizzle-orm");
5504
6143
  init_ids();
5505
6144
  init_database_wrapper();
5506
6145
  init_schema();
@@ -5564,17 +6203,17 @@ var GroupRepository = class {
5564
6203
  }
5565
6204
  async findAll(filter) {
5566
6205
  const conditions = [];
5567
- if (filter?.archived !== void 0) conditions.push((0, import_drizzle_orm15.eq)(groups3.archived, filter.archived));
6206
+ if (filter?.archived !== void 0) conditions.push((0, import_drizzle_orm13.eq)(groups3.archived, filter.archived));
5568
6207
  const query = select(this.db).from(groups3);
5569
- const rows = conditions.length > 0 ? await query.where((0, import_drizzle_orm15.and)(...conditions)).all() : await query.all();
6208
+ const rows = conditions.length > 0 ? await query.where((0, import_drizzle_orm13.and)(...conditions)).all() : await query.all();
5570
6209
  return rows.map((row) => this.rowToGroup(row));
5571
6210
  }
5572
6211
  async findById(id) {
5573
- const row = await select(this.db).from(groups3).where((0, import_drizzle_orm15.eq)(groups3.group_id, id)).one();
6212
+ const row = await select(this.db).from(groups3).where((0, import_drizzle_orm13.eq)(groups3.group_id, id)).one();
5574
6213
  return row ? this.rowToGroup(row) : null;
5575
6214
  }
5576
6215
  async findBySlug(slug) {
5577
- const row = await select(this.db).from(groups3).where((0, import_drizzle_orm15.eq)(groups3.slug, slug)).one();
6216
+ const row = await select(this.db).from(groups3).where((0, import_drizzle_orm13.eq)(groups3.slug, slug)).one();
5578
6217
  return row ? this.rowToGroup(row) : null;
5579
6218
  }
5580
6219
  async create(data) {
@@ -5608,7 +6247,7 @@ var GroupRepository = class {
5608
6247
  if (updates.slug !== void 0) patch.slug = normalizeSlug(updates.slug);
5609
6248
  if (updates.description !== void 0) patch.description = updates.description;
5610
6249
  if (updates.archived !== void 0) patch.archived = updates.archived;
5611
- await update(this.db, groups3).set(patch).where((0, import_drizzle_orm15.eq)(groups3.group_id, existing.group_id)).run();
6250
+ await update(this.db, groups3).set(patch).where((0, import_drizzle_orm13.eq)(groups3.group_id, existing.group_id)).run();
5612
6251
  const updatedGroup = await this.findById(existing.group_id);
5613
6252
  if (!updatedGroup) throw new RepositoryError("Failed to retrieve updated group");
5614
6253
  return updatedGroup;
@@ -5616,19 +6255,19 @@ var GroupRepository = class {
5616
6255
  async delete(id) {
5617
6256
  const existing = await this.findById(id);
5618
6257
  if (!existing) throw new EntityNotFoundError("Group", id);
5619
- await deleteFrom(this.db, groups3).where((0, import_drizzle_orm15.eq)(groups3.group_id, existing.group_id)).run();
6258
+ await deleteFrom(this.db, groups3).where((0, import_drizzle_orm13.eq)(groups3.group_id, existing.group_id)).run();
5620
6259
  return existing;
5621
6260
  }
5622
6261
  async listMemberships(filter) {
5623
6262
  const conditions = [];
5624
- if (filter?.group_id) conditions.push((0, import_drizzle_orm15.eq)(groupMemberships3.group_id, filter.group_id));
5625
- if (filter?.user_id) conditions.push((0, import_drizzle_orm15.eq)(groupMemberships3.user_id, filter.user_id));
6263
+ if (filter?.group_id) conditions.push((0, import_drizzle_orm13.eq)(groupMemberships3.group_id, filter.group_id));
6264
+ if (filter?.user_id) conditions.push((0, import_drizzle_orm13.eq)(groupMemberships3.user_id, filter.user_id));
5626
6265
  const query = select(this.db).from(groupMemberships3);
5627
- const rows = conditions.length > 0 ? await query.where((0, import_drizzle_orm15.and)(...conditions)).all() : await query.all();
6266
+ const rows = conditions.length > 0 ? await query.where((0, import_drizzle_orm13.and)(...conditions)).all() : await query.all();
5628
6267
  return rows.map((row) => this.rowToMembership(row));
5629
6268
  }
5630
6269
  async addMember(groupId, userId, addedBy) {
5631
- const existing = await select(this.db).from(groupMemberships3).where((0, import_drizzle_orm15.and)((0, import_drizzle_orm15.eq)(groupMemberships3.group_id, groupId), (0, import_drizzle_orm15.eq)(groupMemberships3.user_id, userId))).one();
6270
+ const existing = await select(this.db).from(groupMemberships3).where((0, import_drizzle_orm13.and)((0, import_drizzle_orm13.eq)(groupMemberships3.group_id, groupId), (0, import_drizzle_orm13.eq)(groupMemberships3.user_id, userId))).one();
5632
6271
  if (existing) return this.rowToMembership(existing);
5633
6272
  const row = {
5634
6273
  group_id: groupId,
@@ -5640,17 +6279,17 @@ var GroupRepository = class {
5640
6279
  return this.rowToMembership(row);
5641
6280
  }
5642
6281
  async removeMember(groupId, userId) {
5643
- const existing = await select(this.db).from(groupMemberships3).where((0, import_drizzle_orm15.and)((0, import_drizzle_orm15.eq)(groupMemberships3.group_id, groupId), (0, import_drizzle_orm15.eq)(groupMemberships3.user_id, userId))).one();
6282
+ const existing = await select(this.db).from(groupMemberships3).where((0, import_drizzle_orm13.and)((0, import_drizzle_orm13.eq)(groupMemberships3.group_id, groupId), (0, import_drizzle_orm13.eq)(groupMemberships3.user_id, userId))).one();
5644
6283
  if (!existing) return null;
5645
- await deleteFrom(this.db, groupMemberships3).where((0, import_drizzle_orm15.and)((0, import_drizzle_orm15.eq)(groupMemberships3.group_id, groupId), (0, import_drizzle_orm15.eq)(groupMemberships3.user_id, userId))).run();
6284
+ await deleteFrom(this.db, groupMemberships3).where((0, import_drizzle_orm13.and)((0, import_drizzle_orm13.eq)(groupMemberships3.group_id, groupId), (0, import_drizzle_orm13.eq)(groupMemberships3.user_id, userId))).run();
5646
6285
  return this.rowToMembership(existing);
5647
6286
  }
5648
6287
  async getGroupIdsForUser(userId) {
5649
- const rows = await select(this.db, { group_id: groupMemberships3.group_id }).from(groupMemberships3).where((0, import_drizzle_orm15.eq)(groupMemberships3.user_id, userId)).all();
6288
+ const rows = await select(this.db, { group_id: groupMemberships3.group_id }).from(groupMemberships3).where((0, import_drizzle_orm13.eq)(groupMemberships3.user_id, userId)).all();
5650
6289
  return rows.map((r) => r.group_id);
5651
6290
  }
5652
6291
  async listBranchGrants(branchId) {
5653
- const rows = await select(this.db).from(branchGroupGrants3).leftJoin(groups3, (0, import_drizzle_orm15.eq)(branchGroupGrants3.group_id, groups3.group_id)).where((0, import_drizzle_orm15.eq)(branchGroupGrants3.branch_id, branchId)).all();
6292
+ const rows = await select(this.db).from(branchGroupGrants3).leftJoin(groups3, (0, import_drizzle_orm13.eq)(branchGroupGrants3.group_id, groups3.group_id)).where((0, import_drizzle_orm13.eq)(branchGroupGrants3.branch_id, branchId)).all();
5654
6293
  return rows.map(
5655
6294
  (r) => this.rowToGrant(r.branch_group_grants, r.groups ? this.rowToGroup(r.groups) : void 0)
5656
6295
  );
@@ -5658,16 +6297,16 @@ var GroupRepository = class {
5658
6297
  async upsertBranchGrant(data) {
5659
6298
  const now = /* @__PURE__ */ new Date();
5660
6299
  const existing = await select(this.db).from(branchGroupGrants3).where(
5661
- (0, import_drizzle_orm15.and)(
5662
- (0, import_drizzle_orm15.eq)(branchGroupGrants3.branch_id, data.branch_id),
5663
- (0, import_drizzle_orm15.eq)(branchGroupGrants3.group_id, data.group_id)
6300
+ (0, import_drizzle_orm13.and)(
6301
+ (0, import_drizzle_orm13.eq)(branchGroupGrants3.branch_id, data.branch_id),
6302
+ (0, import_drizzle_orm13.eq)(branchGroupGrants3.group_id, data.group_id)
5664
6303
  )
5665
6304
  ).one();
5666
6305
  if (existing) {
5667
6306
  await update(this.db, branchGroupGrants3).set({ can: data.can, fs_access: data.fs_access ?? null, updated_at: now }).where(
5668
- (0, import_drizzle_orm15.and)(
5669
- (0, import_drizzle_orm15.eq)(branchGroupGrants3.branch_id, data.branch_id),
5670
- (0, import_drizzle_orm15.eq)(branchGroupGrants3.group_id, data.group_id)
6307
+ (0, import_drizzle_orm13.and)(
6308
+ (0, import_drizzle_orm13.eq)(branchGroupGrants3.branch_id, data.branch_id),
6309
+ (0, import_drizzle_orm13.eq)(branchGroupGrants3.group_id, data.group_id)
5671
6310
  )
5672
6311
  ).run();
5673
6312
  } else {
@@ -5690,16 +6329,16 @@ var GroupRepository = class {
5690
6329
  const existing = (await this.listBranchGrants(branchId)).find((g) => g.group_id === groupId) ?? null;
5691
6330
  if (!existing) return null;
5692
6331
  await deleteFrom(this.db, branchGroupGrants3).where(
5693
- (0, import_drizzle_orm15.and)((0, import_drizzle_orm15.eq)(branchGroupGrants3.branch_id, branchId), (0, import_drizzle_orm15.eq)(branchGroupGrants3.group_id, groupId))
6332
+ (0, import_drizzle_orm13.and)((0, import_drizzle_orm13.eq)(branchGroupGrants3.branch_id, branchId), (0, import_drizzle_orm13.eq)(branchGroupGrants3.group_id, groupId))
5694
6333
  ).run();
5695
6334
  return existing;
5696
6335
  }
5697
6336
  async getBranchGrantsForUser(branchId, userId) {
5698
- const rows = await select(this.db).from(branchGroupGrants3).innerJoin(groupMemberships3, (0, import_drizzle_orm15.eq)(branchGroupGrants3.group_id, groupMemberships3.group_id)).innerJoin(groups3, (0, import_drizzle_orm15.eq)(groupMemberships3.group_id, groups3.group_id)).where(
5699
- (0, import_drizzle_orm15.and)(
5700
- (0, import_drizzle_orm15.eq)(branchGroupGrants3.branch_id, branchId),
5701
- (0, import_drizzle_orm15.eq)(groupMemberships3.user_id, userId),
5702
- (0, import_drizzle_orm15.eq)(groups3.archived, false)
6337
+ const rows = await select(this.db).from(branchGroupGrants3).innerJoin(groupMemberships3, (0, import_drizzle_orm13.eq)(branchGroupGrants3.group_id, groupMemberships3.group_id)).innerJoin(groups3, (0, import_drizzle_orm13.eq)(groupMemberships3.group_id, groups3.group_id)).where(
6338
+ (0, import_drizzle_orm13.and)(
6339
+ (0, import_drizzle_orm13.eq)(branchGroupGrants3.branch_id, branchId),
6340
+ (0, import_drizzle_orm13.eq)(groupMemberships3.user_id, userId),
6341
+ (0, import_drizzle_orm13.eq)(groups3.archived, false)
5703
6342
  )
5704
6343
  ).all();
5705
6344
  return rows.map(
@@ -5707,7 +6346,7 @@ var GroupRepository = class {
5707
6346
  );
5708
6347
  }
5709
6348
  async listBoardGrants(boardId) {
5710
- const rows = await select(this.db).from(boardGroupGrants3).leftJoin(groups3, (0, import_drizzle_orm15.eq)(boardGroupGrants3.group_id, groups3.group_id)).where((0, import_drizzle_orm15.eq)(boardGroupGrants3.board_id, boardId)).all();
6349
+ const rows = await select(this.db).from(boardGroupGrants3).leftJoin(groups3, (0, import_drizzle_orm13.eq)(boardGroupGrants3.group_id, groups3.group_id)).where((0, import_drizzle_orm13.eq)(boardGroupGrants3.board_id, boardId)).all();
5711
6350
  return rows.map(
5712
6351
  (r) => this.rowToBoardGrant(r.board_group_grants, r.groups ? this.rowToGroup(r.groups) : void 0)
5713
6352
  );
@@ -5715,16 +6354,16 @@ var GroupRepository = class {
5715
6354
  async upsertBoardGrant(data) {
5716
6355
  const now = /* @__PURE__ */ new Date();
5717
6356
  const existing = await select(this.db).from(boardGroupGrants3).where(
5718
- (0, import_drizzle_orm15.and)(
5719
- (0, import_drizzle_orm15.eq)(boardGroupGrants3.board_id, data.board_id),
5720
- (0, import_drizzle_orm15.eq)(boardGroupGrants3.group_id, data.group_id)
6357
+ (0, import_drizzle_orm13.and)(
6358
+ (0, import_drizzle_orm13.eq)(boardGroupGrants3.board_id, data.board_id),
6359
+ (0, import_drizzle_orm13.eq)(boardGroupGrants3.group_id, data.group_id)
5721
6360
  )
5722
6361
  ).one();
5723
6362
  if (existing) {
5724
6363
  await update(this.db, boardGroupGrants3).set({ can: data.can, fs_access: data.fs_access ?? null, updated_at: now }).where(
5725
- (0, import_drizzle_orm15.and)(
5726
- (0, import_drizzle_orm15.eq)(boardGroupGrants3.board_id, data.board_id),
5727
- (0, import_drizzle_orm15.eq)(boardGroupGrants3.group_id, data.group_id)
6364
+ (0, import_drizzle_orm13.and)(
6365
+ (0, import_drizzle_orm13.eq)(boardGroupGrants3.board_id, data.board_id),
6366
+ (0, import_drizzle_orm13.eq)(boardGroupGrants3.group_id, data.group_id)
5728
6367
  )
5729
6368
  ).run();
5730
6369
  } else {
@@ -5746,15 +6385,15 @@ var GroupRepository = class {
5746
6385
  async removeBoardGrant(boardId, groupId) {
5747
6386
  const existing = (await this.listBoardGrants(boardId)).find((g) => g.group_id === groupId) ?? null;
5748
6387
  if (!existing) return null;
5749
- await deleteFrom(this.db, boardGroupGrants3).where((0, import_drizzle_orm15.and)((0, import_drizzle_orm15.eq)(boardGroupGrants3.board_id, boardId), (0, import_drizzle_orm15.eq)(boardGroupGrants3.group_id, groupId))).run();
6388
+ await deleteFrom(this.db, boardGroupGrants3).where((0, import_drizzle_orm13.and)((0, import_drizzle_orm13.eq)(boardGroupGrants3.board_id, boardId), (0, import_drizzle_orm13.eq)(boardGroupGrants3.group_id, groupId))).run();
5750
6389
  return existing;
5751
6390
  }
5752
6391
  async getBoardGrantsForUser(boardId, userId) {
5753
- const rows = await select(this.db).from(boardGroupGrants3).innerJoin(groupMemberships3, (0, import_drizzle_orm15.eq)(boardGroupGrants3.group_id, groupMemberships3.group_id)).innerJoin(groups3, (0, import_drizzle_orm15.eq)(groupMemberships3.group_id, groups3.group_id)).where(
5754
- (0, import_drizzle_orm15.and)(
5755
- (0, import_drizzle_orm15.eq)(boardGroupGrants3.board_id, boardId),
5756
- (0, import_drizzle_orm15.eq)(groupMemberships3.user_id, userId),
5757
- (0, import_drizzle_orm15.eq)(groups3.archived, false)
6392
+ const rows = await select(this.db).from(boardGroupGrants3).innerJoin(groupMemberships3, (0, import_drizzle_orm13.eq)(boardGroupGrants3.group_id, groupMemberships3.group_id)).innerJoin(groups3, (0, import_drizzle_orm13.eq)(groupMemberships3.group_id, groups3.group_id)).where(
6393
+ (0, import_drizzle_orm13.and)(
6394
+ (0, import_drizzle_orm13.eq)(boardGroupGrants3.board_id, boardId),
6395
+ (0, import_drizzle_orm13.eq)(groupMemberships3.user_id, userId),
6396
+ (0, import_drizzle_orm13.eq)(groups3.archived, false)
5758
6397
  )
5759
6398
  ).all();
5760
6399
  return rows.map(
@@ -5814,6 +6453,7 @@ var FS_ACCESS_RANK = {
5814
6453
  };
5815
6454
  var VIEW_OR_BETTER_BRANCH_PERMISSIONS = ["view", "session", "prompt", "all"];
5816
6455
  var BRANCH_PERMISSION_SOURCES = ["board", "override"];
6456
+ var FS_ACCESS_BRANCH_PERMISSIONS = ["read", "write"];
5817
6457
  var BranchRepository = class {
5818
6458
  constructor(db) {
5819
6459
  this.db = db;
@@ -5830,44 +6470,47 @@ var BranchRepository = class {
5830
6470
  rowToBranch(row, baseUrl) {
5831
6471
  const branchId = row.branch_id;
5832
6472
  const url = baseUrl && row.board_id ? getBranchUrl(branchId, baseUrl) : null;
5833
- return {
5834
- branch_id: branchId,
5835
- repo_id: row.repo_id,
5836
- created_at: new Date(row.created_at).toISOString(),
5837
- updated_at: row.updated_at ? new Date(row.updated_at).toISOString() : new Date(row.created_at).toISOString(),
5838
- created_by: row.created_by,
5839
- name: row.name,
5840
- ref: row.ref,
5841
- ref_type: row.ref_type ?? "branch",
5842
- branch_unique_id: row.branch_unique_id,
5843
- start_command: row.start_command ?? void 0,
5844
- // Static environment fields
5845
- stop_command: row.stop_command ?? void 0,
5846
- nuke_command: row.nuke_command ?? void 0,
5847
- health_check_url: row.health_check_url ?? void 0,
5848
- app_url: row.app_url ?? void 0,
5849
- logs_command: row.logs_command ?? void 0,
5850
- environment_variant: row.environment_variant ?? void 0,
5851
- board_id: row.board_id ?? void 0,
5852
- // Top-level column
5853
- needs_attention: Boolean(row.needs_attention),
5854
- // Convert SQLite integer (0/1) to boolean
5855
- archived: Boolean(row.archived),
5856
- // Convert SQLite integer (0/1) to boolean
5857
- archived_at: row.archived_at ? new Date(row.archived_at).toISOString() : void 0,
5858
- archived_by: row.archived_by ?? void 0,
5859
- filesystem_status: row.filesystem_status ?? void 0,
5860
- // RBAC fields
5861
- permission_source: row.permission_source ?? "override",
5862
- others_can: row.others_can ?? void 0,
5863
- others_fs_access: row.others_fs_access ?? void 0,
5864
- unix_group: row.unix_group ?? void 0,
5865
- // Branch storage mode
5866
- storage_mode: row.storage_mode ?? "worktree",
5867
- clone_depth: row.clone_depth ?? void 0,
5868
- ...row.data,
5869
- url
5870
- };
6473
+ return attachHiddenTenant(
6474
+ {
6475
+ branch_id: branchId,
6476
+ repo_id: row.repo_id,
6477
+ created_at: new Date(row.created_at).toISOString(),
6478
+ updated_at: row.updated_at ? new Date(row.updated_at).toISOString() : new Date(row.created_at).toISOString(),
6479
+ created_by: row.created_by,
6480
+ name: row.name,
6481
+ ref: row.ref,
6482
+ ref_type: row.ref_type ?? "branch",
6483
+ branch_unique_id: row.branch_unique_id,
6484
+ start_command: row.start_command ?? void 0,
6485
+ // Static environment fields
6486
+ stop_command: row.stop_command ?? void 0,
6487
+ nuke_command: row.nuke_command ?? void 0,
6488
+ health_check_url: row.health_check_url ?? void 0,
6489
+ app_url: row.app_url ?? void 0,
6490
+ logs_command: row.logs_command ?? void 0,
6491
+ environment_variant: row.environment_variant ?? void 0,
6492
+ board_id: row.board_id ?? void 0,
6493
+ // Top-level column
6494
+ needs_attention: Boolean(row.needs_attention),
6495
+ // Convert SQLite integer (0/1) to boolean
6496
+ archived: Boolean(row.archived),
6497
+ // Convert SQLite integer (0/1) to boolean
6498
+ archived_at: row.archived_at ? new Date(row.archived_at).toISOString() : void 0,
6499
+ archived_by: row.archived_by ?? void 0,
6500
+ filesystem_status: row.filesystem_status ?? void 0,
6501
+ // RBAC fields
6502
+ permission_source: row.permission_source ?? "override",
6503
+ others_can: row.others_can ?? void 0,
6504
+ others_fs_access: row.others_fs_access ?? void 0,
6505
+ unix_group: row.unix_group ?? void 0,
6506
+ // Branch storage mode
6507
+ storage_mode: row.storage_mode ?? "worktree",
6508
+ clone_depth: row.clone_depth ?? void 0,
6509
+ ...row.data,
6510
+ url
6511
+ },
6512
+ row
6513
+ );
5871
6514
  }
5872
6515
  /**
5873
6516
  * Convert Branch to database insert format
@@ -5974,10 +6617,10 @@ var BranchRepository = class {
5974
6617
  async findById(id) {
5975
6618
  try {
5976
6619
  const fullId = await resolveByShortIdPrefix(id, "Branch", async (pattern) => {
5977
- const rows = await select(this.db).from(branches3).where((0, import_drizzle_orm16.like)(branches3.branch_id, pattern)).limit(RESOLVE_SHORT_ID_FETCH_LIMIT).all();
6620
+ const rows = await select(this.db).from(branches3).where((0, import_drizzle_orm14.like)(branches3.branch_id, pattern)).limit(RESOLVE_SHORT_ID_FETCH_LIMIT).all();
5978
6621
  return rows.map((r) => r.branch_id);
5979
6622
  });
5980
- const row = await select(this.db).from(branches3).where((0, import_drizzle_orm16.eq)(branches3.branch_id, fullId)).one();
6623
+ const row = await select(this.db).from(branches3).where((0, import_drizzle_orm14.eq)(branches3.branch_id, fullId)).one();
5981
6624
  if (!row) return null;
5982
6625
  const baseUrl = await getBaseUrl();
5983
6626
  return this.rowToBranch(row, baseUrl);
@@ -5992,7 +6635,7 @@ var BranchRepository = class {
5992
6635
  async findRealtimeVisibilityBranch(id) {
5993
6636
  try {
5994
6637
  const fullId = await resolveByShortIdPrefix(id, "Branch", async (pattern) => {
5995
- const rows = await select(this.db, { branch_id: branches3.branch_id }).from(branches3).where((0, import_drizzle_orm16.like)(branches3.branch_id, pattern)).limit(RESOLVE_SHORT_ID_FETCH_LIMIT).all();
6638
+ const rows = await select(this.db, { branch_id: branches3.branch_id }).from(branches3).where((0, import_drizzle_orm14.like)(branches3.branch_id, pattern)).limit(RESOLVE_SHORT_ID_FETCH_LIMIT).all();
5996
6639
  return rows.map((r) => r.branch_id);
5997
6640
  });
5998
6641
  const row = await select(this.db, {
@@ -6000,11 +6643,11 @@ var BranchRepository = class {
6000
6643
  others_can: branches3.others_can,
6001
6644
  board_id: branches3.board_id,
6002
6645
  permission_source: branches3.permission_source
6003
- }).from(branches3).where((0, import_drizzle_orm16.eq)(branches3.branch_id, fullId)).one();
6646
+ }).from(branches3).where((0, import_drizzle_orm14.eq)(branches3.branch_id, fullId)).one();
6004
6647
  if (!row) return null;
6005
6648
  let othersCan = row.others_can;
6006
6649
  if (row.permission_source === "board" && row.board_id) {
6007
- const board = await select(this.db, { data: boards3.data }).from(boards3).where((0, import_drizzle_orm16.eq)(boards3.board_id, row.board_id)).one();
6650
+ const board = await select(this.db, { data: boards3.data }).from(boards3).where((0, import_drizzle_orm14.eq)(boards3.board_id, row.board_id)).one();
6008
6651
  const boardData = board?.data;
6009
6652
  othersCan = (boardData?.access_mode ?? "shared") === "private" ? "none" : boardData?.default_others_can ?? row.others_can;
6010
6653
  }
@@ -6024,21 +6667,109 @@ var BranchRepository = class {
6024
6667
  * Callers that explicitly want to exclude archived branches should pass
6025
6668
  * `{ includeArchived: false }`.
6026
6669
  *
6027
- * @param filter - Optional filters (repo_id, includeArchived)
6670
+ * The `board_id`, `archived`, and `branchIds` filters let the list read path
6671
+ * (`BranchesService.find`) push its high-selectivity predicates into SQL so it
6672
+ * no longer materializes the whole table before filtering in memory.
6673
+ *
6674
+ * @param filter - Optional filters
6028
6675
  * @param filter.repo_id - Filter by repository ID
6029
6676
  * @param filter.includeArchived - Include archived branches (default: true)
6677
+ * @param filter.board_id - Filter to a single board
6678
+ * @param filter.archived - Filter to an exact archived state (takes precedence
6679
+ * over `includeArchived`)
6680
+ * @param filter.branchIds - Restrict to a set of branch IDs (empty set yields
6681
+ * no rows, matching an `{ $in: [] }` filter)
6682
+ * @param filter.visibleToUserId - Restrict to branches visible to this user
6683
+ * under branch RBAC, pushed down as a SQL predicate instead of a preloaded
6684
+ * `branch_id IN (...)` list.
6030
6685
  */
6031
6686
  async findAll(filter) {
6687
+ if (filter?.branchIds !== void 0 && filter.branchIds.length === 0) {
6688
+ return [];
6689
+ }
6032
6690
  const includeArchived = filter?.includeArchived ?? true;
6033
6691
  const conditions = [];
6034
6692
  if (filter?.repo_id) {
6035
- conditions.push((0, import_drizzle_orm16.eq)(branches3.repo_id, filter.repo_id));
6693
+ conditions.push((0, import_drizzle_orm14.eq)(branches3.repo_id, filter.repo_id));
6694
+ }
6695
+ if (filter?.board_id) {
6696
+ conditions.push((0, import_drizzle_orm14.eq)(branches3.board_id, filter.board_id));
6697
+ }
6698
+ if (filter?.archived !== void 0) {
6699
+ conditions.push((0, import_drizzle_orm14.eq)(branches3.archived, filter.archived));
6700
+ } else if (!includeArchived) {
6701
+ conditions.push((0, import_drizzle_orm14.eq)(branches3.archived, false));
6036
6702
  }
6037
- if (!includeArchived) {
6038
- conditions.push((0, import_drizzle_orm16.eq)(branches3.archived, false));
6703
+ if (filter?.branchIds !== void 0) {
6704
+ conditions.push((0, import_drizzle_orm14.inArray)(branches3.branch_id, filter.branchIds));
6039
6705
  }
6040
- const query = select(this.db).from(branches3);
6041
- const rows = conditions.length > 0 ? await query.where((0, import_drizzle_orm16.and)(...conditions)).all() : await query.all();
6706
+ if (filter?.visibleToUserId) {
6707
+ conditions.push(visibleBranchAccessCondition(this.db, filter.visibleToUserId));
6708
+ }
6709
+ const baseQuery = filter?.visibleToUserId ? select(this.db, (0, import_drizzle_orm14.getTableColumns)(branches3)).from(branches3).leftJoin(
6710
+ branchOwners3,
6711
+ (0, import_drizzle_orm14.and)(
6712
+ (0, import_drizzle_orm14.eq)(branchOwners3.branch_id, branches3.branch_id),
6713
+ (0, import_drizzle_orm14.eq)(branchOwners3.user_id, filter.visibleToUserId)
6714
+ )
6715
+ ) : select(this.db).from(branches3);
6716
+ const rows = conditions.length > 0 ? await baseQuery.where((0, import_drizzle_orm14.and)(...conditions)).all() : await baseQuery.all();
6717
+ const baseUrl = await getBaseUrl();
6718
+ return rows.map((row) => this.rowToBranch(row, baseUrl));
6719
+ }
6720
+ /**
6721
+ * Health-monitor discovery query. Returns only routing metadata so the
6722
+ * background monitor can enter the correct tenant DB scope before loading
6723
+ * branch contents or patching health state.
6724
+ */
6725
+ async findActiveEnvironmentRefs() {
6726
+ const tenantColumn = branches3.tenant_id;
6727
+ const columns = isPostgresDatabase(this.db) && tenantColumn ? { branch_id: branches3.branch_id, tenant_id: tenantColumn } : { branch_id: branches3.branch_id };
6728
+ const statusExpr = import_drizzle_orm14.sql`${jsonExtract(this.db, branches3.data, "environment_instance.status")}`;
6729
+ const rows = await select(this.db, columns).from(branches3).where((0, import_drizzle_orm14.or)((0, import_drizzle_orm14.eq)(statusExpr, "running"), (0, import_drizzle_orm14.eq)(statusExpr, "starting"))).all();
6730
+ return rows.map((row) => ({
6731
+ branch_id: row.branch_id,
6732
+ ...typeof row.tenant_id === "string" && row.tenant_id.length > 0 ? { tenant_id: row.tenant_id } : {}
6733
+ }));
6734
+ }
6735
+ /**
6736
+ * Find active assistant branches without paginating the whole branch list first.
6737
+ *
6738
+ * A branch is discoverable as an assistant when it has the canonical assistant
6739
+ * marker in custom_context (new or legacy key), or as a read-time backfill for
6740
+ * older hand-bootstrapped assistants, when it has at least one enabled
6741
+ * first-class schedule.
6742
+ */
6743
+ async findAssistantBranches(filter) {
6744
+ const assistantKindConditions = [
6745
+ (0, import_drizzle_orm14.eq)(import_drizzle_orm14.sql`${jsonExtract(this.db, branches3.data, "custom_context.assistant.kind")}`, "assistant"),
6746
+ (0, import_drizzle_orm14.eq)(
6747
+ import_drizzle_orm14.sql`${jsonExtract(this.db, branches3.data, "custom_context.assistant.kind")}`,
6748
+ "persisted-agent"
6749
+ ),
6750
+ (0, import_drizzle_orm14.eq)(import_drizzle_orm14.sql`${jsonExtract(this.db, branches3.data, "custom_context.agent.kind")}`, "assistant"),
6751
+ (0, import_drizzle_orm14.eq)(
6752
+ import_drizzle_orm14.sql`${jsonExtract(this.db, branches3.data, "custom_context.agent.kind")}`,
6753
+ "persisted-agent"
6754
+ )
6755
+ ];
6756
+ const hasEnabledSchedule = (0, import_drizzle_orm14.exists)(
6757
+ // biome-ignore lint/suspicious/noExplicitAny: Drizzle select has complex cross-dialect overloads
6758
+ this.db.select({ _: import_drizzle_orm14.sql`1` }).from(schedules3).where((0, import_drizzle_orm14.and)((0, import_drizzle_orm14.eq)(schedules3.branch_id, branches3.branch_id), (0, import_drizzle_orm14.eq)(schedules3.enabled, true)))
6759
+ );
6760
+ const conditions = [(0, import_drizzle_orm14.or)(...assistantKindConditions, hasEnabledSchedule) ?? import_drizzle_orm14.sql`false`];
6761
+ if (filter?.repo_id) conditions.push((0, import_drizzle_orm14.eq)(branches3.repo_id, filter.repo_id));
6762
+ if (filter?.archived !== void 0) conditions.push((0, import_drizzle_orm14.eq)(branches3.archived, filter.archived));
6763
+ if (filter?.userId) conditions.push(visibleBranchAccessCondition(this.db, filter.userId));
6764
+ const baseQuery = select(this.db, (0, import_drizzle_orm14.getTableColumns)(branches3)).from(branches3);
6765
+ const query = filter?.userId ? baseQuery.leftJoin(
6766
+ branchOwners3,
6767
+ (0, import_drizzle_orm14.and)(
6768
+ (0, import_drizzle_orm14.eq)(branchOwners3.branch_id, branches3.branch_id),
6769
+ (0, import_drizzle_orm14.eq)(branchOwners3.user_id, filter.userId)
6770
+ )
6771
+ ) : baseQuery;
6772
+ const rows = await query.where((0, import_drizzle_orm14.and)(...conditions)).limit(filter?.limit ?? 200).all();
6042
6773
  const baseUrl = await getBaseUrl();
6043
6774
  return rows.map((row) => this.rowToBranch(row, baseUrl));
6044
6775
  }
@@ -6059,9 +6790,9 @@ var BranchRepository = class {
6059
6790
  txAsDb(tx),
6060
6791
  this.db,
6061
6792
  branches3,
6062
- (0, import_drizzle_orm16.eq)(branches3.branch_id, existing.branch_id)
6793
+ (0, import_drizzle_orm14.eq)(branches3.branch_id, existing.branch_id)
6063
6794
  );
6064
- const currentRow = await select(txAsDb(tx)).from(branches3).where((0, import_drizzle_orm16.eq)(branches3.branch_id, existing.branch_id)).one();
6795
+ const currentRow = await select(txAsDb(tx)).from(branches3).where((0, import_drizzle_orm14.eq)(branches3.branch_id, existing.branch_id)).one();
6065
6796
  if (!currentRow) {
6066
6797
  throw new EntityNotFoundError("Branch", id);
6067
6798
  }
@@ -6078,7 +6809,7 @@ var BranchRepository = class {
6078
6809
  // Always update timestamp
6079
6810
  });
6080
6811
  const insertData = this.branchToInsert(merged);
6081
- const row = await update(txAsDb(tx), branches3).set(insertData).where((0, import_drizzle_orm16.eq)(branches3.branch_id, current.branch_id)).returning().one();
6812
+ const row = await update(txAsDb(tx), branches3).set(insertData).where((0, import_drizzle_orm14.eq)(branches3.branch_id, current.branch_id)).returning().one();
6082
6813
  return this.rowToBranch(row, baseUrl);
6083
6814
  });
6084
6815
  }
@@ -6090,13 +6821,13 @@ var BranchRepository = class {
6090
6821
  if (!existing) {
6091
6822
  throw new EntityNotFoundError("Branch", id);
6092
6823
  }
6093
- await deleteFrom(this.db, branches3).where((0, import_drizzle_orm16.eq)(branches3.branch_id, existing.branch_id)).run();
6824
+ await deleteFrom(this.db, branches3).where((0, import_drizzle_orm14.eq)(branches3.branch_id, existing.branch_id)).run();
6094
6825
  }
6095
6826
  /**
6096
6827
  * Find branch by repo_id and name
6097
6828
  */
6098
6829
  async findByRepoAndName(repoId, name) {
6099
- const row = await select(this.db).from(branches3).where((0, import_drizzle_orm16.and)((0, import_drizzle_orm16.eq)(branches3.repo_id, repoId), (0, import_drizzle_orm16.eq)(branches3.name, name))).one();
6830
+ const row = await select(this.db).from(branches3).where((0, import_drizzle_orm14.and)((0, import_drizzle_orm14.eq)(branches3.repo_id, repoId), (0, import_drizzle_orm14.eq)(branches3.name, name))).one();
6100
6831
  if (!row) return null;
6101
6832
  const baseUrl = await getBaseUrl();
6102
6833
  return this.rowToBranch(row, baseUrl);
@@ -6106,7 +6837,7 @@ var BranchRepository = class {
6106
6837
  */
6107
6838
  async findActiveByRepoAndName(repoId, name) {
6108
6839
  const row = await select(this.db).from(branches3).where(
6109
- (0, import_drizzle_orm16.and)((0, import_drizzle_orm16.eq)(branches3.repo_id, repoId), (0, import_drizzle_orm16.eq)(branches3.name, name), (0, import_drizzle_orm16.eq)(branches3.archived, false))
6840
+ (0, import_drizzle_orm14.and)((0, import_drizzle_orm14.eq)(branches3.repo_id, repoId), (0, import_drizzle_orm14.eq)(branches3.name, name), (0, import_drizzle_orm14.eq)(branches3.archived, false))
6110
6841
  ).one();
6111
6842
  if (!row) return null;
6112
6843
  const baseUrl = await getBaseUrl();
@@ -6125,7 +6856,7 @@ var BranchRepository = class {
6125
6856
  * Used for auto-suffix name conflict resolution — bypasses Feathers pagination.
6126
6857
  */
6127
6858
  async getActiveNamesByRepo(repoId) {
6128
- const rows = await select(this.db, { name: branches3.name }).from(branches3).where((0, import_drizzle_orm16.and)((0, import_drizzle_orm16.eq)(branches3.repo_id, repoId), (0, import_drizzle_orm16.eq)(branches3.archived, false))).all();
6859
+ const rows = await select(this.db, { name: branches3.name }).from(branches3).where((0, import_drizzle_orm14.and)((0, import_drizzle_orm14.eq)(branches3.repo_id, repoId), (0, import_drizzle_orm14.eq)(branches3.archived, false))).all();
6129
6860
  return rows.map((row) => row.name);
6130
6861
  }
6131
6862
  // ===== RBAC: Ownership Management =====
@@ -6137,7 +6868,7 @@ var BranchRepository = class {
6137
6868
  * @returns true if user is an owner
6138
6869
  */
6139
6870
  async isOwner(branchId, userId) {
6140
- const row = await select(this.db).from(branchOwners3).where((0, import_drizzle_orm16.and)((0, import_drizzle_orm16.eq)(branchOwners3.branch_id, branchId), (0, import_drizzle_orm16.eq)(branchOwners3.user_id, userId))).one();
6871
+ const row = await select(this.db).from(branchOwners3).where((0, import_drizzle_orm14.and)((0, import_drizzle_orm14.eq)(branchOwners3.branch_id, branchId), (0, import_drizzle_orm14.eq)(branchOwners3.user_id, userId))).one();
6141
6872
  return row != null;
6142
6873
  }
6143
6874
  /**
@@ -6149,17 +6880,17 @@ var BranchRepository = class {
6149
6880
  async getBestGroupGrantForUser(branchId, userId) {
6150
6881
  const rows = await select(this.db).from(branchGroupGrants3).innerJoin(
6151
6882
  groupMemberships3,
6152
- (0, import_drizzle_orm16.and)(
6153
- (0, import_drizzle_orm16.eq)(groupMemberships3.group_id, branchGroupGrants3.group_id),
6154
- (0, import_drizzle_orm16.eq)(groupMemberships3.user_id, userId)
6883
+ (0, import_drizzle_orm14.and)(
6884
+ (0, import_drizzle_orm14.eq)(groupMemberships3.group_id, branchGroupGrants3.group_id),
6885
+ (0, import_drizzle_orm14.eq)(groupMemberships3.user_id, userId)
6155
6886
  )
6156
6887
  ).innerJoin(
6157
6888
  groups3,
6158
- (0, import_drizzle_orm16.and)((0, import_drizzle_orm16.eq)(groups3.group_id, branchGroupGrants3.group_id), (0, import_drizzle_orm16.eq)(groups3.archived, false))
6889
+ (0, import_drizzle_orm14.and)((0, import_drizzle_orm14.eq)(groups3.group_id, branchGroupGrants3.group_id), (0, import_drizzle_orm14.eq)(groups3.archived, false))
6159
6890
  ).where(
6160
- (0, import_drizzle_orm16.and)(
6161
- (0, import_drizzle_orm16.eq)(branchGroupGrants3.branch_id, branchId),
6162
- (0, import_drizzle_orm16.inArray)(branchGroupGrants3.can, BRANCH_PERMISSION_LEVELS)
6891
+ (0, import_drizzle_orm14.and)(
6892
+ (0, import_drizzle_orm14.eq)(branchGroupGrants3.branch_id, branchId),
6893
+ (0, import_drizzle_orm14.inArray)(branchGroupGrants3.can, BRANCH_PERMISSION_LEVELS)
6163
6894
  )
6164
6895
  ).all();
6165
6896
  let best = null;
@@ -6189,7 +6920,7 @@ var BranchRepository = class {
6189
6920
  * this method.
6190
6921
  */
6191
6922
  async resolveUserAccess(branch, userId) {
6192
- const board = branch.permission_source === "board" && branch.board_id ? await select(this.db, { data: boards3.data, board_id: boards3.board_id }).from(boards3).where((0, import_drizzle_orm16.eq)(boards3.board_id, branch.board_id)).one() : null;
6923
+ const board = branch.permission_source === "board" && branch.board_id ? await select(this.db, { data: boards3.data, board_id: boards3.board_id }).from(boards3).where((0, import_drizzle_orm14.eq)(boards3.board_id, branch.board_id)).one() : null;
6193
6924
  const boardData = board?.data;
6194
6925
  const boardIsShared = (boardData?.access_mode ?? "shared") === "shared";
6195
6926
  const sharing = branch.permission_source === "board" && boardIsShared ? boardData?.default_dangerously_allow_session_sharing ?? false : branch.dangerously_allow_session_sharing ?? false;
@@ -6205,7 +6936,7 @@ var BranchRepository = class {
6205
6936
  const groupRepo = new GroupRepository(this.db);
6206
6937
  const branchGroupGrants4 = await groupRepo.getBranchGrantsForUser(branch.branch_id, userId);
6207
6938
  if (branch.permission_source === "board" && branch.board_id) {
6208
- const boardOwner = await select(this.db).from(boardOwners3).where((0, import_drizzle_orm16.and)((0, import_drizzle_orm16.eq)(boardOwners3.board_id, branch.board_id), (0, import_drizzle_orm16.eq)(boardOwners3.user_id, userId))).one();
6939
+ const boardOwner = await select(this.db).from(boardOwners3).where((0, import_drizzle_orm14.and)((0, import_drizzle_orm14.eq)(boardOwners3.board_id, branch.board_id), (0, import_drizzle_orm14.eq)(boardOwners3.user_id, userId))).one();
6209
6940
  if (boardOwner) {
6210
6941
  return {
6211
6942
  can: "all",
@@ -6262,34 +6993,34 @@ var BranchRepository = class {
6262
6993
  const branchRow = await select(this.db, {
6263
6994
  board_id: branches3.board_id,
6264
6995
  permission_source: branches3.permission_source
6265
- }).from(branches3).where((0, import_drizzle_orm16.eq)(branches3.branch_id, branchId)).one();
6266
- const ownerRows = await select(this.db, { user_id: branchOwners3.user_id }).from(branchOwners3).where((0, import_drizzle_orm16.eq)(branchOwners3.branch_id, branchId)).all();
6267
- const groupRows = await select(this.db, { user_id: groupMemberships3.user_id }).from(branchGroupGrants3).innerJoin(groupMemberships3, (0, import_drizzle_orm16.eq)(groupMemberships3.group_id, branchGroupGrants3.group_id)).innerJoin(
6996
+ }).from(branches3).where((0, import_drizzle_orm14.eq)(branches3.branch_id, branchId)).one();
6997
+ const ownerRows = await select(this.db, { user_id: branchOwners3.user_id }).from(branchOwners3).where((0, import_drizzle_orm14.eq)(branchOwners3.branch_id, branchId)).all();
6998
+ const groupRows = await select(this.db, { user_id: groupMemberships3.user_id }).from(branchGroupGrants3).innerJoin(groupMemberships3, (0, import_drizzle_orm14.eq)(groupMemberships3.group_id, branchGroupGrants3.group_id)).innerJoin(
6268
6999
  groups3,
6269
- (0, import_drizzle_orm16.and)((0, import_drizzle_orm16.eq)(groups3.group_id, branchGroupGrants3.group_id), (0, import_drizzle_orm16.eq)(groups3.archived, false))
7000
+ (0, import_drizzle_orm14.and)((0, import_drizzle_orm14.eq)(groups3.group_id, branchGroupGrants3.group_id), (0, import_drizzle_orm14.eq)(groups3.archived, false))
6270
7001
  ).where(
6271
- (0, import_drizzle_orm16.and)(
6272
- (0, import_drizzle_orm16.eq)(branchGroupGrants3.branch_id, branchId),
6273
- (0, import_drizzle_orm16.inArray)(branchGroupGrants3.can, VIEW_OR_BETTER_BRANCH_PERMISSIONS)
7002
+ (0, import_drizzle_orm14.and)(
7003
+ (0, import_drizzle_orm14.eq)(branchGroupGrants3.branch_id, branchId),
7004
+ (0, import_drizzle_orm14.inArray)(branchGroupGrants3.can, VIEW_OR_BETTER_BRANCH_PERMISSIONS)
6274
7005
  )
6275
7006
  ).all();
6276
- const boardOwnerRows = branchRow?.permission_source === "board" && branchRow.board_id ? await select(this.db, { user_id: boardOwners3.user_id }).from(boardOwners3).where((0, import_drizzle_orm16.eq)(boardOwners3.board_id, branchRow.board_id)).all() : [];
6277
- const boardGroupRows = branchRow?.permission_source === "board" && branchRow.board_id ? await select(this.db, { user_id: groupMemberships3.user_id }).from(boardGroupGrants3).innerJoin(groupMemberships3, (0, import_drizzle_orm16.eq)(groupMemberships3.group_id, boardGroupGrants3.group_id)).innerJoin(
7007
+ const boardOwnerRows = branchRow?.permission_source === "board" && branchRow.board_id ? await select(this.db, { user_id: boardOwners3.user_id }).from(boardOwners3).where((0, import_drizzle_orm14.eq)(boardOwners3.board_id, branchRow.board_id)).all() : [];
7008
+ const boardGroupRows = branchRow?.permission_source === "board" && branchRow.board_id ? await select(this.db, { user_id: groupMemberships3.user_id }).from(boardGroupGrants3).innerJoin(groupMemberships3, (0, import_drizzle_orm14.eq)(groupMemberships3.group_id, boardGroupGrants3.group_id)).innerJoin(
6278
7009
  groups3,
6279
- (0, import_drizzle_orm16.and)((0, import_drizzle_orm16.eq)(groups3.group_id, boardGroupGrants3.group_id), (0, import_drizzle_orm16.eq)(groups3.archived, false))
7010
+ (0, import_drizzle_orm14.and)((0, import_drizzle_orm14.eq)(groups3.group_id, boardGroupGrants3.group_id), (0, import_drizzle_orm14.eq)(groups3.archived, false))
6280
7011
  ).innerJoin(
6281
7012
  boards3,
6282
- (0, import_drizzle_orm16.and)(
6283
- (0, import_drizzle_orm16.eq)(boards3.board_id, boardGroupGrants3.board_id),
6284
- (0, import_drizzle_orm16.eq)(
6285
- import_drizzle_orm16.sql`coalesce(${jsonExtract(this.db, boards3.data, "access_mode")}, 'shared')`,
7013
+ (0, import_drizzle_orm14.and)(
7014
+ (0, import_drizzle_orm14.eq)(boards3.board_id, boardGroupGrants3.board_id),
7015
+ (0, import_drizzle_orm14.eq)(
7016
+ import_drizzle_orm14.sql`coalesce(${jsonExtract(this.db, boards3.data, "access_mode")}, 'shared')`,
6286
7017
  "shared"
6287
7018
  )
6288
7019
  )
6289
7020
  ).where(
6290
- (0, import_drizzle_orm16.and)(
6291
- (0, import_drizzle_orm16.eq)(boardGroupGrants3.board_id, branchRow.board_id),
6292
- (0, import_drizzle_orm16.inArray)(boardGroupGrants3.can, VIEW_OR_BETTER_BRANCH_PERMISSIONS)
7021
+ (0, import_drizzle_orm14.and)(
7022
+ (0, import_drizzle_orm14.eq)(boardGroupGrants3.board_id, branchRow.board_id),
7023
+ (0, import_drizzle_orm14.inArray)(boardGroupGrants3.can, VIEW_OR_BETTER_BRANCH_PERMISSIONS)
6293
7024
  )
6294
7025
  ).all() : [];
6295
7026
  const userIds = /* @__PURE__ */ new Set();
@@ -6307,6 +7038,83 @@ var BranchRepository = class {
6307
7038
  }
6308
7039
  return Array.from(userIds);
6309
7040
  }
7041
+ /**
7042
+ * Find users whose explicit branch or aligned-board grants should materialize
7043
+ * into filesystem access for the branch.
7044
+ *
7045
+ * This intentionally excludes ambient "others" access because there is no
7046
+ * bounded user set to expand. Board owners apply whenever the branch is
7047
+ * explicitly aligned to board permissions (`permission_source = 'board'`);
7048
+ * board group grants additionally require a shared board. Override branches
7049
+ * must not inherit board grants.
7050
+ */
7051
+ async findExplicitFsAccessUserIds(branchId) {
7052
+ const branchRow = await select(this.db, {
7053
+ board_id: branches3.board_id,
7054
+ permission_source: branches3.permission_source
7055
+ }).from(branches3).where((0, import_drizzle_orm14.eq)(branches3.branch_id, branchId)).one();
7056
+ const ownerRows = await select(this.db, { user_id: branchOwners3.user_id }).from(branchOwners3).where((0, import_drizzle_orm14.eq)(branchOwners3.branch_id, branchId)).all();
7057
+ const groupRows = await select(this.db, { user_id: groupMemberships3.user_id }).from(branchGroupGrants3).innerJoin(groupMemberships3, (0, import_drizzle_orm14.eq)(groupMemberships3.group_id, branchGroupGrants3.group_id)).innerJoin(
7058
+ groups3,
7059
+ (0, import_drizzle_orm14.and)((0, import_drizzle_orm14.eq)(groups3.group_id, branchGroupGrants3.group_id), (0, import_drizzle_orm14.eq)(groups3.archived, false))
7060
+ ).where(
7061
+ (0, import_drizzle_orm14.and)(
7062
+ (0, import_drizzle_orm14.eq)(branchGroupGrants3.branch_id, branchId),
7063
+ (0, import_drizzle_orm14.inArray)(
7064
+ import_drizzle_orm14.sql`coalesce(${branchGroupGrants3.fs_access}, 'read')`,
7065
+ FS_ACCESS_BRANCH_PERMISSIONS
7066
+ )
7067
+ )
7068
+ ).all();
7069
+ const isBoardAligned = branchRow?.permission_source === "board" && branchRow.board_id;
7070
+ const boardOwnerRows = isBoardAligned ? await select(this.db, { user_id: boardOwners3.user_id }).from(boardOwners3).where((0, import_drizzle_orm14.eq)(boardOwners3.board_id, branchRow.board_id)).all() : [];
7071
+ const boardGroupRows = isBoardAligned ? await select(this.db, { user_id: groupMemberships3.user_id }).from(boardGroupGrants3).innerJoin(groupMemberships3, (0, import_drizzle_orm14.eq)(groupMemberships3.group_id, boardGroupGrants3.group_id)).innerJoin(
7072
+ groups3,
7073
+ (0, import_drizzle_orm14.and)((0, import_drizzle_orm14.eq)(groups3.group_id, boardGroupGrants3.group_id), (0, import_drizzle_orm14.eq)(groups3.archived, false))
7074
+ ).innerJoin(
7075
+ boards3,
7076
+ (0, import_drizzle_orm14.and)(
7077
+ (0, import_drizzle_orm14.eq)(boards3.board_id, boardGroupGrants3.board_id),
7078
+ (0, import_drizzle_orm14.eq)(
7079
+ import_drizzle_orm14.sql`coalesce(${jsonExtract(this.db, boards3.data, "access_mode")}, 'shared')`,
7080
+ "shared"
7081
+ )
7082
+ )
7083
+ ).where(
7084
+ (0, import_drizzle_orm14.and)(
7085
+ (0, import_drizzle_orm14.eq)(boardGroupGrants3.board_id, branchRow.board_id),
7086
+ (0, import_drizzle_orm14.inArray)(
7087
+ import_drizzle_orm14.sql`coalesce(${boardGroupGrants3.fs_access}, 'read')`,
7088
+ FS_ACCESS_BRANCH_PERMISSIONS
7089
+ )
7090
+ )
7091
+ ).all() : [];
7092
+ const userIds = /* @__PURE__ */ new Set();
7093
+ for (const row of ownerRows) {
7094
+ userIds.add(row.user_id);
7095
+ }
7096
+ for (const row of groupRows) {
7097
+ userIds.add(row.user_id);
7098
+ }
7099
+ for (const row of boardOwnerRows) {
7100
+ userIds.add(row.user_id);
7101
+ }
7102
+ for (const row of boardGroupRows) {
7103
+ userIds.add(row.user_id);
7104
+ }
7105
+ return Array.from(userIds);
7106
+ }
7107
+ async findBoardAlignedBranches(boardId) {
7108
+ const rows = await select(this.db).from(branches3).where(
7109
+ (0, import_drizzle_orm14.and)(
7110
+ (0, import_drizzle_orm14.eq)(branches3.board_id, boardId),
7111
+ (0, import_drizzle_orm14.eq)(branches3.permission_source, "board"),
7112
+ (0, import_drizzle_orm14.eq)(branches3.archived, false)
7113
+ )
7114
+ ).all();
7115
+ const baseUrl = await getBaseUrl();
7116
+ return rows.map((row) => this.rowToBranch(row, baseUrl));
7117
+ }
6310
7118
  /**
6311
7119
  * Get all owners of a branch
6312
7120
  *
@@ -6318,7 +7126,7 @@ var BranchRepository = class {
6318
7126
  if (!branch) {
6319
7127
  throw new EntityNotFoundError("Branch", branchId);
6320
7128
  }
6321
- const rows = await select(this.db).from(branchOwners3).where((0, import_drizzle_orm16.eq)(branchOwners3.branch_id, branch.branch_id)).all();
7129
+ const rows = await select(this.db).from(branchOwners3).where((0, import_drizzle_orm14.eq)(branchOwners3.branch_id, branch.branch_id)).all();
6322
7130
  return rows.map((row) => row.user_id);
6323
7131
  }
6324
7132
  /**
@@ -6358,7 +7166,7 @@ var BranchRepository = class {
6358
7166
  if (!branch) {
6359
7167
  throw new EntityNotFoundError("Branch", branchId);
6360
7168
  }
6361
- await deleteFrom(this.db, branchOwners3).where((0, import_drizzle_orm16.and)((0, import_drizzle_orm16.eq)(branchOwners3.branch_id, branch.branch_id), (0, import_drizzle_orm16.eq)(branchOwners3.user_id, userId))).run();
7169
+ await deleteFrom(this.db, branchOwners3).where((0, import_drizzle_orm14.and)((0, import_drizzle_orm14.eq)(branchOwners3.branch_id, branch.branch_id), (0, import_drizzle_orm14.eq)(branchOwners3.user_id, userId))).run();
6362
7170
  }
6363
7171
  /**
6364
7172
  * Bulk-load ownership for multiple branches
@@ -6373,7 +7181,7 @@ var BranchRepository = class {
6373
7181
  if (branchIds.length === 0) {
6374
7182
  return /* @__PURE__ */ new Map();
6375
7183
  }
6376
- const rows = await select(this.db).from(branchOwners3).where((0, import_drizzle_orm16.inArray)(branchOwners3.branch_id, branchIds)).all();
7184
+ const rows = await select(this.db).from(branchOwners3).where((0, import_drizzle_orm14.inArray)(branchOwners3.branch_id, branchIds)).all();
6377
7185
  const ownersByBranch = /* @__PURE__ */ new Map();
6378
7186
  for (const row of rows) {
6379
7187
  const wtId = row.branch_id;
@@ -6404,14 +7212,14 @@ var BranchRepository = class {
6404
7212
  async findAccessibleBranches(userId, filter) {
6405
7213
  const conditions = [visibleBranchAccessCondition(this.db, userId)];
6406
7214
  if (filter?.archived === true) {
6407
- conditions.push((0, import_drizzle_orm16.eq)(branches3.archived, true));
7215
+ conditions.push((0, import_drizzle_orm14.eq)(branches3.archived, true));
6408
7216
  } else if (filter?.archived === false) {
6409
- conditions.push((0, import_drizzle_orm16.eq)(branches3.archived, false));
7217
+ conditions.push((0, import_drizzle_orm14.eq)(branches3.archived, false));
6410
7218
  }
6411
- const rows = await select(this.db, (0, import_drizzle_orm16.getTableColumns)(branches3)).from(branches3).leftJoin(
7219
+ const rows = await select(this.db, (0, import_drizzle_orm14.getTableColumns)(branches3)).from(branches3).leftJoin(
6412
7220
  branchOwners3,
6413
- (0, import_drizzle_orm16.and)((0, import_drizzle_orm16.eq)(branchOwners3.branch_id, branches3.branch_id), (0, import_drizzle_orm16.eq)(branchOwners3.user_id, userId))
6414
- ).where((0, import_drizzle_orm16.and)(...conditions)).all();
7221
+ (0, import_drizzle_orm14.and)((0, import_drizzle_orm14.eq)(branchOwners3.branch_id, branches3.branch_id), (0, import_drizzle_orm14.eq)(branchOwners3.user_id, userId))
7222
+ ).where((0, import_drizzle_orm14.and)(...conditions)).all();
6415
7223
  const baseUrl = await getBaseUrl();
6416
7224
  const seen = /* @__PURE__ */ new Set();
6417
7225
  const result = [];
@@ -6434,7 +7242,7 @@ var BranchRepository = class {
6434
7242
  const { jsonExtract: jsonExtract2 } = await Promise.resolve().then(() => (init_database_wrapper(), database_wrapper_exports));
6435
7243
  const rows = await select(this.db, {
6436
7244
  branch_id: boardObjectsTable.branch_id
6437
- }).from(boardObjectsTable).where(import_drizzle_orm16.sql`${jsonExtract2(this.db, boardObjectsTable.data, "zone_id")} = ${zoneId}`).all();
7245
+ }).from(boardObjectsTable).where(import_drizzle_orm14.sql`${jsonExtract2(this.db, boardObjectsTable.data, "zone_id")} = ${zoneId}`).all();
6438
7246
  const uniqueIds = /* @__PURE__ */ new Set();
6439
7247
  for (const row of rows) {
6440
7248
  if (row.branch_id) {
@@ -6486,7 +7294,7 @@ var BranchRepository = class {
6486
7294
  zone_id: jsonExtract2(this.db, boardObjectsTable.data, "zone_id"),
6487
7295
  position: jsonExtract2(this.db, boardObjectsTable.data, "position"),
6488
7296
  board_data: boardsTable.data
6489
- }).from(boardObjectsTable).leftJoin(boardsTable, (0, import_drizzle_orm16.eq)(boardObjectsTable.board_id, boardsTable.board_id)).where((0, import_drizzle_orm16.inArray)(boardObjectsTable.branch_id, branchIds)).all();
7297
+ }).from(boardObjectsTable).leftJoin(boardsTable, (0, import_drizzle_orm14.eq)(boardObjectsTable.board_id, boardsTable.board_id)).where((0, import_drizzle_orm14.inArray)(boardObjectsTable.branch_id, branchIds)).all();
6490
7298
  const boardObjectInfoByBranch = /* @__PURE__ */ new Map();
6491
7299
  for (const row of rows) {
6492
7300
  const info = {
@@ -6565,7 +7373,7 @@ var BranchRepository = class {
6565
7373
  agentic_tool: sessionsTable.agentic_tool,
6566
7374
  updated_at: sessionsTable.updated_at,
6567
7375
  unix_username: sessionsTable.unix_username
6568
- }).from(sessionsTable).where((0, import_drizzle_orm16.inArray)(sessionsTable.branch_id, branchIds)).orderBy(sessionsTable.updated_at).all();
7376
+ }).from(sessionsTable).where((0, import_drizzle_orm14.inArray)(sessionsTable.branch_id, branchIds)).orderBy(sessionsTable.updated_at).all();
6569
7377
  const sessionIds = sessionRows.map((s) => s.session_id);
6570
7378
  if (sessionIds.length === 0) {
6571
7379
  return branches4.map((wt) => ({ ...wt, sessions: [] }));
@@ -6574,8 +7382,8 @@ var BranchRepository = class {
6574
7382
  for (const sessionId of sessionIds) {
6575
7383
  const query = select(this.db, {
6576
7384
  data: messagesTable.data
6577
- }).from(messagesTable).where((0, import_drizzle_orm16.and)((0, import_drizzle_orm16.eq)(messagesTable.session_id, sessionId), (0, import_drizzle_orm16.eq)(messagesTable.role, "assistant")));
6578
- const lastMessage = await query.orderBy((0, import_drizzle_orm16.desc)(messagesTable.index)).limit(1).one();
7385
+ }).from(messagesTable).where((0, import_drizzle_orm14.and)((0, import_drizzle_orm14.eq)(messagesTable.session_id, sessionId), (0, import_drizzle_orm14.eq)(messagesTable.role, "assistant")));
7386
+ const lastMessage = await query.orderBy((0, import_drizzle_orm14.desc)(messagesTable.index)).limit(1).one();
6579
7387
  if (lastMessage) {
6580
7388
  const messageData = lastMessage.data;
6581
7389
  let fullText = "";
@@ -6590,8 +7398,8 @@ var BranchRepository = class {
6590
7398
  }
6591
7399
  const countRows = await select(this.db, {
6592
7400
  session_id: messagesTable.session_id,
6593
- count: import_drizzle_orm16.sql`count(*)`
6594
- }).from(messagesTable).where((0, import_drizzle_orm16.inArray)(messagesTable.session_id, sessionIds)).groupBy(messagesTable.session_id).all();
7401
+ count: import_drizzle_orm14.sql`count(*)`
7402
+ }).from(messagesTable).where((0, import_drizzle_orm14.inArray)(messagesTable.session_id, sessionIds)).groupBy(messagesTable.session_id).all();
6595
7403
  const messageCountBySession = /* @__PURE__ */ new Map();
6596
7404
  for (const r of countRows) {
6597
7405
  messageCountBySession.set(r.session_id, Number(r.count));
@@ -6643,14 +7451,14 @@ var BranchRepository = class {
6643
7451
 
6644
7452
  // src/db/repositories/card-types.ts
6645
7453
  init_cjs_shims();
6646
- var import_drizzle_orm18 = require("drizzle-orm");
7454
+ var import_drizzle_orm16 = require("drizzle-orm");
6647
7455
  init_ids();
6648
7456
  init_database_wrapper();
6649
7457
  init_schema();
6650
7458
 
6651
7459
  // src/db/repositories/cards.ts
6652
7460
  init_cjs_shims();
6653
- var import_drizzle_orm19 = require("drizzle-orm");
7461
+ var import_drizzle_orm17 = require("drizzle-orm");
6654
7462
  init_ids();
6655
7463
  init_database_wrapper();
6656
7464
  init_schema();
@@ -6658,16 +7466,24 @@ init_schema();
6658
7466
  // src/db/repositories/gateway-channels.ts
6659
7467
  init_cjs_shims();
6660
7468
  init_types2();
6661
- var import_drizzle_orm20 = require("drizzle-orm");
7469
+ var import_drizzle_orm18 = require("drizzle-orm");
7470
+ init_ids();
7471
+ init_database_wrapper();
7472
+ init_schema();
7473
+
7474
+ // src/db/repositories/gateway-outbound-messages.ts
7475
+ init_cjs_shims();
7476
+ init_types2();
7477
+ var import_drizzle_orm19 = require("drizzle-orm");
6662
7478
  init_ids();
6663
7479
  init_database_wrapper();
6664
7480
  init_schema();
6665
7481
 
6666
7482
  // src/db/repositories/knowledge.ts
6667
7483
  init_cjs_shims();
6668
- var import_node_crypto4 = require("crypto");
7484
+ var import_node_crypto3 = require("crypto");
6669
7485
  init_types2();
6670
- var import_drizzle_orm21 = require("drizzle-orm");
7486
+ var import_drizzle_orm20 = require("drizzle-orm");
6671
7487
  init_config_manager();
6672
7488
  init_ids();
6673
7489
  init_database_wrapper();
@@ -6675,7 +7491,7 @@ init_schema();
6675
7491
 
6676
7492
  // src/db/repositories/mcp-servers.ts
6677
7493
  init_cjs_shims();
6678
- var import_drizzle_orm22 = require("drizzle-orm");
7494
+ var import_drizzle_orm21 = require("drizzle-orm");
6679
7495
  init_ids();
6680
7496
 
6681
7497
  // src/tools/mcp/auth-secrets.ts
@@ -6690,13 +7506,13 @@ init_schema();
6690
7506
 
6691
7507
  // src/db/repositories/messages.ts
6692
7508
  init_cjs_shims();
6693
- var import_drizzle_orm23 = require("drizzle-orm");
7509
+ var import_drizzle_orm22 = require("drizzle-orm");
6694
7510
  init_database_wrapper();
6695
7511
  init_schema();
6696
7512
 
6697
7513
  // src/db/repositories/repos.ts
6698
7514
  init_cjs_shims();
6699
- var import_drizzle_orm24 = require("drizzle-orm");
7515
+ var import_drizzle_orm23 = require("drizzle-orm");
6700
7516
  init_ids();
6701
7517
  init_database_wrapper();
6702
7518
  init_schema();
@@ -6732,20 +7548,23 @@ var RepoRepository = class {
6732
7548
  const environment = data.environment ?? wrapV1AsV2(data.environment_config);
6733
7549
  const environment_config = data.environment_config ?? deriveV1FromV2(environment);
6734
7550
  const remote_url = typeof data.remote_url === "string" ? stripHttpUrlUserinfo(data.remote_url) : data.remote_url;
6735
- return {
6736
- repo_id: row.repo_id,
6737
- slug: row.slug,
6738
- repo_type: row.repo_type ?? "remote",
6739
- unix_group: row.unix_group ?? void 0,
6740
- created_at: new Date(row.created_at).toISOString(),
6741
- last_updated: row.updated_at ? new Date(row.updated_at).toISOString() : new Date(row.created_at).toISOString(),
6742
- ...data,
6743
- remote_url,
6744
- environment,
6745
- environment_config,
6746
- clone_status: data.clone_status,
6747
- clone_error: data.clone_error
6748
- };
7551
+ return attachHiddenTenant(
7552
+ {
7553
+ repo_id: row.repo_id,
7554
+ slug: row.slug,
7555
+ repo_type: row.repo_type ?? "remote",
7556
+ unix_group: row.unix_group ?? void 0,
7557
+ created_at: new Date(row.created_at).toISOString(),
7558
+ last_updated: row.updated_at ? new Date(row.updated_at).toISOString() : new Date(row.created_at).toISOString(),
7559
+ ...data,
7560
+ remote_url,
7561
+ environment,
7562
+ environment_config,
7563
+ clone_status: data.clone_status,
7564
+ clone_error: data.clone_error
7565
+ },
7566
+ row
7567
+ );
6749
7568
  }
6750
7569
  /**
6751
7570
  * Convert Repo to database insert format
@@ -6795,7 +7614,7 @@ var RepoRepository = class {
6795
7614
  */
6796
7615
  async resolveId(id) {
6797
7616
  return resolveByShortIdPrefix(id, "Repo", async (pattern) => {
6798
- const rows = await select(this.db).from(repos3).where((0, import_drizzle_orm24.like)(repos3.repo_id, pattern)).limit(RESOLVE_SHORT_ID_FETCH_LIMIT).all();
7617
+ const rows = await select(this.db).from(repos3).where((0, import_drizzle_orm23.like)(repos3.repo_id, pattern)).limit(RESOLVE_SHORT_ID_FETCH_LIMIT).all();
6799
7618
  return rows.map((r) => r.repo_id);
6800
7619
  });
6801
7620
  }
@@ -6806,7 +7625,7 @@ var RepoRepository = class {
6806
7625
  try {
6807
7626
  const insertData = this.repoToInsert(data);
6808
7627
  await insert(this.db, repos3).values(insertData).run();
6809
- const row = await select(this.db).from(repos3).where((0, import_drizzle_orm24.eq)(repos3.repo_id, insertData.repo_id)).one();
7628
+ const row = await select(this.db).from(repos3).where((0, import_drizzle_orm23.eq)(repos3.repo_id, insertData.repo_id)).one();
6810
7629
  if (!row) {
6811
7630
  throw new RepositoryError("Failed to retrieve created repo");
6812
7631
  }
@@ -6825,7 +7644,7 @@ var RepoRepository = class {
6825
7644
  async findById(id) {
6826
7645
  try {
6827
7646
  const fullId = await this.resolveId(id);
6828
- const row = await select(this.db).from(repos3).where((0, import_drizzle_orm24.eq)(repos3.repo_id, fullId)).one();
7647
+ const row = await select(this.db).from(repos3).where((0, import_drizzle_orm23.eq)(repos3.repo_id, fullId)).one();
6829
7648
  return row ? this.rowToRepo(row) : null;
6830
7649
  } catch (error) {
6831
7650
  if (error instanceof EntityNotFoundError) return null;
@@ -6841,7 +7660,7 @@ var RepoRepository = class {
6841
7660
  */
6842
7661
  async findBySlug(slug) {
6843
7662
  try {
6844
- const row = await select(this.db).from(repos3).where((0, import_drizzle_orm24.eq)(repos3.slug, slug)).one();
7663
+ const row = await select(this.db).from(repos3).where((0, import_drizzle_orm23.eq)(repos3.slug, slug)).one();
6845
7664
  return row ? this.rowToRepo(row) : null;
6846
7665
  } catch (error) {
6847
7666
  throw new RepositoryError(
@@ -6909,8 +7728,8 @@ var RepoRepository = class {
6909
7728
  let changed = 0;
6910
7729
  for (const finding of scan.findings) {
6911
7730
  await this.db.transaction(async (tx) => {
6912
- await lockRowForUpdate(txAsDb(tx), this.db, repos3, (0, import_drizzle_orm24.eq)(repos3.repo_id, finding.repo_id));
6913
- const currentRow = await select(txAsDb(tx)).from(repos3).where((0, import_drizzle_orm24.eq)(repos3.repo_id, finding.repo_id)).one();
7731
+ await lockRowForUpdate(txAsDb(tx), this.db, repos3, (0, import_drizzle_orm23.eq)(repos3.repo_id, finding.repo_id));
7732
+ const currentRow = await select(txAsDb(tx)).from(repos3).where((0, import_drizzle_orm23.eq)(repos3.repo_id, finding.repo_id)).one();
6914
7733
  if (!currentRow) return;
6915
7734
  const data = currentRow.data;
6916
7735
  if (typeof data.remote_url !== "string" || !httpUrlHasUserinfo(data.remote_url)) {
@@ -6922,7 +7741,7 @@ var RepoRepository = class {
6922
7741
  ...data,
6923
7742
  remote_url: stripHttpUrlUserinfo(data.remote_url)
6924
7743
  }
6925
- }).where((0, import_drizzle_orm24.eq)(repos3.repo_id, finding.repo_id)).run();
7744
+ }).where((0, import_drizzle_orm23.eq)(repos3.repo_id, finding.repo_id)).run();
6926
7745
  changed += 1;
6927
7746
  });
6928
7747
  }
@@ -6944,8 +7763,8 @@ var RepoRepository = class {
6944
7763
  try {
6945
7764
  const fullId = await this.resolveId(id);
6946
7765
  return await this.db.transaction(async (tx) => {
6947
- await lockRowForUpdate(txAsDb(tx), this.db, repos3, (0, import_drizzle_orm24.eq)(repos3.repo_id, fullId));
6948
- const currentRow = await select(txAsDb(tx)).from(repos3).where((0, import_drizzle_orm24.eq)(repos3.repo_id, fullId)).one();
7766
+ await lockRowForUpdate(txAsDb(tx), this.db, repos3, (0, import_drizzle_orm23.eq)(repos3.repo_id, fullId));
7767
+ const currentRow = await select(txAsDb(tx)).from(repos3).where((0, import_drizzle_orm23.eq)(repos3.repo_id, fullId)).one();
6949
7768
  if (!currentRow) {
6950
7769
  throw new EntityNotFoundError("Repo", id);
6951
7770
  }
@@ -6959,7 +7778,7 @@ var RepoRepository = class {
6959
7778
  repo_type: insertData.repo_type,
6960
7779
  unix_group: merged.unix_group ?? null,
6961
7780
  data: insertData.data
6962
- }).where((0, import_drizzle_orm24.eq)(repos3.repo_id, fullId)).run();
7781
+ }).where((0, import_drizzle_orm23.eq)(repos3.repo_id, fullId)).run();
6963
7782
  merged.clone_error = insertData.data.clone_error;
6964
7783
  merged.remote_url = insertData.data.remote_url;
6965
7784
  merged.last_updated = newUpdatedAt.toISOString();
@@ -6993,8 +7812,8 @@ var RepoRepository = class {
6993
7812
  try {
6994
7813
  const fullId = await this.resolveId(id);
6995
7814
  return await this.db.transaction(async (tx) => {
6996
- await lockRowForUpdate(txAsDb(tx), this.db, repos3, (0, import_drizzle_orm24.eq)(repos3.repo_id, fullId));
6997
- const currentRow = await select(txAsDb(tx)).from(repos3).where((0, import_drizzle_orm24.eq)(repos3.repo_id, fullId)).one();
7815
+ await lockRowForUpdate(txAsDb(tx), this.db, repos3, (0, import_drizzle_orm23.eq)(repos3.repo_id, fullId));
7816
+ const currentRow = await select(txAsDb(tx)).from(repos3).where((0, import_drizzle_orm23.eq)(repos3.repo_id, fullId)).one();
6998
7817
  if (!currentRow) {
6999
7818
  throw new EntityNotFoundError("Repo", id);
7000
7819
  }
@@ -7008,7 +7827,7 @@ var RepoRepository = class {
7008
7827
  repo_type: insertData.repo_type,
7009
7828
  unix_group: next.unix_group ?? null,
7010
7829
  data: insertData.data
7011
- }).where((0, import_drizzle_orm24.eq)(repos3.repo_id, fullId)).run();
7830
+ }).where((0, import_drizzle_orm23.eq)(repos3.repo_id, fullId)).run();
7012
7831
  next.environment = insertData.data.environment;
7013
7832
  next.environment_config = insertData.data.environment_config;
7014
7833
  next.remote_url = insertData.data.remote_url;
@@ -7048,7 +7867,7 @@ var RepoRepository = class {
7048
7867
  async delete(id) {
7049
7868
  try {
7050
7869
  const fullId = await this.resolveId(id);
7051
- const result = await deleteFrom(this.db, repos3).where((0, import_drizzle_orm24.eq)(repos3.repo_id, fullId)).run();
7870
+ const result = await deleteFrom(this.db, repos3).where((0, import_drizzle_orm23.eq)(repos3.repo_id, fullId)).run();
7052
7871
  if (result.rowsAffected === 0) {
7053
7872
  throw new EntityNotFoundError("Repo", id);
7054
7873
  }
@@ -7079,7 +7898,7 @@ var RepoRepository = class {
7079
7898
  */
7080
7899
  async count() {
7081
7900
  try {
7082
- const result = await select(this.db, { count: import_drizzle_orm24.sql`count(*)` }).from(repos3).one();
7901
+ const result = await select(this.db, { count: import_drizzle_orm23.sql`count(*)` }).from(repos3).one();
7083
7902
  return result?.count ?? 0;
7084
7903
  } catch (error) {
7085
7904
  throw new RepositoryError(
@@ -7092,33 +7911,40 @@ var RepoRepository = class {
7092
7911
 
7093
7912
  // src/db/repositories/schedules.ts
7094
7913
  init_cjs_shims();
7095
- var import_drizzle_orm25 = require("drizzle-orm");
7914
+ var import_drizzle_orm24 = require("drizzle-orm");
7096
7915
  init_ids();
7097
7916
  init_database_wrapper();
7098
7917
  init_schema();
7099
7918
 
7100
7919
  // src/db/repositories/serialized-sessions.ts
7101
7920
  init_cjs_shims();
7102
- var import_drizzle_orm26 = require("drizzle-orm");
7921
+ var import_drizzle_orm25 = require("drizzle-orm");
7103
7922
  init_ids();
7104
7923
  init_database_wrapper();
7105
7924
  init_schema();
7106
7925
 
7107
7926
  // src/db/repositories/session-mcp-servers.ts
7108
7927
  init_cjs_shims();
7109
- var import_drizzle_orm28 = require("drizzle-orm");
7928
+ var import_drizzle_orm27 = require("drizzle-orm");
7110
7929
  init_database_wrapper();
7111
7930
  init_schema();
7112
7931
 
7113
7932
  // src/db/repositories/sessions.ts
7114
7933
  init_cjs_shims();
7115
7934
  init_types2();
7116
- var import_drizzle_orm27 = require("drizzle-orm");
7935
+ var import_drizzle_orm26 = require("drizzle-orm");
7117
7936
  init_config_manager();
7118
7937
  init_ids();
7119
7938
  init_database_wrapper();
7120
7939
  init_schema();
7121
7940
 
7941
+ // src/db/repositories/session-relationships.ts
7942
+ init_cjs_shims();
7943
+ var import_drizzle_orm28 = require("drizzle-orm");
7944
+ init_ids();
7945
+ init_database_wrapper();
7946
+ init_schema();
7947
+
7122
7948
  // src/db/repositories/tasks.ts
7123
7949
  init_cjs_shims();
7124
7950
  init_types2();
@@ -7137,12 +7963,13 @@ init_schema();
7137
7963
 
7138
7964
  // src/db/repositories/user-api-keys.ts
7139
7965
  init_cjs_shims();
7140
- var import_node_crypto5 = require("crypto");
7141
- var import_bcryptjs2 = __toESM(require("bcryptjs"), 1);
7966
+ var import_node_crypto4 = require("crypto");
7967
+ var import_bcryptjs = __toESM(require("bcryptjs"), 1);
7142
7968
  var import_drizzle_orm31 = require("drizzle-orm");
7143
7969
  init_ids();
7144
7970
  init_database_wrapper();
7145
7971
  init_schema();
7972
+ init_tenant_context();
7146
7973
 
7147
7974
  // src/db/repositories/user-mcp-oauth-tokens.ts
7148
7975
  init_cjs_shims();
@@ -7178,7 +8005,12 @@ var UsersRepository = class {
7178
8005
  unix_username: row.unix_username ?? void 0,
7179
8006
  onboarding_completed: row.onboarding_completed,
7180
8007
  must_change_password: row.must_change_password,
8008
+ tokens_valid_after: row.tokens_valid_after ? new Date(row.tokens_valid_after) : void 0,
8009
+ avatar_url: row.data.avatar_url ?? row.data.avatar,
7181
8010
  avatar: row.data.avatar,
8011
+ avatar_source: row.data.avatar_source,
8012
+ avatar_source_id: row.data.avatar_source_id,
8013
+ avatar_synced_at: row.data.avatar_synced_at,
7182
8014
  preferences: row.data.preferences,
7183
8015
  // Convert encrypted per-tool credential blobs into boolean presence flags.
7184
8016
  agentic_tools: toAgenticToolsStatus(row.data.agentic_tools),
@@ -7222,8 +8054,14 @@ var UsersRepository = class {
7222
8054
  role: user.role ?? "member",
7223
8055
  unix_username: user.unix_username ?? null,
7224
8056
  onboarding_completed: user.onboarding_completed ?? false,
8057
+ must_change_password: user.must_change_password ?? false,
8058
+ tokens_valid_after: user.tokens_valid_after ? new Date(user.tokens_valid_after) : null,
7225
8059
  data: {
8060
+ avatar_url: user.avatar_url,
7226
8061
  avatar: user.avatar,
8062
+ avatar_source: user.avatar_source,
8063
+ avatar_source_id: user.avatar_source_id,
8064
+ avatar_synced_at: user.avatar_synced_at,
7227
8065
  preferences: user.preferences,
7228
8066
  // Encrypted per-tool credentials. Only forwarded when caller passes the
7229
8067
  // raw shape (internal credential mutators); regular updates leave it undefined,
@@ -7310,6 +8148,35 @@ var UsersRepository = class {
7310
8148
  }
7311
8149
  return this.rowToUser(result);
7312
8150
  }
8151
+ /**
8152
+ * Find user by email for external identity providers.
8153
+ *
8154
+ * Agor intentionally keeps exact/case-sensitive email lookup semantics for
8155
+ * auth paths because the schema historically allowed case-distinct emails.
8156
+ * External providers such as Slack and GitHub treat email addresses as a
8157
+ * canonical identity hint, so their alignment path needs a case-insensitive
8158
+ * match. Prefer an exact match when present; otherwise return a
8159
+ * case-insensitive match only when it is unambiguous.
8160
+ */
8161
+ async findByEmailForAlignment(email) {
8162
+ const normalizedEmail = email.trim().toLowerCase();
8163
+ if (!normalizedEmail) return null;
8164
+ const exact = await this.findByEmail(normalizedEmail);
8165
+ if (exact) return exact;
8166
+ const results = await select(this.db).from(users3).where(import_drizzle_orm33.sql`LOWER(${users3.email}) = ${normalizedEmail}`).all();
8167
+ if (results.length !== 1) {
8168
+ if (results.length > 1) {
8169
+ console.warn(
8170
+ `[users] Ambiguous case-insensitive email alignment for ${normalizedEmail}: ${results.map((row) => {
8171
+ const userRow = row;
8172
+ return `${shortId(userRow.user_id)}:${userRow.email}`;
8173
+ }).join(", ")}`
8174
+ );
8175
+ }
8176
+ return null;
8177
+ }
8178
+ return this.rowToUser(results[0]);
8179
+ }
7313
8180
  /**
7314
8181
  * Find all users
7315
8182
  */
@@ -7478,130 +8345,10 @@ var UsersRepository = class {
7478
8345
  }
7479
8346
  };
7480
8347
 
7481
- // src/db/index.ts
7482
- init_schema();
7483
-
7484
- // src/db/session-guard.ts
7485
- init_cjs_shims();
7486
- init_ids();
7487
-
7488
- // src/db/index.ts
7489
- init_user_utils();
7490
- var compare = import_bcryptjs3.default.compare;
7491
- var hash = import_bcryptjs3.default.hash;
7492
-
7493
- // src/config/key-resolver.ts
7494
- init_database_wrapper();
7495
- init_schema();
7496
- init_ids();
7497
- init_config_manager();
7498
- var DEBUG_KEY_RESOLUTION = process.env.AGOR_DEBUG_KEY_RESOLUTION === "1" || process.env.DEBUG?.includes("key-resolution");
7499
-
7500
- // src/config/proxies-resolver.ts
7501
- init_cjs_shims();
7502
-
7503
- // src/config/repo-list.ts
7504
- init_cjs_shims();
7505
-
7506
- // src/config/repo-reference.ts
7507
- init_cjs_shims();
7508
- var REPO_SLUG_PATTERN = /^[a-zA-Z0-9._-]+\/[a-zA-Z0-9._-]+$/;
7509
-
7510
- // src/config/resolved-config-slice.ts
7511
- init_cjs_shims();
7512
- var import_zod = require("zod");
7513
- var ResolvedConfigSliceSchema = import_zod.z.object({
7514
- /** From `config.execution.*` */
7515
- execution: import_zod.z.object({
7516
- permission_timeout_ms: import_zod.z.number().int().nonnegative().optional(),
7517
- executor_heartbeat: import_zod.z.object({
7518
- enabled: import_zod.z.boolean(),
7519
- interval_ms: import_zod.z.number().int().positive()
7520
- }).optional()
7521
- }).optional(),
7522
- /** From `config.opencode.*` */
7523
- opencode: import_zod.z.object({
7524
- serverUrl: import_zod.z.string().optional()
7525
- }).optional(),
7526
- /** From `config.daemon.*` (selected fields only) */
7527
- daemon: import_zod.z.object({
7528
- host_ip_address: import_zod.z.string().optional()
7529
- }).optional()
7530
- });
7531
-
7532
- // src/config/resource-schemas.ts
7533
- init_cjs_shims();
7534
- var import_zod2 = require("zod");
7535
- var uuidSchema = import_zod2.z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, "Must be a valid UUID");
7536
- var repoSlugSchema = import_zod2.z.string().regex(
7537
- REPO_SLUG_PATTERN,
7538
- 'Must be org/name format with alphanumeric, hyphens, underscores, or dots (e.g., "my-org/my-repo")'
7539
- );
7540
- var enforcedAgentConfigSchema = import_zod2.z.object({
7541
- agentic_tool: import_zod2.z.enum(["claude-code", "claude-code-cli", "codex", "gemini", "opencode", "copilot", "cursor"]).optional(),
7542
- permission_mode: import_zod2.z.string().optional(),
7543
- model: import_zod2.z.string().optional(),
7544
- mcp_server_ids: import_zod2.z.array(import_zod2.z.string()).optional()
7545
- });
7546
- var resourceRepoConfigSchema = import_zod2.z.object({
7547
- repo_id: uuidSchema,
7548
- slug: repoSlugSchema,
7549
- remote_url: import_zod2.z.string().optional(),
7550
- repo_type: import_zod2.z.enum(["remote", "local"]).default("remote"),
7551
- default_branch: import_zod2.z.string().optional(),
7552
- shallow: import_zod2.z.boolean().optional()
7553
- }).refine((data) => data.repo_type !== "remote" || data.remote_url, {
7554
- message: 'remote_url is required when repo_type is "remote"',
7555
- path: ["remote_url"]
7556
- });
7557
- var resourceBranchConfigSchema = import_zod2.z.object({
7558
- branch_id: uuidSchema,
7559
- name: import_zod2.z.string().min(1, "Branch name is required"),
7560
- ref: import_zod2.z.string().min(1, "Git ref is required"),
7561
- ref_type: import_zod2.z.enum(["branch", "tag"]).optional(),
7562
- others_can: import_zod2.z.enum(["none", "view", "session", "prompt", "all"]).optional(),
7563
- mcp_server_ids: import_zod2.z.array(import_zod2.z.string()).optional(),
7564
- repo: repoSlugSchema,
7565
- readonly: import_zod2.z.boolean().optional(),
7566
- agent: enforcedAgentConfigSchema.optional()
7567
- });
7568
- var resourceUserConfigSchema = import_zod2.z.object({
7569
- user_id: uuidSchema,
7570
- email: import_zod2.z.string().email("Must be a valid email address"),
7571
- name: import_zod2.z.string().optional(),
7572
- role: import_zod2.z.enum(["superadmin", "admin", "member", "viewer"]).default("member"),
7573
- unix_username: import_zod2.z.string().optional(),
7574
- password: import_zod2.z.string().optional()
7575
- });
7576
- var daemonResourcesConfigSchema = import_zod2.z.object({
7577
- repos: import_zod2.z.array(resourceRepoConfigSchema).optional(),
7578
- branches: import_zod2.z.array(resourceBranchConfigSchema).optional(),
7579
- users: import_zod2.z.array(resourceUserConfigSchema).optional()
7580
- });
7581
-
7582
- // src/config/resource-sync.ts
7583
- init_cjs_shims();
7584
-
7585
- // src/config/security-resolver.ts
7586
- init_cjs_shims();
7587
- var DEFAULT_GIT_CONFIG_PARAMETERS = Object.freeze([
7588
- "transfer.credentialsInUrl=die",
7589
- "protocol.file.allow=user",
7590
- "protocol.ext.allow=never",
7591
- "core.protectHFS=true",
7592
- "core.protectNTFS=true"
7593
- ]);
7594
-
7595
- // src/config/index.ts
7596
- init_types();
7597
-
7598
8348
  // src/git/index.ts
8349
+ var git_exports = {};
7599
8350
  init_cjs_shims();
7600
- var import_node_fs3 = require("fs");
7601
- var import_promises2 = require("fs/promises");
7602
- var import_node_path4 = require("path");
7603
- var import_simple_git = require("simple-git");
7604
- init_config_manager();
8351
+ __reExport(git_exports, require("@agor/git"));
7605
8352
 
7606
8353
  // src/unix/run-as-user.ts
7607
8354
  init_cjs_shims();
@@ -7957,116 +8704,13 @@ function buildSpawnArgs(command, args = [], options) {
7957
8704
  };
7958
8705
  }
7959
8706
 
7960
- // src/git/index.ts
7961
- init_config_manager();
7962
- var cachedGitBinary;
7963
- function getGitBinary() {
7964
- if (cachedGitBinary !== void 0) return cachedGitBinary;
7965
- const commonPaths = [
7966
- "/opt/homebrew/bin/git",
7967
- // Homebrew on Apple Silicon
7968
- "/usr/local/bin/git",
7969
- // Homebrew on Intel
7970
- "/usr/bin/git"
7971
- // System git (Docker and Linux)
7972
- ];
7973
- for (const path2 of commonPaths) {
7974
- if ((0, import_node_fs3.existsSync)(path2)) {
7975
- cachedGitBinary = path2;
7976
- return path2;
7977
- }
7978
- }
7979
- cachedGitBinary = "git";
7980
- return cachedGitBinary;
7981
- }
7982
- function isLikelyGitToken(token) {
7983
- return /^[A-Za-z0-9_-]{20,255}$/.test(token);
7984
- }
7985
- var DEFAULT_AUTH_HEADER_HOST = "github.com";
7986
- function buildGitConfigEnv(entries) {
7987
- if (entries.length === 0) return {};
7988
- const out = {
7989
- GIT_CONFIG_COUNT: String(entries.length)
7990
- };
7991
- for (let i = 0; i < entries.length; i++) {
7992
- const [key, value] = entries[i];
7993
- out[`GIT_CONFIG_KEY_${i}`] = key;
7994
- out[`GIT_CONFIG_VALUE_${i}`] = value;
7995
- }
7996
- return out;
7997
- }
7998
- function buildAuthHeaderEnv(token, host = DEFAULT_AUTH_HEADER_HOST) {
7999
- if (!token) return [];
8000
- if (!isLikelyGitToken(token)) {
8001
- console.warn(
8002
- "\u{1F511} Skipping http.extraheader: token does not match expected shape. Tokens must match /^[A-Za-z0-9_-]{20,255}$/. Re-save the token to enable the auth header."
8003
- );
8004
- return [];
8005
- }
8006
- const credential = Buffer.from(`x-access-token:${token}`, "utf8").toString("base64");
8007
- const key = `http.https://${host}/.extraheader`;
8008
- return [[key, `Authorization: Basic ${credential}`]];
8009
- }
8010
- function createGit(baseDir, env, authHost) {
8011
- const gitBinary = getGitBinary();
8012
- const config = [];
8013
- const rawToken = env?.GITHUB_TOKEN ?? env?.GH_TOKEN;
8014
- const authConfigEntries = buildAuthHeaderEnv(rawToken, authHost ?? DEFAULT_AUTH_HEADER_HOST);
8015
- let spawnEnv;
8016
- if (env || authConfigEntries.length > 0) {
8017
- spawnEnv = {
8018
- ...process.env,
8019
- ...env ?? {},
8020
- // Inheritance kill (GLOBAL only): ignore the daemon user's
8021
- // ~/.gitconfig. /etc/gitconfig is intentionally NOT killed — it is
8022
- // admin-policy territory (CA bundles, proxies). See block comment.
8023
- GIT_CONFIG_GLOBAL: "/dev/null",
8024
- // Fail fast instead of blocking on an interactive credential prompt
8025
- // (which would hang the daemon).
8026
- GIT_TERMINAL_PROMPT: "0",
8027
- // Inject http.extraheader (and any future server-constructed config)
8028
- // via the env-var protocol so it never lands on argv.
8029
- ...buildGitConfigEnv(authConfigEntries)
8030
- };
8031
- }
8032
- const git = (0, import_simple_git.simpleGit)({
8033
- baseDir,
8034
- binary: gitBinary,
8035
- config,
8036
- unsafe: {
8037
- // simple-git's scanner blocks spawning when these env vars / config keys
8038
- // are present. We own the daemon env (in strict mode it's the user's own
8039
- // env) and inject GIT_CONFIG_* ourselves — opting in here mirrors what a
8040
- // direct `git` invocation on the same machine does.
8041
- allowUnsafeSshCommand: true,
8042
- allowUnsafeConfigPaths: true,
8043
- allowUnsafeConfigEnvCount: true,
8044
- allowUnsafeEditor: true,
8045
- allowUnsafeAskPass: true,
8046
- allowUnsafePager: true,
8047
- allowUnsafeGitProxy: true,
8048
- allowUnsafeTemplateDir: true,
8049
- allowUnsafeDiffExternal: true
8050
- }
8051
- });
8052
- if (spawnEnv) {
8053
- git.env(spawnEnv);
8054
- }
8055
- return { git };
8056
- }
8057
- async function getCurrentSha(repoPath) {
8058
- const { git } = createGit(repoPath);
8059
- const log = await git.log({ maxCount: 1 });
8060
- return log.latest?.hash || "";
8061
- }
8062
-
8063
8707
  // src/unix/user-env-file.ts
8064
8708
  init_cjs_shims();
8065
8709
  var import_node_child_process4 = require("child_process");
8066
- var import_node_crypto6 = require("crypto");
8067
- var import_node_fs4 = require("fs");
8068
- var import_node_os3 = require("os");
8069
- var import_node_path5 = require("path");
8710
+ var import_node_crypto5 = require("crypto");
8711
+ var import_node_fs3 = require("fs");
8712
+ var import_node_os2 = require("os");
8713
+ var import_node_path2 = require("path");
8070
8714
 
8071
8715
  // src/unix/secret-env.ts
8072
8716
  init_cjs_shims();
@@ -8108,8 +8752,8 @@ function writeUserEnvFile(asUser, env) {
8108
8752
  if (!isValidUnixUsername(asUser)) {
8109
8753
  throw new Error(`writeUserEnvFile: invalid Unix username: ${JSON.stringify(asUser)}`);
8110
8754
  }
8111
- const nonce = (0, import_node_crypto6.randomBytes)(16).toString("hex");
8112
- const envFilePath = (0, import_node_path5.join)((0, import_node_os3.tmpdir)(), `${ENV_FILE_PREFIX}${nonce}`);
8755
+ const nonce = (0, import_node_crypto5.randomBytes)(16).toString("hex");
8756
+ const envFilePath = (0, import_node_path2.join)((0, import_node_os2.tmpdir)(), `${ENV_FILE_PREFIX}${nonce}`);
8113
8757
  const lines = [];
8114
8758
  for (const [key, value] of Object.entries(env)) {
8115
8759
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {
@@ -8129,7 +8773,7 @@ function writeUserEnvFile(asUser, env) {
8129
8773
  }
8130
8774
  function tryUnlinkEnvFile(path2) {
8131
8775
  try {
8132
- (0, import_node_fs4.unlinkSync)(path2);
8776
+ (0, import_node_fs3.unlinkSync)(path2);
8133
8777
  } catch {
8134
8778
  }
8135
8779
  }
@@ -8175,7 +8819,7 @@ function prepareImpersonationEnv(options) {
8175
8819
  // src/unix/environment-command-spawn.ts
8176
8820
  async function captureBranchBuildSha(branchPath2) {
8177
8821
  try {
8178
- const sha = await getCurrentSha(branchPath2);
8822
+ const sha = await (0, git_exports.getCurrentSha)(branchPath2);
8179
8823
  return sha ? sha.slice(0, 7) : void 0;
8180
8824
  } catch {
8181
8825
  return void 0;
@@ -8474,7 +9118,7 @@ var REPO_GIT_PERMISSION_MODE = "2770";
8474
9118
  // src/unix/id-lookups.ts
8475
9119
  init_cjs_shims();
8476
9120
  var import_node_child_process6 = require("child_process");
8477
- var import_node_fs5 = __toESM(require("fs"), 1);
9121
+ var import_node_fs4 = __toESM(require("fs"), 1);
8478
9122
  function getGidFromGroupName(groupName) {
8479
9123
  if (!groupName) {
8480
9124
  return void 0;
@@ -8495,8 +9139,8 @@ function getGidFromGroupName(groupName) {
8495
9139
  }
8496
9140
  } catch {
8497
9141
  }
8498
- if (import_node_fs5.default.existsSync("/etc/group")) {
8499
- const groupFile = import_node_fs5.default.readFileSync("/etc/group", "utf-8");
9142
+ if (import_node_fs4.default.existsSync("/etc/group")) {
9143
+ const groupFile = import_node_fs4.default.readFileSync("/etc/group", "utf-8");
8500
9144
  const line = groupFile.split("\n").find((l) => l.startsWith(`${groupName}:`));
8501
9145
  if (line) {
8502
9146
  const parts = line.split(":");
@@ -8550,8 +9194,8 @@ function getUidFromUsername(username) {
8550
9194
  }
8551
9195
  } catch {
8552
9196
  }
8553
- if (import_node_fs5.default.existsSync("/etc/passwd")) {
8554
- const passwdFile = import_node_fs5.default.readFileSync("/etc/passwd", "utf-8");
9197
+ if (import_node_fs4.default.existsSync("/etc/passwd")) {
9198
+ const passwdFile = import_node_fs4.default.readFileSync("/etc/passwd", "utf-8");
8555
9199
  const line = passwdFile.split("\n").find((l) => l.startsWith(`${username}:`));
8556
9200
  if (line) {
8557
9201
  const parts = line.split(":");
@@ -8590,8 +9234,8 @@ function getHomedirFromUsername(username) {
8590
9234
  }
8591
9235
  } catch {
8592
9236
  }
8593
- if (import_node_fs5.default.existsSync("/etc/passwd")) {
8594
- const passwdFile = import_node_fs5.default.readFileSync("/etc/passwd", "utf-8");
9237
+ if (import_node_fs4.default.existsSync("/etc/passwd")) {
9238
+ const passwdFile = import_node_fs4.default.readFileSync("/etc/passwd", "utf-8");
8595
9239
  const line = passwdFile.split("\n").find((l) => l.startsWith(`${username}:`));
8596
9240
  if (line) {
8597
9241
  const parts = line.split(":");
@@ -8842,6 +9486,30 @@ var UnixIntegrationService = class {
8842
9486
  this.usersRepo = new UsersRepository(db);
8843
9487
  this.repoRepo = new RepoRepository(db);
8844
9488
  }
9489
+ async getUnixUsernamesForUsers(userIds) {
9490
+ const unixUsernames = /* @__PURE__ */ new Set();
9491
+ for (const userId of userIds) {
9492
+ const user = await this.usersRepo.findById(userId);
9493
+ if (user?.unix_username) {
9494
+ unixUsernames.add(user.unix_username);
9495
+ }
9496
+ }
9497
+ return unixUsernames;
9498
+ }
9499
+ async reconcileUnixGroupMembers(groupName, allowedUnixUsernames, options) {
9500
+ if (this.config.daemonUser) {
9501
+ allowedUnixUsernames.add(this.config.daemonUser);
9502
+ }
9503
+ const result = await this.executor.exec(UnixGroupCommands.listGroupMembers(groupName));
9504
+ const currentMembers = result.stdout.trim().split(",").filter(Boolean);
9505
+ for (const unixUsername of currentMembers) {
9506
+ if (allowedUnixUsernames.has(unixUsername)) continue;
9507
+ console.log(
9508
+ `[UnixIntegration] Removing stale ${options.label} group member ${unixUsername} from ${groupName}`
9509
+ );
9510
+ await this.executor.exec(UnixGroupCommands.removeUserFromGroup(unixUsername, groupName));
9511
+ }
9512
+ }
8845
9513
  /**
8846
9514
  * Get the configured daemon user
8847
9515
  *
@@ -9085,19 +9753,26 @@ var UnixIntegrationService = class {
9085
9753
  /**
9086
9754
  * Initialize Unix group for an existing branch
9087
9755
  *
9088
- * Creates group and adds all current owners.
9756
+ * Creates group and adds all users with explicit filesystem access.
9089
9757
  *
9090
9758
  * @param branchId - Branch ID
9091
9759
  */
9092
9760
  async initializeBranchGroup(branchId) {
9093
9761
  const groupName = await this.createBranchGroup(branchId);
9094
- const ownerIds = await this.branchRepo.getOwners(branchId);
9095
- for (const ownerId of ownerIds) {
9096
- await this.addUserToBranchGroup(branchId, ownerId);
9762
+ const userIds = await this.branchRepo.findExplicitFsAccessUserIds(branchId);
9763
+ for (const userId of userIds) {
9764
+ await this.addUserToBranchGroup(branchId, userId);
9097
9765
  }
9766
+ await this.reconcileUnixGroupMembers(groupName, await this.getUnixUsernamesForUsers(userIds), {
9767
+ label: "branch"
9768
+ });
9098
9769
  console.log(
9099
- `[UnixIntegration] Initialized group ${groupName} with ${ownerIds.length} owner(s)`
9770
+ `[UnixIntegration] Initialized group ${groupName} with ${userIds.length} explicit filesystem user(s)`
9100
9771
  );
9772
+ const branch = await this.branchRepo.findById(branchId);
9773
+ if (branch?.repo_id) {
9774
+ await this.syncRepo(branch.repo_id);
9775
+ }
9101
9776
  }
9102
9777
  // ============================================================
9103
9778
  // REPO GROUP MANAGEMENT
@@ -9329,8 +10004,8 @@ var UnixIntegrationService = class {
9329
10004
  /**
9330
10005
  * Check if a user should be in a repo's Unix group
9331
10006
  *
9332
- * A user should be in the repo group if they have ownership
9333
- * of ANY branch in that repo.
10007
+ * A user should be in the repo group if they have explicit filesystem access
10008
+ * to ANY branch in that repo.
9334
10009
  *
9335
10010
  * @param repoId - Repo ID
9336
10011
  * @param userId - User ID to check
@@ -9339,8 +10014,8 @@ var UnixIntegrationService = class {
9339
10014
  async shouldUserBeInRepoGroup(repoId, userId) {
9340
10015
  const branches4 = await this.branchRepo.findAll({ repo_id: repoId });
9341
10016
  for (const wt of branches4) {
9342
- const isOwner = await this.branchRepo.isOwner(wt.branch_id, userId);
9343
- if (isOwner) {
10017
+ const userIds = await this.branchRepo.findExplicitFsAccessUserIds(wt.branch_id);
10018
+ if (userIds.includes(userId)) {
9344
10019
  return true;
9345
10020
  }
9346
10021
  }
@@ -9349,33 +10024,36 @@ var UnixIntegrationService = class {
9349
10024
  /**
9350
10025
  * Initialize Unix group for an existing repo
9351
10026
  *
9352
- * Creates group, sets .git permissions, and adds all users who
9353
- * own any branch in the repo.
10027
+ * Creates group, sets .git permissions, and adds all users who have explicit
10028
+ * filesystem access to any branch in the repo.
9354
10029
  *
9355
10030
  * @param repoId - Repo ID
9356
10031
  */
9357
10032
  async initializeRepoGroup(repoId) {
9358
10033
  const groupName = await this.createRepoGroup(repoId);
9359
10034
  const branches4 = await this.branchRepo.findAll({ repo_id: repoId });
9360
- const ownerIds = /* @__PURE__ */ new Set();
10035
+ const userIds = /* @__PURE__ */ new Set();
9361
10036
  for (const wt of branches4) {
9362
- const wtOwners = await this.branchRepo.getOwners(wt.branch_id);
9363
- for (const ownerId of wtOwners) {
9364
- ownerIds.add(ownerId);
10037
+ const branchUserIds = await this.branchRepo.findExplicitFsAccessUserIds(wt.branch_id);
10038
+ for (const userId of branchUserIds) {
10039
+ userIds.add(userId);
9365
10040
  }
9366
10041
  }
9367
- for (const ownerId of ownerIds) {
9368
- await this.addUserToRepoGroup(repoId, ownerId);
10042
+ for (const userId of userIds) {
10043
+ await this.addUserToRepoGroup(repoId, userId);
9369
10044
  }
10045
+ await this.reconcileUnixGroupMembers(groupName, await this.getUnixUsernamesForUsers(userIds), {
10046
+ label: "repo"
10047
+ });
9370
10048
  console.log(
9371
- `[UnixIntegration] Initialized repo group ${groupName} with ${ownerIds.size} unique owner(s)`
10049
+ `[UnixIntegration] Initialized repo group ${groupName} with ${userIds.size} unique filesystem user(s)`
9372
10050
  );
9373
10051
  }
9374
10052
  /**
9375
10053
  * Full sync for a repo
9376
10054
  *
9377
10055
  * Ensures repo group exists, .git permissions are set, and all
9378
- * branch owners are in the repo group.
10056
+ * branch filesystem-access users are in the repo group.
9379
10057
  *
9380
10058
  * @param repoId - Repo ID
9381
10059
  */
@@ -9383,15 +10061,23 @@ var UnixIntegrationService = class {
9383
10061
  console.log(`[UnixIntegration] Full sync for repo ${shortId(repoId)}`);
9384
10062
  await this.createRepoGroup(repoId);
9385
10063
  const branches4 = await this.branchRepo.findAll({ repo_id: repoId });
9386
- const ownerIds = /* @__PURE__ */ new Set();
10064
+ const userIds = /* @__PURE__ */ new Set();
9387
10065
  for (const wt of branches4) {
9388
- const wtOwners = await this.branchRepo.getOwners(wt.branch_id);
9389
- for (const ownerId of wtOwners) {
9390
- ownerIds.add(ownerId);
10066
+ const branchUserIds = await this.branchRepo.findExplicitFsAccessUserIds(wt.branch_id);
10067
+ for (const userId of branchUserIds) {
10068
+ userIds.add(userId);
9391
10069
  }
9392
10070
  }
9393
- for (const ownerId of ownerIds) {
9394
- await this.addUserToRepoGroup(repoId, ownerId);
10071
+ for (const userId of userIds) {
10072
+ await this.addUserToRepoGroup(repoId, userId);
10073
+ }
10074
+ const repo = await this.repoRepo.findById(repoId);
10075
+ if (repo?.unix_group) {
10076
+ await this.reconcileUnixGroupMembers(
10077
+ repo.unix_group,
10078
+ await this.getUnixUsernamesForUsers(userIds),
10079
+ { label: "repo" }
10080
+ );
9395
10081
  }
9396
10082
  }
9397
10083
  // ============================================================
@@ -9668,16 +10354,28 @@ var UnixIntegrationService = class {
9668
10354
  /**
9669
10355
  * Full sync for a branch
9670
10356
  *
9671
- * Ensures group exists, all owners are in group, and symlinks are created.
10357
+ * Ensures group exists, all explicit filesystem-access users are in group,
10358
+ * and symlinks are created.
9672
10359
  *
9673
10360
  * @param branchId - Branch ID
9674
10361
  */
9675
10362
  async syncBranch(branchId) {
9676
10363
  console.log(`[UnixIntegration] Full sync for branch ${shortId(branchId)}`);
9677
10364
  await this.createBranchGroup(branchId);
9678
- const ownerIds = await this.branchRepo.getOwners(branchId);
9679
- for (const ownerId of ownerIds) {
9680
- await this.addUserToBranchGroup(branchId, ownerId);
10365
+ const userIds = await this.branchRepo.findExplicitFsAccessUserIds(branchId);
10366
+ for (const userId of userIds) {
10367
+ await this.addUserToBranchGroup(branchId, userId);
10368
+ }
10369
+ const branch = await this.branchRepo.findById(branchId);
10370
+ if (branch?.unix_group) {
10371
+ await this.reconcileUnixGroupMembers(
10372
+ branch.unix_group,
10373
+ await this.getUnixUsernamesForUsers(userIds),
10374
+ { label: "branch" }
10375
+ );
10376
+ }
10377
+ if (branch?.repo_id) {
10378
+ await this.syncRepo(branch.repo_id);
9681
10379
  }
9682
10380
  }
9683
10381
  /**