@atproto/bsky 0.0.141 → 0.0.143

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 (85) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/api/app/bsky/graph/getSuggestedFollowsByActor.js +2 -2
  3. package/dist/api/app/bsky/graph/getSuggestedFollowsByActor.js.map +1 -1
  4. package/dist/data-plane/server/db/database-schema.d.ts +2 -1
  5. package/dist/data-plane/server/db/database-schema.d.ts.map +1 -1
  6. package/dist/data-plane/server/db/migrations/20250404T163421487Z-verifications.d.ts +4 -0
  7. package/dist/data-plane/server/db/migrations/20250404T163421487Z-verifications.d.ts.map +1 -0
  8. package/dist/data-plane/server/db/migrations/20250404T163421487Z-verifications.js +36 -0
  9. package/dist/data-plane/server/db/migrations/20250404T163421487Z-verifications.js.map +1 -0
  10. package/dist/data-plane/server/db/migrations/index.d.ts +1 -0
  11. package/dist/data-plane/server/db/migrations/index.d.ts.map +1 -1
  12. package/dist/data-plane/server/db/migrations/index.js +2 -1
  13. package/dist/data-plane/server/db/migrations/index.js.map +1 -1
  14. package/dist/data-plane/server/db/tables/actor.d.ts +2 -0
  15. package/dist/data-plane/server/db/tables/actor.d.ts.map +1 -1
  16. package/dist/data-plane/server/db/tables/actor.js.map +1 -1
  17. package/dist/data-plane/server/db/tables/verification.d.ts +18 -0
  18. package/dist/data-plane/server/db/tables/verification.d.ts.map +1 -0
  19. package/dist/data-plane/server/db/tables/verification.js +5 -0
  20. package/dist/data-plane/server/db/tables/verification.js.map +1 -0
  21. package/dist/data-plane/server/indexing/index.d.ts +2 -0
  22. package/dist/data-plane/server/indexing/index.d.ts.map +1 -1
  23. package/dist/data-plane/server/indexing/index.js +2 -0
  24. package/dist/data-plane/server/indexing/index.js.map +1 -1
  25. package/dist/data-plane/server/indexing/plugins/verification.d.ts +11 -0
  26. package/dist/data-plane/server/indexing/plugins/verification.d.ts.map +1 -0
  27. package/dist/data-plane/server/indexing/plugins/verification.js +95 -0
  28. package/dist/data-plane/server/indexing/plugins/verification.js.map +1 -0
  29. package/dist/data-plane/server/routes/profile.d.ts.map +1 -1
  30. package/dist/data-plane/server/routes/profile.js +28 -1
  31. package/dist/data-plane/server/routes/profile.js.map +1 -1
  32. package/dist/data-plane/server/util.d.ts +6 -6
  33. package/dist/hydration/actor.d.ts +11 -0
  34. package/dist/hydration/actor.d.ts.map +1 -1
  35. package/dist/hydration/actor.js +19 -0
  36. package/dist/hydration/actor.js.map +1 -1
  37. package/dist/hydration/label.d.ts +1 -0
  38. package/dist/hydration/label.d.ts.map +1 -1
  39. package/dist/hydration/label.js +7 -0
  40. package/dist/hydration/label.js.map +1 -1
  41. package/dist/lexicon/lexicons.d.ts +160 -2
  42. package/dist/lexicon/lexicons.d.ts.map +1 -1
  43. package/dist/lexicon/lexicons.js +80 -0
  44. package/dist/lexicon/lexicons.js.map +1 -1
  45. package/dist/lexicon/types/app/bsky/actor/defs.d.ts +38 -1
  46. package/dist/lexicon/types/app/bsky/actor/defs.d.ts.map +1 -1
  47. package/dist/lexicon/types/app/bsky/actor/defs.js +27 -0
  48. package/dist/lexicon/types/app/bsky/actor/defs.js.map +1 -1
  49. package/dist/lexicon/types/chat/bsky/actor/defs.d.ts +1 -0
  50. package/dist/lexicon/types/chat/bsky/actor/defs.d.ts.map +1 -1
  51. package/dist/lexicon/types/chat/bsky/actor/defs.js.map +1 -1
  52. package/dist/proto/bsky_connect.d.ts +30 -1
  53. package/dist/proto/bsky_connect.d.ts.map +1 -1
  54. package/dist/proto/bsky_connect.js +29 -0
  55. package/dist/proto/bsky_connect.js.map +1 -1
  56. package/dist/proto/bsky_pb.d.ts +243 -0
  57. package/dist/proto/bsky_pb.d.ts.map +1 -1
  58. package/dist/proto/bsky_pb.js +733 -5
  59. package/dist/proto/bsky_pb.js.map +1 -1
  60. package/dist/views/index.d.ts +2 -1
  61. package/dist/views/index.d.ts.map +1 -1
  62. package/dist/views/index.js +42 -0
  63. package/dist/views/index.js.map +1 -1
  64. package/package.json +4 -4
  65. package/proto/bsky.proto +67 -0
  66. package/src/api/app/bsky/graph/getSuggestedFollowsByActor.ts +2 -2
  67. package/src/data-plane/server/db/database-schema.ts +3 -1
  68. package/src/data-plane/server/db/migrations/20250404T163421487Z-verifications.ts +39 -0
  69. package/src/data-plane/server/db/migrations/index.ts +1 -0
  70. package/src/data-plane/server/db/tables/actor.ts +3 -0
  71. package/src/data-plane/server/db/tables/verification.ts +20 -0
  72. package/src/data-plane/server/indexing/index.ts +8 -2
  73. package/src/data-plane/server/indexing/plugins/verification.ts +96 -0
  74. package/src/data-plane/server/routes/profile.ts +63 -19
  75. package/src/hydration/actor.ts +38 -0
  76. package/src/hydration/label.ts +12 -0
  77. package/src/lexicon/lexicons.ts +84 -0
  78. package/src/lexicon/types/app/bsky/actor/defs.ts +65 -0
  79. package/src/lexicon/types/chat/bsky/actor/defs.ts +1 -0
  80. package/src/proto/bsky_connect.ts +35 -0
  81. package/src/proto/bsky_pb.ts +676 -0
  82. package/src/views/index.ts +60 -1
  83. package/tests/views/verification.test.ts +301 -0
  84. package/tsconfig.build.tsbuildinfo +1 -1
  85. package/tsconfig.tests.tsbuildinfo +1 -1
@@ -0,0 +1,96 @@
1
+ import { Selectable } from 'kysely'
2
+ import { CID } from 'multiformats/cid'
3
+ import { AtUri, normalizeDatetimeAlways } from '@atproto/syntax'
4
+ import * as lex from '../../../../lexicon/lexicons'
5
+ import * as Verification from '../../../../lexicon/types/app/bsky/graph/verification'
6
+ import { BackgroundQueue } from '../../background'
7
+ import { Database } from '../../db'
8
+ import { DatabaseSchema, DatabaseSchemaType } from '../../db/database-schema'
9
+ import { RecordProcessor } from '../processor'
10
+
11
+ const lexId = lex.ids.AppBskyGraphVerification
12
+ type IndexedVerification = Selectable<DatabaseSchemaType['verification']>
13
+
14
+ const insertFn = async (
15
+ db: DatabaseSchema,
16
+ uri: AtUri,
17
+ cid: CID,
18
+ obj: Verification.Record,
19
+ timestamp: string,
20
+ ): Promise<IndexedVerification | null> => {
21
+ const inserted = await db
22
+ .insertInto('verification')
23
+ .values({
24
+ uri: uri.toString(),
25
+ cid: cid.toString(),
26
+ rkey: uri.rkey,
27
+ creator: uri.host,
28
+ subject: obj.subject,
29
+ handle: obj.handle,
30
+ displayName: obj.displayName,
31
+ createdAt: normalizeDatetimeAlways(obj.createdAt),
32
+ indexedAt: timestamp,
33
+ })
34
+ .onConflict((oc) => oc.doNothing())
35
+ .returningAll()
36
+ .executeTakeFirst()
37
+ return inserted || null
38
+ }
39
+
40
+ const findDuplicate = async (
41
+ db: DatabaseSchema,
42
+ uri: AtUri,
43
+ obj: Verification.Record,
44
+ ): Promise<AtUri | null> => {
45
+ const found = await db
46
+ .selectFrom('verification')
47
+ .where('subject', '=', obj.subject)
48
+ .where('creator', '=', uri.host)
49
+ .selectAll()
50
+ .executeTakeFirst()
51
+ return found ? new AtUri(found.uri) : null
52
+ }
53
+
54
+ const notifsForInsert = (_obj: IndexedVerification) => {
55
+ return []
56
+ }
57
+
58
+ const deleteFn = async (
59
+ db: DatabaseSchema,
60
+ uri: AtUri,
61
+ ): Promise<IndexedVerification | null> => {
62
+ const deleted = await db
63
+ .deleteFrom('verification')
64
+ .where('uri', '=', uri.toString())
65
+ .returningAll()
66
+ .executeTakeFirst()
67
+ return deleted || null
68
+ }
69
+
70
+ const notifsForDelete = (
71
+ _deleted: IndexedVerification,
72
+ _replacedBy: IndexedVerification | null,
73
+ ) => {
74
+ return { notifs: [], toDelete: [] }
75
+ }
76
+
77
+ export type PluginType = RecordProcessor<
78
+ Verification.Record,
79
+ IndexedVerification
80
+ >
81
+
82
+ export const makePlugin = (
83
+ db: Database,
84
+ background: BackgroundQueue,
85
+ ): PluginType => {
86
+ return new RecordProcessor(db, background, {
87
+ lexId,
88
+ insertFn,
89
+ findDuplicate,
90
+ deleteFn,
91
+ notifsForInsert,
92
+ notifsForDelete,
93
+ })
94
+ }
95
+
96
+ export default makePlugin
@@ -1,11 +1,21 @@
1
+ import { Timestamp } from '@bufbuild/protobuf'
1
2
  import { ServiceImpl } from '@connectrpc/connect'
2
- import { sql } from 'kysely'
3
+ import { Selectable, sql } from 'kysely'
3
4
  import { keyBy } from '@atproto/common'
4
5
  import { parseRecordBytes } from '../../../hydration/util'
5
6
  import { Service } from '../../../proto/bsky_connect'
7
+ import { VerificationMeta } from '../../../proto/bsky_pb'
6
8
  import { Database } from '../db'
9
+ import { Verification } from '../db/tables/verification'
7
10
  import { getRecords } from './records'
8
11
 
12
+ type VerifiedBy = {
13
+ [handle: string]: Pick<
14
+ VerificationMeta,
15
+ 'rkey' | 'handle' | 'displayName' | 'sortedAt'
16
+ >
17
+ }
18
+
9
19
  export default (db: Database): Partial<ServiceImpl<typeof Service>> => ({
10
20
  async getActors(req) {
11
21
  const { dids } = req
@@ -19,30 +29,62 @@ export default (db: Database): Partial<ServiceImpl<typeof Service>> => ({
19
29
  (did) => `at://${did}/chat.bsky.actor.declaration/self`,
20
30
  )
21
31
  const { ref } = db.db.dynamic
22
- const [handlesRes, profiles, chatDeclarations] = await Promise.all([
23
- db.db
24
- .selectFrom('actor')
25
- .leftJoin('actor_state', 'actor_state.did', 'actor.did')
26
- .where('actor.did', 'in', dids)
27
- .selectAll('actor')
28
- .select('actor_state.priorityNotifs')
29
- .select([
30
- db.db
31
- .selectFrom('labeler')
32
- .whereRef('creator', '=', ref('actor.did'))
33
- .select(sql<true>`${true}`.as('val'))
34
- .as('isLabeler'),
35
- ])
36
- .execute(),
37
- getRecords(db)({ uris: profileUris }),
38
- getRecords(db)({ uris: chatDeclarationUris }),
39
- ])
32
+ const [handlesRes, verificationsReceived, profiles, chatDeclarations] =
33
+ await Promise.all([
34
+ db.db
35
+ .selectFrom('actor')
36
+ .leftJoin('actor_state', 'actor_state.did', 'actor.did')
37
+ .where('actor.did', 'in', dids)
38
+ .selectAll('actor')
39
+ .select('actor_state.priorityNotifs')
40
+ .select([
41
+ db.db
42
+ .selectFrom('labeler')
43
+ .whereRef('creator', '=', ref('actor.did'))
44
+ .select(sql<true>`${true}`.as('val'))
45
+ .as('isLabeler'),
46
+ ])
47
+ .execute(),
48
+ db.db
49
+ .selectFrom('verification')
50
+ .selectAll('verification')
51
+ .innerJoin('actor', 'actor.did', 'verification.creator')
52
+ .where('verification.subject', 'in', dids)
53
+ .where('actor.trustedVerifier', '=', true)
54
+ .orderBy('sortedAt', 'asc')
55
+ .execute(),
56
+ getRecords(db)({ uris: profileUris }),
57
+ getRecords(db)({ uris: chatDeclarationUris }),
58
+ ])
59
+
60
+ const verificationsBySubjectDid = verificationsReceived.reduce(
61
+ (acc, cur) => {
62
+ const list = acc.get(cur.subject) ?? []
63
+ list.push(cur)
64
+ acc.set(cur.subject, list)
65
+ return acc
66
+ },
67
+ new Map<string, Selectable<Verification>[]>(),
68
+ )
69
+
40
70
  const byDid = keyBy(handlesRes, 'did')
41
71
  const actors = dids.map((did, i) => {
42
72
  const row = byDid.get(did)
43
73
  const chatDeclaration = parseRecordBytes(
44
74
  chatDeclarations.records[i].record,
45
75
  )
76
+
77
+ const verifications = verificationsBySubjectDid.get(did) ?? []
78
+ const verifiedBy: VerifiedBy = verifications.reduce((acc, cur) => {
79
+ acc[cur.creator] = {
80
+ rkey: cur.rkey,
81
+ handle: cur.handle,
82
+ displayName: cur.displayName,
83
+ sortedAt: Timestamp.fromDate(new Date(cur.sortedAt)),
84
+ }
85
+ return acc
86
+ }, {} as VerifiedBy)
87
+
46
88
  return {
47
89
  exists: !!row,
48
90
  handle: row?.handle ?? undefined,
@@ -58,6 +100,8 @@ export default (db: Database): Partial<ServiceImpl<typeof Service>> => ({
58
100
  upstreamStatus: row?.upstreamStatus ?? '',
59
101
  createdAt: profiles.records[i].createdAt, // @NOTE profile creation date not trusted in production
60
102
  priorityNotifications: row?.priorityNotifs ?? false,
103
+ trustedVerifier: row?.trustedVerifier ?? false,
104
+ verifiedBy,
61
105
  }
62
106
  })
63
107
  return { actors }
@@ -1,6 +1,8 @@
1
+ import { mapDefined } from '@atproto/common'
1
2
  import { DataPlaneClient } from '../data-plane/client'
2
3
  import { Record as ProfileRecord } from '../lexicon/types/app/bsky/actor/profile'
3
4
  import { Record as ChatDeclarationRecord } from '../lexicon/types/chat/bsky/actor/declaration'
5
+ import { VerificationMeta } from '../proto/bsky_pb'
4
6
  import {
5
7
  HydrationMap,
6
8
  RecordInfo,
@@ -23,8 +25,20 @@ export type Actor = {
23
25
  upstreamStatus?: string
24
26
  createdAt?: Date
25
27
  priorityNotifications: boolean
28
+ trustedVerifier?: boolean
29
+ verifications: VerificationHydrationState[]
26
30
  }
27
31
 
32
+ export type VerificationHydrationState = {
33
+ issuer: string
34
+ uri: string
35
+ handle: string
36
+ displayName: string
37
+ createdAt: string
38
+ }
39
+
40
+ export type VerificationMetaRequired = Required<VerificationMeta>
41
+
28
42
  export type Actors = HydrationMap<Actor>
29
43
 
30
44
  export type ChatDeclaration = RecordInfo<ChatDeclarationRecord>
@@ -127,6 +141,28 @@ export class ActorHydrator {
127
141
  ? parseRecord<ProfileRecord>(actor.profile, includeTakedowns)
128
142
  : undefined
129
143
 
144
+ const verifications = mapDefined(
145
+ Object.entries(actor.verifiedBy),
146
+ ([actorDid, verificationMeta]) => {
147
+ if (
148
+ verificationMeta.displayName &&
149
+ verificationMeta.handle &&
150
+ verificationMeta.rkey &&
151
+ verificationMeta.sortedAt
152
+ ) {
153
+ return {
154
+ issuer: actorDid,
155
+ uri: `at://${actorDid}/app.bsky.graph.verification/${verificationMeta.rkey}`,
156
+ handle: verificationMeta.handle,
157
+ displayName: verificationMeta.displayName,
158
+ createdAt: verificationMeta.sortedAt.toDate().toISOString(),
159
+ }
160
+ }
161
+ // Filter out the verification meta that doesn't contain all info.
162
+ return undefined
163
+ },
164
+ )
165
+
130
166
  return acc.set(did, {
131
167
  did,
132
168
  handle: parseString(actor.handle),
@@ -141,6 +177,8 @@ export class ActorHydrator {
141
177
  upstreamStatus: actor.upstreamStatus || undefined,
142
178
  createdAt: actor.createdAt?.toDate(),
143
179
  priorityNotifications: actor.priorityNotifications,
180
+ trustedVerifier: actor.trustedVerifier,
181
+ verifications,
144
182
  })
145
183
  }, new HydrationMap<Actor>())
146
184
  }
@@ -16,6 +16,7 @@ import {
16
16
  export type { Label } from '../lexicon/types/com/atproto/label/defs'
17
17
 
18
18
  export type SubjectLabels = {
19
+ isImpersonation: boolean
19
20
  isTakendown: boolean
20
21
  needsReview: boolean
21
22
  labels: HydrationMap<Label> // src + val -> label
@@ -84,12 +85,14 @@ export class LabelHydrator {
84
85
  let entry = acc.get(label.uri)
85
86
  if (!entry) {
86
87
  entry = {
88
+ isImpersonation: false,
87
89
  isTakendown: false,
88
90
  needsReview: false,
89
91
  labels: new HydrationMap(),
90
92
  }
91
93
  acc.set(label.uri, entry)
92
94
  }
95
+
93
96
  const isActionableNeedsReview =
94
97
  label.val === NEEDS_REVIEW_LABEL &&
95
98
  !label.neg &&
@@ -110,6 +113,14 @@ export class LabelHydrator {
110
113
  if (isActionableNeedsReview) {
111
114
  entry.needsReview = true
112
115
  }
116
+ if (
117
+ label.val === IMPERSONATION_LABEL &&
118
+ !label.neg &&
119
+ labelers.redact.has(label.src)
120
+ ) {
121
+ entry.isImpersonation = true
122
+ }
123
+
113
124
  return acc
114
125
  }, new Labels())
115
126
  }
@@ -160,5 +171,6 @@ const labelerDidToUri = (did: string): string => {
160
171
  return AtUri.make(did, ids.AppBskyLabelerService, 'self').toString()
161
172
  }
162
173
 
174
+ const IMPERSONATION_LABEL = 'impersonation'
163
175
  const TAKEDOWN_LABELS = ['!takedown', '!suspend']
164
176
  const NEEDS_REVIEW_LABEL = 'needs-review'
@@ -4564,6 +4564,10 @@ export const schemaDict = {
4564
4564
  type: 'string',
4565
4565
  format: 'datetime',
4566
4566
  },
4567
+ verification: {
4568
+ type: 'ref',
4569
+ ref: 'lex:app.bsky.actor.defs#verificationState',
4570
+ },
4567
4571
  },
4568
4572
  },
4569
4573
  profileView: {
@@ -4615,6 +4619,10 @@ export const schemaDict = {
4615
4619
  ref: 'lex:com.atproto.label.defs#label',
4616
4620
  },
4617
4621
  },
4622
+ verification: {
4623
+ type: 'ref',
4624
+ ref: 'lex:app.bsky.actor.defs#verificationState',
4625
+ },
4618
4626
  },
4619
4627
  },
4620
4628
  profileViewDetailed: {
@@ -4687,6 +4695,10 @@ export const schemaDict = {
4687
4695
  type: 'ref',
4688
4696
  ref: 'lex:com.atproto.repo.strongRef',
4689
4697
  },
4698
+ verification: {
4699
+ type: 'ref',
4700
+ ref: 'lex:app.bsky.actor.defs#verificationState',
4701
+ },
4690
4702
  },
4691
4703
  },
4692
4704
  profileAssociated: {
@@ -4776,6 +4788,60 @@ export const schemaDict = {
4776
4788
  },
4777
4789
  },
4778
4790
  },
4791
+ verificationState: {
4792
+ type: 'object',
4793
+ description:
4794
+ 'Represents the verification information about the user this object is attached to.',
4795
+ required: ['verifications', 'verifiedStatus', 'trustedVerifierStatus'],
4796
+ properties: {
4797
+ verifications: {
4798
+ type: 'array',
4799
+ description:
4800
+ 'All verifications issued by trusted verifiers on behalf of this user. Verifications by untrusted verifiers are not included.',
4801
+ items: {
4802
+ type: 'ref',
4803
+ ref: 'lex:app.bsky.actor.defs#verificationView',
4804
+ },
4805
+ },
4806
+ verifiedStatus: {
4807
+ type: 'string',
4808
+ description: "The user's status as a verified account.",
4809
+ knownValues: ['valid', 'invalid', 'none'],
4810
+ },
4811
+ trustedVerifierStatus: {
4812
+ type: 'string',
4813
+ description: "The user's status as a trusted verifier.",
4814
+ knownValues: ['valid', 'invalid', 'none'],
4815
+ },
4816
+ },
4817
+ },
4818
+ verificationView: {
4819
+ type: 'object',
4820
+ description: 'An individual verification for an associated subject.',
4821
+ required: ['issuer', 'uri', 'isValid', 'createdAt'],
4822
+ properties: {
4823
+ issuer: {
4824
+ type: 'string',
4825
+ description: 'The user who issued this verification.',
4826
+ format: 'did',
4827
+ },
4828
+ uri: {
4829
+ type: 'string',
4830
+ description: 'The AT-URI of the verification record.',
4831
+ format: 'at-uri',
4832
+ },
4833
+ isValid: {
4834
+ type: 'boolean',
4835
+ description:
4836
+ 'True if the verification passes validation, otherwise false.',
4837
+ },
4838
+ createdAt: {
4839
+ type: 'string',
4840
+ description: 'Timestamp when the verification was created.',
4841
+ format: 'datetime',
4842
+ },
4843
+ },
4844
+ },
4779
4845
  preferences: {
4780
4846
  type: 'array',
4781
4847
  items: {
@@ -4794,6 +4860,7 @@ export const schemaDict = {
4794
4860
  'lex:app.bsky.actor.defs#bskyAppStatePref',
4795
4861
  'lex:app.bsky.actor.defs#labelersPref',
4796
4862
  'lex:app.bsky.actor.defs#postInteractionSettingsPref',
4863
+ 'lex:app.bsky.actor.defs#verificationPrefs',
4797
4864
  ],
4798
4865
  },
4799
4866
  },
@@ -5127,6 +5194,19 @@ export const schemaDict = {
5127
5194
  },
5128
5195
  },
5129
5196
  },
5197
+ verificationPrefs: {
5198
+ type: 'object',
5199
+ description: 'Preferences for how verified accounts appear in the app.',
5200
+ required: [],
5201
+ properties: {
5202
+ hideBadges: {
5203
+ description:
5204
+ 'Hide the blue check badges for verified accounts and trusted verifiers.',
5205
+ type: 'boolean',
5206
+ default: false,
5207
+ },
5208
+ },
5209
+ },
5130
5210
  postInteractionSettingsPref: {
5131
5211
  type: 'object',
5132
5212
  description:
@@ -11014,6 +11094,10 @@ export const schemaDict = {
11014
11094
  description:
11015
11095
  'Set to true when the actor cannot actively participate in converations',
11016
11096
  },
11097
+ verification: {
11098
+ type: 'ref',
11099
+ ref: 'lex:app.bsky.actor.defs#verificationState',
11100
+ },
11017
11101
  },
11018
11102
  },
11019
11103
  },
@@ -29,6 +29,7 @@ export interface ProfileViewBasic {
29
29
  viewer?: ViewerState
30
30
  labels?: ComAtprotoLabelDefs.Label[]
31
31
  createdAt?: string
32
+ verification?: VerificationState
32
33
  }
33
34
 
34
35
  const hashProfileViewBasic = 'profileViewBasic'
@@ -53,6 +54,7 @@ export interface ProfileView {
53
54
  createdAt?: string
54
55
  viewer?: ViewerState
55
56
  labels?: ComAtprotoLabelDefs.Label[]
57
+ verification?: VerificationState
56
58
  }
57
59
 
58
60
  const hashProfileView = 'profileView'
@@ -83,6 +85,7 @@ export interface ProfileViewDetailed {
83
85
  viewer?: ViewerState
84
86
  labels?: ComAtprotoLabelDefs.Label[]
85
87
  pinnedPost?: ComAtprotoRepoStrongRef.Main
88
+ verification?: VerificationState
86
89
  }
87
90
 
88
91
  const hashProfileViewDetailed = 'profileViewDetailed'
@@ -169,6 +172,50 @@ export function validateKnownFollowers<V>(v: V) {
169
172
  return validate<KnownFollowers & V>(v, id, hashKnownFollowers)
170
173
  }
171
174
 
175
+ /** Represents the verification information about the user this object is attached to. */
176
+ export interface VerificationState {
177
+ $type?: 'app.bsky.actor.defs#verificationState'
178
+ /** All verifications issued by trusted verifiers on behalf of this user. Verifications by untrusted verifiers are not included. */
179
+ verifications: VerificationView[]
180
+ /** The user's status as a verified account. */
181
+ verifiedStatus: 'valid' | 'invalid' | 'none' | (string & {})
182
+ /** The user's status as a trusted verifier. */
183
+ trustedVerifierStatus: 'valid' | 'invalid' | 'none' | (string & {})
184
+ }
185
+
186
+ const hashVerificationState = 'verificationState'
187
+
188
+ export function isVerificationState<V>(v: V) {
189
+ return is$typed(v, id, hashVerificationState)
190
+ }
191
+
192
+ export function validateVerificationState<V>(v: V) {
193
+ return validate<VerificationState & V>(v, id, hashVerificationState)
194
+ }
195
+
196
+ /** An individual verification for an associated subject. */
197
+ export interface VerificationView {
198
+ $type?: 'app.bsky.actor.defs#verificationView'
199
+ /** The user who issued this verification. */
200
+ issuer: string
201
+ /** The AT-URI of the verification record. */
202
+ uri: string
203
+ /** True if the verification passes validation, otherwise false. */
204
+ isValid: boolean
205
+ /** Timestamp when the verification was created. */
206
+ createdAt: string
207
+ }
208
+
209
+ const hashVerificationView = 'verificationView'
210
+
211
+ export function isVerificationView<V>(v: V) {
212
+ return is$typed(v, id, hashVerificationView)
213
+ }
214
+
215
+ export function validateVerificationView<V>(v: V) {
216
+ return validate<VerificationView & V>(v, id, hashVerificationView)
217
+ }
218
+
172
219
  export type Preferences = (
173
220
  | $Typed<AdultContentPref>
174
221
  | $Typed<ContentLabelPref>
@@ -183,6 +230,7 @@ export type Preferences = (
183
230
  | $Typed<BskyAppStatePref>
184
231
  | $Typed<LabelersPref>
185
232
  | $Typed<PostInteractionSettingsPref>
233
+ | $Typed<VerificationPrefs>
186
234
  | { $type: string }
187
235
  )[]
188
236
 
@@ -496,6 +544,23 @@ export function validateNux<V>(v: V) {
496
544
  return validate<Nux & V>(v, id, hashNux)
497
545
  }
498
546
 
547
+ /** Preferences for how verified accounts appear in the app. */
548
+ export interface VerificationPrefs {
549
+ $type?: 'app.bsky.actor.defs#verificationPrefs'
550
+ /** Hide the blue check badges for verified accounts and trusted verifiers. */
551
+ hideBadges: boolean
552
+ }
553
+
554
+ const hashVerificationPrefs = 'verificationPrefs'
555
+
556
+ export function isVerificationPrefs<V>(v: V) {
557
+ return is$typed(v, id, hashVerificationPrefs)
558
+ }
559
+
560
+ export function validateVerificationPrefs<V>(v: V) {
561
+ return validate<VerificationPrefs & V>(v, id, hashVerificationPrefs)
562
+ }
563
+
499
564
  /** Default post interaction settings for the account. These values should be applied as default values when creating new posts. These refs should mirror the threadgate and postgate records exactly. */
500
565
  export interface PostInteractionSettingsPref {
501
566
  $type?: 'app.bsky.actor.defs#postInteractionSettingsPref'
@@ -27,6 +27,7 @@ export interface ProfileViewBasic {
27
27
  labels?: ComAtprotoLabelDefs.Label[]
28
28
  /** Set to true when the actor cannot actively participate in converations */
29
29
  chatDisabled?: boolean
30
+ verification?: AppBskyActorDefs.VerificationState
30
31
  }
31
32
 
32
33
  const hashProfileViewBasic = 'profileViewBasic'
@@ -168,6 +168,12 @@ import {
168
168
  GetTimelineResponse,
169
169
  GetUnreadNotificationCountRequest,
170
170
  GetUnreadNotificationCountResponse,
171
+ GetVerificationRecordsRequest,
172
+ GetVerificationRecordsResponse,
173
+ GetVerificationsIssuedRequest,
174
+ GetVerificationsIssuedResponse,
175
+ GetVerificationsReceivedRequest,
176
+ GetVerificationsReceivedResponse,
171
177
  PingRequest,
172
178
  PingResponse,
173
179
  SearchActorsRequest,
@@ -373,6 +379,35 @@ export const Service = {
373
379
  O: GetFollowsResponse,
374
380
  kind: MethodKind.Unary,
375
381
  },
382
+ /**
383
+ * Verifications
384
+ *
385
+ * @generated from rpc bsky.Service.GetVerificationRecords
386
+ */
387
+ getVerificationRecords: {
388
+ name: 'GetVerificationRecords',
389
+ I: GetVerificationRecordsRequest,
390
+ O: GetVerificationRecordsResponse,
391
+ kind: MethodKind.Unary,
392
+ },
393
+ /**
394
+ * @generated from rpc bsky.Service.GetVerificationsIssued
395
+ */
396
+ getVerificationsIssued: {
397
+ name: 'GetVerificationsIssued',
398
+ I: GetVerificationsIssuedRequest,
399
+ O: GetVerificationsIssuedResponse,
400
+ kind: MethodKind.Unary,
401
+ },
402
+ /**
403
+ * @generated from rpc bsky.Service.GetVerificationsReceived
404
+ */
405
+ getVerificationsReceived: {
406
+ name: 'GetVerificationsReceived',
407
+ I: GetVerificationsReceivedRequest,
408
+ O: GetVerificationsReceivedResponse,
409
+ kind: MethodKind.Unary,
410
+ },
376
411
  /**
377
412
  * Likes
378
413
  *