@byline/host-tanstack-start 5.0.0 → 5.1.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 (258) hide show
  1. package/dist/admin-shell/chrome/admin-app-bar.d.ts +7 -0
  2. package/dist/admin-shell/chrome/admin-app-bar.js +10 -2
  3. package/dist/admin-shell/chrome/optional-i18n-provider.d.ts +29 -0
  4. package/dist/admin-shell/chrome/optional-i18n-provider.js +24 -0
  5. package/dist/admin-shell/chrome/session-change-boundary.d.ts +14 -0
  6. package/dist/admin-shell/chrome/session-change-boundary.js +119 -0
  7. package/dist/admin-shell/chrome/session-change-boundary.module.js +11 -0
  8. package/dist/admin-shell/chrome/session-change-boundary.test.d.ts +8 -0
  9. package/dist/admin-shell/chrome/session-change-boundary_module.css +81 -0
  10. package/dist/admin-shell/chrome/sign-in-page.d.ts +2 -1
  11. package/dist/admin-shell/chrome/sign-in-page.js +60 -3
  12. package/dist/integrations/byline-admin-services.js +7 -1
  13. package/dist/integrations/client-ip.d.ts +19 -0
  14. package/dist/integrations/client-ip.js +34 -0
  15. package/dist/integrations/session-coordination.d.ts +24 -0
  16. package/dist/integrations/session-coordination.js +85 -0
  17. package/dist/integrations/session-middleware.d.ts +11 -0
  18. package/dist/integrations/session-middleware.js +94 -0
  19. package/dist/integrations/session-request-kind.d.ts +9 -0
  20. package/dist/integrations/session-request-kind.js +10 -0
  21. package/dist/integrations/session-request-middleware.d.ts +9 -0
  22. package/dist/integrations/session-request-middleware.js +7 -0
  23. package/dist/integrations/sign-in-body.d.ts +12 -0
  24. package/dist/integrations/sign-in-body.js +52 -0
  25. package/dist/integrations/sign-in-middleware.d.ts +9 -0
  26. package/dist/integrations/sign-in-middleware.js +10 -0
  27. package/dist/routes/create-admin-layout-route.js +46 -31
  28. package/dist/routes/create-sign-in-route.js +4 -2
  29. package/dist/server-fns/admin-account/change-password.d.ts +3 -1
  30. package/dist/server-fns/admin-account/change-password.js +9 -3
  31. package/dist/server-fns/admin-account/get.d.ts +3 -1
  32. package/dist/server-fns/admin-account/get.js +4 -1
  33. package/dist/server-fns/admin-account/index.d.ts +5 -5
  34. package/dist/server-fns/admin-account/update.d.ts +3 -1
  35. package/dist/server-fns/admin-account/update.js +4 -1
  36. package/dist/server-fns/admin-activity/get.d.ts +3 -1
  37. package/dist/server-fns/admin-activity/get.js +4 -1
  38. package/dist/server-fns/admin-permissions/get-role-abilities.d.ts +3 -1
  39. package/dist/server-fns/admin-permissions/get-role-abilities.js +4 -1
  40. package/dist/server-fns/admin-permissions/index.d.ts +4 -4
  41. package/dist/server-fns/admin-permissions/list-registered.d.ts +3 -1
  42. package/dist/server-fns/admin-permissions/list-registered.js +4 -1
  43. package/dist/server-fns/admin-permissions/set-role-abilities.d.ts +3 -1
  44. package/dist/server-fns/admin-permissions/set-role-abilities.js +4 -1
  45. package/dist/server-fns/admin-permissions/who-has.d.ts +3 -1
  46. package/dist/server-fns/admin-permissions/who-has.js +4 -1
  47. package/dist/server-fns/admin-roles/create.d.ts +3 -1
  48. package/dist/server-fns/admin-roles/create.js +4 -1
  49. package/dist/server-fns/admin-roles/delete.d.ts +3 -1
  50. package/dist/server-fns/admin-roles/delete.js +4 -1
  51. package/dist/server-fns/admin-roles/get.d.ts +3 -1
  52. package/dist/server-fns/admin-roles/get.js +4 -1
  53. package/dist/server-fns/admin-roles/index.d.ts +6 -6
  54. package/dist/server-fns/admin-roles/list.d.ts +3 -1
  55. package/dist/server-fns/admin-roles/list.js +4 -1
  56. package/dist/server-fns/admin-roles/reorder.d.ts +3 -1
  57. package/dist/server-fns/admin-roles/reorder.js +4 -1
  58. package/dist/server-fns/admin-roles/update.d.ts +3 -1
  59. package/dist/server-fns/admin-roles/update.js +4 -1
  60. package/dist/server-fns/admin-users/create.d.ts +3 -1
  61. package/dist/server-fns/admin-users/create.js +4 -1
  62. package/dist/server-fns/admin-users/delete.d.ts +3 -1
  63. package/dist/server-fns/admin-users/delete.js +4 -1
  64. package/dist/server-fns/admin-users/disable.d.ts +3 -1
  65. package/dist/server-fns/admin-users/disable.js +4 -1
  66. package/dist/server-fns/admin-users/enable.d.ts +3 -1
  67. package/dist/server-fns/admin-users/enable.js +4 -1
  68. package/dist/server-fns/admin-users/get-user-roles.d.ts +3 -1
  69. package/dist/server-fns/admin-users/get-user-roles.js +4 -1
  70. package/dist/server-fns/admin-users/get.d.ts +3 -1
  71. package/dist/server-fns/admin-users/get.js +4 -1
  72. package/dist/server-fns/admin-users/index.d.ts +10 -10
  73. package/dist/server-fns/admin-users/list.d.ts +3 -1
  74. package/dist/server-fns/admin-users/list.js +4 -1
  75. package/dist/server-fns/admin-users/set-password.d.ts +3 -1
  76. package/dist/server-fns/admin-users/set-password.js +4 -1
  77. package/dist/server-fns/admin-users/set-user-roles.d.ts +3 -1
  78. package/dist/server-fns/admin-users/set-user-roles.js +4 -1
  79. package/dist/server-fns/admin-users/update.d.ts +3 -1
  80. package/dist/server-fns/admin-users/update.js +4 -1
  81. package/dist/server-fns/ai/execute.d.ts +3 -1
  82. package/dist/server-fns/ai/execute.js +4 -1
  83. package/dist/server-fns/ai/index.d.ts +1 -1
  84. package/dist/server-fns/analytics/maintenance.d.ts +6 -2
  85. package/dist/server-fns/analytics/maintenance.js +7 -2
  86. package/dist/server-fns/analytics/queries.d.ts +18 -6
  87. package/dist/server-fns/analytics/queries.js +19 -6
  88. package/dist/server-fns/auth/current-user.d.ts +1 -0
  89. package/dist/server-fns/auth/current-user.js +5 -2
  90. package/dist/server-fns/auth/renew.d.ts +13 -0
  91. package/dist/server-fns/auth/renew.js +45 -0
  92. package/dist/server-fns/auth/sign-in.d.ts +2 -1
  93. package/dist/server-fns/auth/sign-in.js +88 -17
  94. package/dist/server-fns/auth/sign-out.d.ts +3 -1
  95. package/dist/server-fns/auth/sign-out.js +38 -6
  96. package/dist/server-fns/collections/audit.d.ts +3 -1
  97. package/dist/server-fns/collections/audit.js +4 -1
  98. package/dist/server-fns/collections/copy-to-locale.d.ts +10 -1
  99. package/dist/server-fns/collections/copy-to-locale.js +5 -2
  100. package/dist/server-fns/collections/create.d.ts +10 -1
  101. package/dist/server-fns/collections/create.js +5 -2
  102. package/dist/server-fns/collections/delete-locale.d.ts +10 -1
  103. package/dist/server-fns/collections/delete-locale.js +5 -2
  104. package/dist/server-fns/collections/delete.d.ts +10 -1
  105. package/dist/server-fns/collections/delete.js +5 -2
  106. package/dist/server-fns/collections/duplicate.d.ts +10 -1
  107. package/dist/server-fns/collections/duplicate.js +5 -2
  108. package/dist/server-fns/collections/get.d.ts +7 -0
  109. package/dist/server-fns/collections/get.js +8 -3
  110. package/dist/server-fns/collections/history.d.ts +3 -1
  111. package/dist/server-fns/collections/history.js +4 -1
  112. package/dist/server-fns/collections/index.d.ts +21 -21
  113. package/dist/server-fns/collections/list.d.ts +10 -1
  114. package/dist/server-fns/collections/list.js +5 -2
  115. package/dist/server-fns/collections/reindex.d.ts +3 -1
  116. package/dist/server-fns/collections/reindex.js +4 -1
  117. package/dist/server-fns/collections/reorder.d.ts +10 -1
  118. package/dist/server-fns/collections/reorder.js +5 -2
  119. package/dist/server-fns/collections/restore-version.d.ts +10 -1
  120. package/dist/server-fns/collections/restore-version.js +5 -2
  121. package/dist/server-fns/collections/scheduled-publication.d.ts +22 -5
  122. package/dist/server-fns/collections/scheduled-publication.js +17 -6
  123. package/dist/server-fns/collections/set-list-view-preference.d.ts +3 -1
  124. package/dist/server-fns/collections/set-list-view-preference.js +4 -1
  125. package/dist/server-fns/collections/stats.js +4 -1
  126. package/dist/server-fns/collections/status.d.ts +13 -2
  127. package/dist/server-fns/collections/status.js +8 -3
  128. package/dist/server-fns/collections/tree.d.ts +22 -5
  129. package/dist/server-fns/collections/tree.js +17 -6
  130. package/dist/server-fns/collections/update.d.ts +13 -2
  131. package/dist/server-fns/collections/update.js +8 -3
  132. package/dist/server-fns/collections/upload.d.ts +10 -1
  133. package/dist/server-fns/collections/upload.js +4 -1
  134. package/dist/server-fns/i18n/set-locale.d.ts +3 -1
  135. package/dist/server-fns/i18n/set-locale.js +18 -3
  136. package/dist/server-fns/preview/disable.d.ts +3 -1
  137. package/dist/server-fns/preview/disable.js +4 -1
  138. package/dist/server-fns/preview/enable.d.ts +3 -1
  139. package/dist/server-fns/preview/enable.js +4 -1
  140. package/dist/server-fns/singletons/cancel-scheduled-publish.d.ts +10 -1
  141. package/dist/server-fns/singletons/cancel-scheduled-publish.js +5 -2
  142. package/dist/server-fns/singletons/change-status.d.ts +10 -1
  143. package/dist/server-fns/singletons/change-status.js +5 -2
  144. package/dist/server-fns/singletons/confirm-scheduled-publish.d.ts +10 -1
  145. package/dist/server-fns/singletons/confirm-scheduled-publish.js +5 -2
  146. package/dist/server-fns/singletons/copy-to-locale.d.ts +10 -1
  147. package/dist/server-fns/singletons/copy-to-locale.js +5 -2
  148. package/dist/server-fns/singletons/find-by-version.d.ts +3 -1
  149. package/dist/server-fns/singletons/find-by-version.js +4 -1
  150. package/dist/server-fns/singletons/get-scheduled-publish.d.ts +3 -1
  151. package/dist/server-fns/singletons/get-scheduled-publish.js +4 -1
  152. package/dist/server-fns/singletons/get.d.ts +3 -1
  153. package/dist/server-fns/singletons/get.js +4 -1
  154. package/dist/server-fns/singletons/history.d.ts +3 -1
  155. package/dist/server-fns/singletons/history.js +4 -1
  156. package/dist/server-fns/singletons/restore-version.d.ts +10 -1
  157. package/dist/server-fns/singletons/restore-version.js +5 -2
  158. package/dist/server-fns/singletons/schedule-publish.d.ts +10 -1
  159. package/dist/server-fns/singletons/schedule-publish.js +5 -2
  160. package/dist/server-fns/singletons/unpublish.d.ts +10 -1
  161. package/dist/server-fns/singletons/unpublish.js +5 -2
  162. package/dist/server-fns/singletons/update.d.ts +10 -1
  163. package/dist/server-fns/singletons/update.js +5 -2
  164. package/package.json +19 -19
  165. package/src/admin-shell/chrome/admin-app-bar.tsx +11 -6
  166. package/src/admin-shell/chrome/optional-i18n-provider.tsx +61 -0
  167. package/src/admin-shell/chrome/session-change-boundary.module.css +112 -0
  168. package/src/admin-shell/chrome/session-change-boundary.test.tsx +91 -0
  169. package/src/admin-shell/chrome/session-change-boundary.tsx +155 -0
  170. package/src/admin-shell/chrome/sign-in-page.tsx +68 -3
  171. package/src/integrations/byline-admin-services.ts +7 -1
  172. package/src/integrations/client-ip.test.node.ts +45 -0
  173. package/src/integrations/client-ip.ts +54 -0
  174. package/src/integrations/framework-fetch-shape.test.node.ts +56 -0
  175. package/src/integrations/session-client.test.node.ts +121 -0
  176. package/src/integrations/session-coordination.test.node.ts +77 -0
  177. package/src/integrations/session-coordination.ts +96 -0
  178. package/src/integrations/session-middleware.test.node.ts +87 -0
  179. package/src/integrations/session-middleware.ts +107 -0
  180. package/src/integrations/session-request-kind.ts +18 -0
  181. package/src/integrations/session-request-middleware.ts +17 -0
  182. package/src/integrations/sign-in-body.test.node.ts +59 -0
  183. package/src/integrations/sign-in-body.ts +50 -0
  184. package/src/integrations/sign-in-middleware.ts +24 -0
  185. package/src/routes/create-admin-layout-route.tsx +48 -30
  186. package/src/routes/create-sign-in-route.tsx +10 -2
  187. package/src/server-fns/admin-account/change-password.test.node.ts +69 -0
  188. package/src/server-fns/admin-account/change-password.ts +13 -2
  189. package/src/server-fns/admin-account/get.ts +2 -0
  190. package/src/server-fns/admin-account/update.ts +2 -0
  191. package/src/server-fns/admin-activity/get.ts +2 -0
  192. package/src/server-fns/admin-permissions/get-role-abilities.ts +2 -0
  193. package/src/server-fns/admin-permissions/list-registered.ts +5 -4
  194. package/src/server-fns/admin-permissions/set-role-abilities.ts +2 -0
  195. package/src/server-fns/admin-permissions/who-has.ts +2 -0
  196. package/src/server-fns/admin-roles/create.ts +2 -0
  197. package/src/server-fns/admin-roles/delete.ts +2 -0
  198. package/src/server-fns/admin-roles/get.ts +2 -0
  199. package/src/server-fns/admin-roles/list.ts +5 -4
  200. package/src/server-fns/admin-roles/reorder.ts +2 -0
  201. package/src/server-fns/admin-roles/update.ts +2 -0
  202. package/src/server-fns/admin-users/create.ts +2 -0
  203. package/src/server-fns/admin-users/delete.ts +2 -0
  204. package/src/server-fns/admin-users/disable.ts +2 -0
  205. package/src/server-fns/admin-users/enable.ts +2 -0
  206. package/src/server-fns/admin-users/get-user-roles.ts +2 -0
  207. package/src/server-fns/admin-users/get.ts +2 -0
  208. package/src/server-fns/admin-users/list.ts +2 -0
  209. package/src/server-fns/admin-users/set-password.ts +2 -0
  210. package/src/server-fns/admin-users/set-user-roles.ts +2 -0
  211. package/src/server-fns/admin-users/update.ts +2 -0
  212. package/src/server-fns/ai/execute.ts +3 -0
  213. package/src/server-fns/analytics/maintenance.ts +4 -0
  214. package/src/server-fns/analytics/queries.ts +14 -8
  215. package/src/server-fns/auth/current-user.ts +7 -3
  216. package/src/server-fns/auth/renew.test.node.ts +85 -0
  217. package/src/server-fns/auth/renew.ts +54 -0
  218. package/src/server-fns/auth/sign-in.test.node.ts +114 -0
  219. package/src/server-fns/auth/sign-in.ts +80 -27
  220. package/src/server-fns/auth/sign-out.test.node.ts +85 -0
  221. package/src/server-fns/auth/sign-out.ts +44 -19
  222. package/src/server-fns/collections/audit.ts +2 -0
  223. package/src/server-fns/collections/copy-to-locale.ts +3 -1
  224. package/src/server-fns/collections/create.ts +3 -1
  225. package/src/server-fns/collections/delete-locale.ts +3 -1
  226. package/src/server-fns/collections/delete.ts +3 -1
  227. package/src/server-fns/collections/duplicate.ts +3 -1
  228. package/src/server-fns/collections/get.ts +4 -1
  229. package/src/server-fns/collections/history.ts +2 -0
  230. package/src/server-fns/collections/list.ts +3 -1
  231. package/src/server-fns/collections/reindex.ts +2 -0
  232. package/src/server-fns/collections/reorder.ts +3 -1
  233. package/src/server-fns/collections/restore-version.ts +3 -1
  234. package/src/server-fns/collections/revision-input.test.node.ts +14 -0
  235. package/src/server-fns/collections/scheduled-publication.ts +14 -7
  236. package/src/server-fns/collections/set-list-view-preference.ts +2 -0
  237. package/src/server-fns/collections/stats.ts +2 -0
  238. package/src/server-fns/collections/status.ts +4 -1
  239. package/src/server-fns/collections/tree.ts +7 -1
  240. package/src/server-fns/collections/update.ts +4 -1
  241. package/src/server-fns/collections/upload-singleton.test.node.ts +8 -1
  242. package/src/server-fns/collections/upload.ts +10 -0
  243. package/src/server-fns/i18n/set-locale.ts +19 -3
  244. package/src/server-fns/preview/disable.ts +8 -4
  245. package/src/server-fns/preview/enable.ts +9 -5
  246. package/src/server-fns/singletons/cancel-scheduled-publish.ts +3 -1
  247. package/src/server-fns/singletons/change-status.ts +3 -1
  248. package/src/server-fns/singletons/confirm-scheduled-publish.ts +3 -1
  249. package/src/server-fns/singletons/copy-to-locale.ts +3 -1
  250. package/src/server-fns/singletons/find-by-version.ts +2 -0
  251. package/src/server-fns/singletons/get-scheduled-publish.ts +2 -0
  252. package/src/server-fns/singletons/get.ts +2 -0
  253. package/src/server-fns/singletons/history.ts +2 -0
  254. package/src/server-fns/singletons/restore-version.ts +3 -1
  255. package/src/server-fns/singletons/schedule-publish.ts +3 -1
  256. package/src/server-fns/singletons/singletons.test.node.ts +6 -0
  257. package/src/server-fns/singletons/unpublish.ts +3 -1
  258. package/src/server-fns/singletons/update.ts +3 -1
@@ -0,0 +1,85 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+
9
+ import { beforeEach, describe, expect, it, vi } from 'vitest'
10
+
11
+ const mocks = vi.hoisted(() => ({
12
+ access: 'access' as string | undefined,
13
+ refresh: 'refresh' as string | undefined,
14
+ revoke: vi.fn(),
15
+ clear: vi.fn(),
16
+ clearPreview: vi.fn(),
17
+ }))
18
+ vi.mock('@tanstack/react-start', () => ({
19
+ createMiddleware: () => ({ client: () => ({}) }),
20
+ createServerFn: () => ({ middleware: () => ({ handler: (handler: any) => handler }) }),
21
+ }))
22
+ vi.mock('@byline/core', () => ({
23
+ getServerConfig: () => ({ sessionProvider: { revokeSession: mocks.revoke } }),
24
+ }))
25
+ vi.mock('@byline/client/server', () => ({
26
+ readAccessTokenCookie: () => mocks.access,
27
+ readRefreshTokenCookie: () => mocks.refresh,
28
+ clearSessionCookies: mocks.clear,
29
+ clearPreviewCookie: mocks.clearPreview,
30
+ }))
31
+
32
+ import { adminSignOut } from './sign-out.js'
33
+
34
+ const call = adminSignOut as unknown as (args: {
35
+ context: { expectedSessionId?: string }
36
+ }) => Promise<unknown>
37
+ beforeEach(() => {
38
+ vi.resetAllMocks()
39
+ mocks.access = 'access'
40
+ mocks.refresh = 'refresh'
41
+ })
42
+
43
+ describe('confirmed logout', () => {
44
+ it('revokes with both observed credentials before clearing cookies', async () => {
45
+ mocks.revoke.mockImplementation(async () => {
46
+ expect(mocks.clear).not.toHaveBeenCalled()
47
+ })
48
+ await expect(call({ context: { expectedSessionId: 'A' } })).resolves.toEqual({ status: 'ok' })
49
+ expect(mocks.revoke).toHaveBeenCalledWith({
50
+ accessToken: 'access',
51
+ refreshToken: 'refresh',
52
+ expectedSessionId: 'A',
53
+ })
54
+ expect(mocks.clear).toHaveBeenCalledOnce()
55
+ })
56
+ it('still requests revocation when only the access cookie remains', async () => {
57
+ mocks.refresh = undefined
58
+ await call({ context: { expectedSessionId: 'A' } })
59
+ expect(mocks.revoke).toHaveBeenCalledWith({
60
+ accessToken: 'access',
61
+ refreshToken: undefined,
62
+ expectedSessionId: 'A',
63
+ })
64
+ })
65
+ it('does not clear credentials or report success when revocation fails', async () => {
66
+ mocks.revoke.mockRejectedValue(new Error('database unavailable'))
67
+ await expect(call({ context: { expectedSessionId: 'A' } })).rejects.toThrow(
68
+ 'database unavailable'
69
+ )
70
+ expect(mocks.clear).not.toHaveBeenCalled()
71
+ expect(mocks.clearPreview).not.toHaveBeenCalled()
72
+ })
73
+ it('requires the page identity before revoking any observed credential', async () => {
74
+ await expect(call({ context: {} })).rejects.toMatchObject({ code: 'ERR_SESSION_CHANGED' })
75
+ expect(mocks.revoke).not.toHaveBeenCalled()
76
+ expect(mocks.clear).not.toHaveBeenCalled()
77
+ })
78
+ it('is idempotent when neither credential is present', async () => {
79
+ mocks.access = undefined
80
+ mocks.refresh = undefined
81
+ await expect(call({ context: {} })).resolves.toEqual({ status: 'ok' })
82
+ expect(mocks.revoke).not.toHaveBeenCalled()
83
+ expect(mocks.clear).toHaveBeenCalledOnce()
84
+ })
85
+ })
@@ -9,9 +9,9 @@
9
9
  /**
10
10
  * Admin sign-out server function.
11
11
  *
12
- * Revokes the current refresh token (so a stolen copy cannot be reused),
12
+ * Revokes the login identified by either credential (so a stolen copy cannot be reused),
13
13
  * clears both session cookies, and clears the preview-mode cookie.
14
- * Idempotent — if the caller already lacks a refresh cookie, we still
14
+ * Idempotent — if the caller already lacks both credential cookies, we still
15
15
  * clear whatever's there and return successfully.
16
16
  *
17
17
  * Note: clearing `byline_preview` here is hygiene, not a security
@@ -21,32 +21,57 @@
21
21
  * Clearing it simply means the next sign-in starts in non-preview mode.
22
22
  */
23
23
 
24
- import { createServerFn } from '@tanstack/react-start'
24
+ import { createMiddleware, createServerFn } from '@tanstack/react-start'
25
25
 
26
+ import { ERR_SESSION_CHANGED } from '@byline/auth'
26
27
  import {
27
28
  clearPreviewCookie,
28
29
  clearSessionCookies,
30
+ readAccessTokenCookie,
29
31
  readRefreshTokenCookie,
30
32
  } from '@byline/client/server'
31
33
  import { getServerConfig } from '@byline/core'
32
34
 
33
- export const adminSignOut = createServerFn({ method: 'POST' }).handler(async () => {
34
- const provider = getServerConfig().sessionProvider
35
- const refreshToken = readRefreshTokenCookie()
35
+ import {
36
+ coordinateAuthAction,
37
+ flagSessionChanged,
38
+ notifySessionAction,
39
+ sessionSnapshot,
40
+ } from '../../integrations/session-coordination.js'
36
41
 
37
- if (provider && refreshToken) {
38
- // Best-effort revoke — `revokeSession` itself is idempotent for
39
- // unknown/already-revoked tokens, so failures here would almost
40
- // certainly be transport-level. Swallow and continue: the cookies
41
- // get cleared regardless, so the caller's session ends.
42
+ const signOutBoundary = createMiddleware({ type: 'function' }).client(async ({ next }) => {
43
+ const snapshot = sessionSnapshot()
44
+ return coordinateAuthAction(async () => {
42
45
  try {
43
- await provider.revokeSession(refreshToken)
44
- } catch {
45
- // no-op
46
+ const result = await next({ sendContext: { expectedSessionId: snapshot.sessionId } })
47
+ notifySessionAction()
48
+ return result
49
+ } catch (error) {
50
+ if ((error as { code?: string })?.code === 'ERR_SESSION_CHANGED') flagSessionChanged()
51
+ throw error
46
52
  }
47
- }
48
-
49
- clearSessionCookies()
50
- clearPreviewCookie()
51
- return { status: 'ok' as const }
53
+ })
52
54
  })
55
+
56
+ export const adminSignOut = createServerFn({ method: 'POST' })
57
+ .middleware([signOutBoundary])
58
+ .handler(async ({ context }) => {
59
+ const provider = getServerConfig().sessionProvider
60
+ const refreshToken = readRefreshTokenCookie()
61
+ const accessToken = readAccessTokenCookie()
62
+
63
+ if (refreshToken || accessToken) {
64
+ if (!provider) throw new Error('no sessionProvider configured')
65
+ if (!context.expectedSessionId)
66
+ throw ERR_SESSION_CHANGED({ message: 'logout requires the page login identity' })
67
+ await provider.revokeSession({
68
+ refreshToken,
69
+ accessToken,
70
+ expectedSessionId: context.expectedSessionId,
71
+ })
72
+ }
73
+
74
+ clearSessionCookies()
75
+ clearPreviewCookie()
76
+ return { status: 'ok' as const }
77
+ })
@@ -12,6 +12,7 @@ import { getAdminBylineClient } from '@byline/client/server'
12
12
  import { ERR_NOT_FOUND, getLogger } from '@byline/core'
13
13
 
14
14
  import { ensureCollection } from '../../integrations/api-utils.js'
15
+ import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
15
16
  import { type ActorLabelMap, resolveActorLabels } from './actors.js'
16
17
 
17
18
  // ---------------------------------------------------------------------------
@@ -49,6 +50,7 @@ export interface AuditLogEntryDto {
49
50
  // ---------------------------------------------------------------------------
50
51
 
51
52
  export const getCollectionDocumentAuditLog = createServerFn({ method: 'GET' })
53
+ .middleware([adminSessionMiddleware])
52
54
  .validator((input: { collection: string; id: string; params?: AuditLogSearchParams }) => input)
53
55
  .handler(async ({ data }) => {
54
56
  const { collection: path, id, params } = data
@@ -1,4 +1,3 @@
1
- import { withDocumentMutationErrors } from '../document-mutation-errors.js'
2
1
  /**
3
2
  * This Source Code is subject to the terms of the Mozilla Public
4
3
  * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -15,6 +14,8 @@ import type { CopyToLocaleResult, DocumentLifecycleContext } from '@byline/core/
15
14
  import { copyToLocale } from '@byline/core/services'
16
15
 
17
16
  import { ensureCollection } from '../../integrations/api-utils.js'
17
+ import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
18
+ import { withDocumentMutationErrors } from '../document-mutation-errors.js'
18
19
  import {
19
20
  type CollectionDocumentCommittedHookFailureResponse,
20
21
  toCommittedDocumentHookFailureResponse,
@@ -34,6 +35,7 @@ import {
34
35
  * failures propagate to TanStack Start's transport layer.
35
36
  */
36
37
  export const copyDocumentToLocale = createServerFn({ method: 'POST' })
38
+ .middleware([adminSessionMiddleware])
37
39
  .validator(
38
40
  (input: {
39
41
  expectedRevision: number
@@ -1,4 +1,3 @@
1
- import { withDocumentMutationErrors } from '../document-mutation-errors.js'
2
1
  /**
3
2
  * This Source Code is subject to the terms of the Mozilla Public
4
3
  * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -15,6 +14,8 @@ import type { CreateDocumentResult, DocumentLifecycleContext } from '@byline/cor
15
14
  import { createDocument } from '@byline/core/services'
16
15
 
17
16
  import { ensureCollection } from '../../integrations/api-utils.js'
17
+ import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
18
+ import { withDocumentMutationErrors } from '../document-mutation-errors.js'
18
19
  import { toCommittedDocumentHookFailureResponse } from './save-outcome.js'
19
20
 
20
21
  // ---------------------------------------------------------------------------
@@ -22,6 +23,7 @@ import { toCommittedDocumentHookFailureResponse } from './save-outcome.js'
22
23
  // ---------------------------------------------------------------------------
23
24
 
24
25
  export const createCollectionDocument = createServerFn({ method: 'POST' })
26
+ .middleware([adminSessionMiddleware])
25
27
  .validator(
26
28
  (input: {
27
29
  collection: string
@@ -1,4 +1,3 @@
1
- import { withDocumentMutationErrors } from '../document-mutation-errors.js'
2
1
  /**
3
2
  * This Source Code is subject to the terms of the Mozilla Public
4
3
  * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -15,6 +14,8 @@ import type { DeleteLocaleResult, DocumentLifecycleContext } from '@byline/core/
15
14
  import { deleteLocale } from '@byline/core/services'
16
15
 
17
16
  import { ensureCollection } from '../../integrations/api-utils.js'
17
+ import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
18
+ import { withDocumentMutationErrors } from '../document-mutation-errors.js'
18
19
  import {
19
20
  type CollectionDocumentCommittedHookFailureResponse,
20
21
  toCommittedDocumentHookFailureResponse,
@@ -35,6 +36,7 @@ import {
35
36
  * transport layer.
36
37
  */
37
38
  export const deleteDocumentLocale = createServerFn({ method: 'POST' })
39
+ .middleware([adminSessionMiddleware])
38
40
  .validator(
39
41
  (input: { expectedRevision: number; collection: string; id: string; locale: string }) => input
40
42
  )
@@ -1,4 +1,3 @@
1
- import { withDocumentMutationErrors } from '../document-mutation-errors.js'
2
1
  /**
3
2
  * This Source Code is subject to the terms of the Mozilla Public
4
3
  * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -15,6 +14,8 @@ import type { DocumentLifecycleContext } from '@byline/core/services'
15
14
  import { deleteDocument as deleteDocumentService } from '@byline/core/services'
16
15
 
17
16
  import { ensureCollection } from '../../integrations/api-utils.js'
17
+ import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
18
+ import { withDocumentMutationErrors } from '../document-mutation-errors.js'
18
19
  import { toDeleteDocumentResponse } from './delete-outcome.js'
19
20
 
20
21
  // ---------------------------------------------------------------------------
@@ -22,6 +23,7 @@ import { toDeleteDocumentResponse } from './delete-outcome.js'
22
23
  // ---------------------------------------------------------------------------
23
24
 
24
25
  export const deleteDocument = createServerFn({ method: 'POST' })
26
+ .middleware([adminSessionMiddleware])
25
27
  .validator((input: { expectedRevision: number; collection: string; id: string }) => input)
26
28
  .handler(
27
29
  withDocumentMutationErrors(async ({ data: input }) => {
@@ -1,4 +1,3 @@
1
- import { withDocumentMutationErrors } from '../document-mutation-errors.js'
2
1
  /**
3
2
  * This Source Code is subject to the terms of the Mozilla Public
4
3
  * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -15,6 +14,8 @@ import type { DocumentLifecycleContext, DuplicateDocumentResult } from '@byline/
15
14
  import { duplicateDocument } from '@byline/core/services'
16
15
 
17
16
  import { ensureCollection } from '../../integrations/api-utils.js'
17
+ import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
18
+ import { withDocumentMutationErrors } from '../document-mutation-errors.js'
18
19
  import {
19
20
  type CollectionDocumentCommittedHookFailureResponse,
20
21
  toCommittedDocumentHookFailureResponse,
@@ -36,6 +37,7 @@ import {
36
37
  * TanStack Start's transport layer for the client to branch on.
37
38
  */
38
39
  export const duplicateCollectionDocument = createServerFn({ method: 'POST' })
40
+ .middleware([adminSessionMiddleware])
39
41
  .validator((input: { expectedRevision: number; collection: string; id: string }) => input)
40
42
  .handler(
41
43
  withDocumentMutationErrors(
@@ -1,4 +1,3 @@
1
- import { withEditableRevision } from '../editable-revision.js'
2
1
  /**
3
2
  * This Source Code is subject to the terms of the Mozilla Public
4
3
  * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -21,7 +20,9 @@ import {
21
20
  } from '@byline/core'
22
21
 
23
22
  import { ensureCollection } from '../../integrations/api-utils.js'
23
+ import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
24
24
  import { resolveAdminDocumentRead } from '../admin-document-presentation.js'
25
+ import { withEditableRevision } from '../editable-revision.js'
25
26
  import { serialise } from './utils'
26
27
 
27
28
  // ---------------------------------------------------------------------------
@@ -29,6 +30,7 @@ import { serialise } from './utils'
29
30
  // ---------------------------------------------------------------------------
30
31
 
31
32
  const getDocumentFn = createServerFn({ method: 'GET' })
33
+ .middleware([adminSessionMiddleware])
32
34
  .validator(
33
35
  (input: {
34
36
  collection: string
@@ -177,6 +179,7 @@ const getDocumentFn = createServerFn({ method: 'GET' })
177
179
  // ---------------------------------------------------------------------------
178
180
 
179
181
  const getDocumentByVersionFn = createServerFn({ method: 'GET' })
182
+ .middleware([adminSessionMiddleware])
180
183
  .validator((input: { collection: string; versionId: string; locale?: string }) => input)
181
184
  .handler(async ({ data }) => {
182
185
  const { collection: path, versionId, locale } = data
@@ -12,6 +12,7 @@ import { getAdminBylineClient } from '@byline/client/server'
12
12
  import { ERR_NOT_FOUND, getCollectionSchemasForPath, getLogger } from '@byline/core'
13
13
 
14
14
  import { ensureCollection } from '../../integrations/api-utils.js'
15
+ import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
15
16
  import { type ActorLabelMap, resolveActorLabels } from './actors.js'
16
17
  import { serialise } from './utils'
17
18
 
@@ -32,6 +33,7 @@ export interface HistorySearchParams {
32
33
  // ---------------------------------------------------------------------------
33
34
 
34
35
  export const getCollectionDocumentHistory = createServerFn({ method: 'GET' })
36
+ .middleware([adminSessionMiddleware])
35
37
  .validator((input: { collection: string; id: string; params: HistorySearchParams }) => input)
36
38
  .handler(async ({ data }) => {
37
39
  const { collection: path, id, params } = data
@@ -1,4 +1,3 @@
1
- import { withEditableRevision } from '../editable-revision.js'
2
1
  /**
3
2
  * This Source Code is subject to the terms of the Mozilla Public
4
3
  * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -25,6 +24,8 @@ import {
25
24
 
26
25
  import { ensureCollection } from '../../integrations/api-utils.js'
27
26
  import { bylineCore } from '../../integrations/byline-core.js'
27
+ import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
28
+ import { withEditableRevision } from '../editable-revision.js'
28
29
  import { resolveListViewState, sortableFieldNames } from './list-view-state.js'
29
30
  import { serialise } from './utils'
30
31
  import type { ListViewPreferenceValue } from './list-view-state.js'
@@ -49,6 +50,7 @@ export interface CollectionSearchParams {
49
50
  // ---------------------------------------------------------------------------
50
51
 
51
52
  export const getCollectionDocuments = createServerFn({ method: 'GET' })
53
+ .middleware([adminSessionMiddleware])
52
54
  .validator((input: { collection: string; params: CollectionSearchParams }) => input)
53
55
  .handler(async ({ data }) => {
54
56
  const { collection: path, params } = data
@@ -26,10 +26,12 @@ import { getAdminBylineClient } from '@byline/client/server'
26
26
  import { ERR_NOT_FOUND, getLogger } from '@byline/core'
27
27
 
28
28
  import { ensureCollection } from '../../integrations/api-utils.js'
29
+ import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
29
30
 
30
31
  export type { ReindexResult }
31
32
 
32
33
  export const reindexCollection = createServerFn({ method: 'POST' })
34
+ .middleware([adminSessionMiddleware])
33
35
  .validator((input: { collection: string }) => input)
34
36
  .handler(async ({ data }): Promise<ReindexResult> => {
35
37
  const { collection } = data
@@ -1,4 +1,3 @@
1
- import { withDocumentMutationErrors } from '../document-mutation-errors.js'
2
1
  /**
3
2
  * This Source Code is subject to the terms of the Mozilla Public
4
3
  * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -13,6 +12,8 @@ import { getAdminRequestContext } from '@byline/client/server'
13
12
  import { ERR_NOT_FOUND, getLogger, getServerConfig, reorderDocument } from '@byline/core'
14
13
 
15
14
  import { ensureCollection } from '../../integrations/api-utils.js'
15
+ import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
16
+ import { withDocumentMutationErrors } from '../document-mutation-errors.js'
16
17
 
17
18
  // ---------------------------------------------------------------------------
18
19
  // Reorder a single document within an `orderable: true` collection.
@@ -30,6 +31,7 @@ import { ensureCollection } from '../../integrations/api-utils.js'
30
31
  // ---------------------------------------------------------------------------
31
32
 
32
33
  export const reorderCollectionDocument = createServerFn({ method: 'POST' })
34
+ .middleware([adminSessionMiddleware])
33
35
  .validator(
34
36
  (input: {
35
37
  expectedRevision: number
@@ -1,4 +1,3 @@
1
- import { withDocumentMutationErrors } from '../document-mutation-errors.js'
2
1
  /**
3
2
  * This Source Code is subject to the terms of the Mozilla Public
4
3
  * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -15,6 +14,8 @@ import type { DocumentLifecycleContext } from '@byline/core/services'
15
14
  import { restoreDocumentVersion as restoreDocumentVersionService } from '@byline/core/services'
16
15
 
17
16
  import { ensureCollection } from '../../integrations/api-utils.js'
17
+ import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
18
+ import { withDocumentMutationErrors } from '../document-mutation-errors.js'
18
19
  import { toCommittedDocumentHookFailureResponse } from './save-outcome.js'
19
20
 
20
21
  // ---------------------------------------------------------------------------
@@ -22,6 +23,7 @@ import { toCommittedDocumentHookFailureResponse } from './save-outcome.js'
22
23
  // ---------------------------------------------------------------------------
23
24
 
24
25
  export const restoreDocumentVersion = createServerFn({ method: 'POST' })
26
+ .middleware([adminSessionMiddleware])
25
27
  .validator(
26
28
  (input: { expectedRevision: number; collection: string; id: string; versionId: string }) =>
27
29
  input
@@ -1,3 +1,14 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+
9
+ // Handler-level tests isolate transport; session-middleware tests exercise the real pre-handler boundary.
10
+ vi.mock('../../integrations/session-middleware.js', () => ({ adminSessionMiddleware: {} }))
11
+
1
12
  import { createSuperAdminContext } from '@byline/auth'
2
13
  import {
3
14
  defineCollection,
@@ -16,6 +27,9 @@ vi.mock('@tanstack/react-start', () => ({
16
27
  createServerFn: () => {
17
28
  let validate = (value: unknown) => value
18
29
  const chain = {
30
+ middleware() {
31
+ return chain
32
+ },
19
33
  validator(fn: (value: unknown) => unknown) {
20
34
  validate = fn
21
35
  return chain
@@ -1,4 +1,3 @@
1
- import { withDocumentMutationErrors } from '../document-mutation-errors.js'
2
1
  /**
3
2
  * This Source Code is subject to the terms of the Mozilla Public
4
3
  * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -22,6 +21,8 @@ import {
22
21
  import { listDocumentPublishSchedules } from '@byline/core/services'
23
22
 
24
23
  import { bylineCore } from '../../integrations/byline-core.js'
24
+ import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
25
+ import { withDocumentMutationErrors } from '../document-mutation-errors.js'
25
26
  import { omitScheduleExecutionState } from './scheduled-publication-response.js'
26
27
  import { serialise } from './utils.js'
27
28
 
@@ -138,14 +139,17 @@ async function scheduledPublicationRuntime(): Promise<ScheduledPublicationRuntim
138
139
  }
139
140
 
140
141
  /** Authenticated feature discovery for the admin shell and health warning. */
141
- export const getScheduledPublicationRuntime = createServerFn({ method: 'GET' }).handler(
142
- withDocumentMutationErrors(async () => {
143
- await getAdminRequestContext()
144
- return scheduledPublicationRuntime()
145
- })
146
- )
142
+ export const getScheduledPublicationRuntime = createServerFn({ method: 'GET' })
143
+ .middleware([adminSessionMiddleware])
144
+ .handler(
145
+ withDocumentMutationErrors(async () => {
146
+ await getAdminRequestContext()
147
+ return scheduledPublicationRuntime()
148
+ })
149
+ )
147
150
 
148
151
  export const scheduleCollectionDocumentPublish = createServerFn({ method: 'POST' })
152
+ .middleware([adminSessionMiddleware])
149
153
  .validator(
150
154
  (input: {
151
155
  expectedRevision: number
@@ -170,6 +174,7 @@ export const scheduleCollectionDocumentPublish = createServerFn({ method: 'POST'
170
174
  )
171
175
 
172
176
  export const confirmCollectionDocumentScheduledPublish = createServerFn({ method: 'POST' })
177
+ .middleware([adminSessionMiddleware])
173
178
  .validator(
174
179
  (input: {
175
180
  expectedRevision: number
@@ -192,6 +197,7 @@ export const confirmCollectionDocumentScheduledPublish = createServerFn({ method
192
197
  )
193
198
 
194
199
  export const cancelCollectionDocumentScheduledPublish = createServerFn({ method: 'POST' })
200
+ .middleware([adminSessionMiddleware])
195
201
  .validator((input: { expectedRevision: number; collection: string; id: string }) => input)
196
202
  .handler(
197
203
  withDocumentMutationErrors(async ({ data }) => {
@@ -210,6 +216,7 @@ export const cancelCollectionDocumentScheduledPublish = createServerFn({ method:
210
216
  )
211
217
 
212
218
  export const listScheduledPublications = createServerFn({ method: 'GET' })
219
+ .middleware([adminSessionMiddleware])
213
220
  .validator(
214
221
  (input: {
215
222
  states?: readonly DocumentPublishScheduleState[]
@@ -27,6 +27,7 @@ import { ERR_NOT_FOUND, getLogger } from '@byline/core'
27
27
 
28
28
  import { ensureCollection } from '../../integrations/api-utils.js'
29
29
  import { bylineCore } from '../../integrations/byline-core.js'
30
+ import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
30
31
 
31
32
  export interface SetListViewPreferenceInput {
32
33
  collection: string
@@ -38,6 +39,7 @@ export interface SetListViewPreferenceInput {
38
39
  }
39
40
 
40
41
  export const setListViewPreference = createServerFn({ method: 'POST' })
42
+ .middleware([adminSessionMiddleware])
41
43
  .validator((input: SetListViewPreferenceInput) => input)
42
44
  .handler(async ({ data }) => {
43
45
  // Scopes are keyed by collection path — refuse to mint rows for
@@ -11,6 +11,7 @@ import { createServerFn } from '@tanstack/react-start'
11
11
  import { getAdminBylineClient } from '@byline/client/server'
12
12
 
13
13
  import { ensureCollection } from '../../integrations/api-utils.js'
14
+ import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
14
15
 
15
16
  // ---------------------------------------------------------------------------
16
17
  // Shared types
@@ -26,6 +27,7 @@ export interface CollectionStatusCount {
26
27
  // ---------------------------------------------------------------------------
27
28
 
28
29
  const getCollectionStatsFn = createServerFn({ method: 'GET' })
30
+ .middleware([adminSessionMiddleware])
29
31
  .validator((input: { collection: string }) => input)
30
32
  .handler(async ({ data }) => {
31
33
  const config = await ensureCollection(data.collection)
@@ -1,4 +1,3 @@
1
- import { withDocumentMutationErrors } from '../document-mutation-errors.js'
2
1
  /**
3
2
  * This Source Code is subject to the terms of the Mozilla Public
4
3
  * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -18,12 +17,15 @@ import {
18
17
  } from '@byline/core/services'
19
18
 
20
19
  import { ensureCollection } from '../../integrations/api-utils.js'
20
+ import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
21
+ import { withDocumentMutationErrors } from '../document-mutation-errors.js'
21
22
 
22
23
  // ---------------------------------------------------------------------------
23
24
  // Change document workflow status
24
25
  // ---------------------------------------------------------------------------
25
26
 
26
27
  export const updateDocumentStatus = createServerFn({ method: 'POST' })
28
+ .middleware([adminSessionMiddleware])
27
29
  .validator(
28
30
  (input: { expectedRevision: number; collection: string; id: string; status: string }) => input
29
31
  )
@@ -72,6 +74,7 @@ export const updateDocumentStatus = createServerFn({ method: 'POST' })
72
74
  // ---------------------------------------------------------------------------
73
75
 
74
76
  export const unpublishDocument = createServerFn({ method: 'POST' })
77
+ .middleware([adminSessionMiddleware])
75
78
  .validator((input: { expectedRevision: number; collection: string; id: string }) => input)
76
79
  .handler(
77
80
  withDocumentMutationErrors(async ({ data: input }) => {
@@ -1,4 +1,3 @@
1
- import { withDocumentMutationErrors } from '../document-mutation-errors.js'
2
1
  /**
3
2
  * This Source Code is subject to the terms of the Mozilla Public
4
3
  * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -21,6 +20,8 @@ import { getAdminBylineClient } from '@byline/client/server'
21
20
  import { createReadContext, ERR_NOT_FOUND, getLogger } from '@byline/core'
22
21
 
23
22
  import { ensureCollection } from '../../integrations/api-utils.js'
23
+ import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
24
+ import { withDocumentMutationErrors } from '../document-mutation-errors.js'
24
25
  import { placeAdminTreeNode, removeAdminTreeNode } from './tree-mutation.js'
25
26
  import { getAdminTreeParent } from './tree-read.js'
26
27
 
@@ -29,6 +30,7 @@ import { getAdminTreeParent } from './tree-read.js'
29
30
  // ---------------------------------------------------------------------------
30
31
 
31
32
  export const placeTreeNode = createServerFn({ method: 'POST' })
33
+ .middleware([adminSessionMiddleware])
32
34
  .validator(
33
35
  (input: {
34
36
  expectedRevision: number
@@ -67,6 +69,7 @@ export const placeTreeNode = createServerFn({ method: 'POST' })
67
69
  // ---------------------------------------------------------------------------
68
70
 
69
71
  export const removeFromTree = createServerFn({ method: 'POST' })
72
+ .middleware([adminSessionMiddleware])
70
73
  .validator(
71
74
  (input: {
72
75
  expectedRevision: number
@@ -102,6 +105,7 @@ export const removeFromTree = createServerFn({ method: 'POST' })
102
105
  // ---------------------------------------------------------------------------
103
106
 
104
107
  export const getTreeAncestors = createServerFn({ method: 'GET' })
108
+ .middleware([adminSessionMiddleware])
105
109
  .validator((input: { collection: string; documentId: string }) => input)
106
110
  .handler(
107
111
  withDocumentMutationErrors(async ({ data }) => {
@@ -135,6 +139,7 @@ export const getTreeAncestors = createServerFn({ method: 'GET' })
135
139
  // ---------------------------------------------------------------------------
136
140
 
137
141
  export const getTreeParent = createServerFn({ method: 'GET' })
142
+ .middleware([adminSessionMiddleware])
138
143
  .validator((input: { collection: string; documentId: string }) => input)
139
144
  .handler(
140
145
  withDocumentMutationErrors(async ({ data }) => {
@@ -173,6 +178,7 @@ export interface CollectionTreeRow {
173
178
  }
174
179
 
175
180
  export const getCollectionTree = createServerFn({ method: 'GET' })
181
+ .middleware([adminSessionMiddleware])
176
182
  .validator((input: { collection: string; locale?: string }) => input)
177
183
  .handler(
178
184
  withDocumentMutationErrors(async ({ data }) => {
@@ -1,4 +1,3 @@
1
- import { withDocumentMutationErrors } from '../document-mutation-errors.js'
2
1
  /**
3
2
  * This Source Code is subject to the terms of the Mozilla Public
4
3
  * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -16,6 +15,8 @@ import type { DocumentLifecycleContext } from '@byline/core/services'
16
15
  import { saveDocument, updateDocumentSystemFields } from '@byline/core/services'
17
16
 
18
17
  import { ensureCollection } from '../../integrations/api-utils.js'
18
+ import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
19
+ import { withDocumentMutationErrors } from '../document-mutation-errors.js'
19
20
  import { toCommittedDocumentHookFailureResponse } from './save-outcome.js'
20
21
 
21
22
  // ---------------------------------------------------------------------------
@@ -24,6 +25,7 @@ import { toCommittedDocumentHookFailureResponse } from './save-outcome.js'
24
25
  // ---------------------------------------------------------------------------
25
26
 
26
27
  export const updateCollectionDocumentWithPatches = createServerFn({ method: 'POST' })
28
+ .middleware([adminSessionMiddleware])
27
29
  .validator(
28
30
  (input: {
29
31
  collection: string
@@ -102,6 +104,7 @@ export const updateCollectionDocumentWithPatches = createServerFn({ method: 'POS
102
104
  // ---------------------------------------------------------------------------
103
105
 
104
106
  export const updateCollectionDocumentSystemFields = createServerFn({ method: 'POST' })
107
+ .middleware([adminSessionMiddleware])
105
108
  .validator(
106
109
  (input: {
107
110
  collection: string