@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
@@ -18,9 +18,17 @@
18
18
  import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
19
19
 
20
20
  vi.mock("@tanstack/react-start", () => ({
21
+ // 迁移后经 .middleware([authContextMiddleware]) 注入 context.user:
22
+ // mock 依序执行 middleware 的 server 段(复现框架 executeMiddleware 的
23
+ // context 合并语义),真实鉴权链由被 mock 的 auth-helpers/getRequest 承接
21
24
  createServerFn: (config: any) => {
22
25
  const api: any = {
23
26
  _validator: undefined,
27
+ _middlewares: [] as any[],
28
+ middleware(mws: any[]) {
29
+ api._middlewares.push(...mws);
30
+ return api;
31
+ },
24
32
  validator(schema: any) {
25
33
  this._validator = schema;
26
34
  return this;
@@ -28,16 +36,40 @@ vi.mock("@tanstack/react-start", () => ({
28
36
  handler(fn: Function) {
29
37
  const wrapped = async (args: any) => {
30
38
  let data = args?.data;
31
- if (this._validator && data !== undefined) {
32
- data = this._validator.parse ? this._validator.parse(data) : data;
39
+ if (api._validator && data !== undefined) {
40
+ data = api._validator.parse ? api._validator.parse(data) : data;
41
+ }
42
+ let context: any = {};
43
+ for (const mw of api._middlewares) {
44
+ const serverFn = mw?.options?.server;
45
+ if (!serverFn) continue;
46
+ const result = await serverFn({
47
+ data,
48
+ context,
49
+ method: "POST",
50
+ serverFnMeta: {},
51
+ signal: new AbortController().signal,
52
+ next: async (inner: any) => ({ context: { ...context, ...(inner?.context ?? {}) } }),
53
+ });
54
+ context = result.context;
33
55
  }
34
- return fn({ data });
56
+ return fn({ data, context });
35
57
  };
36
58
  return wrapped;
37
59
  },
38
60
  };
39
61
  return api;
40
62
  },
63
+ // auth-context.ts 依赖 createMiddleware({ type: "function" }).server(fn):
64
+ // mock 产出与真实 middleware 同构的 { options: { server } } 形状
65
+ createMiddleware: (opts: any) => {
66
+ const mw: any = { options: { type: opts?.type } };
67
+ mw.server = (fn: Function) => {
68
+ mw.options.server = fn;
69
+ return mw;
70
+ };
71
+ return mw;
72
+ },
41
73
  }));
42
74
 
43
75
  vi.mock("@tanstack/react-start/server", () => ({
@@ -18,9 +18,17 @@
18
18
  import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
19
19
 
20
20
  vi.mock("@tanstack/react-start", () => ({
21
+ // 迁移后经 .middleware([authContextMiddleware]) 注入 context.user:
22
+ // mock 依序执行 middleware 的 server 段(复现框架 executeMiddleware 的
23
+ // context 合并语义),真实鉴权链由被 mock 的 auth-helpers/getRequest 承接
21
24
  createServerFn: (config: any) => {
22
25
  const api: any = {
23
26
  _validator: undefined,
27
+ _middlewares: [] as any[],
28
+ middleware(mws: any[]) {
29
+ api._middlewares.push(...mws);
30
+ return api;
31
+ },
24
32
  validator(schema: any) {
25
33
  this._validator = schema;
26
34
  return this;
@@ -28,16 +36,40 @@ vi.mock("@tanstack/react-start", () => ({
28
36
  handler(fn: Function) {
29
37
  const wrapped = async (args: any) => {
30
38
  let data = args?.data;
31
- if (this._validator && data !== undefined) {
32
- data = this._validator.parse ? this._validator.parse(data) : data;
39
+ if (api._validator && data !== undefined) {
40
+ data = api._validator.parse ? api._validator.parse(data) : data;
41
+ }
42
+ let context: any = {};
43
+ for (const mw of api._middlewares) {
44
+ const serverFn = mw?.options?.server;
45
+ if (!serverFn) continue;
46
+ const result = await serverFn({
47
+ data,
48
+ context,
49
+ method: "POST",
50
+ serverFnMeta: {},
51
+ signal: new AbortController().signal,
52
+ next: async (inner: any) => ({ context: { ...context, ...(inner?.context ?? {}) } }),
53
+ });
54
+ context = result.context;
33
55
  }
34
- return fn({ data });
56
+ return fn({ data, context });
35
57
  };
36
58
  return wrapped;
37
59
  },
38
60
  };
39
61
  return api;
40
62
  },
63
+ // auth-context.ts 依赖 createMiddleware({ type: "function" }).server(fn):
64
+ // mock 产出与真实 middleware 同构的 { options: { server } } 形状
65
+ createMiddleware: (opts: any) => {
66
+ const mw: any = { options: { type: opts?.type } };
67
+ mw.server = (fn: Function) => {
68
+ mw.options.server = fn;
69
+ return mw;
70
+ };
71
+ return mw;
72
+ },
41
73
  }));
42
74
 
43
75
  vi.mock("@tanstack/react-start/server", () => ({
@@ -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 { toDatePart } from "@/lib/iteration/status";
24
23
  import { ensureUpcomingIterations } from "@/server/iteration/auto-schedule-internal";
25
24
  import { assertIterationProjectMembership as assertProjectMembership } from "@/server/iteration/permissions";
@@ -31,12 +30,11 @@ const CONFIG_SELECT = {
31
30
 
32
31
 
33
32
  export const getAutoScheduleFn = createServerFn({ method: "GET" })
33
+ .middleware([authContextMiddleware])
34
34
  .validator(z.object({ projectId: z.string() }))
35
- .handler(async ({ data }) => {
35
+ .handler(async ({ data, context }) => {
36
36
  const prisma = await getPrisma()
37
- const request = getRequest();
38
- const session = await requireAuth(request);
39
- await assertProjectMembership(data.projectId, session.user.id);
37
+ await assertProjectMembership(data.projectId, context.user.id);
40
38
  const [cfg] = await prisma.iterationAutoSchedule.findMany({
41
39
  where: { projectId: data.projectId }, select: CONFIG_SELECT, take: 1,
42
40
  });
@@ -44,6 +42,7 @@ export const getAutoScheduleFn = createServerFn({ method: "GET" })
44
42
  });
45
43
 
46
44
  export const updateAutoScheduleFn = createServerFn({ method: "POST" })
45
+ .middleware([authContextMiddleware])
47
46
  .validator(
48
47
  z.object({
49
48
  projectId: z.string(),
@@ -56,12 +55,10 @@ export const updateAutoScheduleFn = createServerFn({ method: "POST" })
56
55
  autoRollover: z.boolean(),
57
56
  }),
58
57
  )
59
- .handler(async ({ data }) => {
58
+ .handler(async ({ data, context }) => {
60
59
  const prisma = await getPrisma()
61
- const request = getRequest();
62
- const session = await requireAuth(request);
63
60
  // 配置写入会连锁触发排期补建,须为项目有效成员(SEC-03)
64
- await assertProjectMembership(data.projectId, session.user.id);
61
+ await assertProjectMembership(data.projectId, context.user.id);
65
62
  await prisma.iterationAutoSchedule.upsert({
66
63
  where: { projectId: data.projectId },
67
64
  create: { ...data, startsOn: new Date(data.startsOn + "T00:00:00.000Z") },
@@ -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 { assertIterationProjectMember } from "@/server/iteration/permissions";
24
23
  import { toDatePart } from "@/lib/iteration/status";
25
24
  import { computeBurndown } from "@/lib/iteration/burndown";
@@ -29,12 +28,11 @@ const ACTIVITY_STORY_SELECT = {
29
28
  } as const;
30
29
 
31
30
  export const getIterationBurndownFn = createServerFn({ method: "GET" })
31
+ .middleware([authContextMiddleware])
32
32
  .validator(z.object({ iterationId: z.string() }))
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
- await assertIterationProjectMember(data.iterationId, session.user.id);
35
+ await assertIterationProjectMember(data.iterationId, context.user.id);
38
36
  const iteration = await prisma.iteration.findUnique({
39
37
  where: { id: data.iterationId },
40
38
  select: { startDate: true, endDate: true, project: { select: { timezone: true } } },
@@ -18,8 +18,7 @@
18
18
  import { getPrisma } from "@allbluecn/database/get-prisma"
19
19
  import { z } from "zod";
20
20
  import { createServerFn } from "@tanstack/react-start";
21
- import { getRequest } from "@tanstack/react-start/server";
22
- import { requireAuth } from "@/server/auth-helpers";
21
+ import { authContextMiddleware } from "@/server/middlewares/auth-context"
23
22
  import { deriveIterationStatus, isDateRangeOverlapping, toDatePart } from "@/lib/iteration/status";
24
23
  import {
25
24
  listIterationsSchema,
@@ -77,14 +76,13 @@ function toSummary(
77
76
  }
78
77
 
79
78
  export const listIterationsFn = createServerFn({ method: "GET" })
79
+ .middleware([authContextMiddleware])
80
80
  .validator(listIterationsSchema)
81
- .handler(async ({ data }) => {
81
+ .handler(async ({ data, context }) => {
82
82
  const prisma = await getPrisma()
83
- const request = getRequest();
84
- const session = await requireAuth(request);
85
83
  // 读门槛与列表 scope 同口径(SEC-03):非成员静默回退独立项目,
86
84
  // 同时避免借读路径触发他人项目的迭代自愈排期
87
- const scopeProjectId = await resolveStoryScopeProjectId(data.projectId, session.user.id);
85
+ const scopeProjectId = await resolveStoryScopeProjectId(data.projectId, context.user.id);
88
86
  // 惰性自愈:自动排期补建 + autoRollover(规格 §3.6)
89
87
  await ensureUpcomingIterations(scopeProjectId);
90
88
  await ensureAutoRollover(scopeProjectId);
@@ -118,12 +116,11 @@ export const listIterationsFn = createServerFn({ method: "GET" })
118
116
  * listIterationsFn 的读时惰性自愈,避免只读视图触发建行。
119
117
  */
120
118
  export const listIterationsScopeFn = createServerFn({ method: "GET" })
119
+ .middleware([authContextMiddleware])
121
120
  .validator(z.object({ projectId: z.string().optional() }))
122
- .handler(async ({ data }) => {
121
+ .handler(async ({ data, context }) => {
123
122
  const prisma = await getPrisma()
124
- const request = getRequest();
125
- const session = await requireAuth(request);
126
- const projectIds = await resolveStoryScopeProjectIds(data.projectId, session.user.id);
123
+ const projectIds = await resolveStoryScopeProjectIds(data.projectId, context.user.id);
127
124
  const items = await prisma.iteration.findMany({
128
125
  where: { projectId: { in: projectIds }, archived: false },
129
126
  select: { id: true, name: true, startDate: true, endDate: true },
@@ -133,13 +130,12 @@ export const listIterationsScopeFn = createServerFn({ method: "GET" })
133
130
  });
134
131
 
135
132
  export const getIterationFn = createServerFn({ method: "GET" })
133
+ .middleware([authContextMiddleware])
136
134
  .validator(iterationIdSchema)
137
- .handler(async ({ data }) => {
135
+ .handler(async ({ data, context }) => {
138
136
  const prisma = await getPrisma()
139
- const request = getRequest();
140
- const session = await requireAuth(request);
141
137
  // 读侧与写侧同口径:须为迭代所属项目的有效成员(审计 2026-10-25 读路径缺口)
142
- await assertIterationProjectMember(data.id, session.user.id);
138
+ await assertIterationProjectMember(data.id, context.user.id);
143
139
  const it = await prisma.iteration.findUnique({ where: { id: data.id }, select: ITERATION_SELECT });
144
140
  if (!it) throw new Error("迭代不存在");
145
141
  const grouped = await prisma.story.groupBy({
@@ -152,13 +148,12 @@ export const getIterationFn = createServerFn({ method: "GET" })
152
148
  });
153
149
 
154
150
  export const createIterationsFn = createServerFn({ method: "POST" })
151
+ .middleware([authContextMiddleware])
155
152
  .validator(createIterationSchema)
156
- .handler(async ({ data }) => {
153
+ .handler(async ({ data, context }) => {
157
154
  const prisma = await getPrisma()
158
- const request = getRequest();
159
- const session = await requireAuth(request);
160
155
  // 与 testcase createTestCaseFn 同范式:建入前校验目标项目成员资格(SEC-03 残口收口)
161
- await assertProjectMembership(data.projectId, session.user.id);
156
+ await assertProjectMembership(data.projectId, context.user.id);
162
157
  await assertNoOverlap(data.projectId, data);
163
158
  const created = await prisma.iteration.create({
164
159
  data: {
@@ -167,7 +162,7 @@ export const createIterationsFn = createServerFn({ method: "POST" })
167
162
  description: data.description,
168
163
  startDate: new Date(data.startDate + "T00:00:00.000Z"),
169
164
  endDate: new Date(data.endDate + "T00:00:00.000Z"),
170
- createdById: session.user.id,
165
+ createdById: context.user.id,
171
166
  },
172
167
  select: { id: true },
173
168
  });
@@ -175,12 +170,11 @@ export const createIterationsFn = createServerFn({ method: "POST" })
175
170
  });
176
171
 
177
172
  export const updateIterationsFn = createServerFn({ method: "POST" })
173
+ .middleware([authContextMiddleware])
178
174
  .validator(updateIterationSchema)
179
- .handler(async ({ data }) => {
175
+ .handler(async ({ data, context }) => {
180
176
  const prisma = await getPrisma()
181
- const request = getRequest();
182
- const session = await requireAuth(request);
183
- const userId = session.user.id;
177
+ const userId = context.user.id;
184
178
  const existing = await prisma.iteration.findUnique({ where: { id: data.id }, select: ITERATION_SELECT });
185
179
  if (!existing) throw new Error("迭代不存在");
186
180
  await assertProjectMembership(existing.projectId, userId);
@@ -207,18 +201,17 @@ export const updateIterationsFn = createServerFn({ method: "POST" })
207
201
  });
208
202
 
209
203
  export const archiveIterationsFn = createServerFn({ method: "POST" })
204
+ .middleware([authContextMiddleware])
210
205
  .validator(z.object({ id: z.string(), archived: z.boolean() }))
211
- .handler(async ({ data }) => {
206
+ .handler(async ({ data, context }) => {
212
207
  const prisma = await getPrisma()
213
- const request = getRequest();
214
- const session = await requireAuth(request);
215
208
  // 先取回目标行校验成员资格,再改(SEC-03:防跨项目归档他人迭代)
216
209
  const existing = await prisma.iteration.findUnique({
217
210
  where: { id: data.id },
218
211
  select: { id: true, projectId: true },
219
212
  });
220
213
  if (!existing) throw new Error("迭代不存在");
221
- await assertProjectMembership(existing.projectId, session.user.id);
214
+ await assertProjectMembership(existing.projectId, context.user.id);
222
215
  await prisma.iteration.update({
223
216
  where: { id: data.id },
224
217
  data: { archived: data.archived, archivedAt: data.archived ? new Date() : null },
@@ -227,18 +220,17 @@ export const archiveIterationsFn = createServerFn({ method: "POST" })
227
220
  });
228
221
 
229
222
  export const deleteIterationsFn = createServerFn({ method: "POST" })
223
+ .middleware([authContextMiddleware])
230
224
  .validator(iterationIdSchema)
231
- .handler(async ({ data }) => {
225
+ .handler(async ({ data, context }) => {
232
226
  const prisma = await getPrisma()
233
- const request = getRequest();
234
- const session = await requireAuth(request);
235
227
  // 先取回目标行校验成员资格,再删(SEC-03:防跨项目删除他人迭代)
236
228
  const existing = await prisma.iteration.findUnique({
237
229
  where: { id: data.id },
238
230
  select: { id: true, projectId: true },
239
231
  });
240
232
  if (!existing) throw new Error("迭代不存在");
241
- await assertProjectMembership(existing.projectId, session.user.id);
233
+ await assertProjectMembership(existing.projectId, context.user.id);
242
234
  await prisma.iteration.delete({ where: { id: data.id } }); // Story.iterationId SetNull 自动解绑
243
235
  return { ok: true };
244
236
  });
@@ -246,12 +238,11 @@ export const deleteIterationsFn = createServerFn({ method: "POST" })
246
238
  const listIterationStoriesSchema = z.object({ iterationId: z.string() });
247
239
 
248
240
  export const listIterationStoriesFn = createServerFn({ method: "GET" })
241
+ .middleware([authContextMiddleware])
249
242
  .validator(listIterationStoriesSchema)
250
- .handler(async ({ data }) => {
243
+ .handler(async ({ data, context }) => {
251
244
  const prisma = await getPrisma()
252
- const request = getRequest();
253
- const session = await requireAuth(request);
254
- await assertIterationProjectMember(data.iterationId, session.user.id);
245
+ await assertIterationProjectMember(data.iterationId, context.user.id);
255
246
  const stories = await prisma.story.findMany({
256
247
  where: { iterationId: data.iterationId, archived: false },
257
248
  orderBy: [{ state: "asc" }, { updatedAt: "desc" }],
@@ -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 { deriveIterationStatus, toDatePart } from "@/lib/iteration/status";
24
23
  import { assertIterationProjectMembership as assertProjectMembership } from "@/server/iteration/permissions";
25
24
 
@@ -40,12 +39,11 @@ async function assertTargetJoinable(iterationId: string, userId: string) {
40
39
  }
41
40
 
42
41
  export const setStoryIterationFn = createServerFn({ method: "POST" })
42
+ .middleware([authContextMiddleware])
43
43
  .validator(z.object({ storyId: z.string(), iterationId: z.string().nullable() }))
44
- .handler(async ({ data }) => {
44
+ .handler(async ({ data, context }) => {
45
45
  const prisma = await getPrisma()
46
- const request = getRequest();
47
- const session = await requireAuth(request);
48
- const userId = session.user.id;
46
+ const userId = context.user.id;
49
47
  const story = await prisma.story.findUnique({
50
48
  where: { id: data.storyId },
51
49
  select: { projectId: true, iterationId: true, iteration: { select: { name: true } } },
@@ -73,12 +71,11 @@ export const setStoryIterationFn = createServerFn({ method: "POST" })
73
71
  });
74
72
 
75
73
  export const addStoriesToIterationFn = createServerFn({ method: "POST" })
74
+ .middleware([authContextMiddleware])
76
75
  .validator(z.object({ iterationId: z.string(), storyIds: z.array(z.string()).min(1).max(200) }))
77
- .handler(async ({ data }) => {
76
+ .handler(async ({ data, context }) => {
78
77
  const prisma = await getPrisma()
79
- const request = getRequest();
80
- const session = await requireAuth(request);
81
- const userId = session.user.id;
78
+ const userId = context.user.id;
82
79
  const newName = await assertTargetJoinable(data.iterationId, userId);
83
80
  // 批量圈定后按项目去重校验成员资格(SEC-03:任一跨项目 id 整批拒绝,不做部分写入)
84
81
  const stories = await prisma.story.findMany({
@@ -114,12 +111,11 @@ export const addStoriesToIterationFn = createServerFn({ method: "POST" })
114
111
  });
115
112
 
116
113
  export const removeStoryFromIterationFn = createServerFn({ method: "POST" })
114
+ .middleware([authContextMiddleware])
117
115
  .validator(z.object({ storyId: z.string() }))
118
- .handler(async ({ data }) => {
116
+ .handler(async ({ data, context }) => {
119
117
  const prisma = await getPrisma()
120
- const request = getRequest();
121
- const session = await requireAuth(request);
122
- const userId = session.user.id;
118
+ const userId = context.user.id;
123
119
  const story = await prisma.story.findUnique({
124
120
  where: { id: data.storyId },
125
121
  select: { projectId: true, iterationId: true, iteration: { select: { name: true } } },
@@ -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";
19
+ import { authContextMiddleware } from "@/server/middlewares/auth-context"
20
20
  import { z } from "zod";
21
- import { requireAuth } from "@/server/auth-helpers";
22
21
  import { transferStoriesInternal } from "@/server/iteration/transfer-internal";
23
22
 
24
23
  // 模块私有:serverFn 文件只准导出 createServerFn(客户端 split 会保留普通导出)
@@ -29,15 +28,14 @@ const transferUnfinishedSchema = z.object({
29
28
  });
30
29
 
31
30
  export const transferUnfinishedFn = createServerFn({ method: "POST" })
31
+ .middleware([authContextMiddleware])
32
32
  .validator(transferUnfinishedSchema)
33
- .handler(async ({ data }) => {
34
- const request = getRequest();
35
- const session = await requireAuth(request);
33
+ .handler(async ({ data, context }) => {
36
34
  const count = await transferStoriesInternal(
37
35
  data.iterationId,
38
36
  data.targetIterationId,
39
37
  data.storyIds,
40
- session.user.id,
38
+ context.user.id,
41
39
  );
42
40
  return { count };
43
41
  });
@@ -17,41 +17,38 @@
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'
21
20
  import { z } from 'zod'
22
- import { requireAuth } from '@/server/auth-helpers'
21
+ import { authContextMiddleware } from '@/server/middlewares/auth-context'
23
22
 
24
23
  export const listBookmarkCategoriesFn = createServerFn({ method: 'GET' })
24
+ .middleware([authContextMiddleware])
25
25
  .validator(z.object({}).optional())
26
- .handler(async () => {
26
+ .handler(async ({ context }) => {
27
27
  const prisma = await getPrisma()
28
- const request = getRequest()
29
- const session = await requireAuth(request)
30
28
  return prisma.bookmarkCategory.findMany({
31
- where: { OR: [{ userId: null }, { userId: session.user.id }] },
29
+ where: { OR: [{ userId: null }, { userId: context.user.id }] },
32
30
  orderBy: [{ sortOrder: 'asc' }, { name: 'asc' }],
33
31
  select: { id: true, name: true, icon: true, sortOrder: true, isDefault: true, userId: true },
34
32
  })
35
33
  })
36
34
 
37
35
  export const createBookmarkCategoryFn = createServerFn({ method: 'POST' })
36
+ .middleware([authContextMiddleware])
38
37
  .validator(z.object({ name: z.string().min(1).max(20), icon: z.string().default('Folder') }))
39
- .handler(async ({ data }) => {
38
+ .handler(async ({ data, context }) => {
40
39
  const prisma = await getPrisma()
41
- const request = getRequest()
42
- const session = await requireAuth(request)
43
40
  // max+1 聚合与创建同事务(审计 2026-10-25:收窄 check-then-act 竞态窗口;
44
41
  // 极端并发仍可能重复 sortOrder,展示层按 sortOrder+name 排序可容忍)
45
42
  return prisma.$transaction(async (tx) => {
46
43
  const last = await tx.bookmarkCategory.findFirst({
47
- where: { userId: session.user.id },
44
+ where: { userId: context.user.id },
48
45
  orderBy: { sortOrder: 'desc' },
49
46
  })
50
47
  return tx.bookmarkCategory.create({
51
48
  data: {
52
49
  name: data.name,
53
50
  icon: data.icon,
54
- userId: session.user.id,
51
+ userId: context.user.id,
55
52
  sortOrder: (last?.sortOrder ?? 0) + 1,
56
53
  },
57
54
  select: { id: true, name: true, icon: true, sortOrder: true },
@@ -60,15 +57,14 @@ export const createBookmarkCategoryFn = createServerFn({ method: 'POST' })
60
57
  })
61
58
 
62
59
  export const deleteBookmarkCategoryFn = createServerFn({ method: 'POST' })
60
+ .middleware([authContextMiddleware])
63
61
  .validator(z.object({ id: z.string() }))
64
- .handler(async ({ data }) => {
62
+ .handler(async ({ data, context }) => {
65
63
  const prisma = await getPrisma()
66
- const request = getRequest()
67
- const session = await requireAuth(request)
68
64
  const cat = await prisma.bookmarkCategory.findUnique({ where: { id: data.id } })
69
65
  if (!cat) throw new Error('未找到')
70
66
  if (cat.isDefault) throw new Error('预置分类不可删除')
71
- if (cat.userId !== session.user.id) throw new Error('无权限')
67
+ if (cat.userId !== context.user.id) throw new Error('无权限')
72
68
  await prisma.bookmarkCategory.delete({ where: { id: data.id } })
73
69
  return { success: true }
74
70
  })
@@ -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'
21
20
  import { z } from 'zod'
22
- import { requireAuth } from '@/server/auth-helpers'
21
+ import { authContextMiddleware } from '@/server/middlewares/auth-context'
23
22
  import { checkUserActionRateLimit } from '@/server/lib/rate-limit'
24
23
  import { bookmarkCanonicalId, parseGithubUrl } from '@/server/knowledge/public/canonical-id'
25
24
  import { fetchGithubData } from '@/server/knowledge/public/github-sync'
@@ -41,12 +40,11 @@ const createSchema = z.object({
41
40
  })
42
41
 
43
42
  export const createBookmarkFn = createServerFn({ method: 'POST' })
43
+ .middleware([authContextMiddleware])
44
44
  .validator(createSchema)
45
- .handler(async ({ data }) => {
45
+ .handler(async ({ data, context }) => {
46
46
  const prisma = await getPrisma()
47
- const request = getRequest()
48
- const session = await requireAuth(request)
49
- const userId = session.user.id
47
+ const userId = context.user.id
50
48
  // categoryId 必须存在且属于当前用户或为公共分类(审计 2026-10-25:
51
49
  // 防把书签挂到他人自定义分类下造成数据关联错乱)
52
50
  if (data.categoryId) {
@@ -17,20 +17,18 @@
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'
21
20
  import { z } from 'zod'
22
- import { requireAuth } from '@/server/auth-helpers'
21
+ import { authContextMiddleware } from '@/server/middlewares/auth-context'
23
22
 
24
23
  export const deleteBookmarkFn = createServerFn({ method: 'POST' })
24
+ .middleware([authContextMiddleware])
25
25
  .validator(z.object({ id: z.string() }))
26
- .handler(async ({ data }) => {
26
+ .handler(async ({ data, context }) => {
27
27
  const prisma = await getPrisma()
28
- const request = getRequest()
29
- const session = await requireAuth(request)
30
28
  const existing = await prisma.websiteBookmark.findUnique({ where: { id: data.id } })
31
29
  if (!existing) throw new Error('未找到')
32
- const isOwner = existing.userId === session.user.id
33
- const isAdmin = session.user.role === 'ADMIN' || session.user.role === 'SUPER_ADMIN'
30
+ const isOwner = existing.userId === context.user.id
31
+ const isAdmin = context.user.role === 'ADMIN' || context.user.role === 'SUPER_ADMIN'
34
32
  if (!isOwner && !isAdmin) throw new Error('无权限')
35
33
  await prisma.websiteBookmark.update({ where: { id: data.id }, data: { isDeleted: true } })
36
34
  return { success: true }
@@ -17,18 +17,16 @@
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'
21
20
  import { z } from 'zod'
22
- import { requireAuth } from '@/server/auth-helpers'
21
+ import { authContextMiddleware } from '@/server/middlewares/auth-context'
23
22
  import { aggregateSharers, type PublicSharer } from '@/server/knowledge/public/share-merge'
24
23
 
25
24
  export const getBookmarkDetailFn = createServerFn({ method: 'GET' })
25
+ .middleware([authContextMiddleware])
26
26
  .validator(z.object({ id: z.string() }))
27
- .handler(async ({ data }) => {
27
+ .handler(async ({ data, context }) => {
28
28
  const prisma = await getPrisma()
29
- const request = getRequest()
30
- const session = await requireAuth(request)
31
- const userId = session.user.id
29
+ const userId = context.user.id
32
30
  const item = await prisma.websiteBookmark.findFirst({
33
31
  where: { id: data.id, isDeleted: false },
34
32
  include: { category: { select: { icon: true } } },
@@ -17,17 +17,15 @@
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'
21
20
  import { z } from 'zod'
22
- import { requireAuth } from '@/server/auth-helpers'
21
+ import { authContextMiddleware } from '@/server/middlewares/auth-context'
23
22
 
24
23
  export const toggleFavoriteBookmarkFn = createServerFn({ method: 'POST' })
24
+ .middleware([authContextMiddleware])
25
25
  .validator(z.object({ canonicalId: z.string() }))
26
- .handler(async ({ data }) => {
26
+ .handler(async ({ data, context }) => {
27
27
  const prisma = await getPrisma()
28
- const request = getRequest()
29
- const session = await requireAuth(request)
30
- const userId = session.user.id
28
+ const userId = context.user.id
31
29
  // DB-03:同 toggleFavoriteFn——deleteMany 计数判定合并查后写,防并发重复收藏。
32
30
  // 审计 2026-10-25 核实:ArticleFavorite 有 @@unique([entityType, entityId, userId])
33
31
  // 兜底,并发双击时 create 撞唯一约束(P2002)——按「已收藏」语义吞掉该竞态。
@@ -18,9 +18,8 @@
18
18
  import { getPrisma } from "@allbluecn/database/get-prisma"
19
19
  import { Prisma } from '@allbluecn/database'
20
20
  import { createServerFn } from '@tanstack/react-start'
21
- import { getRequest } from '@tanstack/react-start/server'
22
21
  import { z } from 'zod'
23
- import { requireAuth } from '@/server/auth-helpers'
22
+ import { authContextMiddleware } from '@/server/middlewares/auth-context'
24
23
  import { aggregateSharers } from '@/server/knowledge/public/share-merge'
25
24
 
26
25
  const listSchema = z.object({
@@ -33,12 +32,11 @@ const listSchema = z.object({
33
32
  })
34
33
 
35
34
  export const listBookmarksFn = createServerFn({ method: 'GET' })
35
+ .middleware([authContextMiddleware])
36
36
  .validator(listSchema)
37
- .handler(async ({ data }) => {
37
+ .handler(async ({ data, context }) => {
38
38
  const prisma = await getPrisma()
39
- const request = getRequest()
40
- const session = await requireAuth(request)
41
- const userId = session.user.id
39
+ const userId = context.user.id
42
40
  const where: Prisma.WebsiteBookmarkWhereInput = { isDeleted: false }
43
41
  if (data.scope === 'private') {
44
42
  where.userId = userId