@atproto/pds 0.5.12 → 0.5.15

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 (326) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/dist/api/app/bsky/notification/index.d.ts.map +1 -1
  3. package/dist/api/app/bsky/notification/index.js +2 -0
  4. package/dist/api/app/bsky/notification/index.js.map +1 -1
  5. package/dist/api/app/bsky/notification/unregisterPush.d.ts +4 -0
  6. package/dist/api/app/bsky/notification/unregisterPush.d.ts.map +1 -0
  7. package/dist/api/app/bsky/notification/unregisterPush.js +48 -0
  8. package/dist/api/app/bsky/notification/unregisterPush.js.map +1 -0
  9. package/dist/lexicons/app/bsky/actor/defs.defs.d.ts +6 -0
  10. package/dist/lexicons/app/bsky/actor/defs.defs.d.ts.map +1 -1
  11. package/dist/lexicons/app/bsky/actor/defs.defs.js +1 -0
  12. package/dist/lexicons/app/bsky/actor/defs.defs.js.map +1 -1
  13. package/package.json +42 -38
  14. package/build.templates.cjs +0 -22
  15. package/example.env +0 -42
  16. package/jest.config.cjs +0 -27
  17. package/src/account-manager/account-manager.ts +0 -916
  18. package/src/account-manager/db/index.ts +0 -21
  19. package/src/account-manager/db/migrations/001-init.ts +0 -115
  20. package/src/account-manager/db/migrations/002-account-deactivation.ts +0 -17
  21. package/src/account-manager/db/migrations/003-privileged-app-passwords.ts +0 -12
  22. package/src/account-manager/db/migrations/004-oauth.ts +0 -122
  23. package/src/account-manager/db/migrations/005-oauth-account-management.ts +0 -136
  24. package/src/account-manager/db/migrations/006-oauth-permission-sets.ts +0 -20
  25. package/src/account-manager/db/migrations/007-lexicon-failures-index.ts +0 -14
  26. package/src/account-manager/db/migrations/index.ts +0 -17
  27. package/src/account-manager/db/schema/account-device.ts +0 -14
  28. package/src/account-manager/db/schema/account.ts +0 -16
  29. package/src/account-manager/db/schema/actor.ts +0 -17
  30. package/src/account-manager/db/schema/app-password.ts +0 -13
  31. package/src/account-manager/db/schema/authorization-request.ts +0 -30
  32. package/src/account-manager/db/schema/authorized-client.ts +0 -23
  33. package/src/account-manager/db/schema/device.ts +0 -18
  34. package/src/account-manager/db/schema/email-token.ts +0 -19
  35. package/src/account-manager/db/schema/index.ts +0 -43
  36. package/src/account-manager/db/schema/invite-code.ts +0 -24
  37. package/src/account-manager/db/schema/lexicon.ts +0 -15
  38. package/src/account-manager/db/schema/refresh-token.ts +0 -11
  39. package/src/account-manager/db/schema/repo-root.ts +0 -12
  40. package/src/account-manager/db/schema/token.ts +0 -38
  41. package/src/account-manager/db/schema/used-refresh-token.ts +0 -13
  42. package/src/account-manager/helpers/account-device.ts +0 -63
  43. package/src/account-manager/helpers/account.ts +0 -355
  44. package/src/account-manager/helpers/auth.ts +0 -222
  45. package/src/account-manager/helpers/authorization-request.ts +0 -90
  46. package/src/account-manager/helpers/authorized-client.ts +0 -75
  47. package/src/account-manager/helpers/device.ts +0 -47
  48. package/src/account-manager/helpers/email-token.ts +0 -87
  49. package/src/account-manager/helpers/invite.ts +0 -263
  50. package/src/account-manager/helpers/lexicon.ts +0 -67
  51. package/src/account-manager/helpers/password.ts +0 -136
  52. package/src/account-manager/helpers/repo.ts +0 -24
  53. package/src/account-manager/helpers/scrypt.ts +0 -53
  54. package/src/account-manager/helpers/token.ts +0 -158
  55. package/src/account-manager/helpers/used-refresh-token.ts +0 -30
  56. package/src/account-manager/oauth-store.ts +0 -880
  57. package/src/account-manager/scope-reference-getter.ts +0 -106
  58. package/src/actor-store/actor-store-reader.ts +0 -45
  59. package/src/actor-store/actor-store-resources.ts +0 -8
  60. package/src/actor-store/actor-store-transactor.ts +0 -31
  61. package/src/actor-store/actor-store-writer.ts +0 -17
  62. package/src/actor-store/actor-store.ts +0 -210
  63. package/src/actor-store/blob/reader.ts +0 -160
  64. package/src/actor-store/blob/transactor.ts +0 -383
  65. package/src/actor-store/db/index.ts +0 -20
  66. package/src/actor-store/db/migrations/001-init.ts +0 -105
  67. package/src/actor-store/db/migrations/index.ts +0 -5
  68. package/src/actor-store/db/schema/account-pref.ts +0 -11
  69. package/src/actor-store/db/schema/backlink.ts +0 -9
  70. package/src/actor-store/db/schema/blob.ts +0 -14
  71. package/src/actor-store/db/schema/index.ts +0 -23
  72. package/src/actor-store/db/schema/record-blob.ts +0 -8
  73. package/src/actor-store/db/schema/record.ts +0 -14
  74. package/src/actor-store/db/schema/repo-block.ts +0 -10
  75. package/src/actor-store/db/schema/repo-root.ts +0 -10
  76. package/src/actor-store/migrate.ts +0 -39
  77. package/src/actor-store/preference/reader.ts +0 -48
  78. package/src/actor-store/preference/transactor.ts +0 -55
  79. package/src/actor-store/preference/util.ts +0 -39
  80. package/src/actor-store/record/reader.ts +0 -374
  81. package/src/actor-store/record/transactor.ts +0 -111
  82. package/src/actor-store/repo/reader.ts +0 -31
  83. package/src/actor-store/repo/sql-repo-reader.ts +0 -150
  84. package/src/actor-store/repo/sql-repo-transactor.ts +0 -105
  85. package/src/actor-store/repo/transactor.ts +0 -227
  86. package/src/api/app/bsky/actor/getPreferences.ts +0 -57
  87. package/src/api/app/bsky/actor/getProfile.ts +0 -41
  88. package/src/api/app/bsky/actor/getProfiles.ts +0 -51
  89. package/src/api/app/bsky/actor/index.ts +0 -13
  90. package/src/api/app/bsky/actor/putPreferences.ts +0 -62
  91. package/src/api/app/bsky/feed/getActorLikes.ts +0 -63
  92. package/src/api/app/bsky/feed/getAuthorFeed.ts +0 -84
  93. package/src/api/app/bsky/feed/getFeed.ts +0 -47
  94. package/src/api/app/bsky/feed/getPostThread.ts +0 -251
  95. package/src/api/app/bsky/feed/getTimeline.ts +0 -50
  96. package/src/api/app/bsky/feed/index.ts +0 -15
  97. package/src/api/app/bsky/index.ts +0 -11
  98. package/src/api/app/bsky/notification/index.ts +0 -7
  99. package/src/api/app/bsky/notification/registerPush.ts +0 -71
  100. package/src/api/app/bsky/util/resolver.ts +0 -20
  101. package/src/api/com/atproto/admin/deleteAccount.ts +0 -22
  102. package/src/api/com/atproto/admin/disableAccountInvites.ts +0 -18
  103. package/src/api/com/atproto/admin/disableInviteCodes.ts +0 -21
  104. package/src/api/com/atproto/admin/enableAccountInvites.ts +0 -18
  105. package/src/api/com/atproto/admin/getAccountInfo.ts +0 -32
  106. package/src/api/com/atproto/admin/getAccountInfos.ts +0 -34
  107. package/src/api/com/atproto/admin/getInviteCodes.ts +0 -126
  108. package/src/api/com/atproto/admin/getSubjectStatus.ts +0 -76
  109. package/src/api/com/atproto/admin/index.ts +0 -31
  110. package/src/api/com/atproto/admin/sendEmail.ts +0 -47
  111. package/src/api/com/atproto/admin/updateAccountEmail.ts +0 -32
  112. package/src/api/com/atproto/admin/updateAccountHandle.ts +0 -47
  113. package/src/api/com/atproto/admin/updateAccountPassword.ts +0 -34
  114. package/src/api/com/atproto/admin/updateSubjectStatus.ts +0 -68
  115. package/src/api/com/atproto/admin/util.ts +0 -66
  116. package/src/api/com/atproto/identity/getRecommendedDidCredentials.ts +0 -50
  117. package/src/api/com/atproto/identity/index.ts +0 -17
  118. package/src/api/com/atproto/identity/requestPlcOperationSignature.ts +0 -59
  119. package/src/api/com/atproto/identity/resolveHandle.ts +0 -50
  120. package/src/api/com/atproto/identity/signPlcOperation.ts +0 -85
  121. package/src/api/com/atproto/identity/submitPlcOperation.ts +0 -65
  122. package/src/api/com/atproto/identity/updateHandle.ts +0 -66
  123. package/src/api/com/atproto/index.ts +0 -19
  124. package/src/api/com/atproto/moderation/createReport.ts +0 -41
  125. package/src/api/com/atproto/moderation/index.ts +0 -7
  126. package/src/api/com/atproto/repo/applyWrites.ts +0 -226
  127. package/src/api/com/atproto/repo/createRecord.ts +0 -143
  128. package/src/api/com/atproto/repo/deleteRecord.ts +0 -122
  129. package/src/api/com/atproto/repo/describeRepo.ts +0 -43
  130. package/src/api/com/atproto/repo/getRecord.ts +0 -40
  131. package/src/api/com/atproto/repo/importRepo.ts +0 -101
  132. package/src/api/com/atproto/repo/index.ts +0 -25
  133. package/src/api/com/atproto/repo/listMissingBlobs.ts +0 -29
  134. package/src/api/com/atproto/repo/listRecords.ts +0 -36
  135. package/src/api/com/atproto/repo/putRecord.ts +0 -211
  136. package/src/api/com/atproto/repo/uploadBlob.ts +0 -60
  137. package/src/api/com/atproto/server/activateAccount.ts +0 -37
  138. package/src/api/com/atproto/server/checkAccountStatus.ts +0 -51
  139. package/src/api/com/atproto/server/confirmEmail.ts +0 -39
  140. package/src/api/com/atproto/server/createAccount.ts +0 -327
  141. package/src/api/com/atproto/server/createAppPassword.ts +0 -53
  142. package/src/api/com/atproto/server/createInviteCode.ts +0 -38
  143. package/src/api/com/atproto/server/createInviteCodes.ts +0 -42
  144. package/src/api/com/atproto/server/createSession.ts +0 -97
  145. package/src/api/com/atproto/server/deactivateAccount.ts +0 -41
  146. package/src/api/com/atproto/server/deleteAccount.ts +0 -85
  147. package/src/api/com/atproto/server/deleteSession.ts +0 -23
  148. package/src/api/com/atproto/server/describeServer.ts +0 -29
  149. package/src/api/com/atproto/server/getAccountInviteCodes.ts +0 -142
  150. package/src/api/com/atproto/server/getServiceAuth.ts +0 -111
  151. package/src/api/com/atproto/server/getSession.ts +0 -80
  152. package/src/api/com/atproto/server/index.ts +0 -55
  153. package/src/api/com/atproto/server/listAppPasswords.ts +0 -45
  154. package/src/api/com/atproto/server/refreshSession.ts +0 -72
  155. package/src/api/com/atproto/server/requestAccountDelete.ts +0 -66
  156. package/src/api/com/atproto/server/requestEmailConfirmation.ts +0 -68
  157. package/src/api/com/atproto/server/requestEmailUpdate.ts +0 -86
  158. package/src/api/com/atproto/server/requestPasswordReset.ts +0 -52
  159. package/src/api/com/atproto/server/reserveSigningKey.ts +0 -15
  160. package/src/api/com/atproto/server/resetPassword.ts +0 -50
  161. package/src/api/com/atproto/server/revokeAppPassword.ts +0 -42
  162. package/src/api/com/atproto/server/updateEmail.ts +0 -52
  163. package/src/api/com/atproto/server/util.ts +0 -136
  164. package/src/api/com/atproto/sync/deprecated/getCheckout.ts +0 -27
  165. package/src/api/com/atproto/sync/deprecated/getHead.ts +0 -33
  166. package/src/api/com/atproto/sync/getBlob.ts +0 -61
  167. package/src/api/com/atproto/sync/getBlocks.ts +0 -37
  168. package/src/api/com/atproto/sync/getLatestCommit.ts +0 -33
  169. package/src/api/com/atproto/sync/getRecord.ts +0 -49
  170. package/src/api/com/atproto/sync/getRepo.ts +0 -75
  171. package/src/api/com/atproto/sync/getRepoStatus.ts +0 -34
  172. package/src/api/com/atproto/sync/index.ts +0 -27
  173. package/src/api/com/atproto/sync/listBlobs.ts +0 -33
  174. package/src/api/com/atproto/sync/listRepos.ts +0 -74
  175. package/src/api/com/atproto/sync/subscribeRepos.ts +0 -73
  176. package/src/api/com/atproto/sync/util.ts +0 -37
  177. package/src/api/com/atproto/temp/checkSignupQueue.ts +0 -34
  178. package/src/api/com/atproto/temp/index.ts +0 -7
  179. package/src/api/index.ts +0 -10
  180. package/src/api/proxy.ts +0 -44
  181. package/src/app-view.ts +0 -24
  182. package/src/auth-output.ts +0 -52
  183. package/src/auth-routes.ts +0 -64
  184. package/src/auth-scope.ts +0 -40
  185. package/src/auth-verifier.ts +0 -668
  186. package/src/background.ts +0 -65
  187. package/src/basic-routes.ts +0 -52
  188. package/src/bsky-app-view.ts +0 -33
  189. package/src/config/config.ts +0 -553
  190. package/src/config/env.ts +0 -167
  191. package/src/config/index.ts +0 -3
  192. package/src/config/secrets.ts +0 -54
  193. package/src/context.ts +0 -523
  194. package/src/crawlers.ts +0 -46
  195. package/src/db/cast.ts +0 -52
  196. package/src/db/db.ts +0 -140
  197. package/src/db/index.ts +0 -4
  198. package/src/db/migrator.ts +0 -40
  199. package/src/db/pagination.ts +0 -132
  200. package/src/db/tables/moderation.ts +0 -80
  201. package/src/db/util.ts +0 -108
  202. package/src/did-cache/db/index.ts +0 -21
  203. package/src/did-cache/db/migrations.ts +0 -17
  204. package/src/did-cache/db/schema.ts +0 -9
  205. package/src/did-cache/index.ts +0 -131
  206. package/src/disk-blobstore.ts +0 -172
  207. package/src/error.ts +0 -19
  208. package/src/handle/explicit-slurs.ts +0 -22
  209. package/src/handle/index.ts +0 -49
  210. package/src/handle/reserved.ts +0 -1059
  211. package/src/image/image-url-builder.ts +0 -16
  212. package/src/index.ts +0 -189
  213. package/src/lexicons.ts +0 -4
  214. package/src/logger.ts +0 -35
  215. package/src/mailer/index.ts +0 -111
  216. package/src/mailer/moderation.ts +0 -33
  217. package/src/mailer/templates/confirm-email.d.ts +0 -4
  218. package/src/mailer/templates/confirm-email.hbs +0 -158
  219. package/src/mailer/templates/delete-account.d.ts +0 -4
  220. package/src/mailer/templates/delete-account.hbs +0 -156
  221. package/src/mailer/templates/plc-operation.d.ts +0 -4
  222. package/src/mailer/templates/plc-operation.hbs +0 -153
  223. package/src/mailer/templates/reset-password.d.ts +0 -4
  224. package/src/mailer/templates/reset-password.hbs +0 -154
  225. package/src/mailer/templates/update-email.d.ts +0 -4
  226. package/src/mailer/templates/update-email.hbs +0 -153
  227. package/src/mailer/templates.ts +0 -17
  228. package/src/pipethrough.ts +0 -716
  229. package/src/rate-limits.ts +0 -59
  230. package/src/read-after-write/index.ts +0 -3
  231. package/src/read-after-write/types.ts +0 -35
  232. package/src/read-after-write/util.ts +0 -101
  233. package/src/read-after-write/viewer.ts +0 -290
  234. package/src/redis.ts +0 -25
  235. package/src/repo/index.ts +0 -2
  236. package/src/repo/prepare.ts +0 -266
  237. package/src/repo/types.ts +0 -65
  238. package/src/scripts/README.md +0 -40
  239. package/src/scripts/index.ts +0 -20
  240. package/src/scripts/publish-identity.ts +0 -60
  241. package/src/scripts/rebuild-repo.ts +0 -119
  242. package/src/scripts/rotate-keys.ts +0 -146
  243. package/src/scripts/sequencer-recovery/index.ts +0 -23
  244. package/src/scripts/sequencer-recovery/recoverer.ts +0 -297
  245. package/src/scripts/sequencer-recovery/recovery-db.ts +0 -65
  246. package/src/scripts/sequencer-recovery/repair-repos.ts +0 -49
  247. package/src/scripts/sequencer-recovery/user-queues.ts +0 -44
  248. package/src/scripts/util.ts +0 -7
  249. package/src/sequencer/db/index.ts +0 -21
  250. package/src/sequencer/db/migrations/001-init.ts +0 -35
  251. package/src/sequencer/db/migrations/index.ts +0 -5
  252. package/src/sequencer/db/schema.ts +0 -19
  253. package/src/sequencer/events.ts +0 -199
  254. package/src/sequencer/index.ts +0 -3
  255. package/src/sequencer/outbox.ts +0 -123
  256. package/src/sequencer/sequencer.ts +0 -290
  257. package/src/util/compression.ts +0 -16
  258. package/src/util/debug.ts +0 -10
  259. package/src/util/http.ts +0 -31
  260. package/src/util/types.ts +0 -7
  261. package/src/well-known.ts +0 -30
  262. package/test.env +0 -2
  263. package/tests/__snapshots__/takedown-appeal.test.ts.snap +0 -43
  264. package/tests/_oauth_client_assets_middleware.ts +0 -23
  265. package/tests/_puppeteer.ts +0 -147
  266. package/tests/_types.d.ts +0 -16
  267. package/tests/_util.ts +0 -191
  268. package/tests/account-deactivation.test.ts +0 -204
  269. package/tests/account-deletion.test.ts +0 -300
  270. package/tests/account-manager.test.ts +0 -462
  271. package/tests/account-migration.test.ts +0 -221
  272. package/tests/account-status.test.ts +0 -206
  273. package/tests/account.test.ts +0 -595
  274. package/tests/app-passwords.test.ts +0 -262
  275. package/tests/auth.test.ts +0 -405
  276. package/tests/blob-deletes.test.ts +0 -204
  277. package/tests/create-post.test.ts +0 -79
  278. package/tests/crud.test.ts +0 -1595
  279. package/tests/db.test.ts +0 -170
  280. package/tests/email-confirmation.test.ts +0 -227
  281. package/tests/entryway-mock.ts +0 -323
  282. package/tests/entryway.test.ts +0 -145
  283. package/tests/file-uploads.test.ts +0 -301
  284. package/tests/get-service-auth.test.ts +0 -81
  285. package/tests/handle-validation.test.ts +0 -56
  286. package/tests/handles.test.ts +0 -274
  287. package/tests/invite-codes.test.ts +0 -367
  288. package/tests/invites-admin.test.ts +0 -252
  289. package/tests/moderation.test.ts +0 -280
  290. package/tests/moderator-auth.test.ts +0 -177
  291. package/tests/oauth.test.ts +0 -334
  292. package/tests/plc-operations.test.ts +0 -239
  293. package/tests/preferences.test.ts +0 -352
  294. package/tests/proxied/__snapshots__/admin.test.ts.snap +0 -516
  295. package/tests/proxied/__snapshots__/feedgen.test.ts.snap +0 -215
  296. package/tests/proxied/__snapshots__/views.test.ts.snap +0 -4456
  297. package/tests/proxied/admin.test.ts +0 -340
  298. package/tests/proxied/feedgen.test.ts +0 -66
  299. package/tests/proxied/notif.test.ts +0 -85
  300. package/tests/proxied/procedures.test.ts +0 -175
  301. package/tests/proxied/proxy-catchall.test.ts +0 -256
  302. package/tests/proxied/proxy-header.test.ts +0 -239
  303. package/tests/proxied/proxy-oauth-aud.test.ts +0 -182
  304. package/tests/proxied/read-after-write.test.ts +0 -382
  305. package/tests/proxied/views.test.ts +0 -608
  306. package/tests/races.test.ts +0 -89
  307. package/tests/rate-limits.test.ts +0 -70
  308. package/tests/recovery.test.ts +0 -180
  309. package/tests/seeds/basic.ts +0 -165
  310. package/tests/seeds/follows.ts +0 -57
  311. package/tests/seeds/likes.ts +0 -14
  312. package/tests/seeds/reposts.ts +0 -18
  313. package/tests/seeds/thread.ts +0 -40
  314. package/tests/seeds/users-bulk.ts +0 -246
  315. package/tests/seeds/users.ts +0 -67
  316. package/tests/sequencer.test.ts +0 -251
  317. package/tests/server.test.ts +0 -151
  318. package/tests/sync/invertible-ops.test.ts +0 -99
  319. package/tests/sync/list.test.ts +0 -43
  320. package/tests/sync/subscribe-repos.test.ts +0 -672
  321. package/tests/sync/sync.test.ts +0 -316
  322. package/tests/takedown-appeal.test.ts +0 -166
  323. package/tsconfig.build.json +0 -9
  324. package/tsconfig.build.tsbuildinfo +0 -1
  325. package/tsconfig.json +0 -7
  326. package/tsconfig.tests.json +0 -8
@@ -1,146 +0,0 @@
1
- import assert from 'node:assert'
2
- import fs from 'node:fs/promises'
3
- import * as plc from '@did-plc/lib'
4
- import PQueue from 'p-queue'
5
- import AtpAgent from '@atproto/api'
6
- import { Keypair } from '@atproto/crypto'
7
- import { IdResolver } from '@atproto/identity'
8
- import { DidString, isDidString } from '@atproto/lex'
9
- import { ActorStore } from '../actor-store/actor-store.js'
10
- import { SyncEvtData } from '../repo/index.js'
11
- import { Sequencer } from '../sequencer/index.js'
12
- import { getRecoveryDbFromSequencerLoc } from './sequencer-recovery/recovery-db.js'
13
- import { parseIntArg } from './util.js'
14
-
15
- export type RotateKeysContext = {
16
- sequencer: Sequencer
17
- actorStore: ActorStore
18
- idResolver: IdResolver
19
- plcClient: plc.Client
20
- plcRotationKey: Keypair
21
- entrywayAdminAgent?: AtpAgent
22
- }
23
-
24
- export const rotateKeys = async (ctx: RotateKeysContext, args: string[]) => {
25
- const dids = args
26
- assert(dids.every(isDidString), 'All arguments must be DIDs')
27
- await rotateKeysForRepos(ctx, dids, 10)
28
- }
29
-
30
- export const rotateKeysFromFile = async (
31
- ctx: RotateKeysContext,
32
- args: string[],
33
- ) => {
34
- const filepath = args[0]
35
- if (!filepath) {
36
- throw new Error('Expected filepath as argument')
37
- }
38
- const concurrency = args[1] ? parseIntArg(args[1]) : 25
39
- const file = await fs.readFile(filepath)
40
- const dids = file
41
- .toString()
42
- .split('\n')
43
- .map((did) => did.trim())
44
- .filter((did) => did.startsWith('did:plc'))
45
-
46
- assert(dids.every(isDidString), 'File contains invalid DIDs')
47
-
48
- await rotateKeysForRepos(ctx, dids, concurrency)
49
- }
50
-
51
- export const rotateKeysRecovery = async (
52
- ctx: RotateKeysContext,
53
- args: string[],
54
- ) => {
55
- const concurrency = args[1] ? parseIntArg(args[0]) : 10
56
-
57
- const recoveryDb = await getRecoveryDbFromSequencerLoc(
58
- ctx.sequencer.dbLocation,
59
- )
60
- const rows = await recoveryDb.db
61
- .selectFrom('new_account')
62
- .select('did')
63
- .where('new_account.published', '=', 0)
64
- .execute()
65
- const dids = rows.map((r) => r.did as DidString)
66
-
67
- await rotateKeysForRepos(ctx, dids, concurrency, async (did) => {
68
- await recoveryDb.db
69
- .updateTable('new_account')
70
- .set({ published: 1 })
71
- .where('did', '=', did)
72
- .execute()
73
- })
74
- }
75
-
76
- const rotateKeysForRepos = async (
77
- ctx: RotateKeysContext,
78
- dids: DidString[],
79
- concurrency: number,
80
- onSuccess?: (did: DidString) => Promise<void>,
81
- ) => {
82
- const queue = new PQueue({ concurrency })
83
- let completed = 0
84
- for (const did of dids) {
85
- queue.add(async () => {
86
- try {
87
- await updatePlcSigningKey(ctx, did)
88
- } catch (err) {
89
- console.error(`failed to update key for ${did}: ${err}`)
90
- return
91
- }
92
- let syncData: SyncEvtData
93
- try {
94
- syncData = await ctx.actorStore.transact(did, async (actorTxn) => {
95
- await actorTxn.repo.processWrites([])
96
- return actorTxn.repo.getSyncEventData()
97
- })
98
- } catch (err) {
99
- console.error(`failed to write new commit for ${did}: ${err}`)
100
- return
101
- }
102
- try {
103
- await ctx.sequencer.sequenceIdentity(did)
104
- } catch (err) {
105
- console.error(`failed to sequence new identity evt for ${did}: ${err}`)
106
- return
107
- }
108
- try {
109
- await ctx.sequencer.sequenceSync(did, syncData)
110
- } catch (err) {
111
- console.error(`failed to sequence for ${did}: ${err}`)
112
- return
113
- }
114
- if (onSuccess) {
115
- await onSuccess(did)
116
- }
117
- completed++
118
- if (completed % 10 === 0) {
119
- console.log(`${completed}/${dids.length}`)
120
- }
121
- })
122
- }
123
- await queue.onIdle()
124
- console.log('DONE')
125
- }
126
-
127
- const updatePlcSigningKey = async (ctx: RotateKeysContext, did: DidString) => {
128
- const updateTo = await ctx.actorStore.keypair(did)
129
- const currSigningKey = await ctx.idResolver.did.resolveAtprotoKey(did, true)
130
- if (updateTo.did() === currSigningKey) {
131
- // already up to date
132
- return
133
- }
134
- if (ctx.entrywayAdminAgent) {
135
- await ctx.entrywayAdminAgent.api.com.atproto.admin.updateAccountSigningKey({
136
- did,
137
- signingKey: updateTo.did(),
138
- })
139
- } else {
140
- await ctx.plcClient.updateAtprotoKey(
141
- did,
142
- ctx.plcRotationKey,
143
- updateTo.did(),
144
- )
145
- }
146
- }
@@ -1,23 +0,0 @@
1
- import { parseIntArg } from '../util.js'
2
- import { Recoverer, RecovererContextNoDb } from './recoverer.js'
3
- import { getRecoveryDbFromSequencerLoc } from './recovery-db.js'
4
-
5
- export const sequencerRecovery = async (
6
- ctx: RecovererContextNoDb,
7
- args: string[],
8
- ) => {
9
- const cursor = args[0] ? parseIntArg(args[0]) : 0
10
- const concurrency = args[1] ? parseIntArg(args[1]) : 10
11
-
12
- const recoveryDb = await getRecoveryDbFromSequencerLoc(
13
- ctx.sequencer.dbLocation,
14
- )
15
-
16
- const recover = new Recoverer(
17
- { ...ctx, recoveryDb },
18
- {
19
- concurrency,
20
- },
21
- )
22
- await recover.run(cursor)
23
- }
@@ -1,297 +0,0 @@
1
- import { rmIfExists } from '@atproto/common'
2
- import { Secp256k1Keypair } from '@atproto/crypto'
3
- import { DidString, isNsidString, isRecordKeyString } from '@atproto/lex'
4
- import {
5
- BlockMap,
6
- CidSet,
7
- CommitData,
8
- WriteOpAction,
9
- cborToLexRecord,
10
- parseDataKey,
11
- readCar,
12
- } from '@atproto/repo'
13
- import {
14
- AccountManager,
15
- AccountStatus,
16
- } from '../../account-manager/account-manager.js'
17
- import { ActorStoreTransactor } from '../../actor-store/actor-store-transactor.js'
18
- import { ActorStore } from '../../actor-store/actor-store.js'
19
- import { countAll } from '../../db/index.js'
20
- import {
21
- PreparedWrite,
22
- prepareCreate,
23
- prepareDelete,
24
- prepareUpdate,
25
- } from '../../repo/index.js'
26
- import {
27
- AccountEvt,
28
- CommitEvt,
29
- SeqEvt,
30
- Sequencer,
31
- } from '../../sequencer/index.js'
32
- import { RecoveryDb } from './recovery-db.js'
33
- import { UserQueues } from './user-queues.js'
34
-
35
- export type RecovererContextNoDb = {
36
- sequencer: Sequencer
37
- accountManager: AccountManager
38
- actorStore: ActorStore
39
- }
40
-
41
- export type RecovererContext = RecovererContextNoDb & {
42
- recoveryDb: RecoveryDb
43
- }
44
-
45
- const PAGE_SIZE = 5000
46
-
47
- export class Recoverer {
48
- queues: UserQueues
49
- failed: Set<string>
50
-
51
- constructor(
52
- public ctx: RecovererContext,
53
- opts: { concurrency: number },
54
- ) {
55
- this.queues = new UserQueues(opts.concurrency)
56
- this.failed = new Set()
57
- }
58
-
59
- async run(startCursor = 0) {
60
- const failed = await this.ctx.recoveryDb.db
61
- .selectFrom('failed')
62
- .select('did')
63
- .execute()
64
- for (const row of failed) {
65
- this.failed.add(row.did)
66
- }
67
-
68
- const totalRes = await this.ctx.sequencer.db.db
69
- .selectFrom('repo_seq')
70
- .select(countAll.as('count'))
71
- .executeTakeFirstOrThrow()
72
- const totalEvts = totalRes.count
73
- let completed = 0
74
-
75
- let cursor: number | undefined = startCursor
76
- while (cursor !== undefined) {
77
- const page = await this.ctx.sequencer.requestSeqRange({
78
- earliestSeq: cursor,
79
- limit: PAGE_SIZE,
80
- })
81
- page.forEach((evt) => this.processEvent(evt))
82
- cursor = page.at(-1)?.seq
83
-
84
- await this.queues.onEmpty()
85
-
86
- completed += PAGE_SIZE
87
- const percentComplete = (completed / totalEvts) * 100
88
- console.log(`${percentComplete.toFixed(2)}% - ${cursor}`)
89
- }
90
-
91
- await this.queues.processAll()
92
- }
93
-
94
- async processAll() {
95
- await this.queues.processAll()
96
- }
97
-
98
- async destroy() {
99
- await this.queues.destroy()
100
- }
101
-
102
- processEvent(evt: SeqEvt) {
103
- const did = didFromEvt(evt)
104
- if (!did) {
105
- return
106
- }
107
- this.queues.addToUser(did, async () => {
108
- if (this.failed.has(did)) {
109
- return
110
- }
111
- await processSeqEvt(this.ctx, evt).catch(async (err) => {
112
- this.failed.add(did)
113
- await trackFailure(this.ctx.recoveryDb, did, err)
114
- })
115
- })
116
- }
117
- }
118
-
119
- export const processSeqEvt = async (ctx: RecovererContext, evt: SeqEvt) => {
120
- // only need to process commits & tombstones
121
- if (evt.type === 'account') {
122
- await processAccountEvt(ctx, evt.evt)
123
- }
124
- if (evt.type === 'commit') {
125
- await processCommit(ctx, evt.evt).catch()
126
- }
127
- }
128
-
129
- const processCommit = async (ctx: RecovererContext, evt: CommitEvt) => {
130
- const did = evt.repo
131
- const { writes, blocks } = await parseCommitEvt(evt)
132
- if (evt.since === null) {
133
- const actorExists = await ctx.actorStore.exists(did)
134
- if (!actorExists) {
135
- await processRepoCreation(ctx, evt, writes, blocks)
136
- return
137
- }
138
- }
139
- await ctx.actorStore.transact(did, async (actorTxn) => {
140
- const root = await actorTxn.repo.storage.getRootDetailed()
141
- if (root.rev >= evt.rev) {
142
- return
143
- }
144
- const commit = await actorTxn.repo.formatCommit(writes)
145
- commit.newBlocks = blocks
146
- commit.cid = evt.commit
147
- commit.rev = evt.rev
148
- await actorTxn.repo.storage.applyCommit(commit)
149
- await actorTxn.repo.indexWrites(writes, commit.rev)
150
- await trackBlobs(actorTxn, writes)
151
- })
152
- }
153
-
154
- const processRepoCreation = async (
155
- ctx: RecovererContext,
156
- evt: CommitEvt,
157
- writes: PreparedWrite[],
158
- blocks: BlockMap,
159
- ) => {
160
- const did = evt.repo
161
- const keypair = await Secp256k1Keypair.create({ exportable: true })
162
- await ctx.actorStore.create(did, keypair)
163
- const commit: CommitData = {
164
- cid: evt.commit,
165
- rev: evt.rev,
166
- since: evt.since,
167
- prev: null,
168
- newBlocks: blocks,
169
- relevantBlocks: new BlockMap(),
170
- removedCids: new CidSet(),
171
- }
172
- await ctx.actorStore.transact(did, async (actorTxn) => {
173
- await actorTxn.repo.storage.applyCommit(commit, true)
174
- await actorTxn.repo.indexWrites(writes, commit.rev)
175
- await actorTxn.repo.blob.processWriteBlobs(commit.rev, writes)
176
- })
177
- await trackNewAccount(ctx.recoveryDb, did)
178
- }
179
-
180
- const processAccountEvt = async (ctx: RecovererContext, evt: AccountEvt) => {
181
- // do not need to process deactivation/takedowns because we backup account DB as well
182
-
183
- if (evt.status === AccountStatus.Deleted) {
184
- // In case an account deletion was sequenced, let's make sure to (first)
185
- // delete the accounts database, and (then) unlink the actor store from the
186
- // file system. Order matters here.
187
- await ctx.accountManager.deleteAccount(evt.did)
188
-
189
- const { directory } = await ctx.actorStore.getLocation(evt.did)
190
- await rmIfExists(directory, true)
191
- }
192
- }
193
-
194
- const trackBlobs = async (
195
- store: ActorStoreTransactor,
196
- writes: PreparedWrite[],
197
- ) => {
198
- await store.repo.blob.deleteDereferencedBlobs(writes)
199
-
200
- for (const write of writes) {
201
- if (
202
- write.action === WriteOpAction.Create ||
203
- write.action === WriteOpAction.Update
204
- ) {
205
- for (const blob of write.blobs) {
206
- await store.repo.blob.insertBlobMetadata(blob)
207
- await store.repo.blob.associateBlob(blob, write.uri)
208
- }
209
- }
210
- }
211
- }
212
-
213
- const trackFailure = async (
214
- recoveryDb: RecoveryDb,
215
- did: DidString,
216
- err: unknown,
217
- ) => {
218
- await recoveryDb.db
219
- .insertInto('failed')
220
- .values({
221
- did,
222
- error: err?.toString(),
223
- fixed: 0,
224
- })
225
- .onConflict((oc) => oc.doNothing())
226
- .execute()
227
- }
228
-
229
- const trackNewAccount = async (recoveryDb: RecoveryDb, did: DidString) => {
230
- await recoveryDb.db
231
- .insertInto('new_account')
232
- .values({
233
- did,
234
- published: 0,
235
- })
236
- .onConflict((oc) => oc.doNothing())
237
- .execute()
238
- }
239
-
240
- const parseCommitEvt = async (
241
- evt: CommitEvt,
242
- ): Promise<{
243
- writes: PreparedWrite[]
244
- blocks: BlockMap
245
- }> => {
246
- const did = evt.repo
247
- const evtCar = await readCar(evt.blocks, { skipCidVerification: true })
248
- const writesUnfiltered = await Promise.all(
249
- evt.ops.map(async (op) => {
250
- const { collection, rkey } = parseDataKey(op.path)
251
- if (!isNsidString(collection)) return undefined
252
- if (!isRecordKeyString(rkey)) return undefined
253
-
254
- if (op.action === 'delete') {
255
- return prepareDelete({ did, collection, rkey })
256
- }
257
- if (!op.cid) return undefined
258
-
259
- const recordBytes = evtCar.blocks.get(op.cid)
260
- if (!recordBytes) return undefined
261
- const record = cborToLexRecord(recordBytes)
262
-
263
- if (op.action === 'create') {
264
- return prepareCreate({
265
- did,
266
- collection,
267
- rkey,
268
- record,
269
- validate: false,
270
- })
271
- } else {
272
- return prepareUpdate({
273
- did,
274
- collection,
275
- rkey,
276
- record,
277
- validate: false,
278
- })
279
- }
280
- }),
281
- )
282
-
283
- return {
284
- writes: writesUnfiltered.filter((w) => w != null),
285
- blocks: evtCar.blocks,
286
- }
287
- }
288
-
289
- const didFromEvt = (evt: SeqEvt): DidString | null => {
290
- if (evt.type === 'account') {
291
- return evt.evt.did
292
- } else if (evt.type === 'commit') {
293
- return evt.evt.repo
294
- } else {
295
- return null
296
- }
297
- }
@@ -1,65 +0,0 @@
1
- import path from 'node:path'
2
- import { Kysely } from 'kysely'
3
- import { DidString } from '@atproto/syntax'
4
- import { Database, Migrator } from '../../db/index.js'
5
-
6
- export interface NewAccount {
7
- did: DidString
8
- published: 0 | 1
9
- }
10
-
11
- export interface Failed {
12
- did: DidString
13
- error: string | null
14
- fixed: 0 | 1
15
- }
16
-
17
- export type RecoveryDbSchema = {
18
- new_account: NewAccount
19
- failed: Failed
20
- }
21
-
22
- export type RecoveryDb = Database<RecoveryDbSchema>
23
-
24
- export const getRecoveryDbFromSequencerLoc = (
25
- sequencerLoc: string,
26
- ): Promise<RecoveryDb> => {
27
- const recoveryDbLoc = path.join(path.dirname(sequencerLoc), 'recovery.sqlite')
28
- return getAndMigrateRecoveryDb(recoveryDbLoc)
29
- }
30
-
31
- export const getAndMigrateRecoveryDb = async (
32
- location: string,
33
- disableWalAutoCheckpoint = false,
34
- ): Promise<RecoveryDb> => {
35
- const pragmas: Record<string, string> = disableWalAutoCheckpoint
36
- ? { wal_autocheckpoint: '0' }
37
- : {}
38
- const db = Database.sqlite<RecoveryDbSchema>(location, pragmas)
39
- const migrator = new Migrator(db.db, migrations)
40
- await migrator.migrateToLatestOrThrow()
41
- return db
42
- }
43
-
44
- const migrations = {
45
- '001': {
46
- up: async (db: Kysely<unknown>) => {
47
- await db.schema
48
- .createTable('new_account')
49
- .addColumn('did', 'varchar', (col) => col.primaryKey())
50
- .addColumn('published', 'int2', (col) => col.notNull())
51
- .execute()
52
-
53
- await db.schema
54
- .createTable('failed')
55
- .addColumn('did', 'varchar', (col) => col.primaryKey())
56
- .addColumn('error', 'varchar')
57
- .addColumn('fixed', 'int2', (col) => col.notNull())
58
- .execute()
59
- },
60
- down: async (db: Kysely<unknown>) => {
61
- await db.schema.dropTable('new_account').execute()
62
- await db.schema.dropTable('failed').execute()
63
- },
64
- },
65
- }
@@ -1,49 +0,0 @@
1
- import { DidString } from '@atproto/syntax'
2
- import { parseRepoSeqRows } from '../../sequencer/index.js'
3
- import { rebuildRepo } from '../rebuild-repo.js'
4
- import {
5
- RecovererContext,
6
- RecovererContextNoDb,
7
- processSeqEvt,
8
- } from './recoverer.js'
9
- import { getRecoveryDbFromSequencerLoc } from './recovery-db.js'
10
-
11
- export const repairRepos = async (ctx: RecovererContextNoDb) => {
12
- const recoveryDb = await getRecoveryDbFromSequencerLoc(
13
- ctx.sequencer.dbLocation,
14
- )
15
- const repairRes = await recoveryDb.db
16
- .selectFrom('failed')
17
- .select('did')
18
- .where('failed.fixed', '=', 0)
19
- .execute()
20
- const dids = repairRes.map((row) => row.did)
21
- let fixed = 0
22
- for (const did of dids) {
23
- await rebuildRepo(ctx, did, false)
24
- await recoverFromSequencer({ ...ctx, recoveryDb }, did)
25
- fixed++
26
- console.log(`${fixed}/${dids.length}`)
27
- }
28
- }
29
-
30
- const recoverFromSequencer = async (ctx: RecovererContext, did: DidString) => {
31
- const didEvts = await ctx.sequencer.db.db
32
- .selectFrom('repo_seq')
33
- .selectAll()
34
- .where('did', '=', did)
35
- .orderBy('seq', 'asc')
36
- .execute()
37
- const seqEvts = parseRepoSeqRows(didEvts)
38
- for (const evt of seqEvts) {
39
- await processSeqEvt(ctx, evt)
40
- }
41
- await ctx.recoveryDb.db
42
- .updateTable('failed')
43
- .set({
44
- fixed: 1,
45
- error: null,
46
- })
47
- .where('did', '=', did)
48
- .execute()
49
- }
@@ -1,44 +0,0 @@
1
- import PQueue from 'p-queue'
2
-
3
- type Queue = InstanceType<typeof PQueue>
4
-
5
- export class UserQueues {
6
- main: Queue
7
- queues: Map<string, Queue> = new Map()
8
-
9
- constructor(concurrency: number) {
10
- this.main = new PQueue({ concurrency })
11
- }
12
-
13
- async addToUser(did: string, task: () => Promise<void>) {
14
- if (this.main.isPaused) return
15
- return this.main.add(() => {
16
- return this.getQueue(did).add(task)
17
- })
18
- }
19
-
20
- private getQueue(did: string) {
21
- let queue = this.queues.get(did)
22
- if (!queue) {
23
- queue = new PQueue({ concurrency: 1 })
24
- queue.once('idle', () => this.queues.delete(did))
25
- this.queues.set(did, queue)
26
- }
27
- return queue
28
- }
29
-
30
- async onEmpty() {
31
- await this.main.onEmpty()
32
- }
33
-
34
- async processAll() {
35
- await this.main.onIdle()
36
- }
37
-
38
- async destroy() {
39
- this.main.pause()
40
- this.main.clear()
41
- this.queues.forEach((q) => q.clear())
42
- await this.processAll()
43
- }
44
- }
@@ -1,7 +0,0 @@
1
- export const parseIntArg = (arg: string): number => {
2
- const parsed = parseInt(arg, 10)
3
- if (isNaN(parsed)) {
4
- throw new Error(`Invalid arg, expected number: ${arg}`)
5
- }
6
- return parsed
7
- }
@@ -1,21 +0,0 @@
1
- import { Database, Migrator } from '../../db/index.js'
2
- import migrations from './migrations/index.js'
3
- import { SequencerDbSchema } from './schema.js'
4
-
5
- export * from './schema.js'
6
-
7
- export type SequencerDb = Database<SequencerDbSchema>
8
-
9
- export const getDb = (
10
- location: string,
11
- disableWalAutoCheckpoint = false,
12
- ): SequencerDb => {
13
- const pragmas: Record<string, string> = disableWalAutoCheckpoint
14
- ? { wal_autocheckpoint: '0' }
15
- : {}
16
- return Database.sqlite(location, pragmas)
17
- }
18
-
19
- export const getMigrator = (db: Database<SequencerDbSchema>) => {
20
- return new Migrator(db.db, migrations)
21
- }
@@ -1,35 +0,0 @@
1
- import { Kysely } from 'kysely'
2
-
3
- export async function up(db: Kysely<unknown>): Promise<void> {
4
- await db.schema
5
- .createTable('repo_seq')
6
- .addColumn('seq', 'integer', (col) => col.autoIncrement().primaryKey())
7
- .addColumn('did', 'varchar', (col) => col.notNull())
8
- .addColumn('eventType', 'varchar', (col) => col.notNull())
9
- .addColumn('event', 'blob', (col) => col.notNull())
10
- .addColumn('invalidated', 'int2', (col) => col.notNull().defaultTo(0))
11
- .addColumn('sequencedAt', 'varchar', (col) => col.notNull())
12
- .execute()
13
- // for filtering seqs based on did
14
- await db.schema
15
- .createIndex('repo_seq_did_idx')
16
- .on('repo_seq')
17
- .column('did')
18
- .execute()
19
- // for filtering seqs based on event type
20
- await db.schema
21
- .createIndex('repo_seq_event_type_idx')
22
- .on('repo_seq')
23
- .column('eventType')
24
- .execute()
25
- // for entering into the seq stream at a particular time
26
- await db.schema
27
- .createIndex('repo_seq_sequenced_at_index')
28
- .on('repo_seq')
29
- .column('sequencedAt')
30
- .execute()
31
- }
32
-
33
- export async function down(db: Kysely<unknown>): Promise<void> {
34
- await db.schema.dropTable('repo_seq').execute()
35
- }
@@ -1,5 +0,0 @@
1
- import * as init from './001-init.js'
2
-
3
- export default {
4
- '001': init,
5
- }