@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,23 @@
1
+ import assert from 'assert'
2
+ import { OzoneEnvironment } from './env'
3
+
4
+ export const envToSecrets = (env: OzoneEnvironment): OzoneSecrets => {
5
+ assert(env.adminPassword)
6
+ assert(env.moderatorPassword)
7
+ assert(env.triagePassword)
8
+ assert(env.signingKeyHex)
9
+
10
+ return {
11
+ adminPassword: env.adminPassword,
12
+ moderatorPassword: env.moderatorPassword,
13
+ triagePassword: env.triagePassword,
14
+ signingKeyHex: env.signingKeyHex,
15
+ }
16
+ }
17
+
18
+ export type OzoneSecrets = {
19
+ adminPassword: string
20
+ moderatorPassword: string
21
+ triagePassword: string
22
+ signingKeyHex: string
23
+ }
package/src/context.ts ADDED
@@ -0,0 +1,180 @@
1
+ import * as plc from '@did-plc/lib'
2
+ import { IdResolver } from '@atproto/identity'
3
+ import { AtpAgent } from '@atproto/api'
4
+ import { Keypair, Secp256k1Keypair } from '@atproto/crypto'
5
+ import { createServiceAuthHeaders } from '@atproto/xrpc-server'
6
+ import { Database } from './db'
7
+ import { OzoneConfig, OzoneSecrets } from './config'
8
+ import { ModerationService, ModerationServiceCreator } from './mod-service'
9
+ import * as auth from './auth'
10
+ import { BackgroundQueue } from './background'
11
+ import assert from 'assert'
12
+ import { EventPusher } from './daemon'
13
+
14
+ export type AppContextOptions = {
15
+ db: Database
16
+ cfg: OzoneConfig
17
+ modService: ModerationServiceCreator
18
+ appviewAgent: AtpAgent
19
+ pdsAgent: AtpAgent | undefined
20
+ signingKey: Keypair
21
+ idResolver: IdResolver
22
+ backgroundQueue: BackgroundQueue
23
+ }
24
+
25
+ export class AppContext {
26
+ constructor(private opts: AppContextOptions, private secrets: OzoneSecrets) {}
27
+
28
+ static async fromConfig(
29
+ cfg: OzoneConfig,
30
+ secrets: OzoneSecrets,
31
+ overrides?: Partial<AppContextOptions>,
32
+ ): Promise<AppContext> {
33
+ const db = new Database({
34
+ url: cfg.db.postgresUrl,
35
+ schema: cfg.db.postgresSchema,
36
+ })
37
+ const signingKey = await Secp256k1Keypair.import(secrets.signingKeyHex)
38
+ const appviewAgent = new AtpAgent({ service: cfg.appview.url })
39
+ const pdsAgent = cfg.pds
40
+ ? new AtpAgent({ service: cfg.pds.url })
41
+ : undefined
42
+
43
+ const createAuthHeaders = (aud: string) =>
44
+ createServiceAuthHeaders({
45
+ iss: cfg.service.did,
46
+ aud,
47
+ keypair: signingKey,
48
+ })
49
+ const appviewAuth = async () =>
50
+ cfg.appview.did ? createAuthHeaders(cfg.appview.did) : undefined
51
+
52
+ const backgroundQueue = new BackgroundQueue(db)
53
+ const eventPusher = new EventPusher(db, createAuthHeaders, {
54
+ appview: cfg.appview,
55
+ pds: cfg.pds ?? undefined,
56
+ })
57
+
58
+ const modService = ModerationService.creator(
59
+ backgroundQueue,
60
+ eventPusher,
61
+ appviewAgent,
62
+ appviewAuth,
63
+ )
64
+
65
+ const idResolver = new IdResolver({
66
+ plcUrl: cfg.identity.plcUrl,
67
+ })
68
+
69
+ return new AppContext(
70
+ {
71
+ db,
72
+ cfg,
73
+ modService,
74
+ appviewAgent,
75
+ pdsAgent,
76
+ signingKey,
77
+ idResolver,
78
+ backgroundQueue,
79
+ ...(overrides ?? {}),
80
+ },
81
+ secrets,
82
+ )
83
+ }
84
+
85
+ assignPort(port: number) {
86
+ assert(
87
+ !this.cfg.service.port || this.cfg.service.port === port,
88
+ 'Conflicting port in config',
89
+ )
90
+ this.opts.cfg.service.port = port
91
+ }
92
+
93
+ get db(): Database {
94
+ return this.opts.db
95
+ }
96
+
97
+ get cfg(): OzoneConfig {
98
+ return this.opts.cfg
99
+ }
100
+
101
+ get modService(): ModerationServiceCreator {
102
+ return this.opts.modService
103
+ }
104
+
105
+ get appviewAgent(): AtpAgent {
106
+ return this.opts.appviewAgent
107
+ }
108
+
109
+ get pdsAgent(): AtpAgent | undefined {
110
+ return this.opts.pdsAgent
111
+ }
112
+
113
+ get signingKey(): Keypair {
114
+ return this.opts.signingKey
115
+ }
116
+
117
+ get plcClient(): plc.Client {
118
+ return new plc.Client(this.cfg.identity.plcUrl)
119
+ }
120
+
121
+ get idResolver(): IdResolver {
122
+ return this.opts.idResolver
123
+ }
124
+
125
+ get backgroundQueue(): BackgroundQueue {
126
+ return this.opts.backgroundQueue
127
+ }
128
+
129
+ get authVerifier() {
130
+ return auth.authVerifier(this.idResolver, { aud: this.cfg.service.did })
131
+ }
132
+
133
+ get authVerifierAnyAudience() {
134
+ return auth.authVerifier(this.idResolver, { aud: null })
135
+ }
136
+
137
+ get authOptionalVerifierAnyAudience() {
138
+ return auth.authOptionalVerifier(this.idResolver, { aud: null })
139
+ }
140
+
141
+ get authOptionalVerifier() {
142
+ return auth.authOptionalVerifier(this.idResolver, {
143
+ aud: this.cfg.service.did,
144
+ })
145
+ }
146
+
147
+ get authOptionalAccessOrRoleVerifier() {
148
+ return auth.authOptionalAccessOrRoleVerifier(
149
+ this.idResolver,
150
+ this.secrets,
151
+ this.cfg.service.did,
152
+ )
153
+ }
154
+
155
+ get roleVerifier() {
156
+ return auth.roleVerifier(this.secrets)
157
+ }
158
+
159
+ async serviceAuthHeaders(aud: string) {
160
+ const iss = this.cfg.service.did
161
+ return createServiceAuthHeaders({
162
+ iss,
163
+ aud,
164
+ keypair: this.signingKey,
165
+ })
166
+ }
167
+
168
+ async pdsAuth() {
169
+ if (!this.cfg.pds) {
170
+ return undefined
171
+ }
172
+ return this.serviceAuthHeaders(this.cfg.pds.did)
173
+ }
174
+
175
+ async appviewAuth() {
176
+ return this.serviceAuthHeaders(this.cfg.appview.did)
177
+ }
178
+ }
179
+
180
+ export default AppContext
@@ -0,0 +1,90 @@
1
+ import { Keypair, Secp256k1Keypair } from '@atproto/crypto'
2
+ import { createServiceAuthHeaders } from '@atproto/xrpc-server'
3
+ import AtpAgent from '@atproto/api'
4
+ import { OzoneConfig, OzoneSecrets } from '../config'
5
+ import { Database } from '../db'
6
+ import { EventPusher } from './event-pusher'
7
+ import { EventReverser } from './event-reverser'
8
+ import { ModerationService, ModerationServiceCreator } from '../mod-service'
9
+ import { BackgroundQueue } from '../background'
10
+
11
+ export type DaemonContextOptions = {
12
+ db: Database
13
+ cfg: OzoneConfig
14
+ modService: ModerationServiceCreator
15
+ signingKey: Keypair
16
+ eventPusher: EventPusher
17
+ eventReverser: EventReverser
18
+ }
19
+
20
+ export class DaemonContext {
21
+ constructor(private opts: DaemonContextOptions) {}
22
+
23
+ static async fromConfig(
24
+ cfg: OzoneConfig,
25
+ secrets: OzoneSecrets,
26
+ overrides?: Partial<DaemonContextOptions>,
27
+ ): Promise<DaemonContext> {
28
+ const db = new Database({
29
+ url: cfg.db.postgresUrl,
30
+ schema: cfg.db.postgresSchema,
31
+ })
32
+ const signingKey = await Secp256k1Keypair.import(secrets.signingKeyHex)
33
+
34
+ const appviewAgent = new AtpAgent({ service: cfg.appview.url })
35
+ const createAuthHeaders = (aud: string) =>
36
+ createServiceAuthHeaders({
37
+ iss: cfg.service.did,
38
+ aud,
39
+ keypair: signingKey,
40
+ })
41
+
42
+ const appviewAuth = async () =>
43
+ cfg.appview.did ? createAuthHeaders(cfg.appview.did) : undefined
44
+
45
+ const eventPusher = new EventPusher(db, createAuthHeaders, {
46
+ appview: cfg.appview,
47
+ pds: cfg.pds ?? undefined,
48
+ })
49
+ const backgroundQueue = new BackgroundQueue(db)
50
+ const modService = ModerationService.creator(
51
+ backgroundQueue,
52
+ eventPusher,
53
+ appviewAgent,
54
+ appviewAuth,
55
+ )
56
+ const eventReverser = new EventReverser(db, modService)
57
+
58
+ return new DaemonContext({
59
+ db,
60
+ cfg,
61
+ modService,
62
+ signingKey,
63
+ eventPusher,
64
+ eventReverser,
65
+ ...(overrides ?? {}),
66
+ })
67
+ }
68
+
69
+ get db(): Database {
70
+ return this.opts.db
71
+ }
72
+
73
+ get cfg(): OzoneConfig {
74
+ return this.opts.cfg
75
+ }
76
+
77
+ get modService(): ModerationServiceCreator {
78
+ return this.opts.modService
79
+ }
80
+
81
+ get eventPusher(): EventPusher {
82
+ return this.opts.eventPusher
83
+ }
84
+
85
+ get eventReverser(): EventReverser {
86
+ return this.opts.eventReverser
87
+ }
88
+ }
89
+
90
+ export default DaemonContext
@@ -0,0 +1,296 @@
1
+ import AtpAgent from '@atproto/api'
2
+ import { SECOND } from '@atproto/common'
3
+ import Database from '../db'
4
+ import { retryHttp } from '../util'
5
+ import { dbLogger } from '../logger'
6
+ import { InputSchema } from '../lexicon/types/com/atproto/admin/updateSubjectStatus'
7
+ import assert from 'assert'
8
+
9
+ type EventSubject = InputSchema['subject']
10
+
11
+ type PollState = {
12
+ timer?: NodeJS.Timer
13
+ promise: Promise<void>
14
+ }
15
+
16
+ type AuthHeaders = {
17
+ headers: {
18
+ authorization: string
19
+ }
20
+ }
21
+
22
+ type Service = {
23
+ agent: AtpAgent
24
+ did: string
25
+ }
26
+
27
+ export class EventPusher {
28
+ destroyed = false
29
+
30
+ repoPollState: PollState = {
31
+ promise: Promise.resolve(),
32
+ }
33
+ recordPollState: PollState = {
34
+ promise: Promise.resolve(),
35
+ }
36
+ blobPollState: PollState = {
37
+ promise: Promise.resolve(),
38
+ }
39
+
40
+ appview: Service | undefined
41
+ pds: Service | undefined
42
+
43
+ constructor(
44
+ public db: Database,
45
+ public createAuthHeaders: (aud: string) => Promise<AuthHeaders>,
46
+ services: {
47
+ appview?: {
48
+ url: string
49
+ did: string
50
+ }
51
+ pds?: {
52
+ url: string
53
+ did: string
54
+ }
55
+ },
56
+ ) {
57
+ if (services.appview) {
58
+ this.appview = {
59
+ agent: new AtpAgent({ service: services.appview.url }),
60
+ did: services.appview.did,
61
+ }
62
+ }
63
+ if (services.pds) {
64
+ this.pds = {
65
+ agent: new AtpAgent({ service: services.pds.url }),
66
+ did: services.pds.did,
67
+ }
68
+ }
69
+ }
70
+
71
+ start() {
72
+ this.poll(this.repoPollState, () => this.pushRepoEvents())
73
+ this.poll(this.recordPollState, () => this.pushRecordEvents())
74
+ this.poll(this.blobPollState, () => this.pushBlobEvents())
75
+ }
76
+
77
+ poll(state: PollState, fn: () => Promise<void>) {
78
+ if (this.destroyed) return
79
+ state.promise = fn()
80
+ .catch((err) => {
81
+ dbLogger.error({ err }, 'event push failed')
82
+ })
83
+ .finally(() => {
84
+ state.timer = setTimeout(() => this.poll(state, fn), 30 * SECOND)
85
+ })
86
+ }
87
+
88
+ async processAll() {
89
+ await Promise.all([
90
+ this.pushRepoEvents(),
91
+ this.pushRecordEvents(),
92
+ this.pushBlobEvents(),
93
+ this.repoPollState.promise,
94
+ this.recordPollState.promise,
95
+ this.blobPollState.promise,
96
+ ])
97
+ }
98
+
99
+ async destroy() {
100
+ this.destroyed = true
101
+ const destroyState = (state: PollState) => {
102
+ if (state.timer) {
103
+ clearTimeout(state.timer)
104
+ }
105
+ return state.promise
106
+ }
107
+ await Promise.all([
108
+ destroyState(this.repoPollState),
109
+ destroyState(this.recordPollState),
110
+ destroyState(this.blobPollState),
111
+ ])
112
+ }
113
+
114
+ async pushRepoEvents() {
115
+ const toPush = await this.db.db
116
+ .selectFrom('repo_push_event')
117
+ .select('id')
118
+ .forUpdate()
119
+ .skipLocked()
120
+ .where('confirmedAt', 'is', null)
121
+ .where('attempts', '<', 10)
122
+ .execute()
123
+ await Promise.all(toPush.map((evt) => this.attemptRepoEvent(evt.id)))
124
+ }
125
+
126
+ async pushRecordEvents() {
127
+ const toPush = await this.db.db
128
+ .selectFrom('record_push_event')
129
+ .select('id')
130
+ .forUpdate()
131
+ .skipLocked()
132
+ .where('confirmedAt', 'is', null)
133
+ .where('attempts', '<', 10)
134
+ .execute()
135
+ await Promise.all(toPush.map((evt) => this.attemptRecordEvent(evt.id)))
136
+ }
137
+
138
+ async pushBlobEvents() {
139
+ const toPush = await this.db.db
140
+ .selectFrom('blob_push_event')
141
+ .select('id')
142
+ .forUpdate()
143
+ .skipLocked()
144
+ .where('confirmedAt', 'is', null)
145
+ .where('attempts', '<', 10)
146
+ .execute()
147
+ await Promise.all(toPush.map((evt) => this.attemptBlobEvent(evt.id)))
148
+ }
149
+
150
+ private async updateSubjectOnService(
151
+ service: Service,
152
+ subject: EventSubject,
153
+ takedownRef: string | null,
154
+ ): Promise<boolean> {
155
+ const auth = await this.createAuthHeaders(service.did)
156
+ try {
157
+ await retryHttp(() =>
158
+ service.agent.com.atproto.admin.updateSubjectStatus(
159
+ {
160
+ subject,
161
+ takedown: {
162
+ applied: !!takedownRef,
163
+ ref: takedownRef ?? undefined,
164
+ },
165
+ },
166
+ {
167
+ ...auth,
168
+ encoding: 'application/json',
169
+ },
170
+ ),
171
+ )
172
+ return true
173
+ } catch (err) {
174
+ dbLogger.error({ err, subject, takedownRef }, 'failed to push out event')
175
+ return false
176
+ }
177
+ }
178
+
179
+ async attemptRepoEvent(id: number) {
180
+ await this.db.transaction(async (dbTxn) => {
181
+ const evt = await dbTxn.db
182
+ .selectFrom('repo_push_event')
183
+ .selectAll()
184
+ .forUpdate()
185
+ .skipLocked()
186
+ .where('id', '=', id)
187
+ .where('confirmedAt', 'is', null)
188
+ .executeTakeFirst()
189
+ if (!evt) return
190
+ const service = evt.eventType === 'pds_takedown' ? this.pds : this.appview
191
+ assert(service)
192
+ const subject = {
193
+ $type: 'com.atproto.admin.defs#repoRef',
194
+ did: evt.subjectDid,
195
+ }
196
+ const succeeded = await this.updateSubjectOnService(
197
+ service,
198
+ subject,
199
+ evt.takedownRef,
200
+ )
201
+ await dbTxn.db
202
+ .updateTable('repo_push_event')
203
+ .set(
204
+ succeeded
205
+ ? { confirmedAt: new Date() }
206
+ : {
207
+ lastAttempted: new Date(),
208
+ attempts: evt.attempts ?? 0 + 1,
209
+ },
210
+ )
211
+ .where('subjectDid', '=', evt.subjectDid)
212
+ .where('eventType', '=', evt.eventType)
213
+ .execute()
214
+ })
215
+ }
216
+
217
+ async attemptRecordEvent(id: number) {
218
+ await this.db.transaction(async (dbTxn) => {
219
+ const evt = await dbTxn.db
220
+ .selectFrom('record_push_event')
221
+ .selectAll()
222
+ .forUpdate()
223
+ .skipLocked()
224
+ .where('id', '=', id)
225
+ .where('confirmedAt', 'is', null)
226
+ .executeTakeFirst()
227
+ if (!evt) return
228
+ const service = evt.eventType === 'pds_takedown' ? this.pds : this.appview
229
+ assert(service)
230
+ const subject = {
231
+ $type: 'com.atproto.repo.strongRef',
232
+ uri: evt.subjectUri,
233
+ cid: evt.subjectCid,
234
+ }
235
+ const succeeded = await this.updateSubjectOnService(
236
+ service,
237
+ subject,
238
+ evt.takedownRef,
239
+ )
240
+ await dbTxn.db
241
+ .updateTable('record_push_event')
242
+ .set(
243
+ succeeded
244
+ ? { confirmedAt: new Date() }
245
+ : {
246
+ lastAttempted: new Date(),
247
+ attempts: evt.attempts ?? 0 + 1,
248
+ },
249
+ )
250
+ .where('subjectUri', '=', evt.subjectUri)
251
+ .where('eventType', '=', evt.eventType)
252
+ .execute()
253
+ })
254
+ }
255
+
256
+ async attemptBlobEvent(id: number) {
257
+ await this.db.transaction(async (dbTxn) => {
258
+ const evt = await dbTxn.db
259
+ .selectFrom('blob_push_event')
260
+ .selectAll()
261
+ .forUpdate()
262
+ .skipLocked()
263
+ .where('id', '=', id)
264
+ .where('confirmedAt', 'is', null)
265
+ .executeTakeFirst()
266
+ if (!evt) return
267
+
268
+ const service = evt.eventType === 'pds_takedown' ? this.pds : this.appview
269
+ assert(service)
270
+ const subject = {
271
+ $type: 'com.atproto.admin.defs#repoBlobRef',
272
+ did: evt.subjectDid,
273
+ cid: evt.subjectBlobCid,
274
+ }
275
+ const succeeded = await this.updateSubjectOnService(
276
+ service,
277
+ subject,
278
+ evt.takedownRef,
279
+ )
280
+ await dbTxn.db
281
+ .updateTable('blob_push_event')
282
+ .set(
283
+ succeeded
284
+ ? { confirmedAt: new Date() }
285
+ : {
286
+ lastAttempted: new Date(),
287
+ attempts: evt.attempts ?? 0 + 1,
288
+ },
289
+ )
290
+ .where('subjectDid', '=', evt.subjectDid)
291
+ .where('subjectBlobCid', '=', evt.subjectBlobCid)
292
+ .where('eventType', '=', evt.eventType)
293
+ .execute()
294
+ })
295
+ }
296
+ }
@@ -0,0 +1,74 @@
1
+ import { MINUTE } from '@atproto/common'
2
+ import { dbLogger } from '../logger'
3
+ import { ModerationServiceCreator, ReversalSubject } from '../mod-service'
4
+ import Database from '../db'
5
+
6
+ export class EventReverser {
7
+ destroyed = false
8
+ reversalPromise: Promise<void> = Promise.resolve()
9
+ timer: NodeJS.Timer | undefined
10
+
11
+ constructor(
12
+ private db: Database,
13
+ private modService: ModerationServiceCreator,
14
+ ) {}
15
+
16
+ start() {
17
+ this.poll()
18
+ }
19
+
20
+ poll() {
21
+ if (this.destroyed) return
22
+ this.reversalPromise = this.findAndRevertDueActions()
23
+ .catch((err) =>
24
+ dbLogger.error({ err }, 'moderation action reversal errored'),
25
+ )
26
+ .finally(() => {
27
+ this.timer = setTimeout(() => this.poll(), getInterval())
28
+ })
29
+ }
30
+
31
+ async destroy() {
32
+ this.destroyed = true
33
+ if (this.timer) {
34
+ clearTimeout(this.timer)
35
+ }
36
+ await this.reversalPromise
37
+ }
38
+
39
+ async revertState(subject: ReversalSubject) {
40
+ await this.db.transaction(async (dbTxn) => {
41
+ const moderationTxn = this.modService(dbTxn)
42
+ const originalEvent =
43
+ await moderationTxn.getLastReversibleEventForSubject(subject)
44
+ if (originalEvent) {
45
+ await moderationTxn.revertState({
46
+ action: originalEvent.action,
47
+ createdBy: originalEvent.createdBy,
48
+ comment:
49
+ '[SCHEDULED_REVERSAL] Reverting action as originally scheduled',
50
+ subject: subject.subject,
51
+ createdAt: new Date(),
52
+ })
53
+ }
54
+ })
55
+ }
56
+
57
+ async findAndRevertDueActions() {
58
+ const moderationService = this.modService(this.db)
59
+ const subjectsDueForReversal =
60
+ await moderationService.getSubjectsDueForReversal()
61
+
62
+ // We shouldn't have too many actions due for reversal at any given time, so running in parallel is probably fine
63
+ // Internally, each reversal runs within its own transaction
64
+ await Promise.all(subjectsDueForReversal.map(this.revertState.bind(this)))
65
+ }
66
+ }
67
+
68
+ const getInterval = (): number => {
69
+ // super basic synchronization by agreeing when the intervals land relative to unix timestamp
70
+ const now = Date.now()
71
+ const intervalMs = MINUTE
72
+ const nextIteration = Math.ceil(now / intervalMs)
73
+ return nextIteration * intervalMs - now
74
+ }
@@ -0,0 +1,33 @@
1
+ import { OzoneConfig, OzoneSecrets } from '../config'
2
+ import DaemonContext from './context'
3
+ import { AppContextOptions } from '../context'
4
+
5
+ export { EventPusher } from './event-pusher'
6
+ export { EventReverser } from './event-reverser'
7
+
8
+ export class OzoneDaemon {
9
+ constructor(public ctx: DaemonContext) {}
10
+ static async create(
11
+ cfg: OzoneConfig,
12
+ secrets: OzoneSecrets,
13
+ overrides?: Partial<AppContextOptions>,
14
+ ): Promise<OzoneDaemon> {
15
+ const ctx = await DaemonContext.fromConfig(cfg, secrets, overrides)
16
+ return new OzoneDaemon(ctx)
17
+ }
18
+
19
+ async start() {
20
+ this.ctx.eventPusher.start()
21
+ this.ctx.eventReverser.start()
22
+ }
23
+
24
+ async processAll() {
25
+ await this.ctx.eventPusher.processAll()
26
+ }
27
+
28
+ async destroy() {
29
+ await this.ctx.eventReverser.destroy()
30
+ await this.ctx.eventPusher.destroy()
31
+ await this.ctx.db.close()
32
+ }
33
+ }