@atproto/bsky 0.0.10 → 0.0.12

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 (173) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/api/com/atproto/admin/util.d.ts +5 -0
  3. package/dist/config.d.ts +2 -0
  4. package/dist/context.d.ts +8 -0
  5. package/dist/db/index.js +51 -2
  6. package/dist/db/index.js.map +3 -3
  7. package/dist/db/migrations/20230929T192920807Z-record-cursor-indexes.d.ts +3 -0
  8. package/dist/db/migrations/index.d.ts +1 -0
  9. package/dist/did-cache.d.ts +2 -2
  10. package/dist/index.d.ts +2 -0
  11. package/dist/index.js +1818 -580
  12. package/dist/index.js.map +3 -3
  13. package/dist/lexicon/index.d.ts +16 -0
  14. package/dist/lexicon/lexicons.d.ts +330 -3
  15. package/dist/lexicon/types/app/bsky/actor/defs.d.ts +1 -0
  16. package/dist/lexicon/types/com/atproto/admin/defs.d.ts +28 -0
  17. package/dist/lexicon/types/com/atproto/admin/getAccountInfo.d.ts +29 -0
  18. package/dist/lexicon/types/com/atproto/admin/getSubjectStatus.d.ts +39 -0
  19. package/dist/lexicon/types/com/atproto/admin/searchRepos.d.ts +0 -1
  20. package/dist/lexicon/types/com/atproto/admin/updateSubjectStatus.d.ts +46 -0
  21. package/dist/lexicon/types/com/atproto/server/confirmEmail.d.ts +27 -0
  22. package/dist/lexicon/types/com/atproto/server/createAccount.d.ts +2 -0
  23. package/dist/lexicon/types/com/atproto/server/createSession.d.ts +2 -0
  24. package/dist/lexicon/types/com/atproto/server/getSession.d.ts +1 -0
  25. package/dist/lexicon/types/com/atproto/server/refreshSession.d.ts +1 -0
  26. package/dist/lexicon/types/com/atproto/server/requestEmailConfirmation.d.ts +19 -0
  27. package/dist/lexicon/types/com/atproto/server/requestEmailUpdate.d.ts +30 -0
  28. package/dist/lexicon/types/com/atproto/server/reserveSigningKey.d.ts +30 -0
  29. package/dist/lexicon/types/com/atproto/server/updateEmail.d.ts +27 -0
  30. package/dist/lexicon/types/com/atproto/sync/listRepos.d.ts +1 -0
  31. package/dist/services/actor/index.d.ts +2 -2
  32. package/dist/services/actor/types.d.ts +1 -0
  33. package/dist/services/graph/index.d.ts +2 -0
  34. package/dist/services/moderation/index.d.ts +13 -3
  35. package/dist/services/util/search.d.ts +3 -3
  36. package/package.json +13 -14
  37. package/src/api/app/bsky/actor/searchActors.ts +36 -22
  38. package/src/api/app/bsky/actor/searchActorsTypeahead.ts +24 -17
  39. package/src/api/app/bsky/feed/getAuthorFeed.ts +2 -2
  40. package/src/api/app/bsky/feed/getPostThread.ts +2 -2
  41. package/src/api/app/bsky/graph/getSuggestedFollowsByActor.ts +1 -0
  42. package/src/api/app/bsky/notification/listNotifications.ts +33 -22
  43. package/src/api/com/atproto/admin/getModerationAction.ts +28 -2
  44. package/src/api/com/atproto/admin/getModerationReport.ts +27 -2
  45. package/src/api/com/atproto/admin/getRecord.ts +14 -2
  46. package/src/api/com/atproto/admin/getRepo.ts +13 -2
  47. package/src/api/com/atproto/admin/reverseModerationAction.ts +31 -5
  48. package/src/api/com/atproto/admin/searchRepos.ts +6 -12
  49. package/src/api/com/atproto/admin/takeModerationAction.ts +41 -7
  50. package/src/api/com/atproto/admin/util.ts +50 -0
  51. package/src/api/well-known.ts +8 -0
  52. package/src/auth.ts +12 -5
  53. package/src/auto-moderator/index.ts +1 -0
  54. package/src/config.ts +7 -0
  55. package/src/context.ts +30 -0
  56. package/src/db/migrations/20230929T192920807Z-record-cursor-indexes.ts +40 -0
  57. package/src/db/migrations/index.ts +1 -0
  58. package/src/did-cache.ts +29 -14
  59. package/src/feed-gen/with-friends.ts +2 -2
  60. package/src/index.ts +9 -1
  61. package/src/indexer/subscription.ts +1 -21
  62. package/src/lexicon/index.ts +96 -0
  63. package/src/lexicon/lexicons.ts +368 -4
  64. package/src/lexicon/types/app/bsky/actor/defs.ts +1 -0
  65. package/src/lexicon/types/com/atproto/admin/defs.ts +61 -0
  66. package/src/lexicon/types/com/atproto/admin/getAccountInfo.ts +41 -0
  67. package/src/lexicon/types/com/atproto/admin/getSubjectStatus.ts +54 -0
  68. package/src/lexicon/types/com/atproto/admin/searchRepos.ts +0 -1
  69. package/src/lexicon/types/com/atproto/admin/updateSubjectStatus.ts +61 -0
  70. package/src/lexicon/types/com/atproto/server/confirmEmail.ts +40 -0
  71. package/src/lexicon/types/com/atproto/server/createAccount.ts +2 -0
  72. package/src/lexicon/types/com/atproto/server/createSession.ts +2 -0
  73. package/src/lexicon/types/com/atproto/server/getSession.ts +1 -0
  74. package/src/lexicon/types/com/atproto/server/refreshSession.ts +1 -0
  75. package/src/lexicon/types/com/atproto/server/requestEmailConfirmation.ts +31 -0
  76. package/src/lexicon/types/com/atproto/server/requestEmailUpdate.ts +43 -0
  77. package/src/lexicon/types/com/atproto/server/reserveSigningKey.ts +44 -0
  78. package/src/lexicon/types/com/atproto/server/updateEmail.ts +41 -0
  79. package/src/lexicon/types/com/atproto/sync/listRepos.ts +1 -0
  80. package/src/logger.ts +8 -0
  81. package/src/services/actor/index.ts +16 -10
  82. package/src/services/actor/types.ts +1 -0
  83. package/src/services/actor/views.ts +26 -8
  84. package/src/services/graph/index.ts +26 -7
  85. package/src/services/indexing/index.ts +15 -17
  86. package/src/services/moderation/index.ts +94 -14
  87. package/src/services/moderation/views.ts +1 -0
  88. package/src/services/util/search.ts +24 -23
  89. package/tests/__snapshots__/feed-generation.test.ts.snap +12 -12
  90. package/tests/__snapshots__/indexing.test.ts.snap +4 -4
  91. package/tests/admin/__snapshots__/get-moderation-action.test.ts.snap +172 -0
  92. package/tests/admin/__snapshots__/get-moderation-actions.test.ts.snap +178 -0
  93. package/tests/admin/__snapshots__/get-moderation-report.test.ts.snap +177 -0
  94. package/tests/admin/__snapshots__/get-moderation-reports.test.ts.snap +307 -0
  95. package/tests/admin/__snapshots__/get-record.test.ts.snap +275 -0
  96. package/tests/admin/__snapshots__/get-repo.test.ts.snap +103 -0
  97. package/tests/admin/get-moderation-action.test.ts +100 -0
  98. package/tests/admin/get-moderation-actions.test.ts +164 -0
  99. package/tests/admin/get-moderation-report.test.ts +100 -0
  100. package/tests/admin/get-moderation-reports.test.ts +332 -0
  101. package/tests/admin/get-record.test.ts +115 -0
  102. package/tests/admin/get-repo.test.ts +101 -0
  103. package/tests/{moderation.test.ts → admin/moderation.test.ts} +107 -9
  104. package/tests/admin/repo-search.test.ts +124 -0
  105. package/tests/algos/hot-classic.test.ts +3 -5
  106. package/tests/algos/whats-hot.test.ts +3 -5
  107. package/tests/algos/with-friends.test.ts +2 -4
  108. package/tests/auth.test.ts +64 -0
  109. package/tests/auto-moderator/fuzzy-matcher.test.ts +2 -3
  110. package/tests/auto-moderator/labeler.test.ts +5 -7
  111. package/tests/auto-moderator/takedowns.test.ts +11 -12
  112. package/tests/blob-resolver.test.ts +1 -3
  113. package/tests/did-cache.test.ts +2 -5
  114. package/tests/feed-generation.test.ts +8 -6
  115. package/tests/handle-invalidation.test.ts +2 -3
  116. package/tests/image/server.test.ts +1 -4
  117. package/tests/image/sharp.test.ts +1 -1
  118. package/tests/indexing.test.ts +4 -4
  119. package/tests/notification-server.test.ts +2 -3
  120. package/tests/pipeline/backpressure.test.ts +2 -3
  121. package/tests/pipeline/reingest.test.ts +7 -4
  122. package/tests/pipeline/repartition.test.ts +2 -3
  123. package/tests/reprocessing.test.ts +2 -6
  124. package/tests/seeds/basic.ts +4 -4
  125. package/tests/seeds/follows.ts +1 -1
  126. package/tests/seeds/likes.ts +1 -1
  127. package/tests/seeds/reposts.ts +1 -1
  128. package/tests/seeds/users-bulk.ts +1 -1
  129. package/tests/seeds/users.ts +1 -1
  130. package/tests/server.test.ts +1 -3
  131. package/tests/subscription/repo.test.ts +2 -4
  132. package/tests/views/__snapshots__/author-feed.test.ts.snap +24 -24
  133. package/tests/views/__snapshots__/block-lists.test.ts.snap +42 -7
  134. package/tests/views/__snapshots__/blocks.test.ts.snap +2 -2
  135. package/tests/views/__snapshots__/list-feed.test.ts.snap +6 -6
  136. package/tests/views/__snapshots__/mute-lists.test.ts.snap +15 -4
  137. package/tests/views/__snapshots__/mutes.test.ts.snap +2 -2
  138. package/tests/views/__snapshots__/notifications.test.ts.snap +2 -2
  139. package/tests/views/__snapshots__/posts.test.ts.snap +8 -8
  140. package/tests/views/__snapshots__/thread.test.ts.snap +10 -10
  141. package/tests/views/__snapshots__/timeline.test.ts.snap +58 -58
  142. package/tests/views/actor-likes.test.ts +2 -3
  143. package/tests/views/actor-search.test.ts +5 -5
  144. package/tests/views/admin/repo-search.test.ts +2 -4
  145. package/tests/views/author-feed.test.ts +2 -4
  146. package/tests/views/block-lists.test.ts +34 -7
  147. package/tests/views/blocks.test.ts +6 -3
  148. package/tests/views/follows.test.ts +2 -4
  149. package/tests/views/likes.test.ts +2 -5
  150. package/tests/views/list-feed.test.ts +2 -4
  151. package/tests/views/mute-lists.test.ts +23 -5
  152. package/tests/views/mutes.test.ts +2 -5
  153. package/tests/views/notifications.test.ts +2 -4
  154. package/tests/views/posts.test.ts +2 -5
  155. package/tests/views/profile.test.ts +4 -5
  156. package/tests/views/reposts.test.ts +2 -4
  157. package/tests/views/suggested-follows.test.ts +2 -3
  158. package/tests/views/suggestions.test.ts +2 -4
  159. package/tests/views/thread.test.ts +2 -4
  160. package/tests/views/threadgating.test.ts +2 -3
  161. package/tests/views/timeline.test.ts +2 -4
  162. package/dist/env.d.ts +0 -1
  163. package/example.dev.env +0 -5
  164. package/src/env.ts +0 -9
  165. package/tests/seeds/client.ts +0 -466
  166. /package/tests/{__snapshots__ → admin/__snapshots__}/moderation.test.ts.snap +0 -0
  167. /package/tests/{image/fixtures → sample-img}/at.png +0 -0
  168. /package/tests/{image/fixtures → sample-img}/hd-key.jpg +0 -0
  169. /package/tests/{image/fixtures → sample-img}/key-alt.jpg +0 -0
  170. /package/tests/{image/fixtures → sample-img}/key-landscape-large.jpg +0 -0
  171. /package/tests/{image/fixtures → sample-img}/key-landscape-small.jpg +0 -0
  172. /package/tests/{image/fixtures → sample-img}/key-portrait-large.jpg +0 -0
  173. /package/tests/{image/fixtures → sample-img}/key-portrait-small.jpg +0 -0
@@ -1,25 +1,25 @@
1
- import { TestNetwork } from '@atproto/dev-env'
1
+ import { TestNetwork, ImageRef, RecordRef, SeedClient } from '@atproto/dev-env'
2
2
  import { TID, cidForCbor } from '@atproto/common'
3
3
  import AtpAgent, { ComAtprotoAdminTakeModerationAction } from '@atproto/api'
4
4
  import { AtUri } from '@atproto/syntax'
5
- import { forSnapshot } from './_util'
6
- import { ImageRef, RecordRef, SeedClient } from './seeds/client'
7
- import basicSeed from './seeds/basic'
5
+ import { forSnapshot } from '../_util'
6
+ import basicSeed from '../seeds/basic'
8
7
  import {
9
8
  ACKNOWLEDGE,
10
9
  ESCALATE,
11
10
  FLAG,
12
11
  TAKEDOWN,
13
- } from '../src/lexicon/types/com/atproto/admin/defs'
12
+ } from '../../src/lexicon/types/com/atproto/admin/defs'
14
13
  import {
15
14
  REASONOTHER,
16
15
  REASONSPAM,
17
- } from '../src/lexicon/types/com/atproto/moderation/defs'
18
- import { PeriodicModerationActionReversal } from '../src'
16
+ } from '../../src/lexicon/types/com/atproto/moderation/defs'
17
+ import { PeriodicModerationActionReversal } from '../../src'
19
18
 
20
19
  describe('moderation', () => {
21
20
  let network: TestNetwork
22
21
  let agent: AtpAgent
22
+ let pdsAgent: AtpAgent
23
23
  let sc: SeedClient
24
24
 
25
25
  beforeAll(async () => {
@@ -27,8 +27,8 @@ describe('moderation', () => {
27
27
  dbPostgresSchema: 'bsky_moderation',
28
28
  })
29
29
  agent = network.bsky.getClient()
30
- const pdsAgent = network.pds.getClient()
31
- sc = new SeedClient(pdsAgent)
30
+ pdsAgent = network.pds.getClient()
31
+ sc = network.getSeedClient()
32
32
  await basicSeed(sc)
33
33
  await network.processAll()
34
34
  })
@@ -962,6 +962,82 @@ describe('moderation', () => {
962
962
  )
963
963
  })
964
964
 
965
+ it('fans out repo takedowns to pds', async () => {
966
+ const { data: action } =
967
+ await agent.api.com.atproto.admin.takeModerationAction(
968
+ {
969
+ action: TAKEDOWN,
970
+ createdBy: 'did:example:moderator',
971
+ reason: 'Y',
972
+ subject: {
973
+ $type: 'com.atproto.admin.defs#repoRef',
974
+ did: sc.dids.bob,
975
+ },
976
+ },
977
+ {
978
+ encoding: 'application/json',
979
+ headers: network.bsky.adminAuthHeaders(),
980
+ },
981
+ )
982
+
983
+ const res1 = await pdsAgent.api.com.atproto.admin.getSubjectStatus(
984
+ {
985
+ did: sc.dids.bob,
986
+ },
987
+ { headers: network.pds.adminAuthHeaders() },
988
+ )
989
+ expect(res1.data.takedown?.applied).toBe(true)
990
+
991
+ // cleanup
992
+ await reverse(action.id)
993
+
994
+ const res2 = await pdsAgent.api.com.atproto.admin.getSubjectStatus(
995
+ {
996
+ did: sc.dids.bob,
997
+ },
998
+ { headers: network.pds.adminAuthHeaders() },
999
+ )
1000
+ expect(res2.data.takedown?.applied).toBe(false)
1001
+ })
1002
+
1003
+ it('fans out record takedowns to pds', async () => {
1004
+ const post = sc.posts[sc.dids.bob][0]
1005
+ const uri = post.ref.uriStr
1006
+ const cid = post.ref.cidStr
1007
+ const { data: action } =
1008
+ await agent.api.com.atproto.admin.takeModerationAction(
1009
+ {
1010
+ action: TAKEDOWN,
1011
+ createdBy: 'did:example:moderator',
1012
+ reason: 'Y',
1013
+ subject: {
1014
+ $type: 'com.atproto.repo.strongRef',
1015
+ uri,
1016
+ cid,
1017
+ },
1018
+ },
1019
+ {
1020
+ encoding: 'application/json',
1021
+ headers: network.bsky.adminAuthHeaders(),
1022
+ },
1023
+ )
1024
+
1025
+ const res1 = await pdsAgent.api.com.atproto.admin.getSubjectStatus(
1026
+ { uri },
1027
+ { headers: network.pds.adminAuthHeaders() },
1028
+ )
1029
+ expect(res1.data.takedown?.applied).toBe(true)
1030
+
1031
+ // cleanup
1032
+ await reverse(action.id)
1033
+
1034
+ const res2 = await pdsAgent.api.com.atproto.admin.getSubjectStatus(
1035
+ { uri },
1036
+ { headers: network.pds.adminAuthHeaders() },
1037
+ )
1038
+ expect(res2.data.takedown?.applied).toBe(false)
1039
+ })
1040
+
965
1041
  it('allows full moderators to takedown.', async () => {
966
1042
  const { data: action } =
967
1043
  await agent.api.com.atproto.admin.takeModerationAction(
@@ -1161,6 +1237,17 @@ describe('moderation', () => {
1161
1237
  expect(await fetchImage.json()).toEqual({ message: 'Image not found' })
1162
1238
  })
1163
1239
 
1240
+ it('fans takedown out to pds', async () => {
1241
+ const res = await pdsAgent.api.com.atproto.admin.getSubjectStatus(
1242
+ {
1243
+ did: sc.dids.carol,
1244
+ blob: blob.image.ref.toString(),
1245
+ },
1246
+ { headers: network.pds.adminAuthHeaders() },
1247
+ )
1248
+ expect(res.data.takedown?.applied).toBe(true)
1249
+ })
1250
+
1164
1251
  it('restores blob when action is reversed.', async () => {
1165
1252
  await agent.api.com.atproto.admin.reverseModerationAction(
1166
1253
  {
@@ -1185,5 +1272,16 @@ describe('moderation', () => {
1185
1272
  const size = Number(fetchImage.headers.get('content-length'))
1186
1273
  expect(size).toBeGreaterThan(9000)
1187
1274
  })
1275
+
1276
+ it('fans reversal out to pds', async () => {
1277
+ const res = await pdsAgent.api.com.atproto.admin.getSubjectStatus(
1278
+ {
1279
+ did: sc.dids.carol,
1280
+ blob: blob.image.ref.toString(),
1281
+ },
1282
+ { headers: network.pds.adminAuthHeaders() },
1283
+ )
1284
+ expect(res.data.takedown?.applied).toBe(false)
1285
+ })
1188
1286
  })
1189
1287
  })
@@ -0,0 +1,124 @@
1
+ import { SeedClient, TestNetwork } from '@atproto/dev-env'
2
+ import AtpAgent from '@atproto/api'
3
+ import { TAKEDOWN } from '@atproto/api/src/client/types/com/atproto/admin/defs'
4
+ import { paginateAll } from '../_util'
5
+ import usersBulkSeed from '../seeds/users-bulk'
6
+
7
+ describe('admin repo search view', () => {
8
+ let network: TestNetwork
9
+ let agent: AtpAgent
10
+ let sc: SeedClient
11
+ let headers: { [s: string]: string }
12
+
13
+ beforeAll(async () => {
14
+ network = await TestNetwork.create({
15
+ dbPostgresSchema: 'views_admin_repo_search',
16
+ })
17
+ agent = network.pds.getClient()
18
+ sc = network.getSeedClient()
19
+ await usersBulkSeed(sc)
20
+ headers = network.pds.adminAuthHeaders()
21
+ })
22
+
23
+ afterAll(async () => {
24
+ await network.close()
25
+ })
26
+
27
+ beforeAll(async () => {
28
+ await sc.takeModerationAction({
29
+ action: TAKEDOWN,
30
+ subject: {
31
+ $type: 'com.atproto.admin.defs#repoRef',
32
+ did: sc.dids['cara-wiegand69.test'],
33
+ },
34
+ })
35
+ })
36
+
37
+ it('gives relevant results', async () => {
38
+ const result = await agent.api.com.atproto.admin.searchRepos(
39
+ { term: 'car' },
40
+ { headers },
41
+ )
42
+
43
+ const handles = result.data.repos.map((u) => u.handle)
44
+
45
+ const shouldContain = [
46
+ 'cara-wiegand69.test', // Present despite repo takedown
47
+ 'carlos6.test',
48
+ 'carolina-mcdermott77.test',
49
+ ]
50
+
51
+ shouldContain.forEach((handle) => expect(handles).toContain(handle))
52
+
53
+ const shouldNotContain = [
54
+ 'sven70.test',
55
+ 'hilario84.test',
56
+ 'santa-hermann78.test',
57
+ 'dylan61.test',
58
+ 'preston-harris.test',
59
+ 'loyce95.test',
60
+ 'melyna-zboncak.test',
61
+ ]
62
+
63
+ shouldNotContain.forEach((handle) => expect(handles).not.toContain(handle))
64
+ })
65
+
66
+ it('finds repo by did', async () => {
67
+ const term = sc.dids['cara-wiegand69.test']
68
+ const res = await agent.api.com.atproto.admin.searchRepos(
69
+ { term },
70
+ { headers },
71
+ )
72
+
73
+ expect(res.data.repos.length).toEqual(1)
74
+ expect(res.data.repos[0].did).toEqual(term)
75
+ })
76
+
77
+ it('paginates with term', async () => {
78
+ const results = (results) => results.flatMap((res) => res.users)
79
+ const paginator = async (cursor?: string) => {
80
+ const res = await agent.api.com.atproto.admin.searchRepos(
81
+ { term: 'p', cursor, limit: 3 },
82
+ { headers },
83
+ )
84
+ return res.data
85
+ }
86
+
87
+ const paginatedAll = await paginateAll(paginator)
88
+ paginatedAll.forEach((res) =>
89
+ expect(res.repos.length).toBeLessThanOrEqual(3),
90
+ )
91
+
92
+ const full = await agent.api.com.atproto.admin.searchRepos(
93
+ { term: 'p' },
94
+ { headers },
95
+ )
96
+
97
+ expect(full.data.repos.length).toBeGreaterThan(3)
98
+ expect(results(paginatedAll)).toEqual(results([full.data]))
99
+ })
100
+
101
+ it('paginates without term', async () => {
102
+ const results = (results) => results.flatMap((res) => res.repos)
103
+ const paginator = async (cursor?: string) => {
104
+ const res = await agent.api.com.atproto.admin.searchRepos(
105
+ { cursor, limit: 3 },
106
+ { headers },
107
+ )
108
+ return res.data
109
+ }
110
+
111
+ const paginatedAll = await paginateAll(paginator, 5)
112
+ paginatedAll.forEach((res) =>
113
+ expect(res.repos.length).toBeLessThanOrEqual(3),
114
+ )
115
+
116
+ const full = await agent.api.com.atproto.admin.searchRepos(
117
+ { limit: 15 },
118
+ { headers },
119
+ )
120
+
121
+ expect(full.data.repos.length).toEqual(15)
122
+ expect(results(paginatedAll)).toEqual(results([full.data]))
123
+ })
124
+ })
@@ -1,8 +1,7 @@
1
1
  import AtpAgent, { AtUri } from '@atproto/api'
2
- import { SeedClient } from '../seeds/client'
2
+ import { TestNetwork, SeedClient } from '@atproto/dev-env'
3
3
  import basicSeed from '../seeds/basic'
4
4
  import { makeAlgos } from '../../src'
5
- import { TestNetwork } from '@atproto/dev-env'
6
5
 
7
6
  describe('algo hot-classic', () => {
8
7
  let network: TestNetwork
@@ -26,8 +25,7 @@ describe('algo hot-classic', () => {
26
25
  bsky: { algos: makeAlgos(feedPublisherDid) },
27
26
  })
28
27
  agent = new AtpAgent({ service: network.bsky.url })
29
- const pdsAgent = new AtpAgent({ service: network.pds.url })
30
- sc = new SeedClient(pdsAgent)
28
+ sc = network.getSeedClient()
31
29
  await basicSeed(sc)
32
30
 
33
31
  alice = sc.dids.alice
@@ -43,7 +41,7 @@ describe('algo hot-classic', () => {
43
41
  it('returns well liked posts', async () => {
44
42
  const img = await sc.uploadFile(
45
43
  alice,
46
- 'tests/image/fixtures/key-landscape-small.jpg',
44
+ 'tests/sample-img/key-landscape-small.jpg',
47
45
  'image/jpeg',
48
46
  )
49
47
  const one = await sc.post(alice, 'first post', undefined, [img])
@@ -1,9 +1,8 @@
1
1
  import { HOUR } from '@atproto/common'
2
2
  import AtpAgent, { AtUri } from '@atproto/api'
3
- import { SeedClient } from '../seeds/client'
3
+ import { TestNetwork, SeedClient } from '@atproto/dev-env'
4
4
  import basicSeed from '../seeds/basic'
5
5
  import { makeAlgos } from '../../src'
6
- import { TestNetwork } from '@atproto/dev-env'
7
6
 
8
7
  describe.skip('algo whats-hot', () => {
9
8
  let network: TestNetwork
@@ -28,8 +27,7 @@ describe.skip('algo whats-hot', () => {
28
27
  bsky: { algos: makeAlgos(feedPublisherDid) },
29
28
  })
30
29
  agent = new AtpAgent({ service: network.bsky.url })
31
- const pdsAgent = new AtpAgent({ service: network.pds.url })
32
- sc = new SeedClient(pdsAgent)
30
+ sc = network.getSeedClient()
33
31
  await basicSeed(sc)
34
32
 
35
33
  alice = sc.dids.alice
@@ -46,7 +44,7 @@ describe.skip('algo whats-hot', () => {
46
44
  it('returns well liked posts', async () => {
47
45
  const img = await sc.uploadFile(
48
46
  alice,
49
- 'tests/image/fixtures/key-landscape-small.jpg',
47
+ 'tests/sample-img/key-landscape-small.jpg',
50
48
  'image/jpeg',
51
49
  )
52
50
  const one = await sc.post(carol, 'carol is in the chat')
@@ -1,8 +1,7 @@
1
1
  import AtpAgent, { AtUri } from '@atproto/api'
2
- import { RecordRef, SeedClient } from '../seeds/client'
3
2
  import userSeed from '../seeds/users'
4
3
  import { makeAlgos } from '../../src'
5
- import { TestNetwork } from '@atproto/dev-env'
4
+ import { TestNetwork, SeedClient, RecordRef } from '@atproto/dev-env'
6
5
 
7
6
  describe.skip('algo with friends', () => {
8
7
  let network: TestNetwork
@@ -28,8 +27,7 @@ describe.skip('algo with friends', () => {
28
27
  bsky: { algos: makeAlgos(feedPublisherDid) },
29
28
  })
30
29
  agent = new AtpAgent({ service: network.bsky.url })
31
- const pdsAgent = new AtpAgent({ service: network.pds.url })
32
- sc = new SeedClient(pdsAgent)
30
+ sc = network.getSeedClient()
33
31
  await userSeed(sc)
34
32
 
35
33
  alice = sc.dids.alice
@@ -0,0 +1,64 @@
1
+ import AtpAgent from '@atproto/api'
2
+ import { SeedClient, TestNetwork } from '@atproto/dev-env'
3
+ import usersSeed from './seeds/users'
4
+ import { createServiceJwt } from '@atproto/xrpc-server'
5
+ import { Keypair, Secp256k1Keypair } from '@atproto/crypto'
6
+
7
+ describe('auth', () => {
8
+ let network: TestNetwork
9
+ let agent: AtpAgent
10
+ let sc: SeedClient
11
+
12
+ beforeAll(async () => {
13
+ network = await TestNetwork.create({
14
+ dbPostgresSchema: 'bsky_auth',
15
+ })
16
+ agent = network.bsky.getClient()
17
+ sc = network.getSeedClient()
18
+ await usersSeed(sc)
19
+ await network.processAll()
20
+ })
21
+
22
+ afterAll(async () => {
23
+ await network.close()
24
+ })
25
+
26
+ it('handles signing key change for service auth.', async () => {
27
+ const issuer = sc.dids.alice
28
+ const attemptWithKey = async (keypair: Keypair) => {
29
+ const jwt = await createServiceJwt({
30
+ iss: issuer,
31
+ aud: network.bsky.ctx.cfg.serverDid,
32
+ keypair,
33
+ })
34
+ return agent.api.app.bsky.actor.getProfile(
35
+ { actor: sc.dids.carol },
36
+ { headers: { authorization: `Bearer ${jwt}` } },
37
+ )
38
+ }
39
+ const origSigningKey = network.pds.ctx.repoSigningKey
40
+ const newSigningKey = await Secp256k1Keypair.create({ exportable: true })
41
+ // confirm original signing key works
42
+ await expect(attemptWithKey(origSigningKey)).resolves.toBeDefined()
43
+ // confirm next signing key doesn't work yet
44
+ await expect(attemptWithKey(newSigningKey)).rejects.toThrow(
45
+ 'jwt signature does not match jwt issuer',
46
+ )
47
+ // update to new signing key
48
+ await network.plc
49
+ .getClient()
50
+ .updateAtprotoKey(
51
+ issuer,
52
+ network.pds.ctx.plcRotationKey,
53
+ newSigningKey.did(),
54
+ )
55
+ // old signing key still works due to did doc cache
56
+ await expect(attemptWithKey(origSigningKey)).resolves.toBeDefined()
57
+ // new signing key works
58
+ await expect(attemptWithKey(newSigningKey)).resolves.toBeDefined()
59
+ // old signing key no longer works after cache is updated
60
+ await expect(attemptWithKey(origSigningKey)).rejects.toThrow(
61
+ 'jwt signature does not match jwt issuer',
62
+ )
63
+ })
64
+ })
@@ -1,6 +1,5 @@
1
+ import { TestNetwork, SeedClient } from '@atproto/dev-env'
1
2
  import { FuzzyMatcher, encode } from '../../src/auto-moderator/fuzzy-matcher'
2
- import { TestNetwork } from '@atproto/dev-env'
3
- import { SeedClient } from '../seeds/client'
4
3
  import basicSeed from '../seeds/basic'
5
4
  import { AtpAgent } from '@atproto/api'
6
5
  import { ImageInvalidator } from '../../src/image/invalidator'
@@ -25,7 +24,7 @@ describe('fuzzy matcher', () => {
25
24
  })
26
25
  fuzzyMatcher = new FuzzyMatcher(['evil', 'mean', 'bad'], ['baddie'])
27
26
  agent = network.pds.getClient()
28
- sc = new SeedClient(agent)
27
+ sc = network.getSeedClient()
29
28
  await basicSeed(sc)
30
29
  await network.processAll()
31
30
  alice = sc.dids.alice
@@ -1,12 +1,11 @@
1
- import { AtUri, AtpAgent, BlobRef } from '@atproto/api'
1
+ import { TestNetwork } from '@atproto/dev-env'
2
+ import { AtUri, BlobRef } from '@atproto/api'
2
3
  import { Readable } from 'stream'
3
4
  import { AutoModerator } from '../../src/auto-moderator'
4
5
  import IndexerContext from '../../src/indexer/context'
5
6
  import { cidForRecord } from '@atproto/repo'
6
- import { cidForCbor, TID } from '@atproto/common'
7
+ import { TID } from '@atproto/common'
7
8
  import { LabelService } from '../../src/services/label'
8
- import { TestNetwork } from '@atproto/dev-env'
9
- import { SeedClient } from '../seeds/client'
10
9
  import usersSeed from '../seeds/users'
11
10
  import { CID } from 'multiformats/cid'
12
11
  import { ImgLabeler } from '../../src/auto-moderator/hive'
@@ -37,8 +36,7 @@ describe('labeler', () => {
37
36
  autoMod = ctx.autoMod
38
37
  autoMod.imgLabeler = new TestImgLabeler()
39
38
  labelSrvc = ctx.services.label(ctx.db)
40
- const pdsAgent = new AtpAgent({ service: network.pds.url })
41
- const sc = new SeedClient(pdsAgent)
39
+ const sc = network.getSeedClient()
42
40
  await usersSeed(sc)
43
41
  await network.processAll()
44
42
  alice = sc.dids.alice
@@ -58,7 +56,7 @@ describe('labeler', () => {
58
56
  await repoSvc.blobs.associateBlob(
59
57
  preparedBlobRef,
60
58
  postUri(),
61
- await cidForCbor(1),
59
+ TID.nextStr(),
62
60
  alice,
63
61
  )
64
62
  return blobRef
@@ -1,10 +1,9 @@
1
1
  import fs from 'fs/promises'
2
+ import { TestNetwork, SeedClient, ImageRef } from '@atproto/dev-env'
2
3
  import { AtpAgent } from '@atproto/api'
3
4
  import { AutoModerator } from '../../src/auto-moderator'
4
5
  import IndexerContext from '../../src/indexer/context'
5
6
  import { sha256RawToCid } from '@atproto/common'
6
- import { TestNetwork } from '@atproto/dev-env'
7
- import { ImageRef, SeedClient } from '../seeds/client'
8
7
  import usersSeed from '../seeds/users'
9
8
  import { CID } from 'multiformats/cid'
10
9
  import { AtUri } from '@atproto/syntax'
@@ -41,31 +40,31 @@ describe('takedowner', () => {
41
40
  autoMod = ctx.autoMod
42
41
  autoMod.imageFlagger = new TestFlagger()
43
42
  pdsAgent = new AtpAgent({ service: network.pds.url })
44
- sc = new SeedClient(pdsAgent)
43
+ sc = network.getSeedClient()
45
44
  await usersSeed(sc)
46
45
  await network.processAll()
47
46
  alice = sc.dids.alice
48
47
  const fileBytes1 = await fs.readFile(
49
- 'tests/image/fixtures/key-portrait-small.jpg',
48
+ 'tests/sample-img/key-portrait-small.jpg',
50
49
  )
51
50
  const fileBytes2 = await fs.readFile(
52
- 'tests/image/fixtures/key-portrait-large.jpg',
51
+ 'tests/sample-img/key-portrait-large.jpg',
53
52
  )
54
53
  badCid1 = sha256RawToCid(await sha256(fileBytes1))
55
54
  badCid2 = sha256RawToCid(await sha256(fileBytes2))
56
55
  goodBlob = await sc.uploadFile(
57
56
  alice,
58
- 'tests/image/fixtures/key-landscape-small.jpg',
57
+ 'tests/sample-img/key-landscape-small.jpg',
59
58
  'image/jpeg',
60
59
  )
61
60
  badBlob1 = await sc.uploadFile(
62
61
  alice,
63
- 'tests/image/fixtures/key-portrait-small.jpg',
62
+ 'tests/sample-img/key-portrait-small.jpg',
64
63
  'image/jpeg',
65
64
  )
66
65
  badBlob2 = await sc.uploadFile(
67
66
  alice,
68
- 'tests/image/fixtures/key-portrait-large.jpg',
67
+ 'tests/sample-img/key-portrait-large.jpg',
69
68
  'image/jpeg',
70
69
  )
71
70
  })
@@ -97,9 +96,9 @@ describe('takedowner', () => {
97
96
  const recordPds = await network.pds.ctx.db.db
98
97
  .selectFrom('record')
99
98
  .where('uri', '=', post.ref.uriStr)
100
- .select('takedownId')
99
+ .select('takedownRef')
101
100
  .executeTakeFirst()
102
- expect(recordPds?.takedownId).toEqual(modAction.id)
101
+ expect(recordPds?.takedownRef).toEqual(modAction.id.toString())
103
102
 
104
103
  expect(testInvalidator.invalidated.length).toBe(1)
105
104
  expect(testInvalidator.invalidated[0].subject).toBe(
@@ -139,9 +138,9 @@ describe('takedowner', () => {
139
138
  const recordPds = await network.pds.ctx.db.db
140
139
  .selectFrom('record')
141
140
  .where('uri', '=', res.data.uri)
142
- .select('takedownId')
141
+ .select('takedownRef')
143
142
  .executeTakeFirst()
144
- expect(recordPds?.takedownId).toEqual(modAction.id)
143
+ expect(recordPds?.takedownRef).toEqual(modAction.id.toString())
145
144
 
146
145
  expect(testInvalidator.invalidated.length).toBe(2)
147
146
  expect(testInvalidator.invalidated[1].subject).toBe(
@@ -2,7 +2,6 @@ import axios, { AxiosInstance } from 'axios'
2
2
  import { CID } from 'multiformats/cid'
3
3
  import { verifyCidForBytes } from '@atproto/common'
4
4
  import { TestNetwork } from '@atproto/dev-env'
5
- import { SeedClient } from './seeds/client'
6
5
  import basicSeed from './seeds/basic'
7
6
  import { randomBytes } from '@atproto/crypto'
8
7
 
@@ -16,8 +15,7 @@ describe('blob resolver', () => {
16
15
  network = await TestNetwork.create({
17
16
  dbPostgresSchema: 'bsky_blob_resolver',
18
17
  })
19
- const pdsAgent = network.pds.getClient()
20
- const sc = new SeedClient(pdsAgent)
18
+ const sc = network.getSeedClient()
21
19
  await basicSeed(sc)
22
20
  await network.processAll()
23
21
  await network.bsky.processAll()
@@ -1,6 +1,4 @@
1
- import AtpAgent from '@atproto/api'
2
- import { TestNetwork } from '@atproto/dev-env'
3
- import { SeedClient } from './seeds/client'
1
+ import { TestNetwork, SeedClient } from '@atproto/dev-env'
4
2
  import userSeed from './seeds/users'
5
3
  import { IdResolver } from '@atproto/identity'
6
4
  import DidSqlCache from '../src/did-cache'
@@ -23,8 +21,7 @@ describe('did cache', () => {
23
21
  })
24
22
  idResolver = network.bsky.indexer.ctx.idResolver
25
23
  didCache = network.bsky.indexer.ctx.didCache
26
- const pdsAgent = new AtpAgent({ service: network.pds.url })
27
- sc = new SeedClient(pdsAgent)
24
+ sc = network.getSeedClient()
28
25
  await userSeed(sc)
29
26
  await network.processAll()
30
27
  alice = sc.dids.alice
@@ -1,8 +1,12 @@
1
1
  import { TID } from '@atproto/common'
2
2
  import { AtUri, AtpAgent } from '@atproto/api'
3
- import { TestNetwork } from '@atproto/dev-env'
4
- import { TestFeedGen } from '@atproto/dev-env/src/feed-gen'
5
- import { Handler as SkeletonHandler } from '@atproto/bsky/src/lexicon/types/app/bsky/feed/getFeedSkeleton'
3
+ import {
4
+ TestNetwork,
5
+ TestFeedGen,
6
+ SeedClient,
7
+ RecordRef,
8
+ } from '@atproto/dev-env'
9
+ import { Handler as SkeletonHandler } from '../src/lexicon/types/app/bsky/feed/getFeedSkeleton'
6
10
  import { GeneratorView } from '@atproto/api/src/client/types/app/bsky/feed/defs'
7
11
  import { UnknownFeedError } from '@atproto/api/src/client/types/app/bsky/feed/getFeed'
8
12
  import { TAKEDOWN } from '@atproto/api/src/client/types/com/atproto/admin/defs'
@@ -11,9 +15,7 @@ import {
11
15
  FeedViewPost,
12
16
  SkeletonFeedPost,
13
17
  } from '../src/lexicon/types/app/bsky/feed/defs'
14
- import { SeedClient } from './seeds/client'
15
18
  import basicSeed from './seeds/basic'
16
- import { RecordRef } from './seeds/client'
17
19
  import { forSnapshot, paginateAll } from './_util'
18
20
 
19
21
  describe('feed generation', () => {
@@ -38,7 +40,7 @@ describe('feed generation', () => {
38
40
  })
39
41
  agent = network.bsky.getClient()
40
42
  pdsAgent = network.pds.getClient()
41
- sc = new SeedClient(pdsAgent)
43
+ sc = network.getSeedClient()
42
44
  await basicSeed(sc)
43
45
  await network.processAll()
44
46
  alice = sc.dids.alice
@@ -1,7 +1,6 @@
1
1
  import { DAY } from '@atproto/common'
2
- import { TestNetwork } from '@atproto/dev-env'
2
+ import { TestNetwork, SeedClient } from '@atproto/dev-env'
3
3
  import { AtpAgent } from '@atproto/api'
4
- import { SeedClient } from './seeds/client'
5
4
  import userSeed from './seeds/users'
6
5
 
7
6
  describe('handle invalidation', () => {
@@ -20,7 +19,7 @@ describe('handle invalidation', () => {
20
19
  })
21
20
  agent = network.bsky.getClient()
22
21
  pdsAgent = network.pds.getClient()
23
- sc = new SeedClient(pdsAgent)
22
+ sc = network.getSeedClient()
24
23
  await userSeed(sc)
25
24
  await network.processAll()
26
25
 
@@ -1,10 +1,8 @@
1
1
  import axios, { AxiosInstance } from 'axios'
2
2
  import { CID } from 'multiformats/cid'
3
- import { AtpAgent } from '@atproto/api'
4
3
  import { cidForCbor } from '@atproto/common'
5
4
  import { TestNetwork } from '@atproto/dev-env'
6
5
  import { getInfo } from '../../src/image/sharp'
7
- import { SeedClient } from '../seeds/client'
8
6
  import basicSeed from '../seeds/basic'
9
7
  import { ImageUriBuilder } from '../../src/image/uri'
10
8
 
@@ -18,8 +16,7 @@ describe('image processing server', () => {
18
16
  network = await TestNetwork.create({
19
17
  dbPostgresSchema: 'bsky_image_processing_server',
20
18
  })
21
- const pdsAgent = new AtpAgent({ service: network.pds.url })
22
- const sc = new SeedClient(pdsAgent)
19
+ const sc = network.getSeedClient()
23
20
  await basicSeed(sc)
24
21
  await network.processAll()
25
22
  await network.bsky.processAll()
@@ -178,7 +178,7 @@ describe('sharp image processor', () => {
178
178
  })
179
179
 
180
180
  async function processFixture(fixture: string, options: Options) {
181
- const image = createReadStream(`${__dirname}/fixtures/${fixture}`)
181
+ const image = createReadStream(`tests/sample-img/${fixture}`)
182
182
  const resized = await resize(image, options)
183
183
  return await getInfo(resized)
184
184
  }