@atproto/bsky 0.0.273 → 0.0.275

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 (255) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/dist/api/app/bsky/actor/getSuggestions.d.ts.map +1 -1
  3. package/dist/api/app/bsky/actor/getSuggestions.js +7 -2
  4. package/dist/api/app/bsky/actor/getSuggestions.js.map +1 -1
  5. package/dist/api/app/bsky/actor/searchActors.d.ts.map +1 -1
  6. package/dist/api/app/bsky/actor/searchActors.js +13 -6
  7. package/dist/api/app/bsky/actor/searchActors.js.map +1 -1
  8. package/dist/api/app/bsky/bookmark/getBookmarks.d.ts.map +1 -1
  9. package/dist/api/app/bsky/bookmark/getBookmarks.js +7 -2
  10. package/dist/api/app/bsky/bookmark/getBookmarks.js.map +1 -1
  11. package/dist/api/app/bsky/contact/getMatches.d.ts.map +1 -1
  12. package/dist/api/app/bsky/contact/getMatches.js +8 -2
  13. package/dist/api/app/bsky/contact/getMatches.js.map +1 -1
  14. package/dist/api/app/bsky/feed/getActorFeeds.d.ts.map +1 -1
  15. package/dist/api/app/bsky/feed/getActorFeeds.js +7 -2
  16. package/dist/api/app/bsky/feed/getActorFeeds.js.map +1 -1
  17. package/dist/api/app/bsky/feed/getActorLikes.d.ts.map +1 -1
  18. package/dist/api/app/bsky/feed/getActorLikes.js +7 -2
  19. package/dist/api/app/bsky/feed/getActorLikes.js.map +1 -1
  20. package/dist/api/app/bsky/feed/getAuthorFeed.d.ts.map +1 -1
  21. package/dist/api/app/bsky/feed/getAuthorFeed.js +7 -2
  22. package/dist/api/app/bsky/feed/getAuthorFeed.js.map +1 -1
  23. package/dist/api/app/bsky/feed/getFeed.d.ts +13 -0
  24. package/dist/api/app/bsky/feed/getFeed.d.ts.map +1 -1
  25. package/dist/api/app/bsky/feed/getFeed.js +41 -8
  26. package/dist/api/app/bsky/feed/getFeed.js.map +1 -1
  27. package/dist/api/app/bsky/feed/getLikes.d.ts.map +1 -1
  28. package/dist/api/app/bsky/feed/getLikes.js +7 -2
  29. package/dist/api/app/bsky/feed/getLikes.js.map +1 -1
  30. package/dist/api/app/bsky/feed/getListFeed.d.ts.map +1 -1
  31. package/dist/api/app/bsky/feed/getListFeed.js +7 -2
  32. package/dist/api/app/bsky/feed/getListFeed.js.map +1 -1
  33. package/dist/api/app/bsky/feed/getQuotes.d.ts.map +1 -1
  34. package/dist/api/app/bsky/feed/getQuotes.js +7 -2
  35. package/dist/api/app/bsky/feed/getQuotes.js.map +1 -1
  36. package/dist/api/app/bsky/feed/getRepostedBy.d.ts.map +1 -1
  37. package/dist/api/app/bsky/feed/getRepostedBy.js +7 -2
  38. package/dist/api/app/bsky/feed/getRepostedBy.js.map +1 -1
  39. package/dist/api/app/bsky/feed/getSuggestedFeeds.d.ts.map +1 -1
  40. package/dist/api/app/bsky/feed/getSuggestedFeeds.js +20 -13
  41. package/dist/api/app/bsky/feed/getSuggestedFeeds.js.map +1 -1
  42. package/dist/api/app/bsky/feed/getTimeline.d.ts.map +1 -1
  43. package/dist/api/app/bsky/feed/getTimeline.js +7 -2
  44. package/dist/api/app/bsky/feed/getTimeline.js.map +1 -1
  45. package/dist/api/app/bsky/feed/searchPosts.d.ts.map +1 -1
  46. package/dist/api/app/bsky/feed/searchPosts.js +14 -7
  47. package/dist/api/app/bsky/feed/searchPosts.js.map +1 -1
  48. package/dist/api/app/bsky/feed/searchPostsV2.d.ts.map +1 -1
  49. package/dist/api/app/bsky/feed/searchPostsV2.js +17 -9
  50. package/dist/api/app/bsky/feed/searchPostsV2.js.map +1 -1
  51. package/dist/api/app/bsky/graph/getActorStarterPacks.d.ts.map +1 -1
  52. package/dist/api/app/bsky/graph/getActorStarterPacks.js +7 -2
  53. package/dist/api/app/bsky/graph/getActorStarterPacks.js.map +1 -1
  54. package/dist/api/app/bsky/graph/getBlocks.d.ts.map +1 -1
  55. package/dist/api/app/bsky/graph/getBlocks.js +7 -2
  56. package/dist/api/app/bsky/graph/getBlocks.js.map +1 -1
  57. package/dist/api/app/bsky/graph/getFollowers.d.ts.map +1 -1
  58. package/dist/api/app/bsky/graph/getFollowers.js +10 -18
  59. package/dist/api/app/bsky/graph/getFollowers.js.map +1 -1
  60. package/dist/api/app/bsky/graph/getFollows.d.ts.map +1 -1
  61. package/dist/api/app/bsky/graph/getFollows.js +7 -2
  62. package/dist/api/app/bsky/graph/getFollows.js.map +1 -1
  63. package/dist/api/app/bsky/graph/getList.d.ts.map +1 -1
  64. package/dist/api/app/bsky/graph/getList.js +7 -2
  65. package/dist/api/app/bsky/graph/getList.js.map +1 -1
  66. package/dist/api/app/bsky/graph/getListBlocks.d.ts.map +1 -1
  67. package/dist/api/app/bsky/graph/getListBlocks.js +7 -2
  68. package/dist/api/app/bsky/graph/getListBlocks.js.map +1 -1
  69. package/dist/api/app/bsky/graph/getListMutes.d.ts.map +1 -1
  70. package/dist/api/app/bsky/graph/getListMutes.js +7 -2
  71. package/dist/api/app/bsky/graph/getListMutes.js.map +1 -1
  72. package/dist/api/app/bsky/graph/getLists.d.ts.map +1 -1
  73. package/dist/api/app/bsky/graph/getLists.js +9 -4
  74. package/dist/api/app/bsky/graph/getLists.js.map +1 -1
  75. package/dist/api/app/bsky/graph/getListsWithMembership.d.ts.map +1 -1
  76. package/dist/api/app/bsky/graph/getListsWithMembership.js +9 -4
  77. package/dist/api/app/bsky/graph/getListsWithMembership.js.map +1 -1
  78. package/dist/api/app/bsky/graph/getMutes.d.ts.map +1 -1
  79. package/dist/api/app/bsky/graph/getMutes.js +22 -30
  80. package/dist/api/app/bsky/graph/getMutes.js.map +1 -1
  81. package/dist/api/app/bsky/graph/getStarterPacksWithMembership.d.ts.map +1 -1
  82. package/dist/api/app/bsky/graph/getStarterPacksWithMembership.js +7 -2
  83. package/dist/api/app/bsky/graph/getStarterPacksWithMembership.js.map +1 -1
  84. package/dist/api/app/bsky/graph/searchStarterPacks.d.ts.map +1 -1
  85. package/dist/api/app/bsky/graph/searchStarterPacks.js +13 -6
  86. package/dist/api/app/bsky/graph/searchStarterPacks.js.map +1 -1
  87. package/dist/api/app/bsky/graph/searchStarterPacksV2.d.ts.map +1 -1
  88. package/dist/api/app/bsky/graph/searchStarterPacksV2.js +7 -2
  89. package/dist/api/app/bsky/graph/searchStarterPacksV2.js.map +1 -1
  90. package/dist/api/app/bsky/notification/listActivitySubscriptions.d.ts.map +1 -1
  91. package/dist/api/app/bsky/notification/listActivitySubscriptions.js +7 -2
  92. package/dist/api/app/bsky/notification/listActivitySubscriptions.js.map +1 -1
  93. package/dist/api/app/bsky/notification/listNotifications.d.ts.map +1 -1
  94. package/dist/api/app/bsky/notification/listNotifications.js +17 -35
  95. package/dist/api/app/bsky/notification/listNotifications.js.map +1 -1
  96. package/dist/api/app/bsky/unspecced/getPopularFeedGenerators.d.ts.map +1 -1
  97. package/dist/api/app/bsky/unspecced/getPopularFeedGenerators.js +49 -43
  98. package/dist/api/app/bsky/unspecced/getPopularFeedGenerators.js.map +1 -1
  99. package/dist/api/app/bsky/unspecced/getTrendingTopics.d.ts.map +1 -1
  100. package/dist/api/app/bsky/unspecced/getTrendingTopics.js +3 -14
  101. package/dist/api/app/bsky/unspecced/getTrendingTopics.js.map +1 -1
  102. package/dist/api/app/bsky/unspecced/getTrends.d.ts.map +1 -1
  103. package/dist/api/app/bsky/unspecced/getTrends.js +3 -14
  104. package/dist/api/app/bsky/unspecced/getTrends.js.map +1 -1
  105. package/dist/api/util.d.ts +15 -0
  106. package/dist/api/util.d.ts.map +1 -1
  107. package/dist/api/util.js +26 -0
  108. package/dist/api/util.js.map +1 -1
  109. package/dist/auth-verifier.d.ts.map +1 -1
  110. package/dist/auth-verifier.js +16 -9
  111. package/dist/auth-verifier.js.map +1 -1
  112. package/dist/config.d.ts +2 -0
  113. package/dist/config.d.ts.map +1 -1
  114. package/dist/config.js +5 -0
  115. package/dist/config.js.map +1 -1
  116. package/dist/data-plane/server/db/pagination.d.ts +8 -0
  117. package/dist/data-plane/server/db/pagination.d.ts.map +1 -1
  118. package/dist/data-plane/server/db/pagination.js +20 -2
  119. package/dist/data-plane/server/db/pagination.js.map +1 -1
  120. package/dist/data-plane/server/op-thread.d.ts +7 -0
  121. package/dist/data-plane/server/op-thread.d.ts.map +1 -0
  122. package/dist/data-plane/server/op-thread.js +71 -0
  123. package/dist/data-plane/server/op-thread.js.map +1 -0
  124. package/dist/data-plane/server/routes/activity-subscription.js +3 -3
  125. package/dist/data-plane/server/routes/activity-subscription.js.map +1 -1
  126. package/dist/data-plane/server/routes/blocks.js +6 -6
  127. package/dist/data-plane/server/routes/blocks.js.map +1 -1
  128. package/dist/data-plane/server/routes/bookmarks.js +3 -3
  129. package/dist/data-plane/server/routes/bookmarks.js.map +1 -1
  130. package/dist/data-plane/server/routes/drafts.js +3 -3
  131. package/dist/data-plane/server/routes/drafts.js.map +1 -1
  132. package/dist/data-plane/server/routes/feed-gens.js +14 -12
  133. package/dist/data-plane/server/routes/feed-gens.js.map +1 -1
  134. package/dist/data-plane/server/routes/feeds.d.ts.map +1 -1
  135. package/dist/data-plane/server/routes/feeds.js +36 -15
  136. package/dist/data-plane/server/routes/feeds.js.map +1 -1
  137. package/dist/data-plane/server/routes/follows.js +6 -6
  138. package/dist/data-plane/server/routes/follows.js.map +1 -1
  139. package/dist/data-plane/server/routes/likes.js +6 -6
  140. package/dist/data-plane/server/routes/likes.js.map +1 -1
  141. package/dist/data-plane/server/routes/lists.js +6 -6
  142. package/dist/data-plane/server/routes/lists.js.map +1 -1
  143. package/dist/data-plane/server/routes/mutes.js +7 -7
  144. package/dist/data-plane/server/routes/mutes.js.map +1 -1
  145. package/dist/data-plane/server/routes/notifs.js +3 -3
  146. package/dist/data-plane/server/routes/notifs.js.map +1 -1
  147. package/dist/data-plane/server/routes/quotes.js +3 -3
  148. package/dist/data-plane/server/routes/quotes.js.map +1 -1
  149. package/dist/data-plane/server/routes/records.d.ts +3 -1
  150. package/dist/data-plane/server/routes/records.d.ts.map +1 -1
  151. package/dist/data-plane/server/routes/records.js +41 -4
  152. package/dist/data-plane/server/routes/records.js.map +1 -1
  153. package/dist/data-plane/server/routes/reposts.js +6 -6
  154. package/dist/data-plane/server/routes/reposts.js.map +1 -1
  155. package/dist/data-plane/server/routes/search.js +9 -9
  156. package/dist/data-plane/server/routes/search.js.map +1 -1
  157. package/dist/data-plane/server/routes/starter-packs.js +3 -3
  158. package/dist/data-plane/server/routes/starter-packs.js.map +1 -1
  159. package/dist/data-plane/server/routes/threads.d.ts.map +1 -1
  160. package/dist/data-plane/server/routes/threads.js +3 -74
  161. package/dist/data-plane/server/routes/threads.js.map +1 -1
  162. package/dist/feature-gates/gates.d.ts +2 -1
  163. package/dist/feature-gates/gates.d.ts.map +1 -1
  164. package/dist/feature-gates/gates.js +2 -1
  165. package/dist/feature-gates/gates.js.map +1 -1
  166. package/dist/hydration/feed.d.ts +3 -0
  167. package/dist/hydration/feed.d.ts.map +1 -1
  168. package/dist/hydration/feed.js +12 -0
  169. package/dist/hydration/feed.js.map +1 -1
  170. package/dist/hydration/hydrator.d.ts.map +1 -1
  171. package/dist/hydration/hydrator.js +4 -2
  172. package/dist/hydration/hydrator.js.map +1 -1
  173. package/dist/image/server.d.ts +1 -1
  174. package/dist/image/server.d.ts.map +1 -1
  175. package/dist/image/server.js +40 -22
  176. package/dist/image/server.js.map +1 -1
  177. package/dist/lexicons/app/bsky/actor/contentVisibilityDeclaration.d.ts +3 -0
  178. package/dist/lexicons/app/bsky/actor/contentVisibilityDeclaration.d.ts.map +1 -0
  179. package/dist/lexicons/app/bsky/actor/contentVisibilityDeclaration.defs.d.ts +66 -0
  180. package/dist/lexicons/app/bsky/actor/contentVisibilityDeclaration.defs.d.ts.map +1 -0
  181. package/dist/lexicons/app/bsky/actor/contentVisibilityDeclaration.defs.js +26 -0
  182. package/dist/lexicons/app/bsky/actor/contentVisibilityDeclaration.defs.js.map +1 -0
  183. package/dist/lexicons/app/bsky/actor/contentVisibilityDeclaration.js +6 -0
  184. package/dist/lexicons/app/bsky/actor/contentVisibilityDeclaration.js.map +1 -0
  185. package/dist/lexicons/app/bsky/actor.d.ts +1 -0
  186. package/dist/lexicons/app/bsky/actor.d.ts.map +1 -1
  187. package/dist/lexicons/app/bsky/actor.js +1 -0
  188. package/dist/lexicons/app/bsky/actor.js.map +1 -1
  189. package/dist/lexicons/app/bsky/authCreatePosts.defs.d.ts.map +1 -1
  190. package/dist/lexicons/app/bsky/authCreatePosts.defs.js +5 -0
  191. package/dist/lexicons/app/bsky/authCreatePosts.defs.js.map +1 -1
  192. package/dist/lexicons/app/bsky/authFullApp.defs.d.ts.map +1 -1
  193. package/dist/lexicons/app/bsky/authFullApp.defs.js +5 -0
  194. package/dist/lexicons/app/bsky/authFullApp.defs.js.map +1 -1
  195. package/dist/lexicons/app/bsky/embed/video.defs.d.ts.map +1 -1
  196. package/dist/lexicons/app/bsky/embed/video.defs.js +2 -4
  197. package/dist/lexicons/app/bsky/embed/video.defs.js.map +1 -1
  198. package/dist/lexicons/app/bsky/video/abortUpload.d.ts +3 -0
  199. package/dist/lexicons/app/bsky/video/abortUpload.d.ts.map +1 -0
  200. package/dist/lexicons/app/bsky/video/abortUpload.defs.d.ts +53 -0
  201. package/dist/lexicons/app/bsky/video/abortUpload.defs.d.ts.map +1 -0
  202. package/dist/lexicons/app/bsky/video/abortUpload.defs.js +26 -0
  203. package/dist/lexicons/app/bsky/video/abortUpload.defs.js.map +1 -0
  204. package/dist/lexicons/app/bsky/video/abortUpload.js +6 -0
  205. package/dist/lexicons/app/bsky/video/abortUpload.js.map +1 -0
  206. package/dist/lexicons/app/bsky/video/defs.defs.d.ts +1 -1
  207. package/dist/lexicons/app/bsky/video/defs.defs.d.ts.map +1 -1
  208. package/dist/lexicons/app/bsky/video/defs.defs.js.map +1 -1
  209. package/dist/lexicons/app/bsky/video/finishUpload.d.ts +3 -0
  210. package/dist/lexicons/app/bsky/video/finishUpload.d.ts.map +1 -0
  211. package/dist/lexicons/app/bsky/video/finishUpload.defs.d.ts +42 -0
  212. package/dist/lexicons/app/bsky/video/finishUpload.defs.d.ts.map +1 -0
  213. package/dist/lexicons/app/bsky/video/finishUpload.defs.js +30 -0
  214. package/dist/lexicons/app/bsky/video/finishUpload.defs.js.map +1 -0
  215. package/dist/lexicons/app/bsky/video/finishUpload.js +6 -0
  216. package/dist/lexicons/app/bsky/video/finishUpload.js.map +1 -0
  217. package/dist/lexicons/app/bsky/video/getUploadStatus.d.ts +3 -0
  218. package/dist/lexicons/app/bsky/video/getUploadStatus.d.ts.map +1 -0
  219. package/dist/lexicons/app/bsky/video/getUploadStatus.defs.d.ts +73 -0
  220. package/dist/lexicons/app/bsky/video/getUploadStatus.defs.d.ts.map +1 -0
  221. package/dist/lexicons/app/bsky/video/getUploadStatus.defs.js +30 -0
  222. package/dist/lexicons/app/bsky/video/getUploadStatus.defs.js.map +1 -0
  223. package/dist/lexicons/app/bsky/video/getUploadStatus.js +6 -0
  224. package/dist/lexicons/app/bsky/video/getUploadStatus.js.map +1 -0
  225. package/dist/lexicons/app/bsky/video/startUpload.d.ts +3 -0
  226. package/dist/lexicons/app/bsky/video/startUpload.d.ts.map +1 -0
  227. package/dist/lexicons/app/bsky/video/startUpload.defs.d.ts +63 -0
  228. package/dist/lexicons/app/bsky/video/startUpload.defs.d.ts.map +1 -0
  229. package/dist/lexicons/app/bsky/video/startUpload.defs.js +36 -0
  230. package/dist/lexicons/app/bsky/video/startUpload.defs.js.map +1 -0
  231. package/dist/lexicons/app/bsky/video/startUpload.js +6 -0
  232. package/dist/lexicons/app/bsky/video/startUpload.js.map +1 -0
  233. package/dist/lexicons/app/bsky/video/uploadPart.d.ts +3 -0
  234. package/dist/lexicons/app/bsky/video/uploadPart.d.ts.map +1 -0
  235. package/dist/lexicons/app/bsky/video/uploadPart.defs.d.ts +37 -0
  236. package/dist/lexicons/app/bsky/video/uploadPart.defs.d.ts.map +1 -0
  237. package/dist/lexicons/app/bsky/video/uploadPart.defs.js +31 -0
  238. package/dist/lexicons/app/bsky/video/uploadPart.defs.js.map +1 -0
  239. package/dist/lexicons/app/bsky/video/uploadPart.js +6 -0
  240. package/dist/lexicons/app/bsky/video/uploadPart.js.map +1 -0
  241. package/dist/lexicons/app/bsky/video.d.ts +5 -0
  242. package/dist/lexicons/app/bsky/video.d.ts.map +1 -1
  243. package/dist/lexicons/app/bsky/video.js +5 -0
  244. package/dist/lexicons/app/bsky/video.js.map +1 -1
  245. package/dist/proto/bsky_pb.d.ts +39 -0
  246. package/dist/proto/bsky_pb.d.ts.map +1 -1
  247. package/dist/proto/bsky_pb.js +55 -0
  248. package/dist/proto/bsky_pb.js.map +1 -1
  249. package/dist/views/index.d.ts.map +1 -1
  250. package/dist/views/index.js +2 -0
  251. package/dist/views/index.js.map +1 -1
  252. package/dist/views/types.d.ts +4 -1
  253. package/dist/views/types.d.ts.map +1 -1
  254. package/dist/views/types.js.map +1 -1
  255. package/package.json +12 -12
@@ -10,14 +10,7 @@ export default function (server, ctx) {
10
10
  handler: async ({ auth, params, req }) => {
11
11
  const viewer = auth.credentials.iss;
12
12
  const labelers = ctx.reqLabelers(req);
13
- const hydrateCtx = await ctx.hydrator.createContext({
14
- labelers,
15
- viewer,
16
- features: ctx.featureGatesClient.scope(ctx.featureGatesClient.parseUserContextFromHandler({
17
- viewer,
18
- req,
19
- })),
20
- });
13
+ const hydrateCtx = await ctx.hydrator.createContext({ labelers, viewer });
21
14
  const headers = noUndefinedVals({
22
15
  'accept-language': req.headers['accept-language'],
23
16
  'x-bsky-topics': Array.isArray(req.headers['x-bsky-topics'])
@@ -38,15 +31,11 @@ export default function (server, ctx) {
38
31
  }
39
32
  const skeleton = async (input) => {
40
33
  const { params, ctx } = input;
41
- // Route treatment users to iris (trending-topics v2), everyone else stays on
42
- // the existing hot-topic service.
43
- const useIris = params.hydrateCtx.features.checkGate(params.hydrateCtx.features.Gate.TrendingTopicsV2);
44
- const topicsClient = (useIris && ctx.irisClient) || ctx.topicsClient;
45
- if (!topicsClient) {
34
+ if (!ctx.irisClient) {
46
35
  // Use 501 instead of 500 as these are not considered retry-able by clients
47
36
  throw new MethodNotImplementedError('Topics agent not available');
48
37
  }
49
- const skeleton = await topicsClient.call(app.bsky.unspecced.getTrendsSkeleton, {
38
+ const skeleton = await ctx.irisClient.call(app.bsky.unspecced.getTrendsSkeleton, {
50
39
  limit: params.limit,
51
40
  viewer: params.hydrateCtx.viewer ?? undefined,
52
41
  }, {
@@ -1 +1 @@
1
- {"version":3,"file":"getTrends.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getTrends.ts"],"names":[],"mappings":"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","sourcesContent":["import { mapDefined, noUndefinedVals } from '@atproto/common'\nimport type { Client, DidString } from '@atproto/lex'\nimport { MethodNotImplementedError, type Server } from '@atproto/xrpc-server'\nimport type { AppContext } from '../../../../context.js'\nimport {\n type HydrateCtx,\n type Hydrator,\n mergeManyStates,\n} from '../../../../hydration/hydrator.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n type HydrationFn,\n type PresentationFn,\n type RulesFn,\n type SkeletonFn,\n createPipeline,\n} from '../../../../pipeline.js'\nimport type { Views } from '../../../../views/index.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const getTrends = createPipeline(skeleton, hydration, noBlocks, presentation)\n server.add(app.bsky.unspecced.getTrends, {\n auth: ctx.authVerifier.standardOptional,\n handler: async ({ auth, params, req }) => {\n const viewer = auth.credentials.iss\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({\n labelers,\n viewer,\n features: ctx.featureGatesClient.scope(\n ctx.featureGatesClient.parseUserContextFromHandler({\n viewer,\n req,\n }),\n ),\n })\n const headers = noUndefinedVals({\n 'accept-language': req.headers['accept-language'],\n 'x-bsky-topics': Array.isArray(req.headers['x-bsky-topics'])\n ? req.headers['x-bsky-topics'].join(',')\n : req.headers['x-bsky-topics'],\n })\n const result = await getTrends(\n {\n ...params,\n hydrateCtx,\n headers,\n },\n ctx,\n )\n return {\n encoding: 'application/json',\n body: result,\n }\n },\n })\n}\n\nconst skeleton: SkeletonFn<Context, Params, SkeletonState> = async (input) => {\n const { params, ctx } = input\n\n // Route treatment users to iris (trending-topics v2), everyone else stays on\n // the existing hot-topic service.\n const useIris = params.hydrateCtx.features.checkGate(\n params.hydrateCtx.features.Gate.TrendingTopicsV2,\n )\n const topicsClient = (useIris && ctx.irisClient) || ctx.topicsClient\n\n if (!topicsClient) {\n // Use 501 instead of 500 as these are not considered retry-able by clients\n throw new MethodNotImplementedError('Topics agent not available')\n }\n\n const skeleton = await topicsClient.call(\n app.bsky.unspecced.getTrendsSkeleton,\n {\n limit: params.limit,\n viewer: params.hydrateCtx.viewer ?? undefined,\n },\n {\n headers: params.headers,\n },\n )\n\n // @TODO Make sure upstream always provides this\n for (const trend of skeleton.trends) trend.dids ??= []\n\n return skeleton\n}\n\nconst hydration: HydrationFn<Context, Params, SkeletonState> = async (\n input,\n) => {\n const { ctx, params, skeleton } = input\n const dids = getUniqueDidsFromTrends(skeleton.trends)\n const pairs: Map<DidString, DidString[]> = new Map()\n const viewer = params.hydrateCtx.viewer\n if (viewer) pairs.set(viewer, dids)\n\n const [profileState, bidirectionalBlocks] = await Promise.all([\n ctx.hydrator.hydrateProfilesBasic(dids, params.hydrateCtx),\n ctx.hydrator.hydrateBidirectionalBlocks(pairs, params.hydrateCtx),\n ])\n\n return mergeManyStates(profileState, { bidirectionalBlocks })\n}\n\nconst noBlocks: RulesFn<Context, Params, SkeletonState> = (input) => {\n const { skeleton, params, hydration } = input\n const viewer = params.hydrateCtx.viewer\n if (!viewer) {\n return skeleton\n }\n\n const blocks = hydration.bidirectionalBlocks?.get(viewer)\n\n return {\n recIdStr: skeleton.recIdStr,\n trends: skeleton.trends.map((t) => ({\n ...t,\n dids: t.dids.filter((did) => !blocks?.get(did)),\n })),\n }\n}\n\nconst presentation: PresentationFn<\n Context,\n Params,\n SkeletonState,\n app.bsky.unspecced.getTrends.$OutputBody\n> = (input) => {\n const { ctx, skeleton, hydration } = input\n\n return {\n recIdStr: skeleton.recIdStr,\n trends: skeleton.trends.map((t) => ({\n topic: t.topic,\n displayName: t.displayName,\n description: t.description,\n link: t.link,\n startedAt: t.startedAt,\n postCount: t.postCount,\n status: t.status,\n category: t.category,\n actors: mapDefined(t.dids, (did) =>\n ctx.views.profileBasic(did, hydration),\n ),\n })),\n }\n}\n\ntype Context = {\n hydrator: Hydrator\n views: Views\n topicsClient: Client | undefined\n irisClient: Client | undefined\n}\n\ntype Params = app.bsky.unspecced.getTrendingTopics.$Params & {\n hydrateCtx: HydrateCtx & { viewer: string | null }\n headers: Record<string, string>\n}\n\ntype SkeletonState = app.bsky.unspecced.getTrendsSkeleton.$OutputBody\n\nfunction getUniqueDidsFromTrends(\n trends?: app.bsky.unspecced.defs.SkeletonTrend[],\n): DidString[] {\n if (!trends) return []\n\n const dids = new Set<DidString>()\n\n for (const trend of trends) {\n if (trend.dids) {\n for (const did of trend.dids) {\n dids.add(did)\n }\n }\n }\n\n return Array.from(dids)\n}\n"]}
1
+ {"version":3,"file":"getTrends.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getTrends.ts"],"names":[],"mappings":"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","sourcesContent":["import { mapDefined, noUndefinedVals } from '@atproto/common'\nimport type { Client, DidString } from '@atproto/lex'\nimport { MethodNotImplementedError, type Server } from '@atproto/xrpc-server'\nimport type { AppContext } from '../../../../context.js'\nimport {\n type HydrateCtx,\n type Hydrator,\n mergeManyStates,\n} from '../../../../hydration/hydrator.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n type HydrationFn,\n type PresentationFn,\n type RulesFn,\n type SkeletonFn,\n createPipeline,\n} from '../../../../pipeline.js'\nimport type { Views } from '../../../../views/index.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const getTrends = createPipeline(skeleton, hydration, noBlocks, presentation)\n server.add(app.bsky.unspecced.getTrends, {\n auth: ctx.authVerifier.standardOptional,\n handler: async ({ auth, params, req }) => {\n const viewer = auth.credentials.iss\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({ labelers, viewer })\n const headers = noUndefinedVals({\n 'accept-language': req.headers['accept-language'],\n 'x-bsky-topics': Array.isArray(req.headers['x-bsky-topics'])\n ? req.headers['x-bsky-topics'].join(',')\n : req.headers['x-bsky-topics'],\n })\n const result = await getTrends(\n {\n ...params,\n hydrateCtx,\n headers,\n },\n ctx,\n )\n return {\n encoding: 'application/json',\n body: result,\n }\n },\n })\n}\n\nconst skeleton: SkeletonFn<Context, Params, SkeletonState> = async (input) => {\n const { params, ctx } = input\n\n if (!ctx.irisClient) {\n // Use 501 instead of 500 as these are not considered retry-able by clients\n throw new MethodNotImplementedError('Topics agent not available')\n }\n\n const skeleton = await ctx.irisClient.call(\n app.bsky.unspecced.getTrendsSkeleton,\n {\n limit: params.limit,\n viewer: params.hydrateCtx.viewer ?? undefined,\n },\n {\n headers: params.headers,\n },\n )\n\n // @TODO Make sure upstream always provides this\n for (const trend of skeleton.trends) trend.dids ??= []\n\n return skeleton\n}\n\nconst hydration: HydrationFn<Context, Params, SkeletonState> = async (\n input,\n) => {\n const { ctx, params, skeleton } = input\n const dids = getUniqueDidsFromTrends(skeleton.trends)\n const pairs: Map<DidString, DidString[]> = new Map()\n const viewer = params.hydrateCtx.viewer\n if (viewer) pairs.set(viewer, dids)\n\n const [profileState, bidirectionalBlocks] = await Promise.all([\n ctx.hydrator.hydrateProfilesBasic(dids, params.hydrateCtx),\n ctx.hydrator.hydrateBidirectionalBlocks(pairs, params.hydrateCtx),\n ])\n\n return mergeManyStates(profileState, { bidirectionalBlocks })\n}\n\nconst noBlocks: RulesFn<Context, Params, SkeletonState> = (input) => {\n const { skeleton, params, hydration } = input\n const viewer = params.hydrateCtx.viewer\n if (!viewer) {\n return skeleton\n }\n\n const blocks = hydration.bidirectionalBlocks?.get(viewer)\n\n return {\n recIdStr: skeleton.recIdStr,\n trends: skeleton.trends.map((t) => ({\n ...t,\n dids: t.dids.filter((did) => !blocks?.get(did)),\n })),\n }\n}\n\nconst presentation: PresentationFn<\n Context,\n Params,\n SkeletonState,\n app.bsky.unspecced.getTrends.$OutputBody\n> = (input) => {\n const { ctx, skeleton, hydration } = input\n\n return {\n recIdStr: skeleton.recIdStr,\n trends: skeleton.trends.map((t) => ({\n topic: t.topic,\n displayName: t.displayName,\n description: t.description,\n link: t.link,\n startedAt: t.startedAt,\n postCount: t.postCount,\n status: t.status,\n category: t.category,\n actors: mapDefined(t.dids, (did) =>\n ctx.views.profileBasic(did, hydration),\n ),\n })),\n }\n}\n\ntype Context = {\n hydrator: Hydrator\n views: Views\n irisClient: Client | undefined\n}\n\ntype Params = app.bsky.unspecced.getTrendingTopics.$Params & {\n hydrateCtx: HydrateCtx & { viewer: string | null }\n headers: Record<string, string>\n}\n\ntype SkeletonState = app.bsky.unspecced.getTrendsSkeleton.$OutputBody\n\nfunction getUniqueDidsFromTrends(\n trends?: app.bsky.unspecced.defs.SkeletonTrend[],\n): DidString[] {\n if (!trends) return []\n\n const dids = new Set<DidString>()\n\n for (const trend of trends) {\n if (trend.dids) {\n for (const did of trend.dids) {\n dids.add(did)\n }\n }\n }\n\n return Array.from(dids)\n}\n"]}
@@ -10,6 +10,21 @@ type ResHeaderOpts = {
10
10
  };
11
11
  export declare const resHeaders: (opts: Partial<ResHeaderOpts>) => Record<string, string>;
12
12
  export declare const clearlyBadCursor: (cursor?: string) => boolean;
13
+ type PageFetch<R extends {
14
+ cursor?: string;
15
+ }> = (params: {
16
+ cursor?: string;
17
+ limit: number;
18
+ }) => Promise<R>;
19
+ export declare const fillPage: <F extends PageFetch<{
20
+ cursor?: string;
21
+ }>, T>(opts: {
22
+ cursor?: string;
23
+ limit: number;
24
+ maxRequests?: number;
25
+ fetch: F;
26
+ items: (result: Awaited<ReturnType<F>>) => T[];
27
+ }) => Promise<Awaited<ReturnType<F>>>;
13
28
  export declare const resolveSearchV2Override: (req: {
14
29
  headers: IncomingHttpHeaders;
15
30
  }, cfg: ServerConfig) => boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/api/util.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAA;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAChD,OAAO,EAAE,KAAK,cAAc,EAAuB,MAAM,YAAY,CAAA;AAErE,eAAO,MAAM,eAAe,gBAAgB,CAAA;AAC5C,eAAO,MAAM,wBAAwB,6BAA6B,CAAA;AAClE,eAAO,MAAM,gBAAgB,qBAAqB,CAAA;AAElD,KAAK,aAAa,GAAG;IACnB,QAAQ,EAAE,cAAc,CAAA;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB,CAAA;AAED,eAAO,MAAM,UAAU,SACf,OAAO,CAAC,aAAa,CAAC,KAC3B,MAAM,CAAC,MAAM,EAAE,MAAM,CASvB,CAAA;AAED,eAAO,MAAM,gBAAgB,YAAa,MAAM,YAG/C,CAAA;AAMD,eAAO,MAAM,uBAAuB,QAC7B;IAAE,OAAO,EAAE,mBAAmB,CAAA;CAAE,OAChC,YAAY,KAChB,OAMF,CAAA"}
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/api/util.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAA;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAChD,OAAO,EAAE,KAAK,cAAc,EAAuB,MAAM,YAAY,CAAA;AAErE,eAAO,MAAM,eAAe,gBAAgB,CAAA;AAC5C,eAAO,MAAM,wBAAwB,6BAA6B,CAAA;AAClE,eAAO,MAAM,gBAAgB,qBAAqB,CAAA;AAElD,KAAK,aAAa,GAAG;IACnB,QAAQ,EAAE,cAAc,CAAA;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB,CAAA;AAED,eAAO,MAAM,UAAU,SACf,OAAO,CAAC,aAAa,CAAC,KAC3B,MAAM,CAAC,MAAM,EAAE,MAAM,CASvB,CAAA;AAED,eAAO,MAAM,gBAAgB,YAAa,MAAM,YAG/C,CAAA;AAID,KAAK,SAAS,CAAC,CAAC,SAAS;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,IAAI,CAAC,MAAM,EAAE;IACvD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;CACd,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;AAEhB,eAAO,MAAM,QAAQ,GACnB,CAAC,SAAS,SAAS,CAAC;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EACxC,CAAC,QACK;IACN,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,EAAE,CAAC,CAAA;IACR,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAA;CAC/C,KAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CA2BjC,CAAA;AAMD,eAAO,MAAM,uBAAuB,QAC7B;IAAE,OAAO,EAAE,mBAAmB,CAAA;CAAE,OAChC,YAAY,KAChB,OAMF,CAAA"}
package/dist/api/util.js CHANGED
@@ -16,6 +16,32 @@ export const clearlyBadCursor = (cursor) => {
16
16
  // hallmark of v1 cursor, highly unlikely in v2 cursors based on time or rkeys
17
17
  return !!cursor?.includes('::');
18
18
  };
19
+ const DEFAULT_FILL_PAGE_MAX_REQUESTS = 10;
20
+ export const fillPage = async (opts) => {
21
+ const maxRequests = opts.maxRequests ?? DEFAULT_FILL_PAGE_MAX_REQUESTS;
22
+ const result = (await opts.fetch({
23
+ cursor: opts.cursor,
24
+ limit: opts.limit,
25
+ }));
26
+ const items = opts.items(result);
27
+ let cursor = result.cursor;
28
+ for (let requests = 1; requests < maxRequests && cursor && items.length < opts.limit; requests++) {
29
+ const previousCursor = cursor;
30
+ const page = (await opts.fetch({
31
+ cursor,
32
+ limit: opts.limit - items.length,
33
+ }));
34
+ items.push(...opts.items(page));
35
+ cursor = page.cursor;
36
+ if (cursor === previousCursor) {
37
+ cursor = undefined;
38
+ break;
39
+ }
40
+ if (!cursor)
41
+ break;
42
+ }
43
+ return { ...result, cursor };
44
+ };
19
45
  // @TEMPORARY backdoor to force search v2 via a request header, gated by the
20
46
  // BSKY_SEARCH_V2_OVERRIDE_HEADER env var. Remove once search v2 is fully rolled out.
21
47
  const SEARCH_V2_OVERRIDE_HEADER = 'x-bsky-search-v2-override';
@@ -1 +1 @@
1
- {"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/api/util.ts"],"names":[],"mappings":"AAEA,OAAO,EAAuB,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAErE,MAAM,CAAC,MAAM,eAAe,GAAG,aAAa,CAAA;AAC5C,MAAM,CAAC,MAAM,wBAAwB,GAAG,0BAA0B,CAAA;AAClE,MAAM,CAAC,MAAM,gBAAgB,GAAG,kBAAkB,CAAA;AAOlD,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,IAA4B,EACJ,EAAE;IAC1B,MAAM,OAAO,GAAG,EAAE,CAAA;IAClB,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,OAAO,CAAC,wBAAwB,CAAC,GAAG,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IACxE,CAAC;IACD,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC,OAAO,CAAA;IAC1C,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAAe,EAAE,EAAE;IAClD,8EAA8E;IAC9E,OAAO,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAA;AACjC,CAAC,CAAA;AAED,4EAA4E;AAC5E,qFAAqF;AACrF,MAAM,yBAAyB,GAAG,2BAA2B,CAAA;AAE7D,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,GAAqC,EACrC,GAAiB,EACR,EAAE;IACX,MAAM,QAAQ,GAAG,GAAG,CAAC,sBAAsB,CAAA;IAC3C,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAA;IAC3B,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAA;IACpD,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;IAC7D,OAAO,MAAM,KAAK,QAAQ,CAAA;AAC5B,CAAC,CAAA","sourcesContent":["import type { IncomingHttpHeaders } from 'node:http'\nimport type { ServerConfig } from '../config.js'\nimport { type ParsedLabelers, formatLabelerHeader } from '../util.js'\n\nexport const BSKY_USER_AGENT = 'BskyAppView'\nexport const ATPROTO_CONTENT_LABELERS = 'Atproto-Content-Labelers'\nexport const ATPROTO_REPO_REV = 'Atproto-Repo-Rev'\n\ntype ResHeaderOpts = {\n labelers: ParsedLabelers\n repoRev: string | null\n}\n\nexport const resHeaders = (\n opts: Partial<ResHeaderOpts>,\n): Record<string, string> => {\n const headers = {}\n if (opts.labelers) {\n headers[ATPROTO_CONTENT_LABELERS] = formatLabelerHeader(opts.labelers)\n }\n if (opts.repoRev) {\n headers[ATPROTO_REPO_REV] = opts.repoRev\n }\n return headers\n}\n\nexport const clearlyBadCursor = (cursor?: string) => {\n // hallmark of v1 cursor, highly unlikely in v2 cursors based on time or rkeys\n return !!cursor?.includes('::')\n}\n\n// @TEMPORARY backdoor to force search v2 via a request header, gated by the\n// BSKY_SEARCH_V2_OVERRIDE_HEADER env var. Remove once search v2 is fully rolled out.\nconst SEARCH_V2_OVERRIDE_HEADER = 'x-bsky-search-v2-override'\n\nexport const resolveSearchV2Override = (\n req: { headers: IncomingHttpHeaders },\n cfg: ServerConfig,\n): boolean => {\n const expected = cfg.searchV2OverrideHeader\n if (!expected) return false\n const value = req.headers[SEARCH_V2_OVERRIDE_HEADER]\n const header = Array.isArray(value) ? value.join(',') : value\n return header === expected\n}\n"]}
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/api/util.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IncomingHttpHeaders } from 'node:http'\nimport type { ServerConfig } from '../config.js'\nimport { type ParsedLabelers, formatLabelerHeader } from '../util.js'\n\nexport const BSKY_USER_AGENT = 'BskyAppView'\nexport const ATPROTO_CONTENT_LABELERS = 'Atproto-Content-Labelers'\nexport const ATPROTO_REPO_REV = 'Atproto-Repo-Rev'\n\ntype ResHeaderOpts = {\n labelers: ParsedLabelers\n repoRev: string | null\n}\n\nexport const resHeaders = (\n opts: Partial<ResHeaderOpts>,\n): Record<string, string> => {\n const headers = {}\n if (opts.labelers) {\n headers[ATPROTO_CONTENT_LABELERS] = formatLabelerHeader(opts.labelers)\n }\n if (opts.repoRev) {\n headers[ATPROTO_REPO_REV] = opts.repoRev\n }\n return headers\n}\n\nexport const clearlyBadCursor = (cursor?: string) => {\n // hallmark of v1 cursor, highly unlikely in v2 cursors based on time or rkeys\n return !!cursor?.includes('::')\n}\n\nconst DEFAULT_FILL_PAGE_MAX_REQUESTS = 10\n\ntype PageFetch<R extends { cursor?: string }> = (params: {\n cursor?: string\n limit: number\n}) => Promise<R>\n\nexport const fillPage = async <\n F extends PageFetch<{ cursor?: string }>,\n T,\n>(opts: {\n cursor?: string\n limit: number\n maxRequests?: number\n fetch: F\n items: (result: Awaited<ReturnType<F>>) => T[]\n}): Promise<Awaited<ReturnType<F>>> => {\n const maxRequests = opts.maxRequests ?? DEFAULT_FILL_PAGE_MAX_REQUESTS\n const result = (await opts.fetch({\n cursor: opts.cursor,\n limit: opts.limit,\n })) as Awaited<ReturnType<F>>\n const items = opts.items(result)\n let cursor = result.cursor\n for (\n let requests = 1;\n requests < maxRequests && cursor && items.length < opts.limit;\n requests++\n ) {\n const previousCursor = cursor\n const page = (await opts.fetch({\n cursor,\n limit: opts.limit - items.length,\n })) as Awaited<ReturnType<F>>\n items.push(...opts.items(page))\n cursor = page.cursor\n if (cursor === previousCursor) {\n cursor = undefined\n break\n }\n if (!cursor) break\n }\n return { ...result, cursor } as Awaited<ReturnType<F>>\n}\n\n// @TEMPORARY backdoor to force search v2 via a request header, gated by the\n// BSKY_SEARCH_V2_OVERRIDE_HEADER env var. Remove once search v2 is fully rolled out.\nconst SEARCH_V2_OVERRIDE_HEADER = 'x-bsky-search-v2-override'\n\nexport const resolveSearchV2Override = (\n req: { headers: IncomingHttpHeaders },\n cfg: ServerConfig,\n): boolean => {\n const expected = cfg.searchV2OverrideHeader\n if (!expected) return false\n const value = req.headers[SEARCH_V2_OVERRIDE_HEADER]\n const header = Array.isArray(value) ? value.join(',') : value\n return header === expected\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"auth-verifier.d.ts","sourceRoot":"","sources":["../src/auth-verifier.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth-verifier.d.ts","sourceRoot":"","sources":["../src/auth-verifier.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAA;AAEpD,OAAO,KAAK,OAAO,MAAM,SAAS,CAAA;AAIlC,OAAO,EAAE,KAAK,SAAS,EAAe,MAAM,cAAc,CAAA;AAC1D,OAAO,EAEL,KAAK,wBAAwB,EAI9B,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAEL,KAAK,eAAe,EAIrB,MAAM,uBAAuB,CAAA;AAG9B,KAAK,MAAM,GAAG;IACZ,GAAG,EAAE,OAAO,CAAC,OAAO,CAAA;CACrB,CAAA;AAED,KAAK,gBAAgB,GAAG;IACtB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAA;CACxC,CAAA;AAED,oBAAY,UAAU;IACpB,KAAK,IAAA;IACL,OAAO,IAAA;IACP,OAAO,IAAA;CACR;AAED,KAAK,UAAU,GAAG;IAChB,WAAW,EAAE;QACX,IAAI,EAAE,MAAM,CAAA;QACZ,GAAG,EAAE,IAAI,CAAA;KACV,CAAA;CACF,CAAA;AAED,KAAK,cAAc,GAAG;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,UAAU,CAAA;QAChB,8FAA8F;QAC9F,GAAG,EAAE,MAAM,CAAA;QACX,GAAG,EAAE,SAAS,GAAG,GAAG,SAAS,IAAI,MAAM,EAAE,CAAA;KAC1C,CAAA;CACF,CAAA;AAED,KAAK,UAAU,GAAG;IAChB,WAAW,EAAE;QACX,IAAI,EAAE,MAAM,CAAA;QACZ,KAAK,EAAE,OAAO,CAAA;KACf,CAAA;CACF,CAAA;AAED,KAAK,gBAAgB,GAAG;IACtB,WAAW,EAAE;QACX,IAAI,EAAE,aAAa,CAAA;QACnB,GAAG,EAAE,SAAS,CAAA;QACd,GAAG,EAAE,SAAS,GAAG,GAAG,SAAS,IAAI,MAAM,EAAE,CAAA;KAC1C,CAAA;CACF,CAAA;AAQD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,SAAS,CAAA;IACjB,qBAAqB,EAAE,SAAS,EAAE,CAAA;IAClC,aAAa,EAAE,SAAS,CAAA;IACxB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,oBAAoB,CAAC,EAAE,SAAS,CAAA;CACjC,CAAA;AAED,qBAAa,YAAY;IAQd,SAAS,EAAE,eAAe;IAP5B,MAAM,EAAE,SAAS,CAAA;IACjB,oBAAoB,EAAE,GAAG,CAAC,SAAS,CAAC,CAAA;IACpC,aAAa,EAAE,SAAS,CAAA;IAC/B,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,oBAAoB,CAAC,CAAW;IAExC,YACS,SAAS,EAAE,eAAe,EACjC,IAAI,EAAE,gBAAgB,EAUvB;IAGD,6BAA6B,SACpB,gBAAgB,WACX,MAAM,KAAG,OAAO,CAAC,cAAc,GAAG,UAAU,CAAC,CAkDxD;IAEH,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,GAAG,UAAU,CAAC,CAC/B;IAExC,QAAQ,QAAe,MAAM,KAAG,OAAO,CAAC,cAAc,CAAC,CAMtD;IAED,IAAI,QAAS,MAAM,KAAG,UAAU,CAW/B;IAED,cAAc,QACP,MAAM,KACV,OAAO,CAAC,cAAc,GAAG,UAAU,CAAC,CAMtC;IAED,sBAAsB,QACf,MAAM,KACV,OAAO,CAAC,cAAc,GAAG,UAAU,GAAG,UAAU,CAAC,CAkBnD;IAKD,eAAe,WAAkB,MAAM,KAAG,OAAO,CAAC,cAAc,CAAC,CAmDhE;IAED,UAAU,WAAkB,MAAM,KAAG,OAAO,CAAC,gBAAgB,CAAC,CAM7D;IAED,gBAAgB,WACN,MAAM,KACb,OAAO,CAAC,UAAU,GAAG,gBAAgB,CAAC,CAMxC;IAED,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO;;;;;;;;;;MAWlC;IAEK,gBAAgB,CACpB,QAAQ,SAAS;QACf,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;QACpB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;QAClB,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAA;KACxC,EACD,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ;aAoER,CAAC,SAAS,GAAG,GAAG,SAAS,IAAI,MAAM,EAAE,CAAC,GACxD,CAAC,QAAQ,SAAS;YAAE,GAAG,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC,CAAA;SAAE,GAAG,CAAC,GAAG,OAAO,CAAC;aAC9C,MAAM,GACxB,CAAC,QAAQ,SAAS;YAAE,GAAG,EAAE,MAAM,CAAC,SAAS,MAAM,CAAA;SAAE,GAAG,CAAC,GAAG,OAAO,CAAC;OAErE;IAED,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,IAAI,SAAS,GAAG,GAAG,SAAS,kBAAkB,CAK3E;IAED,SAAS,IAAI,UAAU,CAOtB;IAED,UAAU,CACR,KAAK,EAAE,cAAc,GAAG,UAAU,GAAG,gBAAgB,GAAG,UAAU;;;;;;;MAyBnE;CACF;AAsBD,eAAO,MAAM,cAAc,UAClB,MAAM,KACZ;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAY3C,CAAA;AAED,eAAO,MAAM,cAAc,aAAc,MAAM,YAAY,MAAM,KAAG,MAKnE,CAAA;AAkBD,eAAO,MAAM,qBAAqB,iBAAkB,MAAM,KAAG,SAE5D,CAAA;AAoBD,eAAO,MAAM,sBAAsB,EAAE,wBAgBpC,CAAA"}
@@ -1,13 +1,11 @@
1
1
  import crypto, {} from 'node:crypto';
2
+ import { secp256k1 } from '@noble/curves/secp256k1';
2
3
  import * as jose from 'jose';
3
- import KeyEncoderModule from 'key-encoder';
4
4
  import * as ui8 from 'uint8arrays';
5
5
  import { SECP256K1_JWT_ALG, parseDidKey } from '@atproto/crypto';
6
6
  import { isDidString } from '@atproto/lex';
7
7
  import { AuthRequiredError, cryptoVerifySignatureWithKey, parseReqNsid, verifyJwt as verifyServiceJwt, } from '@atproto/xrpc-server';
8
8
  import { Code, getKeyAsDidKey, isDataplaneError, unpackIdentityKeys, } from './data-plane/index.js';
9
- // key-encoder is CJS with exports.default; Node ESM interop wraps it as { default: Class }
10
- const KeyEncoder = ((m) => m.default ?? m)(KeyEncoderModule);
11
9
  export var RoleStatus;
12
10
  (function (RoleStatus) {
13
11
  RoleStatus[RoleStatus["Valid"] = 0] = "Valid";
@@ -325,15 +323,24 @@ export const buildBasicAuth = (username, password) => {
325
323
  return (BASIC +
326
324
  ui8.toString(ui8.fromString(`${username}:${password}`, 'utf8'), 'base64pad'));
327
325
  };
328
- const keyEncoder = new KeyEncoder('secp256k1');
326
+ const createSecp256k1KeyObject = (publicKey) => {
327
+ // accepts compressed or uncompressed keys; validates the point is on-curve
328
+ const point = secp256k1.ProjectivePoint.fromHex(publicKey).toRawBytes(false);
329
+ return crypto.createPublicKey({
330
+ format: 'jwk',
331
+ key: {
332
+ kty: 'EC',
333
+ crv: 'secp256k1',
334
+ x: ui8.toString(point.subarray(1, 33), 'base64url'),
335
+ y: ui8.toString(point.subarray(33, 65), 'base64url'),
336
+ },
337
+ });
338
+ };
329
339
  export const createPublicKeyObject = (publicKeyHex) => {
330
- const key = keyEncoder.encodePublic(publicKeyHex, 'raw', 'pem');
331
- return crypto.createPublicKey({ format: 'pem', key });
340
+ return createSecp256k1KeyObject(publicKeyHex);
332
341
  };
333
342
  const verifySig = (publicKey, data, sig) => {
334
- const keyEncoder = new KeyEncoder('secp256k1');
335
- const pemKey = keyEncoder.encodePublic(ui8.toString(publicKey, 'hex'), 'raw', 'pem');
336
- const key = crypto.createPublicKey({ format: 'pem', key: pemKey });
343
+ const key = createSecp256k1KeyObject(publicKey);
337
344
  return crypto.verify('sha256', data, {
338
345
  key,
339
346
  dsaEncoding: 'ieee-p1363',
@@ -1 +1 @@
1
- {"version":3,"file":"auth-verifier.js","sourceRoot":"","sources":["../src/auth-verifier.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,EAAE,EAAkB,MAAM,aAAa,CAAA;AAEpD,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAC5B,OAAO,gBAAgB,MAAM,aAAa,CAAA;AAC1C,OAAO,KAAK,GAAG,MAAM,aAAa,CAAA;AAClC,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAChE,OAAO,EAAkB,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1D,OAAO,EACL,iBAAiB,EAEjB,4BAA4B,EAC5B,YAAY,EACZ,SAAS,IAAI,gBAAgB,GAC9B,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,IAAI,EAEJ,cAAc,EACd,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,uBAAuB,CAAA;AAG9B,2FAA2F;AAC3F,MAAM,UAAU,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAA;AAW5D,MAAM,CAAN,IAAY,UAIX;AAJD,WAAY,UAAU;IACpB,6CAAK,CAAA;IACL,iDAAO,CAAA;IACP,iDAAO,CAAA;AACT,CAAC,EAJW,UAAU,KAAV,UAAU,QAIrB;AAiCD,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;IAClC,oBAAoB;IACpB,qBAAqB;IACrB,+BAA+B;CAChC,CAAC,CAAA;AAUF,MAAM,OAAO,YAAY;IAOvB,YACS,SAA0B,EACjC,IAAsB;QADf,cAAS,GAAT,SAAS,CAAiB;QAanC,0CAA0C;QAC1C,kCAA6B,GAC3B,CAAC,IAAsB,EAAE,EAAE,CAC3B,KAAK,EAAE,GAAW,EAAwC,EAAE;YAC1D,6DAA6D;YAC7D,IAAI,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAA;gBACvB,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAA;gBAC7C,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;oBACjD,MAAM,IAAI,iBAAiB,CAAC,YAAY,CAAC,CAAA;gBAC3C,CAAC;gBACD,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC;oBACxC,MAAM,IAAI,iBAAiB,CAAC,iBAAiB,CAAC,CAAA;gBAChD,CAAC;gBACD,OAAO;oBACL,WAAW,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,EAAE;iBAC5C,CAAA;YACH,CAAC;iBAAM,IAAI,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBAClC,mFAAmF;gBACnF,MAAM,KAAK,GAAG,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;gBACzC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;gBACpE,IAAI,MAAM,EAAE,GAAG,KAAK,QAAQ,EAAE,CAAC;oBAC7B,qHAAqH;oBACrH,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;wBACtB,MAAM,IAAI,iBAAiB,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAA;oBAChE,CAAC;oBACD,OAAO,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAA;gBAClC,CAAC;gBAED,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE;oBACpD,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,GAAG,EAAE,IAAI;oBACT,GAAG,EAAE,IAAI;iBACV,CAAC,CAAA;gBACF,IACE,CAAC,IAAI,CAAC,YAAY;oBAClB,CAAE,IAAI,CAAC,oBAAoC,CAAC,GAAG,CAAC,GAAG,CAAC,EACpD,CAAC;oBACD,MAAM,IAAI,iBAAiB,CACzB,yCAAyC,EACzC,gBAAgB,CACjB,CAAA;gBACH,CAAC;gBACD,OAAO;oBACL,WAAW,EAAE;wBACX,IAAI,EAAE,UAAU;wBAChB,GAAG;wBACH,GAAG;qBACJ;iBACF,CAAA;YACH,CAAC;iBAAM,CAAC;gBACN,OAAO,IAAI,CAAC,SAAS,EAAE,CAAA;YACzB,CAAC;QACH,CAAC,CAAA;QAEH,qBAAgB,GACd,IAAI,CAAC,6BAA6B,CAAC,EAAE,CAAC,CAAA;QAExC,aAAQ,GAAG,KAAK,EAAE,GAAW,EAA2B,EAAE;YACxD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAA;YAC/C,IAAI,MAAM,CAAC,WAAW,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBACvC,MAAM,IAAI,iBAAiB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;YACvD,CAAC;YACD,OAAO,MAAwB,CAAA;QACjC,CAAC,CAAA;QAED,SAAI,GAAG,CAAC,GAAW,EAAc,EAAE;YACjC,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YAC1C,IAAI,KAAK,CAAC,MAAM,KAAK,UAAU,CAAC,KAAK,EAAE,CAAC;gBACtC,MAAM,IAAI,iBAAiB,EAAE,CAAA;YAC/B,CAAC;YACD,OAAO;gBACL,WAAW,EAAE;oBACX,GAAG,KAAK;oBACR,IAAI,EAAE,MAAM;iBACb;aACF,CAAA;QACH,CAAC,CAAA;QAED,mBAAc,GAAG,KAAK,EACpB,GAAW,EAC2B,EAAE;YACxC,IAAI,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC3B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;YAC3B,CAAC;iBAAM,CAAC;gBACN,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACvB,CAAC;QACH,CAAC,CAAA;QAED,2BAAsB,GAAG,KAAK,EAC5B,GAAW,EACwC,EAAE;YACrD,IAAI,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC3B,OAAO,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;YACjC,CAAC;iBAAM,CAAC;gBACN,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;gBAC1C,IAAI,KAAK,CAAC,MAAM,KAAK,UAAU,CAAC,KAAK,EAAE,CAAC;oBACtC,OAAO;wBACL,WAAW,EAAE;4BACX,GAAG,KAAK;4BACR,IAAI,EAAE,MAAM;yBACb;qBACF,CAAA;gBACH,CAAC;qBAAM,IAAI,KAAK,CAAC,MAAM,KAAK,UAAU,CAAC,OAAO,EAAE,CAAC;oBAC/C,OAAO,IAAI,CAAC,SAAS,EAAE,CAAA;gBACzB,CAAC;qBAAM,CAAC;oBACN,MAAM,IAAI,iBAAiB,EAAE,CAAA;gBAC/B,CAAC;YACH,CAAC;QACH,CAAC,CAAA;QAED,wFAAwF;QACxF,6FAA6F;QAC7F,iEAAiE;QACjE,oBAAe,GAAG,KAAK,EAAE,MAAc,EAA2B,EAAE;YAClE,MAAM,KAAK,GAAG,kBAAkB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC5C,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,IAAI,iBAAiB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;YACvD,CAAC;YAED,qEAAqE;YACrE,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC;gBAC/B,MAAM,IAAI,iBAAiB,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAA;YAChE,CAAC;YAED,MAAM,GAAG,GAAG,MAAM,IAAI;iBACnB,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,oBAAoB,CAAC;iBAC3C,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;gBACb,IAAI,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,iBAAiB,EAAE,CAAC;oBACxC,MAAM,IAAI,iBAAiB,CAAC,mBAAmB,EAAE,cAAc,CAAC,CAAA;gBAClE,CAAC;gBACD,MAAM,IAAI,iBAAiB,CACzB,6BAA6B,EAC7B,cAAc,CACf,CAAA;YACH,CAAC,CAAC,CAAA;YAEJ,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC,OAAO,CAAA;YAC5C,IAAI,OAAO,GAAG,KAAK,WAAW,EAAE,CAAC;gBAC/B,wDAAwD;gBACxD,8CAA8C;gBAC9C,MAAM,IAAI,iBAAiB,CACzB,qCAAqC,EACrC,cAAc,CACf,CAAA;YACH,CAAC;YACD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBACvD,MAAM,IAAI,iBAAiB,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAA;YAChE,CAAC;iBAAM,IACL,OAAO,GAAG,KAAK,QAAQ;gBACvB,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC;gBAC3B,CAAC,GAAG,CAAC,QAAQ,CAAC,eAAe,CAAC,EAC9B,CAAC;gBACD,MAAM,IAAI,iBAAiB,CAAC,eAAe,EAAE,cAAc,CAAC,CAAA;YAC9D,CAAC;iBAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxE,MAAM,IAAI,iBAAiB,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAA;YAChE,CAAC;YAED,OAAO;gBACL,WAAW,EAAE;oBACX,IAAI,EAAE,UAAU;oBAChB,GAAG,EAAE,IAAI,CAAC,MAAM;oBAChB,GAAG,EAAE,GAA2C;iBACjD;aACF,CAAA;QACH,CAAC,CAAA;QAED,eAAU,GAAG,KAAK,EAAE,MAAc,EAA6B,EAAE;YAC/D,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE;gBACvD,GAAG,EAAE,IAAI,CAAC,MAAM;gBAChB,GAAG,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,IAAI,CAAC,aAAa,kBAAkB,CAAC;aACnE,CAAC,CAAA;YACF,OAAO,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,CAAA;QAC3D,CAAC,CAAA;QAED,qBAAgB,GAAG,KAAK,EACtB,MAAc,EAC0B,EAAE;YAC1C,IAAI,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC9B,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;YAChC,CAAC;iBAAM,CAAC;gBACN,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YAC1B,CAAC;QACH,CAAC,CAAA;QAjMC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;QACzB,IAAI,CAAC,oBAAoB,GAAG,IAAI,GAAG,CAAC;YAClC,IAAI,CAAC,MAAM;YACX,GAAG,IAAI,CAAC,qBAAqB;SAC9B,CAAC,CAAA;QACF,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAA;QACvC,IAAI,CAAC,WAAW,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QAC5C,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC,oBAAoB,CAAA;IACvD,CAAC;IA2LD,cAAc,CAAC,GAAoB;QACjC,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC,CAAA;QAC9D,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,UAAU,CAAA;QAC9C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAA;QAC3E,CAAC;QACD,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAA;QACrC,IAAI,QAAQ,KAAK,OAAO,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3D,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA;QACvC,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;IAC1C,CAAC;IAED,KAAK,CAAC,gBAAgB,CAMpB,MAAc,EAAE,IAAc;QAC9B,MAAM,aAAa,GAAG,KAAK,EACzB,GAAW,EACX,aAAsB,EACL,EAAE;YACnB,IAAI,IAAI,CAAC,GAAG,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACjD,MAAM,IAAI,iBAAiB,CAAC,kBAAkB,EAAE,cAAc,CAAC,CAAA;YACjE,CAAC;YACD,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YACvC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;gBACtB,MAAM,IAAI,iBAAiB,CAAC,kBAAkB,CAAC,CAAA;YACjD,CAAC;YAED,MAAM,KAAK,GACT,SAAS,KAAK,iBAAiB,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAAA;YAC/D,IAAI,QAAkC,CAAA;YACtC,IAAI,CAAC;gBACH,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,EAAE,GAAG,EAAE,CAAC,CAAA;YAC3D,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACzC,MAAM,IAAI,iBAAiB,CAAC,kBAAkB,CAAC,CAAA;gBACjD,CAAC;gBACD,MAAM,GAAG,CAAA;YACX,CAAC;YACD,MAAM,IAAI,GAAG,kBAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;YAC9C,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;YAClD,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,iBAAiB,CAAC,oBAAoB,CAAC,CAAA;YACnD,CAAC;YACD,OAAO,MAAM,CAAA;QACf,CAAC,CAAA;QACD,MAAM,cAAc,GAAG,GAAG,EAAE;YAC1B,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YACpC,IACE,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAC9C,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,KAAK,GAAG,CAAC,EACvC,CAAC;gBACD,MAAM,IAAI,iBAAiB,CACzB,OAAO,CAAC,GAAG,KAAK,SAAS;oBACvB,CAAC,CAAC,+CAA+C,GAAG,EAAE;oBACtD,CAAC,CAAC,mDAAmD,GAAG,EAAE,EAC5D,qBAAqB,CACtB,CAAA;YACH,CAAC;QACH,CAAC,CAAA;QAED,MAAM,MAAM,GAAG,kBAAkB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAC7C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,iBAAiB,CAAC,aAAa,EAAE,YAAY,CAAC,CAAA;QAC1D,CAAC;QACD,iGAAiG;QACjG,MAAM,OAAO,GAAG,MAAM,gBAAgB,CACpC,MAAM,EACN,IAAI,CAAC,GAAG,EACR,IAAI,EACJ,aAAa,EACb,sBAAsB,CACvB,CAAA;QACD,IACE,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,kBAAkB,CAAC;YACzC,OAAO,CAAC,GAAG,KAAK,SAAS,EACzB,CAAC;YACD,+DAA+D;YAC/D,4EAA4E;YAC5E,cAAc,EAAE,CAAA;QAClB,CAAC;QAED,OAAO;YACL,GAAG,EAAE,OAAO,CAAC,GACqD;YAClE,GAAG,EAAE,OAAO,CAAC,GACqD;SACnE,CAAA;IACH,CAAC;IAED,YAAY,CAAC,GAAW;QACtB,OAAO;YACL,IAAI,CAAC,aAAa;YAClB,GAAG,IAAI,CAAC,aAAa,kBAAkB;SACxC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;IACjB,CAAC;IAED,SAAS;QACP,OAAO;YACL,WAAW,EAAE;gBACX,IAAI,EAAE,MAAM;gBACZ,GAAG,EAAE,IAAI;aACV;SACF,CAAA;IACH,CAAC;IAED,UAAU,CACR,KAAkE;QAElE,MAAM,MAAM,GACV,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAA;QACtE,MAAM,2BAA2B,GAC/B,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC;YAC9D,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,aAAa;YACxC,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,UAAU;gBACpC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAA;QAC7C,MAAM,kBAAkB,GACtB,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC;YAC9D,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,aAAa,CAAA;QAC1C,MAAM,YAAY,GAChB,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,aAAa;YACxC,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,UAAU;gBACpC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAA;QAE7C,OAAO;YACL,MAAM;YACN,gBAAgB,EAAE,2BAA2B;YAC7C,eAAe,EAAE,2BAA2B;YAC5C,kBAAkB;YAClB,YAAY;YACZ,gBAAgB,EAAE,YAAY,IAAI,MAAM,KAAK,IAAI;SAClD,CAAA;IACH,CAAC;CACF;AAED,UAAU;AACV,YAAY;AAEZ,MAAM,MAAM,GAAG,SAAS,CAAA;AACxB,MAAM,KAAK,GAAG,QAAQ,CAAA;AAEtB,MAAM,aAAa,GAAG,CAAC,GAAoB,EAAW,EAAE;IACtD,OAAO,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,UAAU,CAAC,MAAM,CAAC,IAAI,KAAK,CAAA;AAC/D,CAAC,CAAA;AAED,MAAM,YAAY,GAAG,CAAC,GAAoB,EAAW,EAAE;IACrD,OAAO,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,UAAU,CAAC,KAAK,CAAC,IAAI,KAAK,CAAA;AAC9D,CAAC,CAAA;AAED,MAAM,kBAAkB,GAAG,CAAC,GAAoB,EAAE,EAAE;IAClD,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,IAAI,EAAE,CAAA;IAC9C,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAA;IAC3C,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAA;AAC3C,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,KAAa,EACkC,EAAE;IACjD,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACzC,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IACrC,IAAI,MAAgB,CAAA;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC5E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,IAAI,CAAA;IACb,CAAC;IACD,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,MAAM,CAAA;IACnC,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAA;IACvC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAA;AAC/B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,QAAgB,EAAE,QAAgB,EAAU,EAAE;IAC3E,OAAO,CACL,KAAK;QACL,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,QAAQ,IAAI,QAAQ,EAAE,EAAE,MAAM,CAAC,EAAE,WAAW,CAAC,CAC7E,CAAA;AACH,CAAC,CAAA;AAED,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAA;AAC9C,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,YAAoB,EAAa,EAAE;IACvE,MAAM,GAAG,GAAG,UAAU,CAAC,YAAY,CAAC,YAAY,EAAE,KAAK,EAAE,KAAK,CAAC,CAAA;IAC/D,OAAO,MAAM,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;AACvD,CAAC,CAAA;AAED,MAAM,SAAS,GAAG,CAChB,SAAqB,EACrB,IAAgB,EAChB,GAAe,EACf,EAAE;IACF,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAA;IAE9C,MAAM,MAAM,GAAG,UAAU,CAAC,YAAY,CACpC,GAAG,CAAC,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC,EAC9B,KAAK,EACL,KAAK,CACN,CAAA;IACD,MAAM,GAAG,GAAG,MAAM,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAA;IAElE,OAAO,MAAM,CAAC,MAAM,CAClB,QAAQ,EACR,IAAI,EACJ;QACE,GAAG;QACH,WAAW,EAAE,YAAY;KAC1B,EACD,GAAG,CACJ,CAAA;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,sBAAsB,GAA6B,KAAK,EACnE,MAAc,EACd,QAAoB,EACpB,QAAoB,EACpB,GAAW,EACX,EAAE;IACF,IAAI,GAAG,KAAK,iBAAiB,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA;QAClC,IAAI,GAAG,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,oBAAoB,GAAG,SAAS,MAAM,CAAC,MAAM,EAAE,CAAC,CAAA;QAClE,CAAC;QAED,OAAO,SAAS,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAA;IACvD,CAAC;IAED,OAAO,4BAA4B,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAA;AACtE,CAAC,CAAA","sourcesContent":["import crypto, { type KeyObject } from 'node:crypto'\nimport type express from 'express'\nimport * as jose from 'jose'\nimport KeyEncoderModule from 'key-encoder'\nimport * as ui8 from 'uint8arrays'\nimport { SECP256K1_JWT_ALG, parseDidKey } from '@atproto/crypto'\nimport { type DidString, isDidString } from '@atproto/lex'\nimport {\n AuthRequiredError,\n type VerifySignatureWithKeyFn,\n cryptoVerifySignatureWithKey,\n parseReqNsid,\n verifyJwt as verifyServiceJwt,\n} from '@atproto/xrpc-server'\nimport {\n Code,\n type DataPlaneClient,\n getKeyAsDidKey,\n isDataplaneError,\n unpackIdentityKeys,\n} from './data-plane/index.js'\nimport type { GetIdentityByDidResponse } from './proto/bsky_pb.js'\n\n// key-encoder is CJS with exports.default; Node ESM interop wraps it as { default: Class }\nconst KeyEncoder = ((m) => m.default ?? m)(KeyEncoderModule)\n\ntype ReqCtx = {\n req: express.Request\n}\n\ntype StandardAuthOpts = {\n skipAudCheck?: boolean\n lxmCheck?: (method?: string) => boolean\n}\n\nexport enum RoleStatus {\n Valid,\n Invalid,\n Missing,\n}\n\ntype NullOutput = {\n credentials: {\n type: 'none'\n iss: null\n }\n}\n\ntype StandardOutput = {\n credentials: {\n type: 'standard'\n /** @note we don't validate this to be a {@link DidString} (we might want to in the future) */\n aud: string\n iss: DidString | `${DidString}#${string}`\n }\n}\n\ntype RoleOutput = {\n credentials: {\n type: 'role'\n admin: boolean\n }\n}\n\ntype ModServiceOutput = {\n credentials: {\n type: 'mod_service'\n aud: DidString\n iss: DidString | `${DidString}#${string}`\n }\n}\n\nconst ALLOWED_AUTH_SCOPES = new Set([\n 'com.atproto.access',\n 'com.atproto.appPass',\n 'com.atproto.appPassPrivileged',\n])\n\nexport type AuthVerifierOpts = {\n ownDid: DidString\n alternateAudienceDids: DidString[]\n modServiceDid: DidString\n adminPasses: string[]\n entrywayJwtPublicKey?: KeyObject\n}\n\nexport class AuthVerifier {\n public ownDid: DidString\n public standardAudienceDids: Set<DidString>\n public modServiceDid: DidString\n private adminPasses: Set<string>\n private entrywayJwtPublicKey?: KeyObject\n\n constructor(\n public dataplane: DataPlaneClient,\n opts: AuthVerifierOpts,\n ) {\n this.ownDid = opts.ownDid\n this.standardAudienceDids = new Set([\n opts.ownDid,\n ...opts.alternateAudienceDids,\n ])\n this.modServiceDid = opts.modServiceDid\n this.adminPasses = new Set(opts.adminPasses)\n this.entrywayJwtPublicKey = opts.entrywayJwtPublicKey\n }\n\n // verifiers (arrow fns to preserve scope)\n standardOptionalParameterized =\n (opts: StandardAuthOpts) =>\n async (ctx: ReqCtx): Promise<StandardOutput | NullOutput> => {\n // @TODO remove! basic auth + did supported just for testing.\n if (isBasicToken(ctx.req)) {\n const aud = this.ownDid\n const iss = ctx.req.headers['appview-as-did']\n if (typeof iss !== 'string' || !isDidString(iss)) {\n throw new AuthRequiredError('bad issuer')\n }\n if (!this.parseRoleCreds(ctx.req).admin) {\n throw new AuthRequiredError('bad credentials')\n }\n return {\n credentials: { type: 'standard', iss, aud },\n }\n } else if (isBearerToken(ctx.req)) {\n // @NOTE temporarily accept entryway session tokens to shed load from PDS instances\n const token = bearerTokenFromReq(ctx.req)\n const header = token ? jose.decodeProtectedHeader(token) : undefined\n if (header?.typ === 'at+jwt') {\n // we should never use entryway session tokens in the case of flexible auth audiences (namely in the case of getFeed)\n if (opts.skipAudCheck) {\n throw new AuthRequiredError('Malformed token', 'InvalidToken')\n }\n return this.entrywaySession(ctx)\n }\n\n const { iss, aud } = await this.verifyServiceJwt(ctx, {\n lxmCheck: opts.lxmCheck,\n iss: null,\n aud: null,\n })\n if (\n !opts.skipAudCheck &&\n !(this.standardAudienceDids as Set<string>).has(aud)\n ) {\n throw new AuthRequiredError(\n 'jwt audience does not match service did',\n 'BadJwtAudience',\n )\n }\n return {\n credentials: {\n type: 'standard',\n iss,\n aud,\n },\n }\n } else {\n return this.nullCreds()\n }\n }\n\n standardOptional: (ctx: ReqCtx) => Promise<StandardOutput | NullOutput> =\n this.standardOptionalParameterized({})\n\n standard = async (ctx: ReqCtx): Promise<StandardOutput> => {\n const output = await this.standardOptional(ctx)\n if (output.credentials.type === 'none') {\n throw new AuthRequiredError(undefined, 'AuthMissing')\n }\n return output as StandardOutput\n }\n\n role = (ctx: ReqCtx): RoleOutput => {\n const creds = this.parseRoleCreds(ctx.req)\n if (creds.status !== RoleStatus.Valid) {\n throw new AuthRequiredError()\n }\n return {\n credentials: {\n ...creds,\n type: 'role',\n },\n }\n }\n\n standardOrRole = async (\n ctx: ReqCtx,\n ): Promise<StandardOutput | RoleOutput> => {\n if (isBearerToken(ctx.req)) {\n return this.standard(ctx)\n } else {\n return this.role(ctx)\n }\n }\n\n optionalStandardOrRole = async (\n ctx: ReqCtx,\n ): Promise<StandardOutput | RoleOutput | NullOutput> => {\n if (isBearerToken(ctx.req)) {\n return await this.standard(ctx)\n } else {\n const creds = this.parseRoleCreds(ctx.req)\n if (creds.status === RoleStatus.Valid) {\n return {\n credentials: {\n ...creds,\n type: 'role',\n },\n }\n } else if (creds.status === RoleStatus.Missing) {\n return this.nullCreds()\n } else {\n throw new AuthRequiredError()\n }\n }\n }\n\n // @NOTE this auth verifier method is not recommended to be implemented by most appviews\n // this is a short term fix to remove proxy load from Bluesky's PDS and in line with possible\n // future plans to have the client talk directly with the appview\n entrywaySession = async (reqCtx: ReqCtx): Promise<StandardOutput> => {\n const token = bearerTokenFromReq(reqCtx.req)\n if (!token) {\n throw new AuthRequiredError(undefined, 'AuthMissing')\n }\n\n // if entryway jwt key not configured then do not parsed these tokens\n if (!this.entrywayJwtPublicKey) {\n throw new AuthRequiredError('Malformed token', 'InvalidToken')\n }\n\n const res = await jose\n .jwtVerify(token, this.entrywayJwtPublicKey)\n .catch((err) => {\n if (err?.['code'] === 'ERR_JWT_EXPIRED') {\n throw new AuthRequiredError('Token has expired', 'ExpiredToken')\n }\n throw new AuthRequiredError(\n 'Token could not be verified',\n 'InvalidToken',\n )\n })\n\n const { sub, aud, scope, cnf } = res.payload\n if (typeof cnf !== 'undefined') {\n // Proof-of-Possession (PoP) tokens are not allowed here\n // https://www.rfc-editor.org/rfc/rfc7800.html\n throw new AuthRequiredError(\n 'Malformed token: DPoP not supported',\n 'InvalidToken',\n )\n }\n if (typeof sub !== 'string' || !sub.startsWith('did:')) {\n throw new AuthRequiredError('Malformed token', 'InvalidToken')\n } else if (\n typeof aud !== 'string' ||\n !aud.startsWith('did:web:') ||\n !aud.endsWith('.bsky.network')\n ) {\n throw new AuthRequiredError('Bad token aud', 'InvalidToken')\n } else if (typeof scope !== 'string' || !ALLOWED_AUTH_SCOPES.has(scope)) {\n throw new AuthRequiredError('Bad token scope', 'InvalidToken')\n }\n\n return {\n credentials: {\n type: 'standard',\n aud: this.ownDid,\n iss: sub as DidString | `${DidString}#${string}`,\n },\n }\n }\n\n modService = async (reqCtx: ReqCtx): Promise<ModServiceOutput> => {\n const { iss, aud } = await this.verifyServiceJwt(reqCtx, {\n aud: this.ownDid,\n iss: [this.modServiceDid, `${this.modServiceDid}#atproto_labeler`],\n })\n return { credentials: { type: 'mod_service', aud, iss } }\n }\n\n roleOrModService = async (\n reqCtx: ReqCtx,\n ): Promise<RoleOutput | ModServiceOutput> => {\n if (isBearerToken(reqCtx.req)) {\n return this.modService(reqCtx)\n } else {\n return this.role(reqCtx)\n }\n }\n\n parseRoleCreds(req: express.Request) {\n const parsed = parseBasicAuth(req.headers.authorization || '')\n const { Missing, Valid, Invalid } = RoleStatus\n if (!parsed) {\n return { status: Missing, admin: false, moderator: false, triage: false }\n }\n const { username, password } = parsed\n if (username === 'admin' && this.adminPasses.has(password)) {\n return { status: Valid, admin: true }\n }\n return { status: Invalid, admin: false }\n }\n\n async verifyServiceJwt<\n TOptions extends {\n iss: string[] | null\n aud: string | null\n lxmCheck?: (method?: string) => boolean\n },\n >(reqCtx: ReqCtx, opts: TOptions) {\n const getSigningKey = async (\n iss: string,\n _forceRefresh: boolean, // @TODO consider propagating to dataplane\n ): Promise<string> => {\n if (opts.iss !== null && !opts.iss.includes(iss)) {\n throw new AuthRequiredError('Untrusted issuer', 'UntrustedIss')\n }\n const [did, serviceId] = iss.split('#')\n if (!isDidString(did)) {\n throw new AuthRequiredError('identity unknown')\n }\n\n const keyId =\n serviceId === 'atproto_labeler' ? 'atproto_label' : 'atproto'\n let identity: GetIdentityByDidResponse\n try {\n identity = await this.dataplane.getIdentityByDid({ did })\n } catch (err) {\n if (isDataplaneError(err, Code.NotFound)) {\n throw new AuthRequiredError('identity unknown')\n }\n throw err\n }\n const keys = unpackIdentityKeys(identity.keys)\n const didKey = getKeyAsDidKey(keys, { id: keyId })\n if (!didKey) {\n throw new AuthRequiredError('missing or bad key')\n }\n return didKey\n }\n const assertLxmCheck = () => {\n const lxm = parseReqNsid(reqCtx.req)\n if (\n (opts.lxmCheck && !opts.lxmCheck(payload.lxm)) ||\n (!opts.lxmCheck && payload.lxm !== lxm)\n ) {\n throw new AuthRequiredError(\n payload.lxm !== undefined\n ? `bad jwt lexicon method (\"lxm\"). must match: ${lxm}`\n : `missing jwt lexicon method (\"lxm\"). must match: ${lxm}`,\n 'BadJwtLexiconMethod',\n )\n }\n }\n\n const jwtStr = bearerTokenFromReq(reqCtx.req)\n if (!jwtStr) {\n throw new AuthRequiredError('missing jwt', 'MissingJwt')\n }\n // if validating additional scopes, skip scope check in initial validation & follow up afterwards\n const payload = await verifyServiceJwt(\n jwtStr,\n opts.aud,\n null,\n getSigningKey,\n verifySignatureWithKey,\n )\n if (\n !payload.iss.endsWith('#atproto_labeler') ||\n payload.lxm !== undefined\n ) {\n // @TODO currently permissive of labelers who dont set lxm yet.\n // we'll allow ozone self-hosters to upgrade before removing this condition.\n assertLxmCheck()\n }\n\n return {\n iss: payload.iss as (DidString | `${DidString}#${string}`) &\n (TOptions extends { iss: ReadonlyArray<infer I> } ? I : unknown),\n aud: payload.aud as string &\n (TOptions extends { aud: infer A extends string } ? A : unknown),\n }\n }\n\n isModService(iss: string): iss is DidString | `${DidString}#atproto_labeler` {\n return [\n this.modServiceDid,\n `${this.modServiceDid}#atproto_labeler`,\n ].includes(iss)\n }\n\n nullCreds(): NullOutput {\n return {\n credentials: {\n type: 'none',\n iss: null,\n },\n }\n }\n\n parseCreds(\n creds: StandardOutput | RoleOutput | ModServiceOutput | NullOutput,\n ) {\n const viewer =\n creds.credentials.type === 'standard' ? creds.credentials.iss : null\n const includeTakedownsAnd3pBlocks =\n (creds.credentials.type === 'role' && creds.credentials.admin) ||\n creds.credentials.type === 'mod_service' ||\n (creds.credentials.type === 'standard' &&\n this.isModService(creds.credentials.iss))\n const canPerformTakedown =\n (creds.credentials.type === 'role' && creds.credentials.admin) ||\n creds.credentials.type === 'mod_service'\n const isModService =\n creds.credentials.type === 'mod_service' ||\n (creds.credentials.type === 'standard' &&\n this.isModService(creds.credentials.iss))\n\n return {\n viewer,\n includeTakedowns: includeTakedownsAnd3pBlocks,\n include3pBlocks: includeTakedownsAnd3pBlocks,\n canPerformTakedown,\n isModService,\n skipViewerBlocks: isModService && viewer !== null,\n }\n }\n}\n\n// HELPERS\n// ---------\n\nconst BEARER = 'Bearer '\nconst BASIC = 'Basic '\n\nconst isBearerToken = (req: express.Request): boolean => {\n return req.headers.authorization?.startsWith(BEARER) ?? false\n}\n\nconst isBasicToken = (req: express.Request): boolean => {\n return req.headers.authorization?.startsWith(BASIC) ?? false\n}\n\nconst bearerTokenFromReq = (req: express.Request) => {\n const header = req.headers.authorization || ''\n if (!header.startsWith(BEARER)) return null\n return header.slice(BEARER.length).trim()\n}\n\nexport const parseBasicAuth = (\n token: string,\n): { username: string; password: string } | null => {\n if (!token.startsWith(BASIC)) return null\n const b64 = token.slice(BASIC.length)\n let parsed: string[]\n try {\n parsed = ui8.toString(ui8.fromString(b64, 'base64pad'), 'utf8').split(':')\n } catch (err) {\n return null\n }\n const [username, password] = parsed\n if (!username || !password) return null\n return { username, password }\n}\n\nexport const buildBasicAuth = (username: string, password: string): string => {\n return (\n BASIC +\n ui8.toString(ui8.fromString(`${username}:${password}`, 'utf8'), 'base64pad')\n )\n}\n\nconst keyEncoder = new KeyEncoder('secp256k1')\nexport const createPublicKeyObject = (publicKeyHex: string): KeyObject => {\n const key = keyEncoder.encodePublic(publicKeyHex, 'raw', 'pem')\n return crypto.createPublicKey({ format: 'pem', key })\n}\n\nconst verifySig = (\n publicKey: Uint8Array,\n data: Uint8Array,\n sig: Uint8Array,\n) => {\n const keyEncoder = new KeyEncoder('secp256k1')\n\n const pemKey = keyEncoder.encodePublic(\n ui8.toString(publicKey, 'hex'),\n 'raw',\n 'pem',\n )\n const key = crypto.createPublicKey({ format: 'pem', key: pemKey })\n\n return crypto.verify(\n 'sha256',\n data,\n {\n key,\n dsaEncoding: 'ieee-p1363',\n },\n sig,\n )\n}\n\nexport const verifySignatureWithKey: VerifySignatureWithKeyFn = async (\n didKey: string,\n msgBytes: Uint8Array,\n sigBytes: Uint8Array,\n alg: string,\n) => {\n if (alg === SECP256K1_JWT_ALG) {\n const parsed = parseDidKey(didKey)\n if (alg !== parsed.jwtAlg) {\n throw new Error(`Expected key alg ${alg}, got ${parsed.jwtAlg}`)\n }\n\n return verifySig(parsed.keyBytes, msgBytes, sigBytes)\n }\n\n return cryptoVerifySignatureWithKey(didKey, msgBytes, sigBytes, alg)\n}\n"]}
1
+ {"version":3,"file":"auth-verifier.js","sourceRoot":"","sources":["../src/auth-verifier.ts"],"names":[],"mappings":"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","sourcesContent":["import crypto, { type KeyObject } from 'node:crypto'\nimport { secp256k1 } from '@noble/curves/secp256k1'\nimport type express from 'express'\nimport * as jose from 'jose'\nimport * as ui8 from 'uint8arrays'\nimport { SECP256K1_JWT_ALG, parseDidKey } from '@atproto/crypto'\nimport { type DidString, isDidString } from '@atproto/lex'\nimport {\n AuthRequiredError,\n type VerifySignatureWithKeyFn,\n cryptoVerifySignatureWithKey,\n parseReqNsid,\n verifyJwt as verifyServiceJwt,\n} from '@atproto/xrpc-server'\nimport {\n Code,\n type DataPlaneClient,\n getKeyAsDidKey,\n isDataplaneError,\n unpackIdentityKeys,\n} from './data-plane/index.js'\nimport type { GetIdentityByDidResponse } from './proto/bsky_pb.js'\n\ntype ReqCtx = {\n req: express.Request\n}\n\ntype StandardAuthOpts = {\n skipAudCheck?: boolean\n lxmCheck?: (method?: string) => boolean\n}\n\nexport enum RoleStatus {\n Valid,\n Invalid,\n Missing,\n}\n\ntype NullOutput = {\n credentials: {\n type: 'none'\n iss: null\n }\n}\n\ntype StandardOutput = {\n credentials: {\n type: 'standard'\n /** @note we don't validate this to be a {@link DidString} (we might want to in the future) */\n aud: string\n iss: DidString | `${DidString}#${string}`\n }\n}\n\ntype RoleOutput = {\n credentials: {\n type: 'role'\n admin: boolean\n }\n}\n\ntype ModServiceOutput = {\n credentials: {\n type: 'mod_service'\n aud: DidString\n iss: DidString | `${DidString}#${string}`\n }\n}\n\nconst ALLOWED_AUTH_SCOPES = new Set([\n 'com.atproto.access',\n 'com.atproto.appPass',\n 'com.atproto.appPassPrivileged',\n])\n\nexport type AuthVerifierOpts = {\n ownDid: DidString\n alternateAudienceDids: DidString[]\n modServiceDid: DidString\n adminPasses: string[]\n entrywayJwtPublicKey?: KeyObject\n}\n\nexport class AuthVerifier {\n public ownDid: DidString\n public standardAudienceDids: Set<DidString>\n public modServiceDid: DidString\n private adminPasses: Set<string>\n private entrywayJwtPublicKey?: KeyObject\n\n constructor(\n public dataplane: DataPlaneClient,\n opts: AuthVerifierOpts,\n ) {\n this.ownDid = opts.ownDid\n this.standardAudienceDids = new Set([\n opts.ownDid,\n ...opts.alternateAudienceDids,\n ])\n this.modServiceDid = opts.modServiceDid\n this.adminPasses = new Set(opts.adminPasses)\n this.entrywayJwtPublicKey = opts.entrywayJwtPublicKey\n }\n\n // verifiers (arrow fns to preserve scope)\n standardOptionalParameterized =\n (opts: StandardAuthOpts) =>\n async (ctx: ReqCtx): Promise<StandardOutput | NullOutput> => {\n // @TODO remove! basic auth + did supported just for testing.\n if (isBasicToken(ctx.req)) {\n const aud = this.ownDid\n const iss = ctx.req.headers['appview-as-did']\n if (typeof iss !== 'string' || !isDidString(iss)) {\n throw new AuthRequiredError('bad issuer')\n }\n if (!this.parseRoleCreds(ctx.req).admin) {\n throw new AuthRequiredError('bad credentials')\n }\n return {\n credentials: { type: 'standard', iss, aud },\n }\n } else if (isBearerToken(ctx.req)) {\n // @NOTE temporarily accept entryway session tokens to shed load from PDS instances\n const token = bearerTokenFromReq(ctx.req)\n const header = token ? jose.decodeProtectedHeader(token) : undefined\n if (header?.typ === 'at+jwt') {\n // we should never use entryway session tokens in the case of flexible auth audiences (namely in the case of getFeed)\n if (opts.skipAudCheck) {\n throw new AuthRequiredError('Malformed token', 'InvalidToken')\n }\n return this.entrywaySession(ctx)\n }\n\n const { iss, aud } = await this.verifyServiceJwt(ctx, {\n lxmCheck: opts.lxmCheck,\n iss: null,\n aud: null,\n })\n if (\n !opts.skipAudCheck &&\n !(this.standardAudienceDids as Set<string>).has(aud)\n ) {\n throw new AuthRequiredError(\n 'jwt audience does not match service did',\n 'BadJwtAudience',\n )\n }\n return {\n credentials: {\n type: 'standard',\n iss,\n aud,\n },\n }\n } else {\n return this.nullCreds()\n }\n }\n\n standardOptional: (ctx: ReqCtx) => Promise<StandardOutput | NullOutput> =\n this.standardOptionalParameterized({})\n\n standard = async (ctx: ReqCtx): Promise<StandardOutput> => {\n const output = await this.standardOptional(ctx)\n if (output.credentials.type === 'none') {\n throw new AuthRequiredError(undefined, 'AuthMissing')\n }\n return output as StandardOutput\n }\n\n role = (ctx: ReqCtx): RoleOutput => {\n const creds = this.parseRoleCreds(ctx.req)\n if (creds.status !== RoleStatus.Valid) {\n throw new AuthRequiredError()\n }\n return {\n credentials: {\n ...creds,\n type: 'role',\n },\n }\n }\n\n standardOrRole = async (\n ctx: ReqCtx,\n ): Promise<StandardOutput | RoleOutput> => {\n if (isBearerToken(ctx.req)) {\n return this.standard(ctx)\n } else {\n return this.role(ctx)\n }\n }\n\n optionalStandardOrRole = async (\n ctx: ReqCtx,\n ): Promise<StandardOutput | RoleOutput | NullOutput> => {\n if (isBearerToken(ctx.req)) {\n return await this.standard(ctx)\n } else {\n const creds = this.parseRoleCreds(ctx.req)\n if (creds.status === RoleStatus.Valid) {\n return {\n credentials: {\n ...creds,\n type: 'role',\n },\n }\n } else if (creds.status === RoleStatus.Missing) {\n return this.nullCreds()\n } else {\n throw new AuthRequiredError()\n }\n }\n }\n\n // @NOTE this auth verifier method is not recommended to be implemented by most appviews\n // this is a short term fix to remove proxy load from Bluesky's PDS and in line with possible\n // future plans to have the client talk directly with the appview\n entrywaySession = async (reqCtx: ReqCtx): Promise<StandardOutput> => {\n const token = bearerTokenFromReq(reqCtx.req)\n if (!token) {\n throw new AuthRequiredError(undefined, 'AuthMissing')\n }\n\n // if entryway jwt key not configured then do not parsed these tokens\n if (!this.entrywayJwtPublicKey) {\n throw new AuthRequiredError('Malformed token', 'InvalidToken')\n }\n\n const res = await jose\n .jwtVerify(token, this.entrywayJwtPublicKey)\n .catch((err) => {\n if (err?.['code'] === 'ERR_JWT_EXPIRED') {\n throw new AuthRequiredError('Token has expired', 'ExpiredToken')\n }\n throw new AuthRequiredError(\n 'Token could not be verified',\n 'InvalidToken',\n )\n })\n\n const { sub, aud, scope, cnf } = res.payload\n if (typeof cnf !== 'undefined') {\n // Proof-of-Possession (PoP) tokens are not allowed here\n // https://www.rfc-editor.org/rfc/rfc7800.html\n throw new AuthRequiredError(\n 'Malformed token: DPoP not supported',\n 'InvalidToken',\n )\n }\n if (typeof sub !== 'string' || !sub.startsWith('did:')) {\n throw new AuthRequiredError('Malformed token', 'InvalidToken')\n } else if (\n typeof aud !== 'string' ||\n !aud.startsWith('did:web:') ||\n !aud.endsWith('.bsky.network')\n ) {\n throw new AuthRequiredError('Bad token aud', 'InvalidToken')\n } else if (typeof scope !== 'string' || !ALLOWED_AUTH_SCOPES.has(scope)) {\n throw new AuthRequiredError('Bad token scope', 'InvalidToken')\n }\n\n return {\n credentials: {\n type: 'standard',\n aud: this.ownDid,\n iss: sub as DidString | `${DidString}#${string}`,\n },\n }\n }\n\n modService = async (reqCtx: ReqCtx): Promise<ModServiceOutput> => {\n const { iss, aud } = await this.verifyServiceJwt(reqCtx, {\n aud: this.ownDid,\n iss: [this.modServiceDid, `${this.modServiceDid}#atproto_labeler`],\n })\n return { credentials: { type: 'mod_service', aud, iss } }\n }\n\n roleOrModService = async (\n reqCtx: ReqCtx,\n ): Promise<RoleOutput | ModServiceOutput> => {\n if (isBearerToken(reqCtx.req)) {\n return this.modService(reqCtx)\n } else {\n return this.role(reqCtx)\n }\n }\n\n parseRoleCreds(req: express.Request) {\n const parsed = parseBasicAuth(req.headers.authorization || '')\n const { Missing, Valid, Invalid } = RoleStatus\n if (!parsed) {\n return { status: Missing, admin: false, moderator: false, triage: false }\n }\n const { username, password } = parsed\n if (username === 'admin' && this.adminPasses.has(password)) {\n return { status: Valid, admin: true }\n }\n return { status: Invalid, admin: false }\n }\n\n async verifyServiceJwt<\n TOptions extends {\n iss: string[] | null\n aud: string | null\n lxmCheck?: (method?: string) => boolean\n },\n >(reqCtx: ReqCtx, opts: TOptions) {\n const getSigningKey = async (\n iss: string,\n _forceRefresh: boolean, // @TODO consider propagating to dataplane\n ): Promise<string> => {\n if (opts.iss !== null && !opts.iss.includes(iss)) {\n throw new AuthRequiredError('Untrusted issuer', 'UntrustedIss')\n }\n const [did, serviceId] = iss.split('#')\n if (!isDidString(did)) {\n throw new AuthRequiredError('identity unknown')\n }\n\n const keyId =\n serviceId === 'atproto_labeler' ? 'atproto_label' : 'atproto'\n let identity: GetIdentityByDidResponse\n try {\n identity = await this.dataplane.getIdentityByDid({ did })\n } catch (err) {\n if (isDataplaneError(err, Code.NotFound)) {\n throw new AuthRequiredError('identity unknown')\n }\n throw err\n }\n const keys = unpackIdentityKeys(identity.keys)\n const didKey = getKeyAsDidKey(keys, { id: keyId })\n if (!didKey) {\n throw new AuthRequiredError('missing or bad key')\n }\n return didKey\n }\n const assertLxmCheck = () => {\n const lxm = parseReqNsid(reqCtx.req)\n if (\n (opts.lxmCheck && !opts.lxmCheck(payload.lxm)) ||\n (!opts.lxmCheck && payload.lxm !== lxm)\n ) {\n throw new AuthRequiredError(\n payload.lxm !== undefined\n ? `bad jwt lexicon method (\"lxm\"). must match: ${lxm}`\n : `missing jwt lexicon method (\"lxm\"). must match: ${lxm}`,\n 'BadJwtLexiconMethod',\n )\n }\n }\n\n const jwtStr = bearerTokenFromReq(reqCtx.req)\n if (!jwtStr) {\n throw new AuthRequiredError('missing jwt', 'MissingJwt')\n }\n // if validating additional scopes, skip scope check in initial validation & follow up afterwards\n const payload = await verifyServiceJwt(\n jwtStr,\n opts.aud,\n null,\n getSigningKey,\n verifySignatureWithKey,\n )\n if (\n !payload.iss.endsWith('#atproto_labeler') ||\n payload.lxm !== undefined\n ) {\n // @TODO currently permissive of labelers who dont set lxm yet.\n // we'll allow ozone self-hosters to upgrade before removing this condition.\n assertLxmCheck()\n }\n\n return {\n iss: payload.iss as (DidString | `${DidString}#${string}`) &\n (TOptions extends { iss: ReadonlyArray<infer I> } ? I : unknown),\n aud: payload.aud as string &\n (TOptions extends { aud: infer A extends string } ? A : unknown),\n }\n }\n\n isModService(iss: string): iss is DidString | `${DidString}#atproto_labeler` {\n return [\n this.modServiceDid,\n `${this.modServiceDid}#atproto_labeler`,\n ].includes(iss)\n }\n\n nullCreds(): NullOutput {\n return {\n credentials: {\n type: 'none',\n iss: null,\n },\n }\n }\n\n parseCreds(\n creds: StandardOutput | RoleOutput | ModServiceOutput | NullOutput,\n ) {\n const viewer =\n creds.credentials.type === 'standard' ? creds.credentials.iss : null\n const includeTakedownsAnd3pBlocks =\n (creds.credentials.type === 'role' && creds.credentials.admin) ||\n creds.credentials.type === 'mod_service' ||\n (creds.credentials.type === 'standard' &&\n this.isModService(creds.credentials.iss))\n const canPerformTakedown =\n (creds.credentials.type === 'role' && creds.credentials.admin) ||\n creds.credentials.type === 'mod_service'\n const isModService =\n creds.credentials.type === 'mod_service' ||\n (creds.credentials.type === 'standard' &&\n this.isModService(creds.credentials.iss))\n\n return {\n viewer,\n includeTakedowns: includeTakedownsAnd3pBlocks,\n include3pBlocks: includeTakedownsAnd3pBlocks,\n canPerformTakedown,\n isModService,\n skipViewerBlocks: isModService && viewer !== null,\n }\n }\n}\n\n// HELPERS\n// ---------\n\nconst BEARER = 'Bearer '\nconst BASIC = 'Basic '\n\nconst isBearerToken = (req: express.Request): boolean => {\n return req.headers.authorization?.startsWith(BEARER) ?? false\n}\n\nconst isBasicToken = (req: express.Request): boolean => {\n return req.headers.authorization?.startsWith(BASIC) ?? false\n}\n\nconst bearerTokenFromReq = (req: express.Request) => {\n const header = req.headers.authorization || ''\n if (!header.startsWith(BEARER)) return null\n return header.slice(BEARER.length).trim()\n}\n\nexport const parseBasicAuth = (\n token: string,\n): { username: string; password: string } | null => {\n if (!token.startsWith(BASIC)) return null\n const b64 = token.slice(BASIC.length)\n let parsed: string[]\n try {\n parsed = ui8.toString(ui8.fromString(b64, 'base64pad'), 'utf8').split(':')\n } catch (err) {\n return null\n }\n const [username, password] = parsed\n if (!username || !password) return null\n return { username, password }\n}\n\nexport const buildBasicAuth = (username: string, password: string): string => {\n return (\n BASIC +\n ui8.toString(ui8.fromString(`${username}:${password}`, 'utf8'), 'base64pad')\n )\n}\n\nconst createSecp256k1KeyObject = (\n publicKey: Uint8Array | string,\n): KeyObject => {\n // accepts compressed or uncompressed keys; validates the point is on-curve\n const point = secp256k1.ProjectivePoint.fromHex(publicKey).toRawBytes(false)\n return crypto.createPublicKey({\n format: 'jwk',\n key: {\n kty: 'EC',\n crv: 'secp256k1',\n x: ui8.toString(point.subarray(1, 33), 'base64url'),\n y: ui8.toString(point.subarray(33, 65), 'base64url'),\n },\n })\n}\n\nexport const createPublicKeyObject = (publicKeyHex: string): KeyObject => {\n return createSecp256k1KeyObject(publicKeyHex)\n}\n\nconst verifySig = (\n publicKey: Uint8Array,\n data: Uint8Array,\n sig: Uint8Array,\n) => {\n const key = createSecp256k1KeyObject(publicKey)\n\n return crypto.verify(\n 'sha256',\n data,\n {\n key,\n dsaEncoding: 'ieee-p1363',\n },\n sig,\n )\n}\n\nexport const verifySignatureWithKey: VerifySignatureWithKeyFn = async (\n didKey: string,\n msgBytes: Uint8Array,\n sigBytes: Uint8Array,\n alg: string,\n) => {\n if (alg === SECP256K1_JWT_ALG) {\n const parsed = parseDidKey(didKey)\n if (alg !== parsed.jwtAlg) {\n throw new Error(`Expected key alg ${alg}, got ${parsed.jwtAlg}`)\n }\n\n return verifySig(parsed.keyBytes, msgBytes, sigBytes)\n }\n\n return cryptoVerifySignatureWithKey(didKey, msgBytes, sigBytes, alg)\n}\n"]}
package/dist/config.d.ts CHANGED
@@ -61,6 +61,7 @@ export interface ServerConfigValues {
61
61
  topicsUrl?: string;
62
62
  topicsApiKey?: string;
63
63
  irisUrl?: string;
64
+ irisFeedUris?: Set<string>;
64
65
  cdnUrl?: string;
65
66
  videoPlaylistUrlPattern?: string;
66
67
  videoThumbnailUrlPattern?: string;
@@ -138,6 +139,7 @@ export declare class ServerConfig {
138
139
  get topicsUrl(): string | undefined;
139
140
  get topicsApiKey(): string | undefined;
140
141
  get irisUrl(): string | undefined;
142
+ get irisFeedUris(): Set<string> | undefined;
141
143
  get cdnUrl(): string | undefined;
142
144
  get videoPlaylistUrlPattern(): string | undefined;
143
145
  get videoThumbnailUrlPattern(): string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/config.js CHANGED
@@ -54,6 +54,7 @@ export class ServerConfig {
54
54
  const topicsUrl = process.env.BSKY_TOPICS_URL || undefined;
55
55
  const topicsApiKey = process.env.BSKY_TOPICS_API_KEY;
56
56
  const irisUrl = process.env.BSKY_IRIS_URL || undefined;
57
+ const irisFeedUris = new Set(envList(process.env.BSKY_IRIS_FEED_URIS));
57
58
  const dataplaneUrls = overrides?.dataplaneUrls ?? envList(process.env.BSKY_DATAPLANE_URLS);
58
59
  const dataplaneUrlsEtcdKeyPrefix = process.env.BSKY_DATAPLANE_URLS_ETCD_KEY_PREFIX || undefined;
59
60
  const dataplaneHttpVersion = process.env.BSKY_DATAPLANE_HTTP_VERSION || '2';
@@ -194,6 +195,7 @@ export class ServerConfig {
194
195
  topicsUrl,
195
196
  topicsApiKey,
196
197
  irisUrl,
198
+ irisFeedUris,
197
199
  didPlcUrl,
198
200
  labelsFromIssuerDids,
199
201
  handleResolveNameservers,
@@ -349,6 +351,9 @@ export class ServerConfig {
349
351
  get irisUrl() {
350
352
  return this.cfg.irisUrl;
351
353
  }
354
+ get irisFeedUris() {
355
+ return this.cfg.irisFeedUris;
356
+ }
352
357
  get cdnUrl() {
353
358
  return this.cfg.cdnUrl;
354
359
  }