@atproto/ozone 0.1.161 → 0.1.163

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 (87) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/LICENSE.txt +1 -1
  3. package/dist/daemon/materialized-view-refresher.d.ts.map +1 -1
  4. package/dist/daemon/materialized-view-refresher.js +8 -1
  5. package/dist/daemon/materialized-view-refresher.js.map +1 -1
  6. package/dist/lexicon/index.d.ts +13 -0
  7. package/dist/lexicon/index.d.ts.map +1 -1
  8. package/dist/lexicon/index.js +37 -1
  9. package/dist/lexicon/index.js.map +1 -1
  10. package/dist/lexicon/lexicons.d.ts +914 -12
  11. package/dist/lexicon/lexicons.d.ts.map +1 -1
  12. package/dist/lexicon/lexicons.js +474 -5
  13. package/dist/lexicon/lexicons.js.map +1 -1
  14. package/dist/lexicon/types/app/bsky/actor/defs.d.ts +23 -1
  15. package/dist/lexicon/types/app/bsky/actor/defs.d.ts.map +1 -1
  16. package/dist/lexicon/types/app/bsky/actor/defs.js +18 -0
  17. package/dist/lexicon/types/app/bsky/actor/defs.js.map +1 -1
  18. package/dist/lexicon/types/app/bsky/ageassurance/defs.d.ts +2 -0
  19. package/dist/lexicon/types/app/bsky/ageassurance/defs.d.ts.map +1 -1
  20. package/dist/lexicon/types/app/bsky/ageassurance/defs.js.map +1 -1
  21. package/dist/lexicon/types/app/bsky/draft/createDraft.d.ts +27 -0
  22. package/dist/lexicon/types/app/bsky/draft/createDraft.d.ts.map +1 -0
  23. package/dist/lexicon/types/app/bsky/draft/createDraft.js +7 -0
  24. package/dist/lexicon/types/app/bsky/draft/createDraft.js.map +1 -0
  25. package/dist/lexicon/types/app/bsky/draft/defs.d.ts +110 -0
  26. package/dist/lexicon/types/app/bsky/draft/defs.d.ts.map +1 -0
  27. package/dist/lexicon/types/app/bsky/draft/defs.js +97 -0
  28. package/dist/lexicon/types/app/bsky/draft/defs.js.map +1 -0
  29. package/dist/lexicon/types/app/bsky/draft/deleteDraft.d.ts +14 -0
  30. package/dist/lexicon/types/app/bsky/draft/deleteDraft.d.ts.map +1 -0
  31. package/dist/lexicon/types/app/bsky/draft/deleteDraft.js +7 -0
  32. package/dist/lexicon/types/app/bsky/draft/deleteDraft.js.map +1 -0
  33. package/dist/lexicon/types/app/bsky/draft/getDrafts.d.ts +24 -0
  34. package/dist/lexicon/types/app/bsky/draft/getDrafts.d.ts.map +1 -0
  35. package/dist/lexicon/types/app/bsky/draft/getDrafts.js +7 -0
  36. package/dist/lexicon/types/app/bsky/draft/getDrafts.js.map +1 -0
  37. package/dist/lexicon/types/app/bsky/draft/updateDraft.d.ts +15 -0
  38. package/dist/lexicon/types/app/bsky/draft/updateDraft.d.ts.map +1 -0
  39. package/dist/lexicon/types/app/bsky/draft/updateDraft.js +7 -0
  40. package/dist/lexicon/types/app/bsky/draft/updateDraft.js.map +1 -0
  41. package/dist/lexicon/types/app/bsky/embed/video.d.ts +4 -0
  42. package/dist/lexicon/types/app/bsky/embed/video.d.ts.map +1 -1
  43. package/dist/lexicon/types/app/bsky/embed/video.js.map +1 -1
  44. package/dist/lexicon/types/app/bsky/unspecced/getSuggestedUsers.d.ts +2 -0
  45. package/dist/lexicon/types/app/bsky/unspecced/getSuggestedUsers.d.ts.map +1 -1
  46. package/dist/lexicon/types/app/bsky/unspecced/getSuggestedUsers.js.map +1 -1
  47. package/dist/lexicon/types/app/bsky/unspecced/getSuggestedUsersSkeleton.d.ts +2 -0
  48. package/dist/lexicon/types/app/bsky/unspecced/getSuggestedUsersSkeleton.d.ts.map +1 -1
  49. package/dist/lexicon/types/app/bsky/unspecced/getSuggestedUsersSkeleton.js.map +1 -1
  50. package/dist/lexicon/types/com/atproto/server/deleteSession.d.ts +1 -0
  51. package/dist/lexicon/types/com/atproto/server/deleteSession.d.ts.map +1 -1
  52. package/dist/lexicon/types/com/atproto/server/deleteSession.js.map +1 -1
  53. package/dist/lexicon/types/com/atproto/server/getSession.d.ts +3 -3
  54. package/dist/lexicon/types/com/atproto/server/getSession.d.ts.map +1 -1
  55. package/dist/lexicon/types/com/atproto/server/getSession.js.map +1 -1
  56. package/dist/lexicon/types/com/atproto/server/refreshSession.d.ts +4 -1
  57. package/dist/lexicon/types/com/atproto/server/refreshSession.d.ts.map +1 -1
  58. package/dist/lexicon/types/com/atproto/server/refreshSession.js.map +1 -1
  59. package/dist/mod-service/util.d.ts.map +1 -1
  60. package/dist/mod-service/util.js +3 -1
  61. package/dist/mod-service/util.js.map +1 -1
  62. package/dist/verification/issuer.d.ts.map +1 -1
  63. package/dist/verification/issuer.js +9 -0
  64. package/dist/verification/issuer.js.map +1 -1
  65. package/package.json +8 -8
  66. package/src/daemon/materialized-view-refresher.ts +9 -3
  67. package/src/lexicon/index.ts +62 -0
  68. package/src/lexicon/lexicons.ts +491 -5
  69. package/src/lexicon/types/app/bsky/actor/defs.ts +41 -0
  70. package/src/lexicon/types/app/bsky/ageassurance/defs.ts +2 -0
  71. package/src/lexicon/types/app/bsky/draft/createDraft.ts +46 -0
  72. package/src/lexicon/types/app/bsky/draft/defs.ts +212 -0
  73. package/src/lexicon/types/app/bsky/draft/deleteDraft.ts +33 -0
  74. package/src/lexicon/types/app/bsky/draft/getDrafts.ts +42 -0
  75. package/src/lexicon/types/app/bsky/draft/updateDraft.ts +34 -0
  76. package/src/lexicon/types/app/bsky/embed/video.ts +4 -0
  77. package/src/lexicon/types/app/bsky/unspecced/getSuggestedUsers.ts +2 -0
  78. package/src/lexicon/types/app/bsky/unspecced/getSuggestedUsersSkeleton.ts +2 -0
  79. package/src/lexicon/types/com/atproto/server/deleteSession.ts +1 -0
  80. package/src/lexicon/types/com/atproto/server/getSession.ts +1 -1
  81. package/src/lexicon/types/com/atproto/server/refreshSession.ts +4 -1
  82. package/src/mod-service/util.ts +3 -2
  83. package/src/verification/issuer.ts +11 -0
  84. package/tests/query-labels.test.ts +0 -2
  85. package/tests/verification.test.ts +20 -0
  86. package/tsconfig.build.tsbuildinfo +1 -1
  87. package/tsconfig.tests.tsbuildinfo +0 -1
@@ -0,0 +1,46 @@
1
+ /**
2
+ * GENERATED CODE - DO NOT MODIFY
3
+ */
4
+ import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
+ import { CID } from 'multiformats/cid'
6
+ import { validate as _validate } from '../../../../lexicons'
7
+ import {
8
+ type $Typed,
9
+ is$typed as _is$typed,
10
+ type OmitKey,
11
+ } from '../../../../util'
12
+ import type * as AppBskyDraftDefs from './defs.js'
13
+
14
+ const is$typed = _is$typed,
15
+ validate = _validate
16
+ const id = 'app.bsky.draft.createDraft'
17
+
18
+ export type QueryParams = {}
19
+
20
+ export interface InputSchema {
21
+ draft: AppBskyDraftDefs.Draft
22
+ }
23
+
24
+ export interface OutputSchema {
25
+ /** The ID of the created draft. */
26
+ id: string
27
+ }
28
+
29
+ export interface HandlerInput {
30
+ encoding: 'application/json'
31
+ body: InputSchema
32
+ }
33
+
34
+ export interface HandlerSuccess {
35
+ encoding: 'application/json'
36
+ body: OutputSchema
37
+ headers?: { [key: string]: string }
38
+ }
39
+
40
+ export interface HandlerError {
41
+ status: number
42
+ message?: string
43
+ error?: 'DraftLimitReached'
44
+ }
45
+
46
+ export type HandlerOutput = HandlerError | HandlerSuccess
@@ -0,0 +1,212 @@
1
+ /**
2
+ * GENERATED CODE - DO NOT MODIFY
3
+ */
4
+ import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
+ import { CID } from 'multiformats/cid'
6
+ import { validate as _validate } from '../../../../lexicons'
7
+ import {
8
+ type $Typed,
9
+ is$typed as _is$typed,
10
+ type OmitKey,
11
+ } from '../../../../util'
12
+ import type * as AppBskyFeedPostgate from '../feed/postgate.js'
13
+ import type * as AppBskyFeedThreadgate from '../feed/threadgate.js'
14
+ import type * as ComAtprotoLabelDefs from '../../../com/atproto/label/defs.js'
15
+ import type * as ComAtprotoRepoStrongRef from '../../../com/atproto/repo/strongRef.js'
16
+
17
+ const is$typed = _is$typed,
18
+ validate = _validate
19
+ const id = 'app.bsky.draft.defs'
20
+
21
+ /** A draft with an identifier, used to store drafts in private storage (stash). */
22
+ export interface DraftWithId {
23
+ $type?: 'app.bsky.draft.defs#draftWithId'
24
+ /** A TID to be used as a draft identifier. */
25
+ id: string
26
+ draft: Draft
27
+ }
28
+
29
+ const hashDraftWithId = 'draftWithId'
30
+
31
+ export function isDraftWithId<V>(v: V) {
32
+ return is$typed(v, id, hashDraftWithId)
33
+ }
34
+
35
+ export function validateDraftWithId<V>(v: V) {
36
+ return validate<DraftWithId & V>(v, id, hashDraftWithId)
37
+ }
38
+
39
+ /** A draft containing an array of draft posts. */
40
+ export interface Draft {
41
+ $type?: 'app.bsky.draft.defs#draft'
42
+ /** UUIDv4 identifier of the device that created this draft. */
43
+ deviceId?: string
44
+ /** The device and/or platform on which the draft was created. */
45
+ deviceName?: string
46
+ /** Array of draft posts that compose this draft. */
47
+ posts: DraftPost[]
48
+ /** Indicates human language of posts primary text content. */
49
+ langs?: string[]
50
+ /** Embedding rules for the postgates to be created when this draft is published. */
51
+ postgateEmbeddingRules?: (
52
+ | $Typed<AppBskyFeedPostgate.DisableRule>
53
+ | { $type: string }
54
+ )[]
55
+ /** Allow-rules for the threadgate to be created when this draft is published. */
56
+ threadgateAllow?: (
57
+ | $Typed<AppBskyFeedThreadgate.MentionRule>
58
+ | $Typed<AppBskyFeedThreadgate.FollowerRule>
59
+ | $Typed<AppBskyFeedThreadgate.FollowingRule>
60
+ | $Typed<AppBskyFeedThreadgate.ListRule>
61
+ | { $type: string }
62
+ )[]
63
+ }
64
+
65
+ const hashDraft = 'draft'
66
+
67
+ export function isDraft<V>(v: V) {
68
+ return is$typed(v, id, hashDraft)
69
+ }
70
+
71
+ export function validateDraft<V>(v: V) {
72
+ return validate<Draft & V>(v, id, hashDraft)
73
+ }
74
+
75
+ /** One of the posts that compose a draft. */
76
+ export interface DraftPost {
77
+ $type?: 'app.bsky.draft.defs#draftPost'
78
+ /** The primary post content. */
79
+ text: string
80
+ labels?: $Typed<ComAtprotoLabelDefs.SelfLabels> | { $type: string }
81
+ embedImages?: DraftEmbedImage[]
82
+ embedVideos?: DraftEmbedVideo[]
83
+ embedExternals?: DraftEmbedExternal[]
84
+ embedRecords?: DraftEmbedRecord[]
85
+ }
86
+
87
+ const hashDraftPost = 'draftPost'
88
+
89
+ export function isDraftPost<V>(v: V) {
90
+ return is$typed(v, id, hashDraftPost)
91
+ }
92
+
93
+ export function validateDraftPost<V>(v: V) {
94
+ return validate<DraftPost & V>(v, id, hashDraftPost)
95
+ }
96
+
97
+ /** View to present drafts data to users. */
98
+ export interface DraftView {
99
+ $type?: 'app.bsky.draft.defs#draftView'
100
+ /** A TID to be used as a draft identifier. */
101
+ id: string
102
+ draft: Draft
103
+ /** The time the draft was created. */
104
+ createdAt: string
105
+ /** The time the draft was last updated. */
106
+ updatedAt: string
107
+ }
108
+
109
+ const hashDraftView = 'draftView'
110
+
111
+ export function isDraftView<V>(v: V) {
112
+ return is$typed(v, id, hashDraftView)
113
+ }
114
+
115
+ export function validateDraftView<V>(v: V) {
116
+ return validate<DraftView & V>(v, id, hashDraftView)
117
+ }
118
+
119
+ export interface DraftEmbedLocalRef {
120
+ $type?: 'app.bsky.draft.defs#draftEmbedLocalRef'
121
+ /** Local, on-device ref to file to be embedded. Embeds are currently device-bound for drafts. */
122
+ path: string
123
+ }
124
+
125
+ const hashDraftEmbedLocalRef = 'draftEmbedLocalRef'
126
+
127
+ export function isDraftEmbedLocalRef<V>(v: V) {
128
+ return is$typed(v, id, hashDraftEmbedLocalRef)
129
+ }
130
+
131
+ export function validateDraftEmbedLocalRef<V>(v: V) {
132
+ return validate<DraftEmbedLocalRef & V>(v, id, hashDraftEmbedLocalRef)
133
+ }
134
+
135
+ export interface DraftEmbedCaption {
136
+ $type?: 'app.bsky.draft.defs#draftEmbedCaption'
137
+ lang: string
138
+ content: string
139
+ }
140
+
141
+ const hashDraftEmbedCaption = 'draftEmbedCaption'
142
+
143
+ export function isDraftEmbedCaption<V>(v: V) {
144
+ return is$typed(v, id, hashDraftEmbedCaption)
145
+ }
146
+
147
+ export function validateDraftEmbedCaption<V>(v: V) {
148
+ return validate<DraftEmbedCaption & V>(v, id, hashDraftEmbedCaption)
149
+ }
150
+
151
+ export interface DraftEmbedImage {
152
+ $type?: 'app.bsky.draft.defs#draftEmbedImage'
153
+ localRef: DraftEmbedLocalRef
154
+ alt?: string
155
+ }
156
+
157
+ const hashDraftEmbedImage = 'draftEmbedImage'
158
+
159
+ export function isDraftEmbedImage<V>(v: V) {
160
+ return is$typed(v, id, hashDraftEmbedImage)
161
+ }
162
+
163
+ export function validateDraftEmbedImage<V>(v: V) {
164
+ return validate<DraftEmbedImage & V>(v, id, hashDraftEmbedImage)
165
+ }
166
+
167
+ export interface DraftEmbedVideo {
168
+ $type?: 'app.bsky.draft.defs#draftEmbedVideo'
169
+ localRef: DraftEmbedLocalRef
170
+ alt?: string
171
+ captions?: DraftEmbedCaption[]
172
+ }
173
+
174
+ const hashDraftEmbedVideo = 'draftEmbedVideo'
175
+
176
+ export function isDraftEmbedVideo<V>(v: V) {
177
+ return is$typed(v, id, hashDraftEmbedVideo)
178
+ }
179
+
180
+ export function validateDraftEmbedVideo<V>(v: V) {
181
+ return validate<DraftEmbedVideo & V>(v, id, hashDraftEmbedVideo)
182
+ }
183
+
184
+ export interface DraftEmbedExternal {
185
+ $type?: 'app.bsky.draft.defs#draftEmbedExternal'
186
+ uri: string
187
+ }
188
+
189
+ const hashDraftEmbedExternal = 'draftEmbedExternal'
190
+
191
+ export function isDraftEmbedExternal<V>(v: V) {
192
+ return is$typed(v, id, hashDraftEmbedExternal)
193
+ }
194
+
195
+ export function validateDraftEmbedExternal<V>(v: V) {
196
+ return validate<DraftEmbedExternal & V>(v, id, hashDraftEmbedExternal)
197
+ }
198
+
199
+ export interface DraftEmbedRecord {
200
+ $type?: 'app.bsky.draft.defs#draftEmbedRecord'
201
+ record: ComAtprotoRepoStrongRef.Main
202
+ }
203
+
204
+ const hashDraftEmbedRecord = 'draftEmbedRecord'
205
+
206
+ export function isDraftEmbedRecord<V>(v: V) {
207
+ return is$typed(v, id, hashDraftEmbedRecord)
208
+ }
209
+
210
+ export function validateDraftEmbedRecord<V>(v: V) {
211
+ return validate<DraftEmbedRecord & V>(v, id, hashDraftEmbedRecord)
212
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * GENERATED CODE - DO NOT MODIFY
3
+ */
4
+ import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
+ import { CID } from 'multiformats/cid'
6
+ import { validate as _validate } from '../../../../lexicons'
7
+ import {
8
+ type $Typed,
9
+ is$typed as _is$typed,
10
+ type OmitKey,
11
+ } from '../../../../util'
12
+
13
+ const is$typed = _is$typed,
14
+ validate = _validate
15
+ const id = 'app.bsky.draft.deleteDraft'
16
+
17
+ export type QueryParams = {}
18
+
19
+ export interface InputSchema {
20
+ id: string
21
+ }
22
+
23
+ export interface HandlerInput {
24
+ encoding: 'application/json'
25
+ body: InputSchema
26
+ }
27
+
28
+ export interface HandlerError {
29
+ status: number
30
+ message?: string
31
+ }
32
+
33
+ export type HandlerOutput = HandlerError | void
@@ -0,0 +1,42 @@
1
+ /**
2
+ * GENERATED CODE - DO NOT MODIFY
3
+ */
4
+ import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
+ import { CID } from 'multiformats/cid'
6
+ import { validate as _validate } from '../../../../lexicons'
7
+ import {
8
+ type $Typed,
9
+ is$typed as _is$typed,
10
+ type OmitKey,
11
+ } from '../../../../util'
12
+ import type * as AppBskyDraftDefs from './defs.js'
13
+
14
+ const is$typed = _is$typed,
15
+ validate = _validate
16
+ const id = 'app.bsky.draft.getDrafts'
17
+
18
+ export type QueryParams = {
19
+ limit: number
20
+ cursor?: string
21
+ }
22
+ export type InputSchema = undefined
23
+
24
+ export interface OutputSchema {
25
+ cursor?: string
26
+ drafts: AppBskyDraftDefs.DraftView[]
27
+ }
28
+
29
+ export type HandlerInput = void
30
+
31
+ export interface HandlerSuccess {
32
+ encoding: 'application/json'
33
+ body: OutputSchema
34
+ headers?: { [key: string]: string }
35
+ }
36
+
37
+ export interface HandlerError {
38
+ status: number
39
+ message?: string
40
+ }
41
+
42
+ export type HandlerOutput = HandlerError | HandlerSuccess
@@ -0,0 +1,34 @@
1
+ /**
2
+ * GENERATED CODE - DO NOT MODIFY
3
+ */
4
+ import { type ValidationResult, BlobRef } from '@atproto/lexicon'
5
+ import { CID } from 'multiformats/cid'
6
+ import { validate as _validate } from '../../../../lexicons'
7
+ import {
8
+ type $Typed,
9
+ is$typed as _is$typed,
10
+ type OmitKey,
11
+ } from '../../../../util'
12
+ import type * as AppBskyDraftDefs from './defs.js'
13
+
14
+ const is$typed = _is$typed,
15
+ validate = _validate
16
+ const id = 'app.bsky.draft.updateDraft'
17
+
18
+ export type QueryParams = {}
19
+
20
+ export interface InputSchema {
21
+ draft: AppBskyDraftDefs.DraftWithId
22
+ }
23
+
24
+ export interface HandlerInput {
25
+ encoding: 'application/json'
26
+ body: InputSchema
27
+ }
28
+
29
+ export interface HandlerError {
30
+ status: number
31
+ message?: string
32
+ }
33
+
34
+ export type HandlerOutput = HandlerError | void
@@ -23,6 +23,8 @@ export interface Main {
23
23
  /** Alt text description of the video, for accessibility. */
24
24
  alt?: string
25
25
  aspectRatio?: AppBskyEmbedDefs.AspectRatio
26
+ /** A hint to the client about how to present the video. */
27
+ presentation?: 'default' | 'gif' | (string & {})
26
28
  }
27
29
 
28
30
  const hashMain = 'main'
@@ -58,6 +60,8 @@ export interface View {
58
60
  thumbnail?: string
59
61
  alt?: string
60
62
  aspectRatio?: AppBskyEmbedDefs.AspectRatio
63
+ /** A hint to the client about how to present the video. */
64
+ presentation?: 'default' | 'gif' | (string & {})
61
65
  }
62
66
 
63
67
  const hashView = 'view'
@@ -24,6 +24,8 @@ export type InputSchema = undefined
24
24
 
25
25
  export interface OutputSchema {
26
26
  actors: AppBskyActorDefs.ProfileView[]
27
+ /** Snowflake for this recommendation, use when submitting recommendation events. */
28
+ recId?: string
27
29
  }
28
30
 
29
31
  export type HandlerInput = void
@@ -25,6 +25,8 @@ export type InputSchema = undefined
25
25
 
26
26
  export interface OutputSchema {
27
27
  dids: string[]
28
+ /** Snowflake for this recommendation, use when submitting recommendation events. */
29
+ recId?: string
28
30
  }
29
31
 
30
32
  export type HandlerInput = void
@@ -21,6 +21,7 @@ export type HandlerInput = void
21
21
  export interface HandlerError {
22
22
  status: number
23
23
  message?: string
24
+ error?: 'InvalidToken' | 'ExpiredToken'
24
25
  }
25
26
 
26
27
  export type HandlerOutput = HandlerError | void
@@ -20,10 +20,10 @@ export type InputSchema = undefined
20
20
  export interface OutputSchema {
21
21
  handle: string
22
22
  did: string
23
+ didDoc?: { [_ in string]: unknown }
23
24
  email?: string
24
25
  emailConfirmed?: boolean
25
26
  emailAuthFactor?: boolean
26
- didDoc?: { [_ in string]: unknown }
27
27
  active?: boolean
28
28
  /** If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted. */
29
29
  status?: 'takendown' | 'suspended' | 'deactivated' | (string & {})
@@ -23,6 +23,9 @@ export interface OutputSchema {
23
23
  handle: string
24
24
  did: string
25
25
  didDoc?: { [_ in string]: unknown }
26
+ email?: string
27
+ emailConfirmed?: boolean
28
+ emailAuthFactor?: boolean
26
29
  active?: boolean
27
30
  /** Hosting status of the account. If not specified, then assume 'active'. */
28
31
  status?: 'takendown' | 'suspended' | 'deactivated' | (string & {})
@@ -39,7 +42,7 @@ export interface HandlerSuccess {
39
42
  export interface HandlerError {
40
43
  status: number
41
44
  message?: string
42
- error?: 'AccountTakedown'
45
+ error?: 'AccountTakedown' | 'InvalidToken' | 'ExpiredToken'
43
46
  }
44
47
 
45
48
  export type HandlerOutput = HandlerError | HandlerSuccess
@@ -1,5 +1,3 @@
1
- /* eslint-disable import/no-deprecated */
2
-
3
1
  import net from 'node:net'
4
2
  import { sql } from 'kysely'
5
3
  import AtpAgent from '@atproto/api'
@@ -48,6 +46,9 @@ export const signLabel = async (
48
46
  signingKey: Keypair,
49
47
  ): Promise<SignedLabel> => {
50
48
  const { ver, src, uri, cid, val, neg, cts, exp } = label
49
+ // @TODO cborEncode now ignores undefined properties, so we might not need to
50
+ // reformat the label here. We might want to consider this if we ever re-visit
51
+ // the logic below:
51
52
  const reformatted = noUndefinedVals({
52
53
  ver: ver ?? 1,
53
54
  src,
@@ -14,6 +14,8 @@ export type VerificationIssuerCreator = (
14
14
  verifierConfig: VerifierConfig,
15
15
  ) => VerificationIssuer
16
16
 
17
+ const HANDLE_INVALID = 'handle.invalid'
18
+
17
19
  export class VerificationIssuer {
18
20
  private session = new CredentialSession(new URL(this.verifierConfig.url))
19
21
  private agent = new Agent(this.session)
@@ -58,6 +60,15 @@ export class VerificationIssuer {
58
60
  const agent = await this.getAgent()
59
61
  await Promise.allSettled(
60
62
  verifications.map(async ({ displayName, handle, subject, createdAt }) => {
63
+ if (handle.toLowerCase() === HANDLE_INVALID) {
64
+ failedVerifications.push({
65
+ $type: 'tools.ozone.verification.grantVerifications#grantError',
66
+ error: 'Cannot verify with invalid handle',
67
+ subject,
68
+ })
69
+ return
70
+ }
71
+
61
72
  try {
62
73
  const verificationRecord = {
63
74
  createdAt: createdAt || now,
@@ -1,5 +1,3 @@
1
- /* eslint-disable import/no-deprecated */
2
-
3
1
  import { AtpAgent } from '@atproto/api'
4
2
  import { cborEncode } from '@atproto/common'
5
3
  import { Secp256k1Keypair, verifySignature } from '@atproto/crypto'
@@ -132,6 +132,26 @@ describe('verification', () => {
132
132
  'Must be an admin or verifier to grant verifications',
133
133
  )
134
134
  })
135
+
136
+ it('fails if the handle is invalid', async () => {
137
+ const {
138
+ data: { verifications, failedVerifications },
139
+ } = await adminAgent.tools.ozone.verification.grantVerifications({
140
+ verifications: [
141
+ {
142
+ subject: sc.dids.dan,
143
+ handle: 'handle.invalid',
144
+ displayName: 'Bob',
145
+ },
146
+ ],
147
+ })
148
+
149
+ expect(verifications.length).toEqual(0)
150
+ expect(failedVerifications.length).toEqual(1)
151
+ const failed = failedVerifications.at(0)
152
+ expect(failed!.error).toEqual('Cannot verify with invalid handle')
153
+ expect(failed!.subject).toEqual(sc.dids.dan)
154
+ })
135
155
  })
136
156
 
137
157
  it('does not publish record if a valid one already exists', async () => {