@atproto/pds 0.5.11 → 0.5.14

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 (322) hide show
  1. package/CHANGELOG.md +46 -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/package.json +42 -38
  10. package/build.templates.cjs +0 -22
  11. package/example.env +0 -42
  12. package/jest.config.cjs +0 -27
  13. package/src/account-manager/account-manager.ts +0 -916
  14. package/src/account-manager/db/index.ts +0 -21
  15. package/src/account-manager/db/migrations/001-init.ts +0 -115
  16. package/src/account-manager/db/migrations/002-account-deactivation.ts +0 -17
  17. package/src/account-manager/db/migrations/003-privileged-app-passwords.ts +0 -12
  18. package/src/account-manager/db/migrations/004-oauth.ts +0 -122
  19. package/src/account-manager/db/migrations/005-oauth-account-management.ts +0 -136
  20. package/src/account-manager/db/migrations/006-oauth-permission-sets.ts +0 -20
  21. package/src/account-manager/db/migrations/007-lexicon-failures-index.ts +0 -14
  22. package/src/account-manager/db/migrations/index.ts +0 -17
  23. package/src/account-manager/db/schema/account-device.ts +0 -14
  24. package/src/account-manager/db/schema/account.ts +0 -16
  25. package/src/account-manager/db/schema/actor.ts +0 -17
  26. package/src/account-manager/db/schema/app-password.ts +0 -13
  27. package/src/account-manager/db/schema/authorization-request.ts +0 -30
  28. package/src/account-manager/db/schema/authorized-client.ts +0 -23
  29. package/src/account-manager/db/schema/device.ts +0 -18
  30. package/src/account-manager/db/schema/email-token.ts +0 -19
  31. package/src/account-manager/db/schema/index.ts +0 -43
  32. package/src/account-manager/db/schema/invite-code.ts +0 -24
  33. package/src/account-manager/db/schema/lexicon.ts +0 -15
  34. package/src/account-manager/db/schema/refresh-token.ts +0 -11
  35. package/src/account-manager/db/schema/repo-root.ts +0 -12
  36. package/src/account-manager/db/schema/token.ts +0 -38
  37. package/src/account-manager/db/schema/used-refresh-token.ts +0 -13
  38. package/src/account-manager/helpers/account-device.ts +0 -63
  39. package/src/account-manager/helpers/account.ts +0 -355
  40. package/src/account-manager/helpers/auth.ts +0 -222
  41. package/src/account-manager/helpers/authorization-request.ts +0 -90
  42. package/src/account-manager/helpers/authorized-client.ts +0 -75
  43. package/src/account-manager/helpers/device.ts +0 -47
  44. package/src/account-manager/helpers/email-token.ts +0 -87
  45. package/src/account-manager/helpers/invite.ts +0 -263
  46. package/src/account-manager/helpers/lexicon.ts +0 -67
  47. package/src/account-manager/helpers/password.ts +0 -136
  48. package/src/account-manager/helpers/repo.ts +0 -24
  49. package/src/account-manager/helpers/scrypt.ts +0 -53
  50. package/src/account-manager/helpers/token.ts +0 -158
  51. package/src/account-manager/helpers/used-refresh-token.ts +0 -30
  52. package/src/account-manager/oauth-store.ts +0 -880
  53. package/src/account-manager/scope-reference-getter.ts +0 -106
  54. package/src/actor-store/actor-store-reader.ts +0 -45
  55. package/src/actor-store/actor-store-resources.ts +0 -8
  56. package/src/actor-store/actor-store-transactor.ts +0 -31
  57. package/src/actor-store/actor-store-writer.ts +0 -17
  58. package/src/actor-store/actor-store.ts +0 -210
  59. package/src/actor-store/blob/reader.ts +0 -160
  60. package/src/actor-store/blob/transactor.ts +0 -383
  61. package/src/actor-store/db/index.ts +0 -20
  62. package/src/actor-store/db/migrations/001-init.ts +0 -105
  63. package/src/actor-store/db/migrations/index.ts +0 -5
  64. package/src/actor-store/db/schema/account-pref.ts +0 -11
  65. package/src/actor-store/db/schema/backlink.ts +0 -9
  66. package/src/actor-store/db/schema/blob.ts +0 -14
  67. package/src/actor-store/db/schema/index.ts +0 -23
  68. package/src/actor-store/db/schema/record-blob.ts +0 -8
  69. package/src/actor-store/db/schema/record.ts +0 -14
  70. package/src/actor-store/db/schema/repo-block.ts +0 -10
  71. package/src/actor-store/db/schema/repo-root.ts +0 -10
  72. package/src/actor-store/migrate.ts +0 -39
  73. package/src/actor-store/preference/reader.ts +0 -48
  74. package/src/actor-store/preference/transactor.ts +0 -55
  75. package/src/actor-store/preference/util.ts +0 -39
  76. package/src/actor-store/record/reader.ts +0 -374
  77. package/src/actor-store/record/transactor.ts +0 -111
  78. package/src/actor-store/repo/reader.ts +0 -31
  79. package/src/actor-store/repo/sql-repo-reader.ts +0 -150
  80. package/src/actor-store/repo/sql-repo-transactor.ts +0 -105
  81. package/src/actor-store/repo/transactor.ts +0 -227
  82. package/src/api/app/bsky/actor/getPreferences.ts +0 -57
  83. package/src/api/app/bsky/actor/getProfile.ts +0 -41
  84. package/src/api/app/bsky/actor/getProfiles.ts +0 -51
  85. package/src/api/app/bsky/actor/index.ts +0 -13
  86. package/src/api/app/bsky/actor/putPreferences.ts +0 -62
  87. package/src/api/app/bsky/feed/getActorLikes.ts +0 -63
  88. package/src/api/app/bsky/feed/getAuthorFeed.ts +0 -84
  89. package/src/api/app/bsky/feed/getFeed.ts +0 -47
  90. package/src/api/app/bsky/feed/getPostThread.ts +0 -251
  91. package/src/api/app/bsky/feed/getTimeline.ts +0 -50
  92. package/src/api/app/bsky/feed/index.ts +0 -15
  93. package/src/api/app/bsky/index.ts +0 -11
  94. package/src/api/app/bsky/notification/index.ts +0 -7
  95. package/src/api/app/bsky/notification/registerPush.ts +0 -71
  96. package/src/api/app/bsky/util/resolver.ts +0 -20
  97. package/src/api/com/atproto/admin/deleteAccount.ts +0 -22
  98. package/src/api/com/atproto/admin/disableAccountInvites.ts +0 -18
  99. package/src/api/com/atproto/admin/disableInviteCodes.ts +0 -21
  100. package/src/api/com/atproto/admin/enableAccountInvites.ts +0 -18
  101. package/src/api/com/atproto/admin/getAccountInfo.ts +0 -32
  102. package/src/api/com/atproto/admin/getAccountInfos.ts +0 -34
  103. package/src/api/com/atproto/admin/getInviteCodes.ts +0 -126
  104. package/src/api/com/atproto/admin/getSubjectStatus.ts +0 -76
  105. package/src/api/com/atproto/admin/index.ts +0 -31
  106. package/src/api/com/atproto/admin/sendEmail.ts +0 -47
  107. package/src/api/com/atproto/admin/updateAccountEmail.ts +0 -32
  108. package/src/api/com/atproto/admin/updateAccountHandle.ts +0 -47
  109. package/src/api/com/atproto/admin/updateAccountPassword.ts +0 -34
  110. package/src/api/com/atproto/admin/updateSubjectStatus.ts +0 -68
  111. package/src/api/com/atproto/admin/util.ts +0 -66
  112. package/src/api/com/atproto/identity/getRecommendedDidCredentials.ts +0 -50
  113. package/src/api/com/atproto/identity/index.ts +0 -17
  114. package/src/api/com/atproto/identity/requestPlcOperationSignature.ts +0 -59
  115. package/src/api/com/atproto/identity/resolveHandle.ts +0 -50
  116. package/src/api/com/atproto/identity/signPlcOperation.ts +0 -85
  117. package/src/api/com/atproto/identity/submitPlcOperation.ts +0 -65
  118. package/src/api/com/atproto/identity/updateHandle.ts +0 -66
  119. package/src/api/com/atproto/index.ts +0 -19
  120. package/src/api/com/atproto/moderation/createReport.ts +0 -41
  121. package/src/api/com/atproto/moderation/index.ts +0 -7
  122. package/src/api/com/atproto/repo/applyWrites.ts +0 -226
  123. package/src/api/com/atproto/repo/createRecord.ts +0 -143
  124. package/src/api/com/atproto/repo/deleteRecord.ts +0 -122
  125. package/src/api/com/atproto/repo/describeRepo.ts +0 -43
  126. package/src/api/com/atproto/repo/getRecord.ts +0 -40
  127. package/src/api/com/atproto/repo/importRepo.ts +0 -101
  128. package/src/api/com/atproto/repo/index.ts +0 -25
  129. package/src/api/com/atproto/repo/listMissingBlobs.ts +0 -29
  130. package/src/api/com/atproto/repo/listRecords.ts +0 -36
  131. package/src/api/com/atproto/repo/putRecord.ts +0 -211
  132. package/src/api/com/atproto/repo/uploadBlob.ts +0 -60
  133. package/src/api/com/atproto/server/activateAccount.ts +0 -37
  134. package/src/api/com/atproto/server/checkAccountStatus.ts +0 -51
  135. package/src/api/com/atproto/server/confirmEmail.ts +0 -39
  136. package/src/api/com/atproto/server/createAccount.ts +0 -327
  137. package/src/api/com/atproto/server/createAppPassword.ts +0 -53
  138. package/src/api/com/atproto/server/createInviteCode.ts +0 -38
  139. package/src/api/com/atproto/server/createInviteCodes.ts +0 -42
  140. package/src/api/com/atproto/server/createSession.ts +0 -97
  141. package/src/api/com/atproto/server/deactivateAccount.ts +0 -41
  142. package/src/api/com/atproto/server/deleteAccount.ts +0 -85
  143. package/src/api/com/atproto/server/deleteSession.ts +0 -23
  144. package/src/api/com/atproto/server/describeServer.ts +0 -29
  145. package/src/api/com/atproto/server/getAccountInviteCodes.ts +0 -142
  146. package/src/api/com/atproto/server/getServiceAuth.ts +0 -111
  147. package/src/api/com/atproto/server/getSession.ts +0 -80
  148. package/src/api/com/atproto/server/index.ts +0 -55
  149. package/src/api/com/atproto/server/listAppPasswords.ts +0 -45
  150. package/src/api/com/atproto/server/refreshSession.ts +0 -72
  151. package/src/api/com/atproto/server/requestAccountDelete.ts +0 -66
  152. package/src/api/com/atproto/server/requestEmailConfirmation.ts +0 -68
  153. package/src/api/com/atproto/server/requestEmailUpdate.ts +0 -86
  154. package/src/api/com/atproto/server/requestPasswordReset.ts +0 -52
  155. package/src/api/com/atproto/server/reserveSigningKey.ts +0 -15
  156. package/src/api/com/atproto/server/resetPassword.ts +0 -50
  157. package/src/api/com/atproto/server/revokeAppPassword.ts +0 -42
  158. package/src/api/com/atproto/server/updateEmail.ts +0 -52
  159. package/src/api/com/atproto/server/util.ts +0 -136
  160. package/src/api/com/atproto/sync/deprecated/getCheckout.ts +0 -27
  161. package/src/api/com/atproto/sync/deprecated/getHead.ts +0 -33
  162. package/src/api/com/atproto/sync/getBlob.ts +0 -61
  163. package/src/api/com/atproto/sync/getBlocks.ts +0 -37
  164. package/src/api/com/atproto/sync/getLatestCommit.ts +0 -33
  165. package/src/api/com/atproto/sync/getRecord.ts +0 -49
  166. package/src/api/com/atproto/sync/getRepo.ts +0 -75
  167. package/src/api/com/atproto/sync/getRepoStatus.ts +0 -34
  168. package/src/api/com/atproto/sync/index.ts +0 -27
  169. package/src/api/com/atproto/sync/listBlobs.ts +0 -33
  170. package/src/api/com/atproto/sync/listRepos.ts +0 -74
  171. package/src/api/com/atproto/sync/subscribeRepos.ts +0 -73
  172. package/src/api/com/atproto/sync/util.ts +0 -37
  173. package/src/api/com/atproto/temp/checkSignupQueue.ts +0 -34
  174. package/src/api/com/atproto/temp/index.ts +0 -7
  175. package/src/api/index.ts +0 -10
  176. package/src/api/proxy.ts +0 -44
  177. package/src/app-view.ts +0 -24
  178. package/src/auth-output.ts +0 -52
  179. package/src/auth-routes.ts +0 -64
  180. package/src/auth-scope.ts +0 -40
  181. package/src/auth-verifier.ts +0 -668
  182. package/src/background.ts +0 -65
  183. package/src/basic-routes.ts +0 -52
  184. package/src/bsky-app-view.ts +0 -33
  185. package/src/config/config.ts +0 -553
  186. package/src/config/env.ts +0 -167
  187. package/src/config/index.ts +0 -3
  188. package/src/config/secrets.ts +0 -54
  189. package/src/context.ts +0 -523
  190. package/src/crawlers.ts +0 -46
  191. package/src/db/cast.ts +0 -52
  192. package/src/db/db.ts +0 -140
  193. package/src/db/index.ts +0 -4
  194. package/src/db/migrator.ts +0 -40
  195. package/src/db/pagination.ts +0 -132
  196. package/src/db/tables/moderation.ts +0 -80
  197. package/src/db/util.ts +0 -108
  198. package/src/did-cache/db/index.ts +0 -21
  199. package/src/did-cache/db/migrations.ts +0 -17
  200. package/src/did-cache/db/schema.ts +0 -9
  201. package/src/did-cache/index.ts +0 -131
  202. package/src/disk-blobstore.ts +0 -172
  203. package/src/error.ts +0 -19
  204. package/src/handle/explicit-slurs.ts +0 -22
  205. package/src/handle/index.ts +0 -49
  206. package/src/handle/reserved.ts +0 -1059
  207. package/src/image/image-url-builder.ts +0 -16
  208. package/src/index.ts +0 -189
  209. package/src/lexicons.ts +0 -4
  210. package/src/logger.ts +0 -35
  211. package/src/mailer/index.ts +0 -111
  212. package/src/mailer/moderation.ts +0 -33
  213. package/src/mailer/templates/confirm-email.d.ts +0 -4
  214. package/src/mailer/templates/confirm-email.hbs +0 -158
  215. package/src/mailer/templates/delete-account.d.ts +0 -4
  216. package/src/mailer/templates/delete-account.hbs +0 -156
  217. package/src/mailer/templates/plc-operation.d.ts +0 -4
  218. package/src/mailer/templates/plc-operation.hbs +0 -153
  219. package/src/mailer/templates/reset-password.d.ts +0 -4
  220. package/src/mailer/templates/reset-password.hbs +0 -154
  221. package/src/mailer/templates/update-email.d.ts +0 -4
  222. package/src/mailer/templates/update-email.hbs +0 -153
  223. package/src/mailer/templates.ts +0 -17
  224. package/src/pipethrough.ts +0 -716
  225. package/src/rate-limits.ts +0 -59
  226. package/src/read-after-write/index.ts +0 -3
  227. package/src/read-after-write/types.ts +0 -35
  228. package/src/read-after-write/util.ts +0 -101
  229. package/src/read-after-write/viewer.ts +0 -290
  230. package/src/redis.ts +0 -25
  231. package/src/repo/index.ts +0 -2
  232. package/src/repo/prepare.ts +0 -266
  233. package/src/repo/types.ts +0 -65
  234. package/src/scripts/README.md +0 -40
  235. package/src/scripts/index.ts +0 -20
  236. package/src/scripts/publish-identity.ts +0 -60
  237. package/src/scripts/rebuild-repo.ts +0 -119
  238. package/src/scripts/rotate-keys.ts +0 -146
  239. package/src/scripts/sequencer-recovery/index.ts +0 -23
  240. package/src/scripts/sequencer-recovery/recoverer.ts +0 -297
  241. package/src/scripts/sequencer-recovery/recovery-db.ts +0 -65
  242. package/src/scripts/sequencer-recovery/repair-repos.ts +0 -49
  243. package/src/scripts/sequencer-recovery/user-queues.ts +0 -44
  244. package/src/scripts/util.ts +0 -7
  245. package/src/sequencer/db/index.ts +0 -21
  246. package/src/sequencer/db/migrations/001-init.ts +0 -35
  247. package/src/sequencer/db/migrations/index.ts +0 -5
  248. package/src/sequencer/db/schema.ts +0 -19
  249. package/src/sequencer/events.ts +0 -199
  250. package/src/sequencer/index.ts +0 -3
  251. package/src/sequencer/outbox.ts +0 -123
  252. package/src/sequencer/sequencer.ts +0 -290
  253. package/src/util/compression.ts +0 -16
  254. package/src/util/debug.ts +0 -10
  255. package/src/util/http.ts +0 -31
  256. package/src/util/types.ts +0 -7
  257. package/src/well-known.ts +0 -30
  258. package/test.env +0 -2
  259. package/tests/__snapshots__/takedown-appeal.test.ts.snap +0 -43
  260. package/tests/_oauth_client_assets_middleware.ts +0 -23
  261. package/tests/_puppeteer.ts +0 -147
  262. package/tests/_types.d.ts +0 -16
  263. package/tests/_util.ts +0 -191
  264. package/tests/account-deactivation.test.ts +0 -204
  265. package/tests/account-deletion.test.ts +0 -300
  266. package/tests/account-manager.test.ts +0 -462
  267. package/tests/account-migration.test.ts +0 -221
  268. package/tests/account-status.test.ts +0 -206
  269. package/tests/account.test.ts +0 -595
  270. package/tests/app-passwords.test.ts +0 -262
  271. package/tests/auth.test.ts +0 -405
  272. package/tests/blob-deletes.test.ts +0 -204
  273. package/tests/create-post.test.ts +0 -79
  274. package/tests/crud.test.ts +0 -1595
  275. package/tests/db.test.ts +0 -170
  276. package/tests/email-confirmation.test.ts +0 -227
  277. package/tests/entryway-mock.ts +0 -323
  278. package/tests/entryway.test.ts +0 -145
  279. package/tests/file-uploads.test.ts +0 -301
  280. package/tests/get-service-auth.test.ts +0 -81
  281. package/tests/handle-validation.test.ts +0 -56
  282. package/tests/handles.test.ts +0 -274
  283. package/tests/invite-codes.test.ts +0 -367
  284. package/tests/invites-admin.test.ts +0 -252
  285. package/tests/moderation.test.ts +0 -280
  286. package/tests/moderator-auth.test.ts +0 -177
  287. package/tests/oauth.test.ts +0 -334
  288. package/tests/plc-operations.test.ts +0 -239
  289. package/tests/preferences.test.ts +0 -352
  290. package/tests/proxied/__snapshots__/admin.test.ts.snap +0 -516
  291. package/tests/proxied/__snapshots__/feedgen.test.ts.snap +0 -215
  292. package/tests/proxied/__snapshots__/views.test.ts.snap +0 -4456
  293. package/tests/proxied/admin.test.ts +0 -340
  294. package/tests/proxied/feedgen.test.ts +0 -66
  295. package/tests/proxied/notif.test.ts +0 -85
  296. package/tests/proxied/procedures.test.ts +0 -175
  297. package/tests/proxied/proxy-catchall.test.ts +0 -256
  298. package/tests/proxied/proxy-header.test.ts +0 -239
  299. package/tests/proxied/proxy-oauth-aud.test.ts +0 -182
  300. package/tests/proxied/read-after-write.test.ts +0 -382
  301. package/tests/proxied/views.test.ts +0 -608
  302. package/tests/races.test.ts +0 -89
  303. package/tests/rate-limits.test.ts +0 -70
  304. package/tests/recovery.test.ts +0 -180
  305. package/tests/seeds/basic.ts +0 -165
  306. package/tests/seeds/follows.ts +0 -57
  307. package/tests/seeds/likes.ts +0 -14
  308. package/tests/seeds/reposts.ts +0 -18
  309. package/tests/seeds/thread.ts +0 -40
  310. package/tests/seeds/users-bulk.ts +0 -246
  311. package/tests/seeds/users.ts +0 -67
  312. package/tests/sequencer.test.ts +0 -251
  313. package/tests/server.test.ts +0 -151
  314. package/tests/sync/invertible-ops.test.ts +0 -99
  315. package/tests/sync/list.test.ts +0 -43
  316. package/tests/sync/subscribe-repos.test.ts +0 -672
  317. package/tests/sync/sync.test.ts +0 -316
  318. package/tests/takedown-appeal.test.ts +0 -166
  319. package/tsconfig.build.json +0 -9
  320. package/tsconfig.build.tsbuildinfo +0 -1
  321. package/tsconfig.json +0 -7
  322. 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
- }