@allbluecn/web-app 0.22.4 → 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 (500) hide show
  1. package/package.json +4 -14
  2. package/src/__tests__/integration/login-email-acceptance.test.ts +16 -0
  3. package/src/__tests__/story-view.test.ts +33 -1
  4. package/src/components/agents/__tests__/agent-bindings-tab.test.tsx +221 -0
  5. package/src/components/agents/__tests__/agents-page.test.tsx +284 -0
  6. package/src/components/agents/agent-bindings-tab.tsx +59 -45
  7. package/src/components/agents/agent-form-dialog.tsx +3 -3
  8. package/src/components/agents/agent-selector.tsx +2 -3
  9. package/src/components/agents/agents-page.tsx +66 -31
  10. package/src/components/agents/slash-skill-menu.tsx +2 -3
  11. package/src/components/auth/__tests__/session-guard.test.tsx +74 -0
  12. package/src/components/auth/session-guard.tsx +8 -0
  13. package/src/components/billing/login-prompt-dialog.tsx +1 -1
  14. package/src/components/billing/subscription-provider.tsx +2 -16
  15. package/src/components/bug/__tests__/peek-modes.test.tsx +8 -0
  16. package/src/components/bug/__tests__/subgroup-header.test.tsx +202 -40
  17. package/src/components/bug/peek-panel.tsx +5 -3
  18. package/src/components/bug/views/bug-list/group.tsx +12 -2
  19. package/src/components/bug/views/bug-list/index.tsx +94 -67
  20. package/src/components/command/command-palette.tsx +10 -9
  21. package/src/components/design/canvas/document/frame-custom-presets.ts +9 -1
  22. package/src/components/design/canvas/panels/toolbar.tsx +21 -22
  23. package/src/components/design/canvas/react/__tests__/canvas-context-load-echo.test.tsx +199 -0
  24. package/src/components/design/canvas/react/__tests__/hooks.test.tsx +17 -3
  25. package/src/components/design/canvas/react/canvas-context.tsx +47 -26
  26. package/src/components/design/canvas/react/hooks.ts +39 -34
  27. package/src/components/design/editor/layout/__tests__/collab-param-wiring.test.tsx +17 -0
  28. package/src/components/design/editor/layout/__tests__/context-menu.test.tsx +17 -1
  29. package/src/components/design/editor/layout/__tests__/no-page-save-toast.test.tsx +17 -0
  30. package/src/components/design/editor/layout/__tests__/persistence-restore.test.tsx +17 -1
  31. package/src/components/design/editor/layout/__tests__/ssr-localstorage-smoke.test.tsx +17 -1
  32. package/src/components/design/editor/layout/design-editor-layout.tsx +13 -2
  33. package/src/components/design/editor/layout/hooks/use-design-auto-save.ts +3 -19
  34. package/src/components/devtools/devtools-panel.tsx +56 -0
  35. package/src/components/forms/__tests__/create-app-form.test.tsx +131 -0
  36. package/src/components/forms/app-field-error.tsx +21 -1
  37. package/src/components/forms/app-field.tsx +8 -8
  38. package/src/components/forms/app-submit.tsx +12 -9
  39. package/src/components/forms/create-app-form.tsx +124 -0
  40. package/src/components/forms/index.ts +2 -3
  41. package/src/components/harness/__tests__/gallery-behavior.test.tsx +37 -1
  42. package/src/components/harness/__tests__/harness-workbench-first-send.test.tsx +4 -1
  43. package/src/components/harness/__tests__/message-actions.test.tsx +7 -6
  44. package/src/components/harness/__tests__/use-video-generation.test.tsx +165 -0
  45. package/src/components/harness/ai-chat-history/index.tsx +5 -3
  46. package/src/components/harness/gallery/gallery-card.tsx +57 -35
  47. package/src/components/harness/gallery/gallery-grid.tsx +32 -15
  48. package/src/components/harness/gallery/gallery-types.ts +19 -0
  49. package/src/components/harness/gallery/gallery-video-card.tsx +54 -0
  50. package/src/components/harness/gallery/types.ts +2 -0
  51. package/src/components/harness/gallery/use-video-generation.ts +95 -0
  52. package/src/components/harness/harness-workbench-page.tsx +2 -3
  53. package/src/components/harness/message-actions.tsx +5 -3
  54. package/src/components/hotkeys/shortcuts-panel.tsx +28 -13
  55. package/src/components/iteration/__tests__/burndown-chart.test.tsx +118 -0
  56. package/src/components/iteration/burndown-chart.tsx +54 -23
  57. package/src/components/knowledge/editor/__tests__/knowledge-doc-editor-collab.test.tsx +96 -0
  58. package/src/components/knowledge/editor/knowledge-doc-editor.tsx +56 -1
  59. package/src/components/knowledge/editor/mindmap-doc-editor.tsx +12 -0
  60. package/src/components/knowledge/editor/use-auto-save-channels.ts +3 -1
  61. package/src/components/layout/sidebar-03/__tests__/nav-workspace.test.tsx +0 -4
  62. package/src/components/layout/sidebar-03/nav-knowledge.tsx +11 -11
  63. package/src/components/layout/sidebar-03/nav-main.tsx +12 -15
  64. package/src/components/layout/sidebar-03/nav-notifications.tsx +5 -8
  65. package/src/components/layout/sidebar-03/nav-workspace.tsx +11 -9
  66. package/src/components/notifications/__tests__/settings-notifications.test.tsx +158 -0
  67. package/src/components/notifications/settings-notifications.tsx +37 -13
  68. package/src/components/notifications/team-notifications.tsx +10 -14
  69. package/src/components/settings/personal-team/account/__tests__/account-client.test.tsx +170 -0
  70. package/src/components/settings/personal-team/account/account-client.tsx +44 -7
  71. package/src/components/settings/personal-team/team/team-client.tsx +17 -19
  72. package/src/components/shared-kit/list-kit/__tests__/frozen-header.test.ts +210 -41
  73. package/src/components/shared-kit/list-kit/frozen-header.ts +134 -21
  74. package/src/components/shared-kit/list-kit/kanban/frozen-header.ts +20 -27
  75. package/src/components/story/__tests__/peek-panel-patch-sync.test.tsx +8 -0
  76. package/src/components/story/__tests__/story-list-table.test.tsx +214 -0
  77. package/src/components/story/columns.tsx +11 -2
  78. package/src/components/story/peek-panel.tsx +4 -2
  79. package/src/components/story/story-list-table.tsx +16 -1
  80. package/src/components/story/views/story-list/__tests__/frozen-headers.test.tsx +186 -0
  81. package/src/components/story/views/story-list/group.tsx +12 -1
  82. package/src/components/story/views/story-list/index.tsx +101 -68
  83. package/src/components/testcase/__tests__/case-row.test.tsx +134 -2
  84. package/src/components/testcase/__tests__/peek-panel.test.tsx +8 -0
  85. package/src/components/testcase/__tests__/step-editor.test.tsx +106 -0
  86. package/src/components/testcase/list/grouped-list.tsx +50 -22
  87. package/src/components/testcase/peek-panel.tsx +7 -4
  88. package/src/components/testcase/step-editor.tsx +196 -150
  89. package/src/components/tiptap/notion-like/editor-extensions.ts +0 -3
  90. package/src/components/tiptap/notion-like/notion-like-editor-header.tsx +1 -31
  91. package/src/components/tiptap/notion-like/notion-like-editor.tsx +32 -1
  92. package/src/components/workspace/__tests__/dialogs/create-workspace-dialog.test.tsx +2 -28
  93. package/src/components/workspace/__tests__/dialogs/edit-workspace-dialog.test.tsx +2 -28
  94. package/src/components/workspace/dialogs/create-workspace-dialog.tsx +45 -43
  95. package/src/components/workspace/dialogs/edit-workspace-dialog.tsx +38 -36
  96. package/src/design-engine/engine/engine-decor.ts +2 -0
  97. package/src/design-engine/engine/engine-path.ts +2 -0
  98. package/src/hooks/__tests__/use-unsaved-guard.test.tsx +180 -0
  99. package/src/hooks/use-notifications.ts +9 -16
  100. package/src/hooks/use-unsaved-guard.tsx +87 -0
  101. package/src/lib/__tests__/pacer.test.ts +33 -96
  102. package/src/lib/__tests__/query-defaults.test.ts +169 -0
  103. package/src/lib/__tests__/query-global-error.test.ts +256 -0
  104. package/src/lib/anyhub/anyhub-store.ts +2 -2
  105. package/src/lib/changelog/sdk-versions.ts +2 -10
  106. package/src/lib/collab/presence-store.ts +5 -5
  107. package/src/lib/collab/use-presence-list-refresh.ts +2 -2
  108. package/src/lib/collab/use-share-presence.ts +2 -2
  109. package/src/lib/collections/query-keys.ts +7 -2
  110. package/src/lib/commands/__tests__/command-palette-state.test.ts +12 -14
  111. package/src/lib/commands/__tests__/registry.test.ts +6 -3
  112. package/src/lib/commands/command-palette-state.ts +8 -31
  113. package/src/lib/hotkeys/__tests__/registry.test.ts +71 -18
  114. package/src/lib/hotkeys/registry.ts +188 -85
  115. package/src/lib/hotkeys/types.ts +1 -13
  116. package/src/lib/pacer.ts +1 -79
  117. package/src/lib/queries/README.md +67 -0
  118. package/src/lib/queries/__tests__/agents-queries.test.ts +101 -0
  119. package/src/lib/queries/__tests__/compliance-queries.test.ts +136 -0
  120. package/src/lib/queries/__tests__/notifications-queries.test.ts +175 -0
  121. package/src/lib/queries/__tests__/team-queries.test.ts +87 -0
  122. package/src/lib/queries/agents.ts +40 -0
  123. package/src/lib/queries/compliance.ts +69 -0
  124. package/src/lib/queries/notifications.ts +63 -0
  125. package/src/lib/queries/team.ts +39 -0
  126. package/src/lib/query-defaults.ts +8 -0
  127. package/src/lib/query-global-error.ts +128 -0
  128. package/src/lib/remote-auth-client.ts +16 -0
  129. package/src/paraglide/README.md +1 -1
  130. package/src/paraglide/messages/_index.d.ts +11 -0
  131. package/src/paraglide/messages/_index.js +5659 -88285
  132. package/src/paraglide/messages/common_error_generic.d.ts +16 -0
  133. package/src/paraglide/messages/common_error_generic.js +29 -0
  134. package/src/paraglide/messages/common_unsaved_body.d.ts +16 -0
  135. package/src/paraglide/messages/common_unsaved_body.js +29 -0
  136. package/src/paraglide/messages/common_unsaved_leave.d.ts +16 -0
  137. package/src/paraglide/messages/common_unsaved_leave.js +29 -0
  138. package/src/paraglide/messages/common_unsaved_stay.d.ts +16 -0
  139. package/src/paraglide/messages/common_unsaved_stay.js +29 -0
  140. package/src/paraglide/messages/common_unsaved_title.d.ts +16 -0
  141. package/src/paraglide/messages/common_unsaved_title.js +29 -0
  142. package/src/paraglide/messages/gallery_videofailed1.d.ts +17 -0
  143. package/src/paraglide/messages/gallery_videofailed1.js +30 -0
  144. package/src/paraglide/messages/gallery_videogenerating1.d.ts +17 -0
  145. package/src/paraglide/messages/gallery_videogenerating1.js +30 -0
  146. package/src/paraglide/messages/gallery_videomissingprompt2.d.ts +17 -0
  147. package/src/paraglide/messages/gallery_videomissingprompt2.js +30 -0
  148. package/src/paraglide/messages/gallery_videoprogress1.d.ts +19 -0
  149. package/src/paraglide/messages/gallery_videoprogress1.js +30 -0
  150. package/src/paraglide/messages/gallery_videostop1.d.ts +17 -0
  151. package/src/paraglide/messages/gallery_videostop1.js +30 -0
  152. package/src/paraglide/messages/story_table_resizecolumn1.d.ts +17 -0
  153. package/src/paraglide/messages/story_table_resizecolumn1.js +30 -0
  154. package/src/providers/index.tsx +5 -50
  155. package/src/routeTree.gen.ts +21 -0
  156. package/src/router.tsx +21 -8
  157. package/src/routes/__root.tsx +2 -1
  158. package/src/routes/__tests__/-edition-routing.test.tsx +6 -1
  159. package/src/routes/_login/forgot-password/route.lazy.tsx +7 -6
  160. package/src/routes/_login/login/route.lazy.tsx +10 -9
  161. package/src/routes/_login/register/route.lazy.tsx +19 -18
  162. package/src/routes/_login/reset-password/route.lazy.tsx +10 -9
  163. package/src/routes/_nav/knowledge/compliance/$id.lazy.tsx +9 -12
  164. package/src/routes/_nav/knowledge/compliance/index.lazy.tsx +16 -13
  165. package/src/routes/_nav/knowledge/laws/$id.lazy.tsx +1 -1
  166. package/src/routes/_nav/notifications/route.tsx +6 -16
  167. package/src/routes/_nav/settings/-settings-tabs.tsx +9 -12
  168. package/src/routes/api/generate/__tests__/media.test.ts +378 -0
  169. package/src/routes/api/generate/media.ts +179 -0
  170. package/src/server/__tests__/agent-client-graph.test.ts +0 -1
  171. package/src/server/__tests__/agent-crud.test.ts +37 -4
  172. package/src/server/__tests__/bug-groups-two-level.test.ts +34 -1
  173. package/src/server/__tests__/chat-conversations.test.ts +37 -4
  174. package/src/server/__tests__/chat-list-messages.test.ts +40 -7
  175. package/src/server/__tests__/csv-export.test.ts +36 -3
  176. package/src/server/__tests__/desktop-bootstrap.test.ts +189 -0
  177. package/src/server/__tests__/remote-auth.test.ts +72 -0
  178. package/src/server/__tests__/skill-crud.test.ts +37 -4
  179. package/src/server/__tests__/sso-domain.test.ts +1 -1
  180. package/src/server/__tests__/sso-rate-limit-singleton.test.ts +123 -0
  181. package/src/server/__tests__/task-serverfn-crud.test.ts +35 -2
  182. package/src/server/__tests__/task-serverfn-queries.test.ts +35 -2
  183. package/src/server/__tests__/testcase-board.test.ts +38 -5
  184. package/src/server/__tests__/testcase-bulk.test.ts +38 -5
  185. package/src/server/__tests__/testcase-list-scope.test.ts +38 -5
  186. package/src/server/ai-gateway/__tests__/ai-output-guard.test.ts +126 -2
  187. package/src/server/ai-gateway/__tests__/chat-stream-builder-code-mode.test.ts +4 -0
  188. package/src/server/ai-gateway/__tests__/chat-stream-builder-memory.test.ts +4 -0
  189. package/src/server/ai-gateway/__tests__/chat-stream-builder-sandbox.test.ts +4 -0
  190. package/src/server/ai-gateway/__tests__/chat-stream-builder-skills.test.ts +4 -0
  191. package/src/server/ai-gateway/__tests__/pgvector-memory-adapter.test.ts +30 -0
  192. package/src/server/ai-gateway/__tests__/pgvector-memory-conformance.test.ts +92 -0
  193. package/src/server/ai-gateway/__tests__/source-mode.test.ts +49 -8
  194. package/src/server/ai-gateway/ai-output-guard.ts +50 -2
  195. package/src/server/ai-gateway/chat-stream-builder.ts +3 -0
  196. package/src/server/ai-gateway/media/index.ts +36 -29
  197. package/src/server/ai-gateway/media/trim-input.ts +52 -0
  198. package/src/server/ai-gateway/memory/pgvector-adapter.ts +27 -13
  199. package/src/server/ai-gateway/sandbox/__tests__/harness-sandbox.test.ts +252 -41
  200. package/src/server/ai-gateway/sandbox/harness-sandbox.ts +6 -67
  201. package/src/server/ai-gateway/source-mode.ts +24 -8
  202. package/src/server/desktop-bootstrap.ts +74 -0
  203. package/src/server/lib/__tests__/rate-limit.test.ts +0 -1
  204. package/src/server/lib/rate-limit.ts +0 -2
  205. package/src/server/middlewares/__tests__/auth-context.test.ts +156 -0
  206. package/src/server/middlewares/auth-context.ts +62 -0
  207. package/src/server/remote-auth.ts +58 -31
  208. package/src/server/serverFns/__tests__/ai-hosted-models.test.ts +47 -15
  209. package/src/server/serverFns/__tests__/ai-source-mode.test.ts +45 -15
  210. package/src/server/serverFns/__tests__/billing.test.ts +37 -2
  211. package/src/server/serverFns/__tests__/collab-snapshot.test.ts +41 -14
  212. package/src/server/serverFns/__tests__/collab.test.ts +41 -14
  213. package/src/server/serverFns/__tests__/compliance.test.ts +33 -1
  214. package/src/server/serverFns/__tests__/email-verification.test.ts +35 -1
  215. package/src/server/serverFns/__tests__/knowledge-breadcrumb.test.ts +46 -6
  216. package/src/server/serverFns/__tests__/knowledge-delete.test.ts +42 -14
  217. package/src/server/serverFns/__tests__/knowledge-kb-projects.test.ts +46 -6
  218. package/src/server/serverFns/__tests__/knowledge-public-compliance.test.ts +36 -2
  219. package/src/server/serverFns/__tests__/knowledge-readable-kb.test.ts +42 -10
  220. package/src/server/serverFns/__tests__/knowledge-search.test.ts +45 -9
  221. package/src/server/serverFns/__tests__/legal-code-canonical.test.ts +36 -2
  222. package/src/server/serverFns/__tests__/link-preview.test.ts +38 -4
  223. package/src/server/serverFns/__tests__/notifications-list.test.ts +36 -3
  224. package/src/server/serverFns/__tests__/ownership-merge.test.ts +38 -4
  225. package/src/server/serverFns/__tests__/project-delete-transaction.test.ts +39 -2
  226. package/src/server/serverFns/__tests__/project-kb.test.ts +34 -1
  227. package/src/server/serverFns/__tests__/project-member-idor.test.ts +34 -1
  228. package/src/server/serverFns/__tests__/project-team-assign.test.ts +34 -1
  229. package/src/server/serverFns/__tests__/read-write-merge.test.ts +38 -4
  230. package/src/server/serverFns/__tests__/story-comments.test.ts +38 -4
  231. package/src/server/serverFns/__tests__/story-crud-archive-detail.test.ts +38 -4
  232. package/src/server/serverFns/__tests__/story-crud-labels-users.test.ts +37 -3
  233. package/src/server/serverFns/__tests__/story-crud.test.ts +36 -3
  234. package/src/server/serverFns/__tests__/story-links.test.ts +38 -4
  235. package/src/server/serverFns/__tests__/story-reactions.test.ts +38 -4
  236. package/src/server/serverFns/__tests__/story-tree.test.ts +38 -4
  237. package/src/server/serverFns/__tests__/team-accept.test.ts +34 -1
  238. package/src/server/serverFns/__tests__/team-invitation.test.ts +34 -1
  239. package/src/server/serverFns/__tests__/team-join-request.test.ts +34 -1
  240. package/src/server/serverFns/__tests__/team-members.test.ts +34 -1
  241. package/src/server/serverFns/__tests__/team-ownership-merge.test.ts +34 -1
  242. package/src/server/serverFns/__tests__/update-bug-guard.test.ts +37 -3
  243. package/src/server/serverFns/__tests__/update-document-guard.test.ts +38 -4
  244. package/src/server/serverFns/__tests__/update-page-guard.test.ts +40 -4
  245. package/src/server/serverFns/__tests__/update-seats.test.ts +33 -1
  246. package/src/server/serverFns/__tests__/update-story-guard.test.ts +36 -3
  247. package/src/server/serverFns/__tests__/update-testcase-guard.test.ts +37 -3
  248. package/src/server/serverFns/__tests__/workspace-kb-idor.test.ts +36 -2
  249. package/src/server/serverFns/__tests__/workspace-kb.test.ts +36 -2
  250. package/src/server/serverFns/__tests__/workspace.test.ts +34 -1
  251. package/src/server/serverFns/activity.ts +10 -14
  252. package/src/server/serverFns/agents/agent-crud.ts +16 -15
  253. package/src/server/serverFns/agents/bindings.ts +12 -13
  254. package/src/server/serverFns/agents/skill-crud.ts +16 -15
  255. package/src/server/serverFns/ai/code-mode-readiness.ts +3 -4
  256. package/src/server/serverFns/ai/search-capability.ts +3 -4
  257. package/src/server/serverFns/anyhub/app.ts +10 -14
  258. package/src/server/serverFns/anyhub/index.ts +7 -10
  259. package/src/server/serverFns/anyhub/install.ts +4 -4
  260. package/src/server/serverFns/anyhub/permissions.ts +10 -14
  261. package/src/server/serverFns/anyhub/proxy.ts +4 -6
  262. package/src/server/serverFns/auth/email-verification.ts +4 -5
  263. package/src/server/serverFns/auth/session.ts +9 -0
  264. package/src/server/serverFns/billing.ts +18 -28
  265. package/src/server/serverFns/blob-upload.ts +6 -9
  266. package/src/server/serverFns/bug/__tests__/bug-access-tokens.test.ts +34 -1
  267. package/src/server/serverFns/bug/__tests__/bug-activities.test.ts +34 -1
  268. package/src/server/serverFns/bug/__tests__/bug-comments.test.ts +34 -1
  269. package/src/server/serverFns/bug/__tests__/bug-crud.test.ts +34 -1
  270. package/src/server/serverFns/bug/__tests__/bug-fix.test.ts +34 -1
  271. package/src/server/serverFns/bug/__tests__/bug-groups.test.ts +34 -1
  272. package/src/server/serverFns/bug/__tests__/bug-reactions.test.ts +34 -1
  273. package/src/server/serverFns/bug/__tests__/bug-reorder.test.ts +39 -5
  274. package/src/server/serverFns/bug/__tests__/bug-repro.test.ts +34 -1
  275. package/src/server/serverFns/bug/__tests__/bug-story.test.ts +34 -1
  276. package/src/server/serverFns/bug/__tests__/bug-webhooks.test.ts +34 -1
  277. package/src/server/serverFns/bug/bug-access-tokens.ts +16 -22
  278. package/src/server/serverFns/bug/bug-activities.ts +4 -6
  279. package/src/server/serverFns/bug/bug-collect-tokens.ts +13 -18
  280. package/src/server/serverFns/bug/bug-comments.ts +13 -18
  281. package/src/server/serverFns/bug/bug-crud/detail.ts +10 -14
  282. package/src/server/serverFns/bug/bug-crud.ts +28 -38
  283. package/src/server/serverFns/bug/bug-display-options.ts +8 -11
  284. package/src/server/serverFns/bug/bug-export.ts +5 -7
  285. package/src/server/serverFns/bug/bug-fix.ts +10 -14
  286. package/src/server/serverFns/bug/bug-groups.ts +10 -14
  287. package/src/server/serverFns/bug/bug-reactions.ts +10 -14
  288. package/src/server/serverFns/bug/bug-reorder.ts +4 -6
  289. package/src/server/serverFns/bug/bug-repro.ts +8 -11
  290. package/src/server/serverFns/bug/bug-story-bulk.ts +13 -18
  291. package/src/server/serverFns/bug/bug-story.ts +10 -14
  292. package/src/server/serverFns/bug/bug-views.ts +12 -18
  293. package/src/server/serverFns/bug/bug-webhooks.ts +13 -18
  294. package/src/server/serverFns/bug/test-bug-confirm.ts +7 -10
  295. package/src/server/serverFns/changelog/__tests__/fetch.test.ts +40 -1
  296. package/src/server/serverFns/changelog/fetch.ts +4 -6
  297. package/src/server/serverFns/chat/conversations.ts +17 -28
  298. package/src/server/serverFns/chat/list-messages.ts +4 -7
  299. package/src/server/serverFns/collab-presence.ts +11 -13
  300. package/src/server/serverFns/collab-snapshot.ts +6 -7
  301. package/src/server/serverFns/collab.ts +7 -7
  302. package/src/server/serverFns/compliance.ts +8 -8
  303. package/src/server/serverFns/design/__tests__/comments.test.ts +54 -10
  304. package/src/server/serverFns/design/__tests__/designs.test.ts +39 -16
  305. package/src/server/serverFns/design/__tests__/page-versions.test.ts +52 -14
  306. package/src/server/serverFns/design/__tests__/shares-password.test.ts +44 -14
  307. package/src/server/serverFns/design/__tests__/shares.test.ts +44 -14
  308. package/src/server/serverFns/design/__tests__/versions.test.ts +44 -14
  309. package/src/server/serverFns/design/ai/__tests__/agent-conversations.test.ts +50 -21
  310. package/src/server/serverFns/design/ai/__tests__/providers.test.ts +42 -8
  311. package/src/server/serverFns/design/ai/agent-conversations.ts +19 -26
  312. package/src/server/serverFns/design/ai/fill-annotation.ts +5 -7
  313. package/src/server/serverFns/design/ai/generate-prototype.ts +5 -7
  314. package/src/server/serverFns/design/ai/hosted-models.ts +4 -5
  315. package/src/server/serverFns/design/ai/providers.ts +30 -39
  316. package/src/server/serverFns/design/ai/source-mode.ts +10 -12
  317. package/src/server/serverFns/design/comments.ts +14 -13
  318. package/src/server/serverFns/design/designs.ts +13 -19
  319. package/src/server/serverFns/design/page-versions.ts +17 -18
  320. package/src/server/serverFns/design/pages.ts +17 -18
  321. package/src/server/serverFns/design/reviews.ts +8 -9
  322. package/src/server/serverFns/design/shares-password.ts +13 -19
  323. package/src/server/serverFns/design/shares.ts +22 -31
  324. package/src/server/serverFns/design/versions.ts +8 -9
  325. package/src/server/serverFns/harness/__tests__/attach-prototype.spec.ts +52 -2
  326. package/src/server/serverFns/harness/__tests__/attach-to-kb.spec.ts +52 -2
  327. package/src/server/serverFns/harness/__tests__/attach-to-story-ssrf.spec.ts +52 -2
  328. package/src/server/serverFns/harness/__tests__/attach-to-story.spec.ts +52 -2
  329. package/src/server/serverFns/harness/__tests__/cancel-run.test.ts +40 -15
  330. package/src/server/serverFns/harness/__tests__/extract-attachment.spec.ts +52 -2
  331. package/src/server/serverFns/harness/__tests__/gallery.spec.ts +76 -12
  332. package/src/server/serverFns/harness/__tests__/github-workspace.spec.ts +38 -6
  333. package/src/server/serverFns/harness/__tests__/media-prototype.spec.ts +50 -6
  334. package/src/server/serverFns/harness/__tests__/media.spec.ts +55 -11
  335. package/src/server/serverFns/harness/__tests__/sandbox-policy.test.ts +41 -16
  336. package/src/server/serverFns/harness/__tests__/workspace-files.test.ts +41 -16
  337. package/src/server/serverFns/harness/attach-prototype.ts +4 -4
  338. package/src/server/serverFns/harness/attach-to-kb.ts +4 -4
  339. package/src/server/serverFns/harness/attach-to-story.ts +4 -4
  340. package/src/server/serverFns/harness/cancel-run.ts +4 -6
  341. package/src/server/serverFns/harness/extract-attachment.ts +3 -4
  342. package/src/server/serverFns/harness/gallery.ts +19 -23
  343. package/src/server/serverFns/harness/github-workspace.ts +14 -21
  344. package/src/server/serverFns/harness/media.ts +18 -117
  345. package/src/server/serverFns/harness/sandbox-policy.ts +11 -10
  346. package/src/server/serverFns/harness/search-mention-candidates.ts +4 -6
  347. package/src/server/serverFns/harness/workspace-files.ts +19 -26
  348. package/src/server/serverFns/iteration/__tests__/iteration-auto-schedule.test.ts +35 -3
  349. package/src/server/serverFns/iteration/__tests__/iteration-crud.test.ts +35 -3
  350. package/src/server/serverFns/iteration/__tests__/iteration-stories.test.ts +35 -3
  351. package/src/server/serverFns/iteration/__tests__/iteration-transfer.test.ts +35 -3
  352. package/src/server/serverFns/iteration/iteration-auto-schedule.ts +7 -10
  353. package/src/server/serverFns/iteration/iteration-burndown.ts +4 -6
  354. package/src/server/serverFns/iteration/iteration-crud.ts +26 -35
  355. package/src/server/serverFns/iteration/iteration-stories.ts +10 -14
  356. package/src/server/serverFns/iteration/iteration-transfer.ts +4 -6
  357. package/src/server/serverFns/knowledge/public/bookmarks/categories.ts +11 -15
  358. package/src/server/serverFns/knowledge/public/bookmarks/create.ts +4 -6
  359. package/src/server/serverFns/knowledge/public/bookmarks/delete.ts +5 -7
  360. package/src/server/serverFns/knowledge/public/bookmarks/detail.ts +4 -6
  361. package/src/server/serverFns/knowledge/public/bookmarks/favorite.ts +4 -6
  362. package/src/server/serverFns/knowledge/public/bookmarks/list.ts +4 -6
  363. package/src/server/serverFns/knowledge/public/bookmarks/refresh-favicon.ts +4 -6
  364. package/src/server/serverFns/knowledge/public/bookmarks/share.ts +4 -6
  365. package/src/server/serverFns/knowledge/public/bookmarks/sync-github.ts +5 -7
  366. package/src/server/serverFns/knowledge/public/bookmarks/unshare.ts +4 -6
  367. package/src/server/serverFns/knowledge/public/bookmarks/update.ts +6 -8
  368. package/src/server/serverFns/knowledge/public/compliance/create.ts +4 -6
  369. package/src/server/serverFns/knowledge/public/compliance/delete.ts +5 -7
  370. package/src/server/serverFns/knowledge/public/compliance/detail.ts +4 -6
  371. package/src/server/serverFns/knowledge/public/compliance/list.ts +4 -6
  372. package/src/server/serverFns/knowledge/public/compliance/share.ts +4 -6
  373. package/src/server/serverFns/knowledge/public/compliance/unshare.ts +4 -6
  374. package/src/server/serverFns/knowledge/public/compliance/update.ts +5 -7
  375. package/src/server/serverFns/knowledge/public/dictionary/create.ts +4 -6
  376. package/src/server/serverFns/knowledge/public/dictionary/delete.ts +5 -7
  377. package/src/server/serverFns/knowledge/public/dictionary/detail.ts +4 -6
  378. package/src/server/serverFns/knowledge/public/dictionary/list.ts +4 -6
  379. package/src/server/serverFns/knowledge/public/dictionary/share.ts +4 -6
  380. package/src/server/serverFns/knowledge/public/dictionary/unshare.ts +4 -6
  381. package/src/server/serverFns/knowledge/public/dictionary/update.ts +5 -7
  382. package/src/server/serverFns/knowledge/public/entity-tags.ts +4 -6
  383. package/src/server/serverFns/knowledge/public/favorite.ts +7 -10
  384. package/src/server/serverFns/knowledge/public/legal/create.ts +4 -6
  385. package/src/server/serverFns/knowledge/public/legal/delete.ts +5 -7
  386. package/src/server/serverFns/knowledge/public/legal/detail.ts +4 -6
  387. package/src/server/serverFns/knowledge/public/legal/list.ts +4 -6
  388. package/src/server/serverFns/knowledge/public/legal/share.ts +4 -6
  389. package/src/server/serverFns/knowledge/public/legal/unshare.ts +4 -6
  390. package/src/server/serverFns/knowledge/public/legal/update.ts +5 -7
  391. package/src/server/serverFns/knowledge-index.ts +12 -16
  392. package/src/server/serverFns/knowledge.ts +50 -67
  393. package/src/server/serverFns/notifications.ts +25 -34
  394. package/src/server/serverFns/plugins/harness-plugins.ts +16 -23
  395. package/src/server/serverFns/project/module-overview.ts +7 -10
  396. package/src/server/serverFns/project.ts +48 -68
  397. package/src/server/serverFns/references/create.ts +4 -6
  398. package/src/server/serverFns/references/resolve.ts +4 -6
  399. package/src/server/serverFns/references/search.ts +4 -6
  400. package/src/server/serverFns/share/design/[designId]/events.ts +4 -6
  401. package/src/server/serverFns/sso.ts +1 -1
  402. package/src/server/serverFns/story/__tests__/bulk.test.ts +34 -1
  403. package/src/server/serverFns/story/__tests__/story-assoc.test.ts +34 -1
  404. package/src/server/serverFns/story/__tests__/story-attachments.test.ts +34 -1
  405. package/src/server/serverFns/story/__tests__/story-crud-date-key.test.ts +42 -17
  406. package/src/server/serverFns/story/__tests__/story-dependencies.test.ts +34 -1
  407. package/src/server/serverFns/story/__tests__/story-gantt-deps.test.ts +34 -1
  408. package/src/server/serverFns/story/__tests__/story-groups.test.ts +34 -1
  409. package/src/server/serverFns/story/__tests__/story-read-path-authz.test.ts +40 -4
  410. package/src/server/serverFns/story/__tests__/story-search.test.ts +34 -1
  411. package/src/server/serverFns/story/__tests__/story-transfer.test.ts +34 -1
  412. package/src/server/serverFns/story/link-preview.ts +5 -7
  413. package/src/server/serverFns/story/story-assoc.ts +28 -38
  414. package/src/server/serverFns/story/story-attachments.ts +7 -10
  415. package/src/server/serverFns/story/story-children.ts +4 -6
  416. package/src/server/serverFns/story/story-comments.ts +13 -18
  417. package/src/server/serverFns/story/story-crud/activities.ts +4 -6
  418. package/src/server/serverFns/story/story-crud/archive.ts +7 -10
  419. package/src/server/serverFns/story/story-crud/bulk.ts +10 -14
  420. package/src/server/serverFns/story/story-crud/detail.ts +7 -10
  421. package/src/server/serverFns/story/story-crud/label-suggest.ts +4 -6
  422. package/src/server/serverFns/story/story-crud/labels.ts +6 -9
  423. package/src/server/serverFns/story/story-crud/user-brief.ts +4 -6
  424. package/src/server/serverFns/story/story-crud.ts +13 -18
  425. package/src/server/serverFns/story/story-dependencies.ts +16 -22
  426. package/src/server/serverFns/story/story-groups.ts +10 -14
  427. package/src/server/serverFns/story/story-links.ts +13 -18
  428. package/src/server/serverFns/story/story-reactions.ts +13 -18
  429. package/src/server/serverFns/story/story-search.ts +7 -10
  430. package/src/server/serverFns/story/story-transfer.ts +10 -14
  431. package/src/server/serverFns/story/story-tree.ts +7 -10
  432. package/src/server/serverFns/story-display-options.ts +7 -8
  433. package/src/server/serverFns/story-view.ts +12 -18
  434. package/src/server/serverFns/tasks/task-crud.ts +13 -17
  435. package/src/server/serverFns/tasks/task-queries.ts +12 -18
  436. package/src/server/serverFns/team.ts +46 -66
  437. package/src/server/serverFns/testcase/__tests__/automation.test.ts +38 -5
  438. package/src/server/serverFns/testcase/__tests__/evidence-upload.test.ts +37 -3
  439. package/src/server/serverFns/testcase/__tests__/generation.test.ts +38 -5
  440. package/src/server/serverFns/testcase/__tests__/plans.test.ts +36 -3
  441. package/src/server/serverFns/testcase/__tests__/regression.test.ts +36 -3
  442. package/src/server/serverFns/testcase/__tests__/run-cases.test.ts +36 -3
  443. package/src/server/serverFns/testcase/__tests__/runs.test.ts +36 -3
  444. package/src/server/serverFns/testcase/__tests__/stats.test.ts +36 -3
  445. package/src/server/serverFns/testcase/__tests__/testcase-board.test.ts +39 -5
  446. package/src/server/serverFns/testcase/__tests__/testcase-crud.test.ts +36 -3
  447. package/src/server/serverFns/testcase/__tests__/testcase-folders.test.ts +36 -3
  448. package/src/server/serverFns/testcase/__tests__/testcase-groups.test.ts +38 -5
  449. package/src/server/serverFns/testcase/automation.ts +13 -17
  450. package/src/server/serverFns/testcase/bulk.ts +10 -14
  451. package/src/server/serverFns/testcase/evidence-upload.ts +5 -7
  452. package/src/server/serverFns/testcase/generation.ts +10 -13
  453. package/src/server/serverFns/testcase/plans.ts +23 -31
  454. package/src/server/serverFns/testcase/regression.ts +7 -10
  455. package/src/server/serverFns/testcase/run-cases.ts +13 -18
  456. package/src/server/serverFns/testcase/runs.ts +13 -18
  457. package/src/server/serverFns/testcase/stats.ts +13 -18
  458. package/src/server/serverFns/testcase/testcase-activities.ts +4 -6
  459. package/src/server/serverFns/testcase/testcase-board.ts +4 -6
  460. package/src/server/serverFns/testcase/testcase-crud.ts +20 -27
  461. package/src/server/serverFns/testcase/testcase-display-options.ts +8 -11
  462. package/src/server/serverFns/testcase/testcase-export.ts +5 -7
  463. package/src/server/serverFns/testcase/testcase-filter-views.ts +12 -18
  464. package/src/server/serverFns/testcase/testcase-folders.ts +16 -22
  465. package/src/server/serverFns/testcase/testcase-groups.ts +4 -6
  466. package/src/server/serverFns/testcase/testcase-reorder.ts +4 -6
  467. package/src/server/serverFns/translation.ts +4 -6
  468. package/src/server/serverFns/user/avatar.ts +4 -6
  469. package/src/server/serverFns/user/settings.ts +4 -6
  470. package/src/server/serverFns/user/update-locale.ts +4 -6
  471. package/src/server/serverFns/workspace-kb.ts +26 -35
  472. package/src/server/serverFns/workspace.ts +43 -59
  473. package/src/server/serverFns/ws.ts +4 -6
  474. package/src/server/serverfn-public-allowlist.ts +117 -0
  475. package/src/server/story/types.ts +0 -1
  476. package/src/server/sync/__tests__/scopes.test.ts +64 -0
  477. package/src/server/sync/scopes.ts +7 -0
  478. package/src/server/testcase/__tests__/auto-bug.test.ts +44 -12
  479. package/src/__tests__/bench/baselines/format-timestamp.json +0 -44
  480. package/src/__typeprobe__.d.ts +0 -4
  481. package/src/components/forms/app-form-dialog.tsx +0 -126
  482. package/src/components/forms/hooks/use-form-submit.ts +0 -57
  483. package/src/components/forms/types.ts +0 -34
  484. package/src/components/harness/code/workspace-picker.tsx +0 -239
  485. package/src/components/tiptap/extensions/local-file/insert-local-file.ts +0 -35
  486. package/src/components/tiptap/extensions/local-file/local-file-node.ts +0 -71
  487. package/src/devframe-docks/ai-chat-iframe.tsx +0 -29
  488. package/src/devframe-docks/session-iframe.tsx +0 -90
  489. package/src/lib/__tests__/desktop-detect.test.ts +0 -19
  490. package/src/lib/collections/index.ts +0 -22
  491. package/src/lib/collections/knowledge/index.ts +0 -18
  492. package/src/lib/collections/knowledge/knowledge-bases-collection.ts +0 -34
  493. package/src/lib/collections/reference/bookmark-categories-collection.ts +0 -31
  494. package/src/lib/collections/reference/labels-collection.ts +0 -31
  495. package/src/lib/collections/reference/projects-collection.ts +0 -31
  496. package/src/lib/collections/reference/users-brief-collection.ts +0 -35
  497. package/src/lib/collections/reference/workspaces-collection.ts +0 -34
  498. package/src/lib/desktop-detect.ts +0 -29
  499. package/src/paraglide/messages/en.js +0 -28260
  500. package/src/paraglide/messages/zh.js +0 -28258
@@ -17,11 +17,11 @@
17
17
 
18
18
  import { getPrisma } from "@allbluecn/database/get-prisma"
19
19
  import { createServerFn } from "@tanstack/react-start"
20
+ import { authContextMiddleware } from "@/server/middlewares/auth-context"
20
21
  import { getRequest } from "@tanstack/react-start/server"
21
22
  import { z } from "zod"
22
23
  import { requireFeature } from "@/server/entitlements"
23
24
  import { requireResource } from "@/server/resources"
24
- import { requireUserId } from "@/server/auth-helpers"
25
25
  import { SKILL_NAME_CONFLICT_CODE } from "@/lib/agents/skill-errors"
26
26
 
27
27
  const NAME_REGEX = /^[a-z0-9-]+$/
@@ -64,10 +64,10 @@ const SKILL_DTO_SELECT = {
64
64
  updatedAt: true,
65
65
  } as const
66
66
 
67
- export const listSkillsFn = createServerFn({ method: "GET" }).handler(async () => {
67
+ export const listSkillsFn = createServerFn({ method: "GET" })
68
+ .middleware([authContextMiddleware]).handler(async ({ context }) => {
68
69
  const prisma = await getPrisma()
69
- const request = getRequest()
70
- const userId = await requireUserId(request)
70
+ const userId = context.user.id
71
71
 
72
72
  const skills = await prisma.userSkill.findMany({
73
73
  where: { userId, isDeleted: false },
@@ -79,11 +79,12 @@ export const listSkillsFn = createServerFn({ method: "GET" }).handler(async () =
79
79
  })
80
80
 
81
81
  export const createSkillFn = createServerFn({ method: "POST" })
82
+ .middleware([authContextMiddleware])
82
83
  .validator(skillInputSchema)
83
- .handler(async ({ data }) => {
84
+ .handler(async ({ data, context }) => {
84
85
  const prisma = await getPrisma()
85
86
  const request = getRequest()
86
- const userId = await requireUserId(request)
87
+ const userId = context.user.id
87
88
 
88
89
  await requireFeature(request, "customAgents")
89
90
  await requireResource(request, "skillQuota", 1)
@@ -112,11 +113,11 @@ export const createSkillFn = createServerFn({ method: "POST" })
112
113
  const getSkillSchema = z.object({ id: z.string() })
113
114
 
114
115
  export const getSkillFn = createServerFn({ method: "GET" })
116
+ .middleware([authContextMiddleware])
115
117
  .validator(getSkillSchema)
116
- .handler(async ({ data }) => {
118
+ .handler(async ({ data, context }) => {
117
119
  const prisma = await getPrisma()
118
- const request = getRequest()
119
- const userId = await requireUserId(request)
120
+ const userId = context.user.id
120
121
 
121
122
  const skill = await prisma.userSkill.findFirst({
122
123
  where: { id: data.id, userId, isDeleted: false },
@@ -149,11 +150,11 @@ function buildSkillUpdatePayload(input: SkillUpdateInput): Record<string, unknow
149
150
  }
150
151
 
151
152
  export const updateSkillFn = createServerFn({ method: "POST" })
153
+ .middleware([authContextMiddleware])
152
154
  .validator(skillUpdateSchema)
153
- .handler(async ({ data }) => {
155
+ .handler(async ({ data, context }) => {
154
156
  const prisma = await getPrisma()
155
- const request = getRequest()
156
- const userId = await requireUserId(request)
157
+ const userId = context.user.id
157
158
 
158
159
  // DB-03:属主校验合并进写入(updateMany 计数判定),1 次查询替代 2 次
159
160
  const update = buildSkillUpdatePayload(data)
@@ -171,11 +172,11 @@ export const updateSkillFn = createServerFn({ method: "POST" })
171
172
  const deleteSkillSchema = z.object({ id: z.string() })
172
173
 
173
174
  export const deleteSkillFn = createServerFn({ method: "POST" })
175
+ .middleware([authContextMiddleware])
174
176
  .validator(deleteSkillSchema)
175
- .handler(async ({ data }) => {
177
+ .handler(async ({ data, context }) => {
176
178
  const prisma = await getPrisma()
177
- const request = getRequest()
178
- const userId = await requireUserId(request)
179
+ const userId = context.user.id
179
180
 
180
181
  // DB-03:属主校验合并进写入(updateMany 计数判定)
181
182
  const res = await prisma.userSkill.updateMany({
@@ -16,14 +16,13 @@
16
16
  // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
 
18
18
  import { createServerFn } from "@tanstack/react-start"
19
- import { getRequest } from "@tanstack/react-start/server"
19
+ import { authContextMiddleware } from "@/server/middlewares/auth-context"
20
20
  import { getCodeModeReadiness } from "@/server/ai-gateway/code-mode"
21
- import { requireUserId } from "@/server/auth-helpers"
22
21
 
23
22
  // 仅面向已登录的 harness 工作台(useCodeModeReadiness 消费方),非公开端点
24
- export const getCodeModeReadinessFn = createServerFn({ method: "GET" }).handler(
23
+ export const getCodeModeReadinessFn = createServerFn({ method: "GET" })
24
+ .middleware([authContextMiddleware]).handler(
25
25
  async () => {
26
- await requireUserId(getRequest())
27
26
  return getCodeModeReadiness()
28
27
  },
29
28
  )
@@ -16,14 +16,13 @@
16
16
  // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
 
18
18
  import { createServerFn } from "@tanstack/react-start"
19
- import { getRequest } from "@tanstack/react-start/server"
19
+ import { authContextMiddleware } from "@/server/middlewares/auth-context"
20
20
  import { isSearxngEnabled } from "@/server/web-search"
21
- import { requireUserId } from "@/server/auth-helpers"
22
21
 
23
22
  // 仅面向已登录的 harness 对话 UI(useSearchCapability 消费方),非公开端点
24
- export const getSearchCapabilityFn = createServerFn({ method: "GET" }).handler(
23
+ export const getSearchCapabilityFn = createServerFn({ method: "GET" })
24
+ .middleware([authContextMiddleware]).handler(
25
25
  async () => {
26
- await requireUserId(getRequest())
27
26
  return { searxngEnabled: isSearxngEnabled() }
28
27
  },
29
28
  )
@@ -17,9 +17,8 @@
17
17
 
18
18
  import { getPrisma } from "@allbluecn/database/get-prisma"
19
19
  import { createServerFn } from '@tanstack/react-start'
20
- import { getRequest } from '@tanstack/react-start/server'
20
+ import { authContextMiddleware } from '@/server/middlewares/auth-context'
21
21
  import { z } from 'zod'
22
- import { requireAuth } from '@/server/auth-helpers'
23
22
 
24
23
  // DB-05:白名单 select(与 index.ts listAnyHubAppsFn 同一口径,防未来新增敏感列外泄)
25
24
  const ANY_HUB_APP_SELECT = {
@@ -42,13 +41,12 @@ const ANY_HUB_APP_SELECT = {
42
41
  } as const
43
42
 
44
43
  export const getAnyHubAppFn = createServerFn({ method: 'GET' })
44
+ .middleware([authContextMiddleware])
45
45
  .validator(z.object({ id: z.string() }))
46
- .handler(async ({ data }) => {
46
+ .handler(async ({ data, context }) => {
47
47
  const prisma = await getPrisma()
48
- const request = getRequest()
49
- const session = await requireAuth(request)
50
48
  const app = await prisma.anyHubApp.findFirst({
51
- where: { id: data.id, userId: session.user.id },
49
+ where: { id: data.id, userId: context.user.id },
52
50
  select: ANY_HUB_APP_SELECT,
53
51
  })
54
52
  if (!app) throw new Error('应用不存在')
@@ -56,14 +54,13 @@ export const getAnyHubAppFn = createServerFn({ method: 'GET' })
56
54
  })
57
55
 
58
56
  export const updateAnyHubAppFn = createServerFn({ method: 'POST' })
57
+ .middleware([authContextMiddleware])
59
58
  .validator(z.object({ id: z.string() }))
60
- .handler(async ({ data }) => {
59
+ .handler(async ({ data, context }) => {
61
60
  const prisma = await getPrisma()
62
- const request = getRequest()
63
- const session = await requireAuth(request)
64
61
  // DB-03:属主校验合并进写入(updateMany 计数判定);version 由安装流程维护,此处不再回写原值
65
62
  const res = await prisma.anyHubApp.updateMany({
66
- where: { id: data.id, userId: session.user.id },
63
+ where: { id: data.id, userId: context.user.id },
67
64
  data: {
68
65
  status: 'updating',
69
66
  updatedAt: new Date(),
@@ -74,14 +71,13 @@ export const updateAnyHubAppFn = createServerFn({ method: 'POST' })
74
71
  })
75
72
 
76
73
  export const deleteAnyHubAppFn = createServerFn({ method: 'POST' })
74
+ .middleware([authContextMiddleware])
77
75
  .validator(z.object({ id: z.string() }))
78
- .handler(async ({ data }) => {
76
+ .handler(async ({ data, context }) => {
79
77
  const prisma = await getPrisma()
80
- const request = getRequest()
81
- const session = await requireAuth(request)
82
78
  // DB-03:属主校验合并进删除(deleteMany 计数判定)
83
79
  const res = await prisma.anyHubApp.deleteMany({
84
- where: { id: data.id, userId: session.user.id },
80
+ where: { id: data.id, userId: context.user.id },
85
81
  })
86
82
  if (res.count === 0) throw new Error('应用不存在')
87
83
  return { success: true }
@@ -18,9 +18,8 @@
18
18
  import { getPrisma } from "@allbluecn/database/get-prisma"
19
19
  import type { Prisma } from "@allbluecn/database"
20
20
  import { createServerFn } from '@tanstack/react-start'
21
- import { getRequest } from '@tanstack/react-start/server'
21
+ import { authContextMiddleware } from '@/server/middlewares/auth-context'
22
22
  import { z } from 'zod'
23
- import { requireAuth } from '@/server/auth-helpers'
24
23
 
25
24
  // DB-05:白名单 select(消费方 AnyHubAppData 覆盖全部标量列,防未来新增敏感列外泄)
26
25
  const ANY_HUB_APP_SELECT = {
@@ -43,13 +42,12 @@ const ANY_HUB_APP_SELECT = {
43
42
  } as const
44
43
 
45
44
  export const listAnyHubAppsFn = createServerFn({ method: 'GET' })
46
- .handler(async () => {
45
+ .middleware([authContextMiddleware])
46
+ .handler(async ({ context }) => {
47
47
  const prisma = await getPrisma()
48
- const request = getRequest()
49
- const session = await requireAuth(request)
50
48
  // DB-05:白名单 select(消费方 AnyHubAppData 覆盖全部标量列,防未来新增敏感列外泄)
51
49
  return prisma.anyHubApp.findMany({
52
- where: { userId: session.user.id },
50
+ where: { userId: context.user.id },
53
51
  orderBy: { createdAt: 'desc' },
54
52
  select: ANY_HUB_APP_SELECT,
55
53
  })
@@ -91,12 +89,11 @@ export const listMarketplaceAppsFn = createServerFn({ method: 'GET' })
91
89
  })
92
90
 
93
91
  export const togglePinFn = createServerFn({ method: 'POST' })
92
+ .middleware([authContextMiddleware])
94
93
  .validator(z.object({ appId: z.string() }))
95
- .handler(async ({ data }) => {
94
+ .handler(async ({ data, context }) => {
96
95
  const prisma = await getPrisma()
97
- const request = getRequest()
98
- const session = await requireAuth(request)
99
- const userId = session.user.id
96
+ const userId = context.user.id
100
97
  // DB-03:读回 pinned + 条件写收进事务,写路径带 userId 谓词消除 TOCTOU
101
98
  return prisma.$transaction(async (tx) => {
102
99
  const app = await tx.anyHubApp.findFirst({
@@ -17,10 +17,10 @@
17
17
 
18
18
  import { getPrisma } from "@allbluecn/database/get-prisma"
19
19
  import { createServerFn } from '@tanstack/react-start'
20
+ import { authContextMiddleware } from '@/server/middlewares/auth-context'
20
21
  import { getRequest } from '@tanstack/react-start/server'
21
22
  import { z } from 'zod'
22
23
  import path from 'node:path'
23
- import { requireAuth } from '@/server/auth-helpers'
24
24
  import { requireResource } from '@/server/resources'
25
25
  import { isLocalPathAllowed } from '@/lib/anyhub/local-path'
26
26
 
@@ -48,11 +48,11 @@ function assertGithubUrl(githubUrl: string): void {
48
48
  }
49
49
 
50
50
  export const installAnyHubAppFn = createServerFn({ method: 'POST' })
51
+ .middleware([authContextMiddleware])
51
52
  .validator(installSchema)
52
- .handler(async ({ data }) => {
53
+ .handler(async ({ data, context }) => {
53
54
  const prisma = await getPrisma()
54
55
  const request = getRequest()
55
- const session = await requireAuth(request)
56
56
  // S6:安装按尝试计(含 installing/failed),超档拒绝(裁决:三档 200/1000/5000)
57
57
  await requireResource(request, 'installQuota', 1)
58
58
 
@@ -81,7 +81,7 @@ export const installAnyHubAppFn = createServerFn({ method: 'POST' })
81
81
  marketplaceAppId: data.source === 'marketplace' ? data.marketplaceAppId : undefined,
82
82
  githubUrl: data.source === 'github' ? data.githubUrl : undefined,
83
83
  localPath: resolvedLocalPath,
84
- userId: session.user.id,
84
+ userId: context.user.id,
85
85
  status: 'installing',
86
86
  },
87
87
  })
@@ -16,18 +16,16 @@
16
16
  // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
 
18
18
  import { createServerFn } from '@tanstack/react-start'
19
- import { getRequest } from '@tanstack/react-start/server'
19
+ import { authContextMiddleware } from '@/server/middlewares/auth-context'
20
20
  import { z } from 'zod'
21
- import { requireAuth } from '@/server/auth-helpers'
22
21
  import { getAppPermissions, grantPermission, checkPermission } from '@/lib/anyhub/permissions'
23
22
  import { ALL_CAPABILITIES } from '@/lib/anyhub/capabilities'
24
23
 
25
24
  export const getAnyHubPermissionsFn = createServerFn({ method: 'GET' })
25
+ .middleware([authContextMiddleware])
26
26
  .validator(z.object({ id: z.string() }))
27
- .handler(async ({ data }) => {
28
- const request = getRequest()
29
- const session = await requireAuth(request)
30
- return getAppPermissions(data.id, session.user.id)
27
+ .handler(async ({ data, context }) => {
28
+ return getAppPermissions(data.id, context.user.id)
31
29
  })
32
30
 
33
31
  const updatePermissionSchema = z.object({
@@ -38,11 +36,10 @@ const updatePermissionSchema = z.object({
38
36
  })
39
37
 
40
38
  export const updateAnyHubPermissionFn = createServerFn({ method: 'POST' })
39
+ .middleware([authContextMiddleware])
41
40
  .validator(updatePermissionSchema)
42
- .handler(async ({ data }) => {
43
- const request = getRequest()
44
- const session = await requireAuth(request)
45
- await grantPermission(data.id, data.capability, session.user.id, data.granted)
41
+ .handler(async ({ data, context }) => {
42
+ await grantPermission(data.id, data.capability, context.user.id, data.granted)
46
43
  return { success: true }
47
44
  })
48
45
 
@@ -58,9 +55,8 @@ const checkPermissionSchema = z.object({
58
55
  * userId 以 session 为准,不信任客户端传入值。
59
56
  */
60
57
  export const checkAnyHubPermissionFn = createServerFn({ method: 'POST' })
58
+ .middleware([authContextMiddleware])
61
59
  .validator(checkPermissionSchema)
62
- .handler(async ({ data }) => {
63
- const request = getRequest()
64
- const session = await requireAuth(request)
65
- return checkPermission(data.appId, data.method, session.user.id)
60
+ .handler(async ({ data, context }) => {
61
+ return checkPermission(data.appId, data.method, context.user.id)
66
62
  })
@@ -17,9 +17,8 @@
17
17
 
18
18
  import { getPrisma } from "@allbluecn/database/get-prisma"
19
19
  import { createServerFn } from '@tanstack/react-start'
20
- import { getRequest } from '@tanstack/react-start/server'
20
+ import { authContextMiddleware } from '@/server/middlewares/auth-context'
21
21
  import { z } from 'zod'
22
- import { requireAuth } from '@/server/auth-helpers'
23
22
  import { ProxyAdapter } from '@/lib/anyhub/proxy'
24
23
  import { isLocalPathAllowed } from '@/lib/anyhub/local-path'
25
24
 
@@ -29,13 +28,12 @@ const serveFileSchema = z.object({
29
28
  })
30
29
 
31
30
  export const serveAnyHubFileFn = createServerFn({ method: 'POST' })
31
+ .middleware([authContextMiddleware])
32
32
  .validator(serveFileSchema)
33
- .handler(async ({ data }) => {
33
+ .handler(async ({ data, context }) => {
34
34
  const prisma = await getPrisma()
35
- const request = getRequest()
36
- const session = await requireAuth(request)
37
35
  const app = await prisma.anyHubApp.findFirst({
38
- where: { id: data.appId, userId: session.user.id },
36
+ where: { id: data.appId, userId: context.user.id },
39
37
  select: { localPath: true },
40
38
  })
41
39
  if (!app) throw new Error('应用不存在')
@@ -20,6 +20,7 @@ import { createServerFn } from '@tanstack/react-start'
20
20
  import { getRequest } from '@tanstack/react-start/server'
21
21
  import { z } from 'zod'
22
22
  import { getCurrentSession } from '@/lib/session'
23
+ import { authContextMiddleware } from '@/server/middlewares/auth-context'
23
24
  import { checkAuthRateLimit } from '@/server/middlewares/rate-limit'
24
25
  import { sendTemplateEmail, generateEmailToken } from '@/server/email'
25
26
 
@@ -78,13 +79,11 @@ export const confirmEmailVerificationFn = createServerFn({ method: 'GET' })
78
79
  })
79
80
 
80
81
  export const resendVerificationEmailFn = createServerFn({ method: 'POST' })
82
+ .middleware([authContextMiddleware])
81
83
  .validator(z.object({}))
82
- .handler(async () => {
84
+ .handler(async ({ context }) => {
83
85
  const prisma = await getPrisma()
84
- const request = getRequest()
85
- const session = await getCurrentSession(request)
86
- const userId = session?.user?.id
87
- if (!userId) throw new Error('请先登录')
86
+ const userId = context.user.id
88
87
 
89
88
  await checkAuthRateLimit('resendVerify', 5, 15 * 60 * 1000)
90
89
 
@@ -23,6 +23,7 @@ import type { FeatureKey } from '@allbluecn/kernel'
23
23
  import type { Session } from '@/lib/session'
24
24
  import { getCurrentSession } from '@/lib/session'
25
25
  import { buildGuestSession, isDesktopServer } from '@/server/desktop-guest'
26
+ import { ensureLocalShadowUser } from '@/server/desktop-bootstrap'
26
27
  import { readRemoteAuth, writeRemoteAuth, writeRemoteSession, clearRemoteAuth } from '@/server/remote-auth'
27
28
  import { generateEntitlementsToken } from '@/server/entitlements-token'
28
29
  import type { RemoteAuthData } from '@/server/remote-auth'
@@ -76,6 +77,14 @@ export const getSessionFn = createServerFn({ method: 'GET' })
76
77
  if (!isDesktopServer()) return null
77
78
  const remoteAuth = await readRemoteAuth()
78
79
  if (remoteAuth) return buildRemoteSession(remoteAuth)
80
+ // 桌面 guest 分支懒 seed 影子用户(本地优先 P1):首启为 local-guest 落库,
81
+ // 使 assertOwned/requireUserInDb/FK 全链可写。失败仅 warn 不阻断会话发放
82
+ // ——首启体验优先(规格 §3.1),下一请求再重试。
83
+ try {
84
+ await ensureLocalShadowUser()
85
+ } catch (err) {
86
+ console.warn('[getSessionFn] 本地影子用户落库失败(不阻断 guest 会话):', err)
87
+ }
79
88
  return buildGuestSession()
80
89
  })
81
90
 
@@ -20,7 +20,7 @@ import { createServerFn } from '@tanstack/react-start'
20
20
  import { getRequest } from '@tanstack/react-start/server'
21
21
  import { z } from 'zod'
22
22
  import { getProService } from '@/server/pro-services'
23
- import { requireAuth } from '@/server/auth-helpers'
23
+ import { authContextMiddleware } from '@/server/middlewares/auth-context'
24
24
  import { BillingUnavailableError } from '@allbluecn/kernel'
25
25
  import { getEntitlements } from '@/server/entitlements'
26
26
  import { getResourceSnapshots } from '@/server/resources'
@@ -31,9 +31,8 @@ const requireBilling = () => {
31
31
  return billing
32
32
  }
33
33
 
34
- export const getEffectivePlanFn = createServerFn({ method: 'GET' }).handler(async () => {
34
+ export const getEffectivePlanFn = createServerFn({ method: 'GET' }).middleware([authContextMiddleware]).handler(async () => {
35
35
  const request = getRequest()
36
- const session = await requireAuth(request)
37
36
 
38
37
  const { planName, enabled, unavailable, source } = await getEntitlements(request)
39
38
  const resources = await getResourceSnapshots(request)
@@ -47,10 +46,8 @@ export const getEffectivePlanFn = createServerFn({ method: 'GET' }).handler(asyn
47
46
  }
48
47
  })
49
48
 
50
- export const getSubscriptionFn = createServerFn({ method: 'GET' }).handler(async () => {
51
- const request = getRequest()
52
- const session = await requireAuth(request)
53
- const userId = session.user.id
49
+ export const getSubscriptionFn = createServerFn({ method: 'GET' }).middleware([authContextMiddleware]).handler(async ({ context }) => {
50
+ const userId = context.user.id
54
51
  return requireBilling().getSubscription(userId)
55
52
  })
56
53
 
@@ -63,16 +60,15 @@ export const listPublicPlansFn = createServerFn({ method: 'GET' })
63
60
  })
64
61
 
65
62
  export const createCheckoutSessionFn = createServerFn({ method: 'POST' })
63
+ .middleware([authContextMiddleware])
66
64
  .validator(
67
65
  z.object({
68
66
  planId: z.string(),
69
67
  currency: z.enum(['usd', 'cny']),
70
68
  }),
71
69
  )
72
- .handler(async ({ data }) => {
73
- const request = getRequest()
74
- const session = await requireAuth(request)
75
- const userId = session.user.id
70
+ .handler(async ({ data, context }) => {
71
+ const userId = context.user.id
76
72
 
77
73
  const baseUrl = process.env.VITE_APP_URL ?? 'http://localhost:3000'
78
74
  return requireBilling().createCheckoutSession({
@@ -85,11 +81,9 @@ export const createCheckoutSessionFn = createServerFn({ method: 'POST' })
85
81
  })
86
82
  })
87
83
 
88
- export const createCustomerPortalSessionFn = createServerFn({ method: 'POST' }).validator(z.object({})).handler(
89
- async () => {
90
- const request = getRequest()
91
- const session = await requireAuth(request)
92
- const userId = session.user.id
84
+ export const createCustomerPortalSessionFn = createServerFn({ method: 'POST' }).middleware([authContextMiddleware]).validator(z.object({})).handler(
85
+ async ({ context }) => {
86
+ const userId = context.user.id
93
87
 
94
88
  const baseUrl = process.env.VITE_APP_URL ?? 'http://localhost:3000'
95
89
  return requireBilling().createCustomerPortalSession({
@@ -99,20 +93,17 @@ export const createCustomerPortalSessionFn = createServerFn({ method: 'POST' }).
99
93
  },
100
94
  )
101
95
 
102
- export const listInvoicesFn = createServerFn({ method: 'GET' }).handler(async () => {
103
- const request = getRequest()
104
- const session = await requireAuth(request)
105
- const userId = session.user.id
96
+ export const listInvoicesFn = createServerFn({ method: 'GET' }).middleware([authContextMiddleware]).handler(async ({ context }) => {
97
+ const userId = context.user.id
106
98
  return requireBilling().listInvoices(userId, 20)
107
99
  })
108
100
 
109
101
  export const updatePreferredCurrencyFn = createServerFn({ method: 'POST' })
102
+ .middleware([authContextMiddleware])
110
103
  .validator(z.object({ currency: z.enum(['usd', 'cny']) }))
111
- .handler(async ({ data }) => {
104
+ .handler(async ({ data, context }) => {
112
105
  const prisma = await getPrisma()
113
- const request = getRequest()
114
- const session = await requireAuth(request)
115
- const userId = session.user.id
106
+ const userId = context.user.id
116
107
  await prisma.user.update({
117
108
  where: { id: userId },
118
109
  data: { preferredCurrency: data.currency },
@@ -120,17 +111,16 @@ export const updatePreferredCurrencyFn = createServerFn({ method: 'POST' })
120
111
  })
121
112
 
122
113
  export const updateSeatsFn = createServerFn({ method: 'POST' })
114
+ .middleware([authContextMiddleware])
123
115
  .validator(
124
116
  z.object({
125
117
  addonSeats: z.number().int().min(0).max(100),
126
118
  successUrl: z.string().url().optional(),
127
119
  }),
128
120
  )
129
- .handler(async ({ data }) => {
121
+ .handler(async ({ data, context }) => {
130
122
  const prisma = await getPrisma()
131
- const request = getRequest()
132
- const session = await requireAuth(request)
133
- const userId = session.user.id
123
+ const userId = context.user.id
134
124
  const baseUrl = process.env.VITE_APP_URL ?? 'http://localhost:3000'
135
125
 
136
126
  const subscription = await prisma.subscription.findUnique({
@@ -16,9 +16,8 @@
16
16
  // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
 
18
18
  import { createServerFn } from "@tanstack/react-start"
19
- import { getRequest } from "@tanstack/react-start/server"
20
19
  import { z } from "zod"
21
- import { requireAuth } from "@/server/auth-helpers"
20
+ import { authContextMiddleware } from '@/server/middlewares/auth-context'
22
21
  import { getPorts } from "@/server/ai-gateway/runtime"
23
22
 
24
23
  // 与 attachment-policy.ts 的 SUPPORTED_MIME_TYPES 对齐(服务端独立 fail-closed 白名单)。
@@ -48,14 +47,12 @@ const UploadBlobSchema = z.object({
48
47
  * 客户端不接触 BlobStore 实现,不 import @allbluecn/database。
49
48
  */
50
49
  export const uploadBlobFn = createServerFn({ method: "POST" })
50
+ .middleware([authContextMiddleware])
51
51
  .validator(UploadBlobSchema)
52
- .handler(async ({ data }) => {
53
- const request = getRequest()
54
- const session = await requireAuth(request)
55
- if (!session?.user?.id) {
56
- return { error: "Unauthorized" as const }
57
- }
58
- const userId = session.user.id
52
+ .handler(async ({ data, context }) => {
53
+ // 原 requireAuth 后的 !session?.user?.id 软分支不可达(requireAuth 已抛),
54
+ // 迁移后由 middleware 统一抛 UnauthorizedError,死分支一并移除
55
+ const userId = context.user.id
59
56
 
60
57
  if (!BLOB_MIME_TYPES.has(data.mimeType)) {
61
58
  return { error: "UnsupportedMimeType" as const }
@@ -25,6 +25,11 @@ vi.mock("@tanstack/react-start", () => ({
25
25
  createServerFn: (config: any) => {
26
26
  const api: any = {
27
27
  _validator: undefined,
28
+ _middlewares: [] as any[],
29
+ middleware(mws: any[]) {
30
+ this._middlewares.push(...mws);
31
+ return this;
32
+ },
28
33
  validator(schema: any) {
29
34
  this._validator = schema;
30
35
  return this;
@@ -35,13 +40,41 @@ vi.mock("@tanstack/react-start", () => ({
35
40
  if (this._validator && data !== undefined) {
36
41
  data = this._validator.parse ? this._validator.parse(data) : data;
37
42
  }
38
- return fn({ data });
43
+ // 迁移后经 .middleware([authContextMiddleware]) 注入 context.user:
44
+ // mock 依序执行 middleware 的 server 段(复现框架 executeMiddleware 的
45
+ // context 合并语义),真实鉴权链由被 mock 的 auth-helpers/getRequest 承接
46
+ let context: any = {};
47
+ for (const mw of this._middlewares) {
48
+ const serverFn = mw?.options?.server;
49
+ if (!serverFn) continue;
50
+ const result = await serverFn({
51
+ data,
52
+ context,
53
+ method: 'POST',
54
+ serverFnMeta: {},
55
+ signal: new AbortController().signal,
56
+ next: async (inner: any) => ({ context: { ...context, ...(inner?.context ?? {}) } }),
57
+ });
58
+ context = result.context;
59
+ }
60
+ return fn({ data, context });
39
61
  };
40
62
  return wrapped;
41
63
  },
42
64
  };
43
65
  return api;
44
66
  },
67
+ // auth-context.ts 依赖 createMiddleware({ type: 'function' }).server(fn):
68
+ // mock 产出与真实 middleware 同构的 { options: { server } } 形状,
69
+ // 供上方 handler 包装器执行 server 段注入 context.user
70
+ createMiddleware: (opts: any) => {
71
+ const mw: any = { options: { type: opts?.type } };
72
+ mw.server = (fn: Function) => {
73
+ mw.options.server = fn;
74
+ return mw;
75
+ };
76
+ return mw;
77
+ },
45
78
  }));
46
79
 
47
80
  vi.mock("@tanstack/react-start/server", () => ({
@@ -24,6 +24,11 @@ vi.mock("@tanstack/react-start", () => ({
24
24
  createServerFn: (config: any) => {
25
25
  const api: any = {
26
26
  _validator: undefined,
27
+ _middlewares: [] as any[],
28
+ middleware(mws: any[]) {
29
+ this._middlewares.push(...mws);
30
+ return this;
31
+ },
27
32
  validator(schema: any) {
28
33
  this._validator = schema;
29
34
  return this;
@@ -34,13 +39,41 @@ vi.mock("@tanstack/react-start", () => ({
34
39
  if (this._validator && data !== undefined) {
35
40
  data = this._validator.parse ? this._validator.parse(data) : data;
36
41
  }
37
- return fn({ data });
42
+ // 迁移后经 .middleware([authContextMiddleware]) 注入 context.user:
43
+ // mock 依序执行 middleware 的 server 段(复现框架 executeMiddleware 的
44
+ // context 合并语义),真实鉴权链由被 mock 的 auth-helpers/getRequest 承接
45
+ let context: any = {};
46
+ for (const mw of this._middlewares) {
47
+ const serverFn = mw?.options?.server;
48
+ if (!serverFn) continue;
49
+ const result = await serverFn({
50
+ data,
51
+ context,
52
+ method: 'POST',
53
+ serverFnMeta: {},
54
+ signal: new AbortController().signal,
55
+ next: async (inner: any) => ({ context: { ...context, ...(inner?.context ?? {}) } }),
56
+ });
57
+ context = result.context;
58
+ }
59
+ return fn({ data, context });
38
60
  };
39
61
  return wrapped;
40
62
  },
41
63
  };
42
64
  return api;
43
65
  },
66
+ // auth-context.ts 依赖 createMiddleware({ type: 'function' }).server(fn):
67
+ // mock 产出与真实 middleware 同构的 { options: { server } } 形状,
68
+ // 供上方 handler 包装器执行 server 段注入 context.user
69
+ createMiddleware: (opts: any) => {
70
+ const mw: any = { options: { type: opts?.type } };
71
+ mw.server = (fn: Function) => {
72
+ mw.options.server = fn;
73
+ return mw;
74
+ };
75
+ return mw;
76
+ },
44
77
  }));
45
78
 
46
79
  vi.mock("@tanstack/react-start/server", () => ({