@atproto/ozone 0.0.2

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 (444) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/LICENSE.txt +7 -0
  3. package/README.md +15 -0
  4. package/babel.config.js +3 -0
  5. package/bin/migration-create.ts +38 -0
  6. package/build.js +18 -0
  7. package/dist/api/admin/emitModerationEvent.d.ts +3 -0
  8. package/dist/api/admin/getModerationEvent.d.ts +3 -0
  9. package/dist/api/admin/getRecord.d.ts +3 -0
  10. package/dist/api/admin/getRepo.d.ts +3 -0
  11. package/dist/api/admin/queryModerationEvents.d.ts +3 -0
  12. package/dist/api/admin/queryModerationStatuses.d.ts +3 -0
  13. package/dist/api/admin/searchRepos.d.ts +3 -0
  14. package/dist/api/admin/util.d.ts +5 -0
  15. package/dist/api/com/atproto/admin/emitModerationEvent.d.ts +3 -0
  16. package/dist/api/com/atproto/admin/getModerationEvent.d.ts +3 -0
  17. package/dist/api/com/atproto/admin/getRecord.d.ts +3 -0
  18. package/dist/api/com/atproto/admin/getRepo.d.ts +3 -0
  19. package/dist/api/com/atproto/admin/queryModerationEvents.d.ts +3 -0
  20. package/dist/api/com/atproto/admin/queryModerationStatuses.d.ts +3 -0
  21. package/dist/api/com/atproto/admin/searchRepos.d.ts +3 -0
  22. package/dist/api/com/atproto/admin/util.d.ts +5 -0
  23. package/dist/api/com/atproto/moderation/createReport.d.ts +3 -0
  24. package/dist/api/com/atproto/moderation/util.d.ts +4 -0
  25. package/dist/api/com/atproto/temp/fetchLabels.d.ts +3 -0
  26. package/dist/api/health.d.ts +3 -0
  27. package/dist/api/index.d.ts +5 -0
  28. package/dist/api/label/queryLabels.d.ts +3 -0
  29. package/dist/api/label/subscribeLabels.d.ts +3 -0
  30. package/dist/api/moderation/createReport.d.ts +3 -0
  31. package/dist/api/moderation/util.d.ts +4 -0
  32. package/dist/api/temp/fetchLabels.d.ts +3 -0
  33. package/dist/api/util.d.ts +2 -0
  34. package/dist/api/well-known.d.ts +3 -0
  35. package/dist/auth-verifier.d.ts +47 -0
  36. package/dist/auth.d.ts +81 -0
  37. package/dist/background.d.ts +13 -0
  38. package/dist/config/config.d.ts +30 -0
  39. package/dist/config/env.d.ts +19 -0
  40. package/dist/config/index.d.ts +3 -0
  41. package/dist/config/secrets.d.ts +8 -0
  42. package/dist/config.d.ts +42 -0
  43. package/dist/context.d.ts +140 -0
  44. package/dist/daemon/config.d.ts +23 -0
  45. package/dist/daemon/context.d.ts +25 -0
  46. package/dist/daemon/event-pusher.d.ts +48 -0
  47. package/dist/daemon/event-reverser.d.ts +16 -0
  48. package/dist/daemon/index.d.ts +13 -0
  49. package/dist/db/index.d.ts +32 -0
  50. package/dist/db/index.js +33707 -0
  51. package/dist/db/index.js.map +7 -0
  52. package/dist/db/migrations/20231219T205730722Z-init.d.ts +3 -0
  53. package/dist/db/migrations/index.d.ts +1 -0
  54. package/dist/db/migrations/provider.d.ts +11 -0
  55. package/dist/db/pagination.d.ts +66 -0
  56. package/dist/db/schema/blob_push_event.d.ts +17 -0
  57. package/dist/db/schema/index.d.ts +10 -0
  58. package/dist/db/schema/label.d.ts +12 -0
  59. package/dist/db/schema/moderation_event.d.ts +22 -0
  60. package/dist/db/schema/moderation_subject_status.d.ts +25 -0
  61. package/dist/db/schema/record_push_event.d.ts +17 -0
  62. package/dist/db/schema/repo_push_event.d.ts +15 -0
  63. package/dist/db/types.d.ts +12 -0
  64. package/dist/error.d.ts +2 -0
  65. package/dist/index.d.ts +27 -0
  66. package/dist/index.js +131818 -0
  67. package/dist/index.js.map +7 -0
  68. package/dist/lexicon/index.d.ts +372 -0
  69. package/dist/lexicon/lexicons.d.ts +7553 -0
  70. package/dist/lexicon/types/app/bsky/actor/defs.d.ts +104 -0
  71. package/dist/lexicon/types/app/bsky/actor/getPreferences.d.ts +31 -0
  72. package/dist/lexicon/types/app/bsky/actor/getProfile.d.ts +29 -0
  73. package/dist/lexicon/types/app/bsky/actor/getProfiles.d.ts +32 -0
  74. package/dist/lexicon/types/app/bsky/actor/getSuggestions.d.ts +34 -0
  75. package/dist/lexicon/types/app/bsky/actor/profile.d.ts +15 -0
  76. package/dist/lexicon/types/app/bsky/actor/putPreferences.d.ts +26 -0
  77. package/dist/lexicon/types/app/bsky/actor/searchActors.d.ts +36 -0
  78. package/dist/lexicon/types/app/bsky/actor/searchActorsTypeahead.d.ts +34 -0
  79. package/dist/lexicon/types/app/bsky/embed/external.d.ts +31 -0
  80. package/dist/lexicon/types/app/bsky/embed/images.d.ts +37 -0
  81. package/dist/lexicon/types/app/bsky/embed/record.d.ts +54 -0
  82. package/dist/lexicon/types/app/bsky/embed/recordWithMedia.d.ts +24 -0
  83. package/dist/lexicon/types/app/bsky/feed/defs.d.ts +151 -0
  84. package/dist/lexicon/types/app/bsky/feed/describeFeedGenerator.d.ts +46 -0
  85. package/dist/lexicon/types/app/bsky/feed/generator.d.ts +18 -0
  86. package/dist/lexicon/types/app/bsky/feed/getActorFeeds.d.ts +35 -0
  87. package/dist/lexicon/types/app/bsky/feed/getActorLikes.d.ts +36 -0
  88. package/dist/lexicon/types/app/bsky/feed/getAuthorFeed.d.ts +37 -0
  89. package/dist/lexicon/types/app/bsky/feed/getFeed.d.ts +36 -0
  90. package/dist/lexicon/types/app/bsky/feed/getFeedGenerator.d.ts +34 -0
  91. package/dist/lexicon/types/app/bsky/feed/getFeedGenerators.d.ts +32 -0
  92. package/dist/lexicon/types/app/bsky/feed/getFeedSkeleton.d.ts +36 -0
  93. package/dist/lexicon/types/app/bsky/feed/getLikes.d.ts +47 -0
  94. package/dist/lexicon/types/app/bsky/feed/getListFeed.d.ts +36 -0
  95. package/dist/lexicon/types/app/bsky/feed/getPostThread.d.ts +38 -0
  96. package/dist/lexicon/types/app/bsky/feed/getPosts.d.ts +32 -0
  97. package/dist/lexicon/types/app/bsky/feed/getRepostedBy.d.ts +38 -0
  98. package/dist/lexicon/types/app/bsky/feed/getSuggestedFeeds.d.ts +34 -0
  99. package/dist/lexicon/types/app/bsky/feed/getTimeline.d.ts +35 -0
  100. package/dist/lexicon/types/app/bsky/feed/like.d.ts +9 -0
  101. package/dist/lexicon/types/app/bsky/feed/post.d.ts +50 -0
  102. package/dist/lexicon/types/app/bsky/feed/repost.d.ts +9 -0
  103. package/dist/lexicon/types/app/bsky/feed/searchPosts.d.ts +37 -0
  104. package/dist/lexicon/types/app/bsky/feed/threadgate.d.ts +28 -0
  105. package/dist/lexicon/types/app/bsky/graph/block.d.ts +8 -0
  106. package/dist/lexicon/types/app/bsky/graph/defs.d.ts +47 -0
  107. package/dist/lexicon/types/app/bsky/graph/follow.d.ts +8 -0
  108. package/dist/lexicon/types/app/bsky/graph/getBlocks.d.ts +34 -0
  109. package/dist/lexicon/types/app/bsky/graph/getFollowers.d.ts +36 -0
  110. package/dist/lexicon/types/app/bsky/graph/getFollows.d.ts +36 -0
  111. package/dist/lexicon/types/app/bsky/graph/getList.d.ts +36 -0
  112. package/dist/lexicon/types/app/bsky/graph/getListBlocks.d.ts +34 -0
  113. package/dist/lexicon/types/app/bsky/graph/getListMutes.d.ts +34 -0
  114. package/dist/lexicon/types/app/bsky/graph/getLists.d.ts +35 -0
  115. package/dist/lexicon/types/app/bsky/graph/getMutes.d.ts +34 -0
  116. package/dist/lexicon/types/app/bsky/graph/getSuggestedFollowsByActor.d.ts +32 -0
  117. package/dist/lexicon/types/app/bsky/graph/list.d.ts +19 -0
  118. package/dist/lexicon/types/app/bsky/graph/listblock.d.ts +8 -0
  119. package/dist/lexicon/types/app/bsky/graph/listitem.d.ts +9 -0
  120. package/dist/lexicon/types/app/bsky/graph/muteActor.d.ts +25 -0
  121. package/dist/lexicon/types/app/bsky/graph/muteActorList.d.ts +25 -0
  122. package/dist/lexicon/types/app/bsky/graph/unmuteActor.d.ts +25 -0
  123. package/dist/lexicon/types/app/bsky/graph/unmuteActorList.d.ts +25 -0
  124. package/dist/lexicon/types/app/bsky/moderation/defs.d.ts +49 -0
  125. package/dist/lexicon/types/app/bsky/moderation/getService.d.ts +29 -0
  126. package/dist/lexicon/types/app/bsky/moderation/getServices.d.ts +32 -0
  127. package/dist/lexicon/types/app/bsky/moderation/service.d.ts +17 -0
  128. package/dist/lexicon/types/app/bsky/notification/getUnreadCount.d.ts +31 -0
  129. package/dist/lexicon/types/app/bsky/notification/listNotifications.d.ts +52 -0
  130. package/dist/lexicon/types/app/bsky/notification/registerPush.d.ts +28 -0
  131. package/dist/lexicon/types/app/bsky/notification/updateSeen.d.ts +25 -0
  132. package/dist/lexicon/types/app/bsky/richtext/facet.d.ts +36 -0
  133. package/dist/lexicon/types/app/bsky/unspecced/defs.d.ts +13 -0
  134. package/dist/lexicon/types/app/bsky/unspecced/getPopular.d.ts +35 -0
  135. package/dist/lexicon/types/app/bsky/unspecced/getPopularFeedGenerators.d.ts +35 -0
  136. package/dist/lexicon/types/app/bsky/unspecced/getTimelineSkeleton.d.ts +35 -0
  137. package/dist/lexicon/types/app/bsky/unspecced/searchActorsSkeleton.d.ts +38 -0
  138. package/dist/lexicon/types/app/bsky/unspecced/searchPostsSkeleton.d.ts +37 -0
  139. package/dist/lexicon/types/com/atproto/admin/defs.d.ts +319 -0
  140. package/dist/lexicon/types/com/atproto/admin/deleteAccount.d.ts +25 -0
  141. package/dist/lexicon/types/com/atproto/admin/disableAccountInvites.d.ts +26 -0
  142. package/dist/lexicon/types/com/atproto/admin/disableInviteCodes.d.ts +26 -0
  143. package/dist/lexicon/types/com/atproto/admin/emitModerationEvent.d.ts +45 -0
  144. package/dist/lexicon/types/com/atproto/admin/enableAccountInvites.d.ts +26 -0
  145. package/dist/lexicon/types/com/atproto/admin/getAccountInfo.d.ts +29 -0
  146. package/dist/lexicon/types/com/atproto/admin/getAccountInfos.d.ts +32 -0
  147. package/dist/lexicon/types/com/atproto/admin/getInviteCodes.d.ts +35 -0
  148. package/dist/lexicon/types/com/atproto/admin/getModerationEvent.d.ts +29 -0
  149. package/dist/lexicon/types/com/atproto/admin/getRecord.d.ts +31 -0
  150. package/dist/lexicon/types/com/atproto/admin/getRepo.d.ts +30 -0
  151. package/dist/lexicon/types/com/atproto/admin/getSubjectStatus.d.ts +39 -0
  152. package/dist/lexicon/types/com/atproto/admin/queryModerationEvents.d.ts +39 -0
  153. package/dist/lexicon/types/com/atproto/admin/queryModerationStatuses.d.ts +48 -0
  154. package/dist/lexicon/types/com/atproto/admin/searchRepos.d.ts +36 -0
  155. package/dist/lexicon/types/com/atproto/admin/sendEmail.d.ts +40 -0
  156. package/dist/lexicon/types/com/atproto/admin/updateAccountEmail.d.ts +26 -0
  157. package/dist/lexicon/types/com/atproto/admin/updateAccountHandle.d.ts +26 -0
  158. package/dist/lexicon/types/com/atproto/admin/updateSubjectStatus.d.ts +46 -0
  159. package/dist/lexicon/types/com/atproto/identity/resolveHandle.d.ts +31 -0
  160. package/dist/lexicon/types/com/atproto/identity/updateHandle.d.ts +25 -0
  161. package/dist/lexicon/types/com/atproto/label/defs.d.ts +24 -0
  162. package/dist/lexicon/types/com/atproto/label/queryLabels.d.ts +36 -0
  163. package/dist/lexicon/types/com/atproto/label/subscribeLabels.d.ts +36 -0
  164. package/dist/lexicon/types/com/atproto/moderation/createReport.d.ts +52 -0
  165. package/dist/lexicon/types/com/atproto/moderation/defs.d.ts +8 -0
  166. package/dist/lexicon/types/com/atproto/repo/applyWrites.d.ts +53 -0
  167. package/dist/lexicon/types/com/atproto/repo/createRecord.d.ts +43 -0
  168. package/dist/lexicon/types/com/atproto/repo/deleteRecord.d.ts +30 -0
  169. package/dist/lexicon/types/com/atproto/repo/describeRepo.d.ts +35 -0
  170. package/dist/lexicon/types/com/atproto/repo/getRecord.d.ts +36 -0
  171. package/dist/lexicon/types/com/atproto/repo/listRecords.d.ts +47 -0
  172. package/dist/lexicon/types/com/atproto/repo/putRecord.d.ts +44 -0
  173. package/dist/lexicon/types/com/atproto/repo/strongRef.d.ts +8 -0
  174. package/dist/lexicon/types/com/atproto/repo/uploadBlob.d.ts +36 -0
  175. package/dist/lexicon/types/com/atproto/server/confirmEmail.d.ts +27 -0
  176. package/dist/lexicon/types/com/atproto/server/createAccount.d.ts +49 -0
  177. package/dist/lexicon/types/com/atproto/server/createAppPassword.d.ts +43 -0
  178. package/dist/lexicon/types/com/atproto/server/createInviteCode.d.ts +37 -0
  179. package/dist/lexicon/types/com/atproto/server/createInviteCodes.d.ts +46 -0
  180. package/dist/lexicon/types/com/atproto/server/createSession.d.ts +44 -0
  181. package/dist/lexicon/types/com/atproto/server/defs.d.ts +20 -0
  182. package/dist/lexicon/types/com/atproto/server/deleteAccount.d.ts +28 -0
  183. package/dist/lexicon/types/com/atproto/server/deleteSession.d.ts +19 -0
  184. package/dist/lexicon/types/com/atproto/server/describeServer.d.ts +41 -0
  185. package/dist/lexicon/types/com/atproto/server/getAccountInviteCodes.d.ts +34 -0
  186. package/dist/lexicon/types/com/atproto/server/getSession.d.ts +34 -0
  187. package/dist/lexicon/types/com/atproto/server/listAppPasswords.d.ts +39 -0
  188. package/dist/lexicon/types/com/atproto/server/refreshSession.d.ts +35 -0
  189. package/dist/lexicon/types/com/atproto/server/requestAccountDelete.d.ts +19 -0
  190. package/dist/lexicon/types/com/atproto/server/requestEmailConfirmation.d.ts +19 -0
  191. package/dist/lexicon/types/com/atproto/server/requestEmailUpdate.d.ts +30 -0
  192. package/dist/lexicon/types/com/atproto/server/requestPasswordReset.d.ts +25 -0
  193. package/dist/lexicon/types/com/atproto/server/reserveSigningKey.d.ts +36 -0
  194. package/dist/lexicon/types/com/atproto/server/resetPassword.d.ts +27 -0
  195. package/dist/lexicon/types/com/atproto/server/revokeAppPassword.d.ts +25 -0
  196. package/dist/lexicon/types/com/atproto/server/updateEmail.d.ts +27 -0
  197. package/dist/lexicon/types/com/atproto/sync/getBlob.d.ts +30 -0
  198. package/dist/lexicon/types/com/atproto/sync/getBlocks.d.ts +30 -0
  199. package/dist/lexicon/types/com/atproto/sync/getCheckout.d.ts +29 -0
  200. package/dist/lexicon/types/com/atproto/sync/getHead.d.ts +32 -0
  201. package/dist/lexicon/types/com/atproto/sync/getLatestCommit.d.ts +33 -0
  202. package/dist/lexicon/types/com/atproto/sync/getRecord.d.ts +32 -0
  203. package/dist/lexicon/types/com/atproto/sync/getRepo.d.ts +30 -0
  204. package/dist/lexicon/types/com/atproto/sync/listBlobs.d.ts +35 -0
  205. package/dist/lexicon/types/com/atproto/sync/listRepos.d.ts +42 -0
  206. package/dist/lexicon/types/com/atproto/sync/notifyOfUpdate.d.ts +25 -0
  207. package/dist/lexicon/types/com/atproto/sync/requestCrawl.d.ts +25 -0
  208. package/dist/lexicon/types/com/atproto/sync/subscribeRepos.d.ts +80 -0
  209. package/dist/lexicon/types/com/atproto/temp/fetchLabels.d.ts +33 -0
  210. package/dist/lexicon/types/com/atproto/temp/importRepo.d.ts +32 -0
  211. package/dist/lexicon/types/com/atproto/temp/pushBlob.d.ts +25 -0
  212. package/dist/lexicon/types/com/atproto/temp/requestPhoneVerification.d.ts +25 -0
  213. package/dist/lexicon/types/com/atproto/temp/transferAccount.d.ts +42 -0
  214. package/dist/lexicon/util.d.ts +2 -0
  215. package/dist/logger.d.ts +4 -0
  216. package/dist/mod-service/index.d.ts +155 -0
  217. package/dist/mod-service/status.d.ts +12 -0
  218. package/dist/mod-service/subject.d.ts +59 -0
  219. package/dist/mod-service/types.d.ts +19 -0
  220. package/dist/mod-service/views.d.ts +49 -0
  221. package/dist/sequencer/index.d.ts +2 -0
  222. package/dist/sequencer/outbox.d.ts +16 -0
  223. package/dist/sequencer/sequencer.d.ts +35 -0
  224. package/dist/services/index.d.ts +7 -0
  225. package/dist/services/moderation/index.d.ts +144 -0
  226. package/dist/services/moderation/status.d.ts +12 -0
  227. package/dist/services/moderation/subject.d.ts +60 -0
  228. package/dist/services/moderation/types.d.ts +19 -0
  229. package/dist/services/moderation/views.d.ts +42 -0
  230. package/dist/services/types.d.ts +2 -0
  231. package/dist/util/date.d.ts +1 -0
  232. package/dist/util/debug.d.ts +1 -0
  233. package/dist/util/retry.d.ts +3 -0
  234. package/dist/util.d.ts +3 -0
  235. package/jest.config.js +6 -0
  236. package/package.json +67 -0
  237. package/src/api/admin/emitModerationEvent.ts +130 -0
  238. package/src/api/admin/getModerationEvent.ts +19 -0
  239. package/src/api/admin/getRecord.ts +34 -0
  240. package/src/api/admin/getRepo.ts +31 -0
  241. package/src/api/admin/queryModerationEvents.ts +40 -0
  242. package/src/api/admin/queryModerationStatuses.ts +57 -0
  243. package/src/api/admin/searchRepos.ts +42 -0
  244. package/src/api/admin/util.ts +54 -0
  245. package/src/api/health.ts +20 -0
  246. package/src/api/index.ts +28 -0
  247. package/src/api/moderation/createReport.ts +41 -0
  248. package/src/api/moderation/util.ts +65 -0
  249. package/src/api/temp/fetchLabels.ts +29 -0
  250. package/src/api/well-known.ts +35 -0
  251. package/src/auth.ts +147 -0
  252. package/src/background.ts +35 -0
  253. package/src/config/config.ts +84 -0
  254. package/src/config/env.ts +41 -0
  255. package/src/config/index.ts +3 -0
  256. package/src/config/secrets.ts +23 -0
  257. package/src/context.ts +180 -0
  258. package/src/daemon/context.ts +90 -0
  259. package/src/daemon/event-pusher.ts +296 -0
  260. package/src/daemon/event-reverser.ts +74 -0
  261. package/src/daemon/index.ts +33 -0
  262. package/src/db/index.ts +197 -0
  263. package/src/db/migrations/20231219T205730722Z-init.ts +164 -0
  264. package/src/db/migrations/index.ts +5 -0
  265. package/src/db/migrations/provider.ts +25 -0
  266. package/src/db/pagination.ts +216 -0
  267. package/src/db/schema/blob_push_event.ts +21 -0
  268. package/src/db/schema/index.ts +18 -0
  269. package/src/db/schema/label.ts +12 -0
  270. package/src/db/schema/moderation_event.ts +35 -0
  271. package/src/db/schema/moderation_subject_status.ts +32 -0
  272. package/src/db/schema/record_push_event.ts +21 -0
  273. package/src/db/schema/repo_push_event.ts +19 -0
  274. package/src/db/types.ts +15 -0
  275. package/src/error.ts +12 -0
  276. package/src/index.ts +102 -0
  277. package/src/lexicon/index.ts +1626 -0
  278. package/src/lexicon/lexicons.ts +8050 -0
  279. package/src/lexicon/types/app/bsky/actor/defs.ts +235 -0
  280. package/src/lexicon/types/app/bsky/actor/getPreferences.ts +44 -0
  281. package/src/lexicon/types/app/bsky/actor/getProfile.ts +41 -0
  282. package/src/lexicon/types/app/bsky/actor/getProfiles.ts +46 -0
  283. package/src/lexicon/types/app/bsky/actor/getSuggestions.ts +48 -0
  284. package/src/lexicon/types/app/bsky/actor/profile.ts +32 -0
  285. package/src/lexicon/types/app/bsky/actor/putPreferences.ts +39 -0
  286. package/src/lexicon/types/app/bsky/actor/searchActors.ts +52 -0
  287. package/src/lexicon/types/app/bsky/actor/searchActorsTypeahead.ts +50 -0
  288. package/src/lexicon/types/app/bsky/embed/external.ts +82 -0
  289. package/src/lexicon/types/app/bsky/embed/images.ts +96 -0
  290. package/src/lexicon/types/app/bsky/embed/record.ts +120 -0
  291. package/src/lexicon/types/app/bsky/embed/recordWithMedia.ts +53 -0
  292. package/src/lexicon/types/app/bsky/feed/defs.ts +308 -0
  293. package/src/lexicon/types/app/bsky/feed/describeFeedGenerator.ts +80 -0
  294. package/src/lexicon/types/app/bsky/feed/generator.ts +35 -0
  295. package/src/lexicon/types/app/bsky/feed/getActorFeeds.ts +49 -0
  296. package/src/lexicon/types/app/bsky/feed/getActorLikes.ts +50 -0
  297. package/src/lexicon/types/app/bsky/feed/getAuthorFeed.ts +56 -0
  298. package/src/lexicon/types/app/bsky/feed/getFeed.ts +50 -0
  299. package/src/lexicon/types/app/bsky/feed/getFeedGenerator.ts +48 -0
  300. package/src/lexicon/types/app/bsky/feed/getFeedGenerators.ts +46 -0
  301. package/src/lexicon/types/app/bsky/feed/getFeedSkeleton.ts +50 -0
  302. package/src/lexicon/types/app/bsky/feed/getLikes.ts +69 -0
  303. package/src/lexicon/types/app/bsky/feed/getListFeed.ts +50 -0
  304. package/src/lexicon/types/app/bsky/feed/getPostThread.ts +53 -0
  305. package/src/lexicon/types/app/bsky/feed/getPosts.ts +46 -0
  306. package/src/lexicon/types/app/bsky/feed/getRepostedBy.ts +52 -0
  307. package/src/lexicon/types/app/bsky/feed/getSuggestedFeeds.ts +48 -0
  308. package/src/lexicon/types/app/bsky/feed/getTimeline.ts +49 -0
  309. package/src/lexicon/types/app/bsky/feed/like.ts +26 -0
  310. package/src/lexicon/types/app/bsky/feed/post.ts +102 -0
  311. package/src/lexicon/types/app/bsky/feed/repost.ts +27 -0
  312. package/src/lexicon/types/app/bsky/feed/searchPosts.ts +54 -0
  313. package/src/lexicon/types/app/bsky/feed/threadgate.ts +84 -0
  314. package/src/lexicon/types/app/bsky/graph/block.ts +26 -0
  315. package/src/lexicon/types/app/bsky/graph/defs.ts +104 -0
  316. package/src/lexicon/types/app/bsky/graph/follow.ts +26 -0
  317. package/src/lexicon/types/app/bsky/graph/getBlocks.ts +48 -0
  318. package/src/lexicon/types/app/bsky/graph/getFollowers.ts +50 -0
  319. package/src/lexicon/types/app/bsky/graph/getFollows.ts +50 -0
  320. package/src/lexicon/types/app/bsky/graph/getList.ts +50 -0
  321. package/src/lexicon/types/app/bsky/graph/getListBlocks.ts +48 -0
  322. package/src/lexicon/types/app/bsky/graph/getListMutes.ts +48 -0
  323. package/src/lexicon/types/app/bsky/graph/getLists.ts +49 -0
  324. package/src/lexicon/types/app/bsky/graph/getMutes.ts +48 -0
  325. package/src/lexicon/types/app/bsky/graph/getSuggestedFollowsByActor.ts +46 -0
  326. package/src/lexicon/types/app/bsky/graph/list.ts +36 -0
  327. package/src/lexicon/types/app/bsky/graph/listblock.ts +26 -0
  328. package/src/lexicon/types/app/bsky/graph/listitem.ts +27 -0
  329. package/src/lexicon/types/app/bsky/graph/muteActor.ts +38 -0
  330. package/src/lexicon/types/app/bsky/graph/muteActorList.ts +38 -0
  331. package/src/lexicon/types/app/bsky/graph/unmuteActor.ts +38 -0
  332. package/src/lexicon/types/app/bsky/graph/unmuteActorList.ts +38 -0
  333. package/src/lexicon/types/app/bsky/notification/getUnreadCount.ts +45 -0
  334. package/src/lexicon/types/app/bsky/notification/listNotifications.ts +87 -0
  335. package/src/lexicon/types/app/bsky/notification/registerPush.ts +41 -0
  336. package/src/lexicon/types/app/bsky/notification/updateSeen.ts +38 -0
  337. package/src/lexicon/types/app/bsky/richtext/facet.ts +97 -0
  338. package/src/lexicon/types/app/bsky/unspecced/defs.ts +41 -0
  339. package/src/lexicon/types/app/bsky/unspecced/getPopularFeedGenerators.ts +49 -0
  340. package/src/lexicon/types/app/bsky/unspecced/getTimelineSkeleton.ts +49 -0
  341. package/src/lexicon/types/app/bsky/unspecced/searchActorsSkeleton.ts +56 -0
  342. package/src/lexicon/types/app/bsky/unspecced/searchPostsSkeleton.ts +54 -0
  343. package/src/lexicon/types/com/atproto/admin/defs.ts +719 -0
  344. package/src/lexicon/types/com/atproto/admin/deleteAccount.ts +38 -0
  345. package/src/lexicon/types/com/atproto/admin/disableAccountInvites.ts +40 -0
  346. package/src/lexicon/types/com/atproto/admin/disableInviteCodes.ts +39 -0
  347. package/src/lexicon/types/com/atproto/admin/emitModerationEvent.ts +66 -0
  348. package/src/lexicon/types/com/atproto/admin/enableAccountInvites.ts +40 -0
  349. package/src/lexicon/types/com/atproto/admin/getAccountInfo.ts +41 -0
  350. package/src/lexicon/types/com/atproto/admin/getAccountInfos.ts +46 -0
  351. package/src/lexicon/types/com/atproto/admin/getInviteCodes.ts +49 -0
  352. package/src/lexicon/types/com/atproto/admin/getModerationEvent.ts +41 -0
  353. package/src/lexicon/types/com/atproto/admin/getRecord.ts +43 -0
  354. package/src/lexicon/types/com/atproto/admin/getRepo.ts +42 -0
  355. package/src/lexicon/types/com/atproto/admin/getSubjectStatus.ts +54 -0
  356. package/src/lexicon/types/com/atproto/admin/queryModerationEvents.ts +56 -0
  357. package/src/lexicon/types/com/atproto/admin/queryModerationStatuses.ts +72 -0
  358. package/src/lexicon/types/com/atproto/admin/searchRepos.ts +51 -0
  359. package/src/lexicon/types/com/atproto/admin/sendEmail.ts +54 -0
  360. package/src/lexicon/types/com/atproto/admin/updateAccountEmail.ts +40 -0
  361. package/src/lexicon/types/com/atproto/admin/updateAccountHandle.ts +39 -0
  362. package/src/lexicon/types/com/atproto/admin/updateSubjectStatus.ts +61 -0
  363. package/src/lexicon/types/com/atproto/identity/resolveHandle.ts +46 -0
  364. package/src/lexicon/types/com/atproto/identity/updateHandle.ts +38 -0
  365. package/src/lexicon/types/com/atproto/label/defs.ts +73 -0
  366. package/src/lexicon/types/com/atproto/label/queryLabels.ts +52 -0
  367. package/src/lexicon/types/com/atproto/label/subscribeLabels.ts +67 -0
  368. package/src/lexicon/types/com/atproto/moderation/createReport.ts +65 -0
  369. package/src/lexicon/types/com/atproto/moderation/defs.ts +32 -0
  370. package/src/lexicon/types/com/atproto/repo/applyWrites.ts +103 -0
  371. package/src/lexicon/types/com/atproto/repo/createRecord.ts +62 -0
  372. package/src/lexicon/types/com/atproto/repo/deleteRecord.ts +48 -0
  373. package/src/lexicon/types/com/atproto/repo/describeRepo.ts +50 -0
  374. package/src/lexicon/types/com/atproto/repo/getRecord.ts +54 -0
  375. package/src/lexicon/types/com/atproto/repo/listRecords.ts +77 -0
  376. package/src/lexicon/types/com/atproto/repo/putRecord.ts +64 -0
  377. package/src/lexicon/types/com/atproto/repo/strongRef.ts +26 -0
  378. package/src/lexicon/types/com/atproto/repo/uploadBlob.ts +47 -0
  379. package/src/lexicon/types/com/atproto/server/confirmEmail.ts +40 -0
  380. package/src/lexicon/types/com/atproto/server/createAccount.ts +69 -0
  381. package/src/lexicon/types/com/atproto/server/createAppPassword.ts +69 -0
  382. package/src/lexicon/types/com/atproto/server/createInviteCode.ts +50 -0
  383. package/src/lexicon/types/com/atproto/server/createInviteCodes.ts +72 -0
  384. package/src/lexicon/types/com/atproto/server/createSession.ts +58 -0
  385. package/src/lexicon/types/com/atproto/server/defs.ts +48 -0
  386. package/src/lexicon/types/com/atproto/server/deleteAccount.ts +41 -0
  387. package/src/lexicon/types/com/atproto/server/deleteSession.ts +31 -0
  388. package/src/lexicon/types/com/atproto/server/describeServer.ts +64 -0
  389. package/src/lexicon/types/com/atproto/server/getAccountInviteCodes.ts +48 -0
  390. package/src/lexicon/types/com/atproto/server/getSession.ts +47 -0
  391. package/src/lexicon/types/com/atproto/server/listAppPasswords.ts +62 -0
  392. package/src/lexicon/types/com/atproto/server/refreshSession.ts +48 -0
  393. package/src/lexicon/types/com/atproto/server/requestAccountDelete.ts +31 -0
  394. package/src/lexicon/types/com/atproto/server/requestEmailConfirmation.ts +31 -0
  395. package/src/lexicon/types/com/atproto/server/requestEmailUpdate.ts +43 -0
  396. package/src/lexicon/types/com/atproto/server/requestPasswordReset.ts +38 -0
  397. package/src/lexicon/types/com/atproto/server/reserveSigningKey.ts +51 -0
  398. package/src/lexicon/types/com/atproto/server/resetPassword.ts +40 -0
  399. package/src/lexicon/types/com/atproto/server/revokeAppPassword.ts +38 -0
  400. package/src/lexicon/types/com/atproto/server/updateEmail.ts +41 -0
  401. package/src/lexicon/types/com/atproto/sync/getBlob.ts +43 -0
  402. package/src/lexicon/types/com/atproto/sync/getBlocks.ts +42 -0
  403. package/src/lexicon/types/com/atproto/sync/getCheckout.ts +41 -0
  404. package/src/lexicon/types/com/atproto/sync/getHead.ts +47 -0
  405. package/src/lexicon/types/com/atproto/sync/getLatestCommit.ts +48 -0
  406. package/src/lexicon/types/com/atproto/sync/getRecord.ts +45 -0
  407. package/src/lexicon/types/com/atproto/sync/getRepo.ts +43 -0
  408. package/src/lexicon/types/com/atproto/sync/listBlobs.ts +51 -0
  409. package/src/lexicon/types/com/atproto/sync/listRepos.ts +66 -0
  410. package/src/lexicon/types/com/atproto/sync/notifyOfUpdate.ts +39 -0
  411. package/src/lexicon/types/com/atproto/sync/requestCrawl.ts +39 -0
  412. package/src/lexicon/types/com/atproto/sync/subscribeRepos.ts +161 -0
  413. package/src/lexicon/types/com/atproto/temp/fetchLabels.ts +47 -0
  414. package/src/lexicon/types/com/atproto/temp/importRepo.ts +45 -0
  415. package/src/lexicon/types/com/atproto/temp/pushBlob.ts +39 -0
  416. package/src/lexicon/types/com/atproto/temp/requestPhoneVerification.ts +38 -0
  417. package/src/lexicon/types/com/atproto/temp/transferAccount.ts +62 -0
  418. package/src/lexicon/util.ts +13 -0
  419. package/src/logger.ts +19 -0
  420. package/src/mod-service/index.ts +758 -0
  421. package/src/mod-service/status.ts +264 -0
  422. package/src/mod-service/subject.ts +136 -0
  423. package/src/mod-service/types.ts +32 -0
  424. package/src/mod-service/views.ts +531 -0
  425. package/src/util.ts +26 -0
  426. package/test.env +2 -0
  427. package/test.log +0 -0
  428. package/tests/__snapshots__/get-record.test.ts.snap +173 -0
  429. package/tests/__snapshots__/get-repo.test.ts.snap +57 -0
  430. package/tests/__snapshots__/moderation-events.test.ts.snap +168 -0
  431. package/tests/__snapshots__/moderation-statuses.test.ts.snap +64 -0
  432. package/tests/__snapshots__/moderation.test.ts.snap +55 -0
  433. package/tests/_util.ts +192 -0
  434. package/tests/db.test.ts +184 -0
  435. package/tests/get-record.test.ts +110 -0
  436. package/tests/get-repo.test.ts +131 -0
  437. package/tests/moderation-appeals.test.ts +269 -0
  438. package/tests/moderation-events.test.ts +220 -0
  439. package/tests/moderation-statuses.test.ts +144 -0
  440. package/tests/moderation.test.ts +961 -0
  441. package/tests/repo-search.test.ts +123 -0
  442. package/tests/server.test.ts +76 -0
  443. package/tsconfig.build.json +4 -0
  444. package/tsconfig.json +21 -0
@@ -0,0 +1,57 @@
1
+ import { Server } from '../../lexicon'
2
+ import AppContext from '../../context'
3
+ import { getReviewState } from '../moderation/util'
4
+
5
+ export default function (server: Server, ctx: AppContext) {
6
+ server.com.atproto.admin.queryModerationStatuses({
7
+ auth: ctx.roleVerifier,
8
+ handler: async ({ params }) => {
9
+ const {
10
+ subject,
11
+ takendown,
12
+ appealed,
13
+ reviewState,
14
+ reviewedAfter,
15
+ reviewedBefore,
16
+ reportedAfter,
17
+ reportedBefore,
18
+ ignoreSubjects,
19
+ lastReviewedBy,
20
+ sortDirection = 'desc',
21
+ sortField = 'lastReportedAt',
22
+ includeMuted = false,
23
+ limit = 50,
24
+ cursor,
25
+ } = params
26
+ const db = ctx.db
27
+ const modService = ctx.modService(db)
28
+ const results = await modService.getSubjectStatuses({
29
+ reviewState: getReviewState(reviewState),
30
+ subject,
31
+ takendown,
32
+ appealed,
33
+ reviewedAfter,
34
+ reviewedBefore,
35
+ reportedAfter,
36
+ reportedBefore,
37
+ includeMuted,
38
+ ignoreSubjects,
39
+ sortDirection,
40
+ lastReviewedBy,
41
+ sortField,
42
+ limit,
43
+ cursor,
44
+ })
45
+ const subjectStatuses = results.statuses.map((status) =>
46
+ modService.views.formatSubjectStatus(status),
47
+ )
48
+ return {
49
+ encoding: 'application/json',
50
+ body: {
51
+ cursor: results.cursor,
52
+ subjectStatuses,
53
+ },
54
+ }
55
+ },
56
+ })
57
+ }
@@ -0,0 +1,42 @@
1
+ import { Server } from '../../lexicon'
2
+ import AppContext from '../../context'
3
+ import { mapDefined } from '@atproto/common'
4
+
5
+ export default function (server: Server, ctx: AppContext) {
6
+ server.com.atproto.admin.searchRepos({
7
+ auth: ctx.roleVerifier,
8
+ handler: async ({ params }) => {
9
+ const modService = ctx.modService(ctx.db)
10
+
11
+ // prefer new 'q' query param over deprecated 'term'
12
+ const query = params.q ?? params.term
13
+
14
+ // special case for did searches - do exact match
15
+ if (query?.startsWith('did:')) {
16
+ const repos = await modService.views.repos([query])
17
+ const found = repos.get(query)
18
+ return {
19
+ encoding: 'application/json',
20
+ body: {
21
+ repos: found ? [found] : [],
22
+ },
23
+ }
24
+ }
25
+
26
+ const res = await ctx.appviewAgent.api.app.bsky.actor.searchActors(params)
27
+ const repoMap = await modService.views.repos(
28
+ res.data.actors.map((a) => a.did),
29
+ )
30
+ const repos = mapDefined(res.data.actors, (actor) =>
31
+ repoMap.get(actor.did),
32
+ )
33
+ return {
34
+ encoding: 'application/json',
35
+ body: {
36
+ cursor: res.data.cursor,
37
+ repos,
38
+ },
39
+ }
40
+ },
41
+ })
42
+ }
@@ -0,0 +1,54 @@
1
+ import AppContext from '../../context'
2
+ import {
3
+ RepoView,
4
+ RepoViewDetail,
5
+ AccountView,
6
+ } from '../../lexicon/types/com/atproto/admin/defs'
7
+
8
+ export const getPdsAccountInfo = async (
9
+ ctx: AppContext,
10
+ did: string,
11
+ ): Promise<AccountView | null> => {
12
+ const agent = ctx.pdsAgent
13
+ if (!agent) return null
14
+ const auth = await ctx.pdsAuth()
15
+ if (!auth) return null
16
+ try {
17
+ const res = await agent.api.com.atproto.admin.getAccountInfo({ did }, auth)
18
+ return res.data
19
+ } catch (err) {
20
+ return null
21
+ }
22
+ }
23
+
24
+ export const addAccountInfoToRepoViewDetail = (
25
+ repoView: RepoViewDetail,
26
+ accountInfo: AccountView | null,
27
+ includeEmail = false,
28
+ ): RepoViewDetail => {
29
+ if (!accountInfo) return repoView
30
+ return {
31
+ ...repoView,
32
+ email: includeEmail ? accountInfo.email : undefined,
33
+ invitedBy: accountInfo.invitedBy,
34
+ invitesDisabled: accountInfo.invitesDisabled,
35
+ inviteNote: accountInfo.inviteNote,
36
+ invites: accountInfo.invites,
37
+ emailConfirmedAt: accountInfo.emailConfirmedAt,
38
+ }
39
+ }
40
+
41
+ export const addAccountInfoToRepoView = (
42
+ repoView: RepoView,
43
+ accountInfo: AccountView | null,
44
+ includeEmail = false,
45
+ ): RepoView => {
46
+ if (!accountInfo) return repoView
47
+ return {
48
+ ...repoView,
49
+ email: includeEmail ? accountInfo.email : undefined,
50
+ invitedBy: accountInfo.invitedBy,
51
+ invitesDisabled: accountInfo.invitesDisabled,
52
+ inviteNote: accountInfo.inviteNote,
53
+ }
54
+ }
@@ -0,0 +1,20 @@
1
+ import express from 'express'
2
+ import { sql } from 'kysely'
3
+ import AppContext from '../context'
4
+
5
+ export const createRouter = (ctx: AppContext): express.Router => {
6
+ const router = express.Router()
7
+
8
+ router.get('/xrpc/_health', async function (req, res) {
9
+ const { version } = ctx.cfg.service
10
+ try {
11
+ await sql`select 1`.execute(ctx.db.db)
12
+ } catch (err) {
13
+ req.log.error(err, 'failed health check')
14
+ return res.status(503).send({ version, error: 'Service Unavailable' })
15
+ }
16
+ res.send({ version })
17
+ })
18
+
19
+ return router
20
+ }
@@ -0,0 +1,28 @@
1
+ import { Server } from '../lexicon'
2
+ import AppContext from '../context'
3
+ import createReport from './moderation/createReport'
4
+ import emitModerationEvent from './admin/emitModerationEvent'
5
+ import searchRepos from './admin/searchRepos'
6
+ import adminGetRecord from './admin/getRecord'
7
+ import getRepo from './admin/getRepo'
8
+ import queryModerationStatuses from './admin/queryModerationStatuses'
9
+ import queryModerationEvents from './admin/queryModerationEvents'
10
+ import getModerationEvent from './admin/getModerationEvent'
11
+ import fetchLabels from './temp/fetchLabels'
12
+
13
+ export * as health from './health'
14
+
15
+ export * as wellKnown from './well-known'
16
+
17
+ export default function (server: Server, ctx: AppContext) {
18
+ createReport(server, ctx)
19
+ emitModerationEvent(server, ctx)
20
+ searchRepos(server, ctx)
21
+ adminGetRecord(server, ctx)
22
+ getRepo(server, ctx)
23
+ getModerationEvent(server, ctx)
24
+ queryModerationEvents(server, ctx)
25
+ queryModerationStatuses(server, ctx)
26
+ fetchLabels(server, ctx)
27
+ return server
28
+ }
@@ -0,0 +1,41 @@
1
+ import { Server } from '../../lexicon'
2
+ import AppContext from '../../context'
3
+ import { getReasonType } from './util'
4
+ import { subjectFromInput } from '../../mod-service/subject'
5
+ import { REASONAPPEAL } from '../../lexicon/types/com/atproto/moderation/defs'
6
+ import { ForbiddenError } from '@atproto/xrpc-server'
7
+
8
+ export default function (server: Server, ctx: AppContext) {
9
+ server.com.atproto.moderation.createReport({
10
+ // @TODO anonymous reports w/ optional auth are a temporary measure
11
+ auth: ctx.authOptionalAccessOrRoleVerifier,
12
+ handler: async ({ input, auth }) => {
13
+ const requester =
14
+ 'did' in auth.credentials ? auth.credentials.did : ctx.cfg.service.did
15
+ const { reasonType, reason } = input.body
16
+ const subject = subjectFromInput(input.body.subject)
17
+
18
+ // If the report is an appeal, the requester must be the author of the subject
19
+ if (reasonType === REASONAPPEAL && requester !== subject.did) {
20
+ throw new ForbiddenError('You cannot appeal this report')
21
+ }
22
+
23
+ const db = ctx.db
24
+ const report = await db.transaction(async (dbTxn) => {
25
+ const moderationTxn = ctx.modService(dbTxn)
26
+ return moderationTxn.report({
27
+ reasonType: getReasonType(reasonType),
28
+ reason,
29
+ subject,
30
+ reportedBy: requester || ctx.cfg.service.did,
31
+ })
32
+ })
33
+
34
+ const body = ctx.modService(db).views.formatReport(report)
35
+ return {
36
+ encoding: 'application/json',
37
+ body,
38
+ }
39
+ },
40
+ })
41
+ }
@@ -0,0 +1,65 @@
1
+ import { InvalidRequestError } from '@atproto/xrpc-server'
2
+ import { InputSchema as ReportInput } from '../../lexicon/types/com/atproto/moderation/createReport'
3
+ import {
4
+ REASONOTHER,
5
+ REASONSPAM,
6
+ REASONMISLEADING,
7
+ REASONRUDE,
8
+ REASONSEXUAL,
9
+ REASONVIOLATION,
10
+ REASONAPPEAL,
11
+ } from '../../lexicon/types/com/atproto/moderation/defs'
12
+ import {
13
+ REVIEWCLOSED,
14
+ REVIEWESCALATED,
15
+ REVIEWOPEN,
16
+ } from '../../lexicon/types/com/atproto/admin/defs'
17
+ import { ModerationEvent } from '../../db/schema/moderation_event'
18
+ import { ModerationSubjectStatusRow } from '../../mod-service/types'
19
+
20
+ export const getReasonType = (reasonType: ReportInput['reasonType']) => {
21
+ if (reasonTypes.has(reasonType)) {
22
+ return reasonType as NonNullable<ModerationEvent['meta']>['reportType']
23
+ }
24
+ throw new InvalidRequestError('Invalid reason type')
25
+ }
26
+
27
+ export const getEventType = (type: string) => {
28
+ if (eventTypes.has(type)) {
29
+ return type as ModerationEvent['action']
30
+ }
31
+ throw new InvalidRequestError('Invalid event type')
32
+ }
33
+
34
+ export const getReviewState = (reviewState?: string) => {
35
+ if (!reviewState) return undefined
36
+ if (reviewStates.has(reviewState)) {
37
+ return reviewState as ModerationSubjectStatusRow['reviewState']
38
+ }
39
+ throw new InvalidRequestError('Invalid review state')
40
+ }
41
+
42
+ const reviewStates = new Set([REVIEWCLOSED, REVIEWESCALATED, REVIEWOPEN])
43
+
44
+ const reasonTypes = new Set([
45
+ REASONOTHER,
46
+ REASONSPAM,
47
+ REASONMISLEADING,
48
+ REASONRUDE,
49
+ REASONSEXUAL,
50
+ REASONVIOLATION,
51
+ REASONAPPEAL,
52
+ ])
53
+
54
+ const eventTypes = new Set([
55
+ 'com.atproto.admin.defs#modEventTakedown',
56
+ 'com.atproto.admin.defs#modEventAcknowledge',
57
+ 'com.atproto.admin.defs#modEventEscalate',
58
+ 'com.atproto.admin.defs#modEventComment',
59
+ 'com.atproto.admin.defs#modEventLabel',
60
+ 'com.atproto.admin.defs#modEventReport',
61
+ 'com.atproto.admin.defs#modEventMute',
62
+ 'com.atproto.admin.defs#modEventUnmute',
63
+ 'com.atproto.admin.defs#modEventReverseTakedown',
64
+ 'com.atproto.admin.defs#modEventEmail',
65
+ ])
@@ -0,0 +1,29 @@
1
+ import { Server } from '../../lexicon'
2
+ import AppContext from '../../context'
3
+
4
+ export default function (server: Server, ctx: AppContext) {
5
+ server.com.atproto.temp.fetchLabels(async ({ params }) => {
6
+ const { limit } = params
7
+ const since =
8
+ params.since !== undefined ? new Date(params.since).toISOString() : ''
9
+ const labelRes = await ctx.db.db
10
+ .selectFrom('label')
11
+ .selectAll()
12
+ .orderBy('label.cts', 'asc')
13
+ .where('cts', '>', since)
14
+ .limit(limit)
15
+ .execute()
16
+
17
+ const labels = labelRes.map((l) => ({
18
+ ...l,
19
+ cid: l.cid === '' ? undefined : l.cid,
20
+ }))
21
+
22
+ return {
23
+ encoding: 'application/json',
24
+ body: {
25
+ labels,
26
+ },
27
+ }
28
+ })
29
+ }
@@ -0,0 +1,35 @@
1
+ import express from 'express'
2
+ import AppContext from '../context'
3
+
4
+ export const createRouter = (ctx: AppContext): express.Router => {
5
+ const router = express.Router()
6
+
7
+ router.get('/.well-known/did.json', (_req, res) => {
8
+ const hostname =
9
+ ctx.cfg.service.publicUrl && new URL(ctx.cfg.service.publicUrl).hostname
10
+ if (!hostname || ctx.cfg.service.did !== `did:web:${hostname}`) {
11
+ return res.sendStatus(404)
12
+ }
13
+ res.json({
14
+ '@context': ['https://www.w3.org/ns/did/v1'],
15
+ id: ctx.cfg.service.did,
16
+ verificationMethod: [
17
+ {
18
+ id: `${ctx.cfg.service.did}#atproto`,
19
+ type: 'Multikey',
20
+ controller: ctx.cfg.service.did,
21
+ publicKeyMultibase: ctx.signingKey.did().replace('did:key:', ''),
22
+ },
23
+ ],
24
+ service: [
25
+ {
26
+ id: '#atproto_mod',
27
+ type: 'AtprotoModerationService',
28
+ serviceEndpoint: `https://${hostname}`,
29
+ },
30
+ ],
31
+ })
32
+ })
33
+
34
+ return router
35
+ }
package/src/auth.ts ADDED
@@ -0,0 +1,147 @@
1
+ import express from 'express'
2
+ import * as uint8arrays from 'uint8arrays'
3
+ import { AuthRequiredError, verifyJwt } from '@atproto/xrpc-server'
4
+ import { IdResolver } from '@atproto/identity'
5
+ import { OzoneSecrets } from './config'
6
+
7
+ const BASIC = 'Basic '
8
+ const BEARER = 'Bearer '
9
+
10
+ export const authVerifier = (
11
+ idResolver: IdResolver,
12
+ opts: { aud: string | null },
13
+ ) => {
14
+ const getSigningKey = async (
15
+ did: string,
16
+ forceRefresh: boolean,
17
+ ): Promise<string> => {
18
+ const atprotoData = await idResolver.did.resolveAtprotoData(
19
+ did,
20
+ forceRefresh,
21
+ )
22
+ return atprotoData.signingKey
23
+ }
24
+
25
+ return async (reqCtx: { req: express.Request; res: express.Response }) => {
26
+ const jwtStr = getJwtStrFromReq(reqCtx.req)
27
+ if (!jwtStr) {
28
+ throw new AuthRequiredError('missing jwt', 'MissingJwt')
29
+ }
30
+ const payload = await verifyJwt(jwtStr, opts.aud, getSigningKey)
31
+ return { credentials: { did: payload.iss }, artifacts: { aud: opts.aud } }
32
+ }
33
+ }
34
+
35
+ export const authOptionalVerifier = (
36
+ idResolver: IdResolver,
37
+ opts: { aud: string | null },
38
+ ) => {
39
+ const verifyAccess = authVerifier(idResolver, opts)
40
+ return async (reqCtx: { req: express.Request; res: express.Response }) => {
41
+ if (!reqCtx.req.headers.authorization) {
42
+ return { credentials: { did: null } }
43
+ }
44
+ return verifyAccess(reqCtx)
45
+ }
46
+ }
47
+
48
+ export const authOptionalAccessOrRoleVerifier = (
49
+ idResolver: IdResolver,
50
+ secrets: OzoneSecrets,
51
+ serverDid: string,
52
+ ) => {
53
+ const verifyAccess = authVerifier(idResolver, { aud: serverDid })
54
+ const verifyRole = roleVerifier(secrets)
55
+ return async (ctx: { req: express.Request; res: express.Response }) => {
56
+ const defaultUnAuthorizedCredentials = {
57
+ credentials: { did: null, type: 'unauthed' as const },
58
+ }
59
+ if (!ctx.req.headers.authorization) {
60
+ return defaultUnAuthorizedCredentials
61
+ }
62
+ // For non-admin tokens, we don't want to consider alternative verifiers and let it fail if it fails
63
+ const isRoleAuthToken = ctx.req.headers.authorization?.startsWith(BASIC)
64
+ if (isRoleAuthToken) {
65
+ const result = await verifyRole(ctx)
66
+ return {
67
+ ...result,
68
+ credentials: {
69
+ type: 'role' as const,
70
+ ...result.credentials,
71
+ },
72
+ }
73
+ }
74
+ const result = await verifyAccess(ctx)
75
+ return {
76
+ ...result,
77
+ credentials: {
78
+ type: 'access' as const,
79
+ ...result.credentials,
80
+ },
81
+ }
82
+ }
83
+ }
84
+
85
+ export const roleVerifier =
86
+ (secrets: OzoneSecrets) =>
87
+ async (reqCtx: { req: express.Request; res: express.Response }) => {
88
+ const credentials = getRoleCredentials(secrets, reqCtx.req)
89
+ if (!credentials.valid) {
90
+ throw new AuthRequiredError()
91
+ }
92
+ return { credentials }
93
+ }
94
+
95
+ export const getRoleCredentials = (
96
+ secrets: OzoneSecrets,
97
+ req: express.Request,
98
+ ) => {
99
+ const parsed = parseBasicAuth(req.headers.authorization || '')
100
+ const { username, password } = parsed ?? {}
101
+ if (username === 'admin' && password === secrets.triagePassword) {
102
+ return { valid: true, admin: false, moderator: false, triage: true }
103
+ }
104
+ if (username === 'admin' && password === secrets.moderatorPassword) {
105
+ return { valid: true, admin: false, moderator: true, triage: true }
106
+ }
107
+ if (username === 'admin' && password === secrets.adminPassword) {
108
+ return { valid: true, admin: true, moderator: true, triage: true }
109
+ }
110
+ return { valid: false, admin: false, moderator: false, triage: false }
111
+ }
112
+
113
+ export const parseBasicAuth = (
114
+ token: string,
115
+ ): { username: string; password: string } | null => {
116
+ if (!token.startsWith(BASIC)) return null
117
+ const b64 = token.slice(BASIC.length)
118
+ let parsed: string[]
119
+ try {
120
+ parsed = uint8arrays
121
+ .toString(uint8arrays.fromString(b64, 'base64pad'), 'utf8')
122
+ .split(':')
123
+ } catch (err) {
124
+ return null
125
+ }
126
+ const [username, password] = parsed
127
+ if (!username || !password) return null
128
+ return { username, password }
129
+ }
130
+
131
+ export const buildBasicAuth = (username: string, password: string): string => {
132
+ return (
133
+ BASIC +
134
+ uint8arrays.toString(
135
+ uint8arrays.fromString(`${username}:${password}`, 'utf8'),
136
+ 'base64pad',
137
+ )
138
+ )
139
+ }
140
+
141
+ export const getJwtStrFromReq = (req: express.Request): string | null => {
142
+ const { authorization } = req.headers
143
+ if (!authorization?.startsWith(BEARER)) {
144
+ return null
145
+ }
146
+ return authorization.slice(BEARER.length).trim()
147
+ }
@@ -0,0 +1,35 @@
1
+ import PQueue from 'p-queue'
2
+ import { Database } from './db'
3
+ import { dbLogger } from './logger'
4
+
5
+ // A simple queue for in-process, out-of-band/backgrounded work
6
+
7
+ export class BackgroundQueue {
8
+ queue = new PQueue({ concurrency: 20 })
9
+ destroyed = false
10
+ constructor(public db: Database) {}
11
+
12
+ add(task: Task) {
13
+ if (this.destroyed) {
14
+ return
15
+ }
16
+ this.queue
17
+ .add(() => task(this.db))
18
+ .catch((err) => {
19
+ dbLogger.error(err, 'background queue task failed')
20
+ })
21
+ }
22
+
23
+ async processAll() {
24
+ await this.queue.onIdle()
25
+ }
26
+
27
+ // On destroy we stop accepting new tasks, but complete all pending/in-progress tasks.
28
+ // The application calls this only once http connections have drained (tasks no longer being added).
29
+ async destroy() {
30
+ this.destroyed = true
31
+ await this.queue.onIdle()
32
+ }
33
+ }
34
+
35
+ type Task = (db: Database) => Promise<void>
@@ -0,0 +1,84 @@
1
+ import assert from 'node:assert'
2
+ import { OzoneEnvironment } from './env'
3
+
4
+ // off-config but still from env:
5
+ // logging: LOG_LEVEL, LOG_SYSTEMS, LOG_ENABLED, LOG_DESTINATION
6
+
7
+ export const envToCfg = (env: OzoneEnvironment): OzoneConfig => {
8
+ const port = env.port ?? 3000
9
+ assert(env.publicUrl)
10
+ assert(env.serverDid)
11
+ const serviceCfg: OzoneConfig['service'] = {
12
+ port,
13
+ publicUrl: env.publicUrl,
14
+ did: env.serverDid,
15
+ version: env.version,
16
+ }
17
+
18
+ assert(env.dbPostgresUrl)
19
+ const dbCfg: OzoneConfig['db'] = {
20
+ postgresUrl: env.dbPostgresUrl,
21
+ postgresSchema: env.dbPostgresSchema,
22
+ }
23
+
24
+ assert(env.appviewUrl)
25
+ assert(env.appviewDid)
26
+ const appviewCfg: OzoneConfig['appview'] = {
27
+ url: env.appviewUrl,
28
+ did: env.appviewDid,
29
+ }
30
+
31
+ assert(env.pdsUrl)
32
+ assert(env.pdsDid)
33
+ const pdsCfg: OzoneConfig['pds'] = {
34
+ url: env.pdsUrl,
35
+ did: env.pdsDid,
36
+ }
37
+
38
+ assert(env.didPlcUrl)
39
+ const identityCfg: OzoneConfig['identity'] = {
40
+ plcUrl: env.didPlcUrl,
41
+ }
42
+
43
+ return {
44
+ service: serviceCfg,
45
+ db: dbCfg,
46
+ appview: appviewCfg,
47
+ pds: pdsCfg,
48
+ identity: identityCfg,
49
+ }
50
+ }
51
+
52
+ export type OzoneConfig = {
53
+ service: ServiceConfig
54
+ db: DatabaseConfig
55
+ appview: AppviewConfig
56
+ pds: PdsConfig | null
57
+ identity: IdentityConfig
58
+ }
59
+
60
+ export type ServiceConfig = {
61
+ port: number
62
+ publicUrl: string
63
+ did: string
64
+ version?: string
65
+ }
66
+
67
+ export type DatabaseConfig = {
68
+ postgresUrl: string
69
+ postgresSchema?: string
70
+ }
71
+
72
+ export type AppviewConfig = {
73
+ url: string
74
+ did: string
75
+ }
76
+
77
+ export type PdsConfig = {
78
+ url: string
79
+ did: string
80
+ }
81
+
82
+ export type IdentityConfig = {
83
+ plcUrl: string
84
+ }
@@ -0,0 +1,41 @@
1
+ import { envInt, envStr } from '@atproto/common'
2
+
3
+ export const readEnv = (): OzoneEnvironment => {
4
+ return {
5
+ nodeEnv: envStr('NODE_ENV'),
6
+ version: envStr('OZONE_VERSION'),
7
+ port: envInt('OZONE_PORT'),
8
+ publicUrl: envStr('OZONE_PUBLIC_URL'),
9
+ serverDid: envStr('OZONE_SERVER_DID'),
10
+ appviewUrl: envStr('OZONE_APPVIEW_URL'),
11
+ appviewDid: envStr('OZONE_APPVIEW_DID'),
12
+ pdsUrl: envStr('OZONE_PDS_URL'),
13
+ pdsDid: envStr('OZONE_PDS_DID'),
14
+ dbPostgresUrl: envStr('OZONE_DB_POSTGRES_URL'),
15
+ dbPostgresSchema: envStr('OZONE_DB_POSTGRES_SCHEMA'),
16
+ didPlcUrl: envStr('OZONE_DID_PLC_URL'),
17
+ adminPassword: envStr('OZONE_ADMIN_PASSWORD'),
18
+ moderatorPassword: envStr('OZONE_MODERATOR_PASSWORD'),
19
+ triagePassword: envStr('OZONE_TRIAGE_PASSWORD'),
20
+ signingKeyHex: envStr('OZONE_SIGNING_KEY_HEX'),
21
+ }
22
+ }
23
+
24
+ export type OzoneEnvironment = {
25
+ nodeEnv?: string
26
+ version?: string
27
+ port?: number
28
+ publicUrl?: string
29
+ serverDid?: string
30
+ appviewUrl?: string
31
+ appviewDid?: string
32
+ pdsUrl?: string
33
+ pdsDid?: string
34
+ dbPostgresUrl?: string
35
+ dbPostgresSchema?: string
36
+ didPlcUrl?: string
37
+ adminPassword?: string
38
+ moderatorPassword?: string
39
+ triagePassword?: string
40
+ signingKeyHex?: string
41
+ }
@@ -0,0 +1,3 @@
1
+ export * from './config'
2
+ export * from './env'
3
+ export * from './secrets'