@atproto/bsky 0.0.172 → 0.0.173
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.
- package/CHANGELOG.md +6 -0
- package/dist/api/app/bsky/unspecced/initAgeAssurance.d.ts.map +1 -1
- package/dist/api/app/bsky/unspecced/initAgeAssurance.js +52 -10
- package/dist/api/app/bsky/unspecced/initAgeAssurance.js.map +1 -1
- package/dist/kws.d.ts +2 -0
- package/dist/kws.d.ts.map +1 -1
- package/dist/kws.js +10 -2
- package/dist/kws.js.map +1 -1
- package/dist/lexicon/lexicons.d.ts +10 -0
- package/dist/lexicon/lexicons.d.ts.map +1 -1
- package/dist/lexicon/lexicons.js +8 -0
- package/dist/lexicon/lexicons.js.map +1 -1
- package/dist/lexicon/types/app/bsky/unspecced/initAgeAssurance.d.ts +1 -0
- package/dist/lexicon/types/app/bsky/unspecced/initAgeAssurance.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/api/app/bsky/unspecced/initAgeAssurance.ts +65 -12
- package/src/kws.ts +9 -1
- package/src/lexicon/lexicons.ts +8 -0
- package/src/lexicon/types/app/bsky/unspecced/initAgeAssurance.ts +1 -0
|
@@ -23,6 +23,7 @@ export interface HandlerSuccess {
|
|
|
23
23
|
export interface HandlerError {
|
|
24
24
|
status: number;
|
|
25
25
|
message?: string;
|
|
26
|
+
error?: 'InvalidEmail' | 'DidTooLong';
|
|
26
27
|
}
|
|
27
28
|
export type HandlerOutput = HandlerError | HandlerSuccess;
|
|
28
29
|
//# sourceMappingURL=initAgeAssurance.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initAgeAssurance.d.ts","sourceRoot":"","sources":["../../../../../../src/lexicon/types/app/bsky/unspecced/initAgeAssurance.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,KAAK,oBAAoB,MAAM,WAAW,CAAA;AAMtD,MAAM,MAAM,WAAW,GAAG,EAAE,CAAA;AAE5B,MAAM,WAAW,WAAW;IAC1B,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAA;IACb,oFAAoF;IACpF,QAAQ,EAAE,MAAM,CAAA;IAChB,yDAAyD;IACzD,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,MAAM,YAAY,GAAG,oBAAoB,CAAC,iBAAiB,CAAA;AAEjE,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,kBAAkB,CAAA;IAC5B,IAAI,EAAE,WAAW,CAAA;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,kBAAkB,CAAA;IAC5B,IAAI,EAAE,YAAY,CAAA;IAClB,OAAO,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAA;CACpC;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"initAgeAssurance.d.ts","sourceRoot":"","sources":["../../../../../../src/lexicon/types/app/bsky/unspecced/initAgeAssurance.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,KAAK,oBAAoB,MAAM,WAAW,CAAA;AAMtD,MAAM,MAAM,WAAW,GAAG,EAAE,CAAA;AAE5B,MAAM,WAAW,WAAW;IAC1B,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAA;IACb,oFAAoF;IACpF,QAAQ,EAAE,MAAM,CAAA;IAChB,yDAAyD;IACzD,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,MAAM,YAAY,GAAG,oBAAoB,CAAC,iBAAiB,CAAA;AAEjE,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,kBAAkB,CAAA;IAC5B,IAAI,EAAE,WAAW,CAAA;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,kBAAkB,CAAA;IAC5B,IAAI,EAAE,YAAY,CAAA;IAClB,OAAO,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAA;CACpC;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,cAAc,GAAG,YAAY,CAAA;CACtC;AAED,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,cAAc,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/bsky",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.173",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Reference implementation of app.bsky App View (Bluesky API)",
|
|
6
6
|
"keywords": [
|
|
@@ -52,8 +52,8 @@
|
|
|
52
52
|
"zod": "3.23.8",
|
|
53
53
|
"@atproto-labs/fetch-node": "0.1.9",
|
|
54
54
|
"@atproto-labs/xrpc-utils": "0.0.17",
|
|
55
|
-
"@atproto/api": "^0.15.26",
|
|
56
55
|
"@atproto/common": "^0.4.11",
|
|
56
|
+
"@atproto/api": "^0.15.26",
|
|
57
57
|
"@atproto/crypto": "^0.4.4",
|
|
58
58
|
"@atproto/did": "^0.1.5",
|
|
59
59
|
"@atproto/identity": "^0.4.8",
|
|
@@ -8,7 +8,10 @@ import {
|
|
|
8
8
|
} from '@atproto/xrpc-server'
|
|
9
9
|
import { AppContext } from '../../../../context'
|
|
10
10
|
import { GateID } from '../../../../feature-gates'
|
|
11
|
+
import { KwsExternalPayloadError } from '../../../../kws'
|
|
11
12
|
import { Server } from '../../../../lexicon'
|
|
13
|
+
import { InputSchema } from '../../../../lexicon/types/app/bsky/unspecced/initAgeAssurance'
|
|
14
|
+
import { httpLogger as log } from '../../../../logger'
|
|
12
15
|
import { KwsExternalPayload } from '../../../kws/types'
|
|
13
16
|
import { createStashEvent, getClientUa } from '../../../kws/util'
|
|
14
17
|
|
|
@@ -30,12 +33,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
30
33
|
throw new ForbiddenError()
|
|
31
34
|
}
|
|
32
35
|
|
|
33
|
-
const { email, language
|
|
34
|
-
if (!isEmailValid(email) || isDisposableEmail(email)) {
|
|
35
|
-
throw new InvalidRequestError(
|
|
36
|
-
'This email address is not supported, please use a different email.',
|
|
37
|
-
)
|
|
38
|
-
}
|
|
36
|
+
const { countryCode, email, language } = validateInput(input.body)
|
|
39
37
|
|
|
40
38
|
const attemptId = crypto.randomUUID()
|
|
41
39
|
// Assumes `app.set('trust proxy', ...)` configured with `true` or specific values.
|
|
@@ -43,12 +41,26 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
43
41
|
const initUa = getClientUa(req)
|
|
44
42
|
const externalPayload: KwsExternalPayload = { actorDid, attemptId }
|
|
45
43
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
44
|
+
try {
|
|
45
|
+
await ctx.kwsClient.sendEmail({
|
|
46
|
+
countryCode: countryCode.toUpperCase(),
|
|
47
|
+
email,
|
|
48
|
+
externalPayload,
|
|
49
|
+
language,
|
|
50
|
+
})
|
|
51
|
+
} catch (err) {
|
|
52
|
+
if (err instanceof KwsExternalPayloadError) {
|
|
53
|
+
log.error(
|
|
54
|
+
{ externalPayload },
|
|
55
|
+
'Age Assurance flow failed because external payload got too long, which is caused by the DID being too long',
|
|
56
|
+
)
|
|
57
|
+
throw new InvalidRequestError(
|
|
58
|
+
'Age Assurance flow failed because DID is too long',
|
|
59
|
+
'DidTooLong',
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
throw err
|
|
63
|
+
}
|
|
52
64
|
|
|
53
65
|
const event = await createStashEvent(ctx, {
|
|
54
66
|
actorDid,
|
|
@@ -69,3 +81,44 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
69
81
|
},
|
|
70
82
|
})
|
|
71
83
|
}
|
|
84
|
+
|
|
85
|
+
// Supported languages for KWS Adult Verification.
|
|
86
|
+
// This list comes from KWS's AV Developer Guide PDF doc.
|
|
87
|
+
const kwsAvSupportedLanguages = [
|
|
88
|
+
'en',
|
|
89
|
+
'ar',
|
|
90
|
+
'zh-Hans',
|
|
91
|
+
'nl',
|
|
92
|
+
'tl',
|
|
93
|
+
'fr',
|
|
94
|
+
'de',
|
|
95
|
+
'id',
|
|
96
|
+
'it',
|
|
97
|
+
'ja',
|
|
98
|
+
'ko',
|
|
99
|
+
'pl',
|
|
100
|
+
'pt-BR',
|
|
101
|
+
'pt',
|
|
102
|
+
'ru',
|
|
103
|
+
'es',
|
|
104
|
+
'th',
|
|
105
|
+
'tr',
|
|
106
|
+
'vi',
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
const validateInput = (input: InputSchema): InputSchema => {
|
|
110
|
+
const { countryCode, email, language } = input
|
|
111
|
+
|
|
112
|
+
if (!isEmailValid(email) || isDisposableEmail(email)) {
|
|
113
|
+
throw new InvalidRequestError(
|
|
114
|
+
'This email address is not supported, please use a different email.',
|
|
115
|
+
'InvalidEmail',
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
countryCode,
|
|
121
|
+
email,
|
|
122
|
+
language: kwsAvSupportedLanguages.includes(language) ? language : 'en',
|
|
123
|
+
}
|
|
124
|
+
}
|
package/src/kws.ts
CHANGED
|
@@ -14,6 +14,9 @@ const authResponseSchema = z.object({
|
|
|
14
14
|
access_token: z.string(),
|
|
15
15
|
})
|
|
16
16
|
|
|
17
|
+
const EXTERNAL_PAYLOAD_CHAR_LIMIT = 200
|
|
18
|
+
export class KwsExternalPayloadError extends Error {}
|
|
19
|
+
|
|
17
20
|
export class KwsClient {
|
|
18
21
|
constructor(public cfg: KwsConfig) {}
|
|
19
22
|
|
|
@@ -76,6 +79,11 @@ export class KwsClient {
|
|
|
76
79
|
externalPayload: KwsExternalPayload
|
|
77
80
|
language: string
|
|
78
81
|
}) {
|
|
82
|
+
const serializedExternalPayload = serializeExternalPayload(externalPayload)
|
|
83
|
+
if (serializedExternalPayload.length > EXTERNAL_PAYLOAD_CHAR_LIMIT) {
|
|
84
|
+
throw new KwsExternalPayloadError()
|
|
85
|
+
}
|
|
86
|
+
|
|
79
87
|
const res = await this.fetchWithAuth(
|
|
80
88
|
`${this.cfg.apiOrigin}/v1/verifications/send-email`,
|
|
81
89
|
{
|
|
@@ -86,7 +94,7 @@ export class KwsClient {
|
|
|
86
94
|
},
|
|
87
95
|
body: JSON.stringify({
|
|
88
96
|
email,
|
|
89
|
-
externalPayload:
|
|
97
|
+
externalPayload: serializedExternalPayload,
|
|
90
98
|
language,
|
|
91
99
|
location: countryCode,
|
|
92
100
|
userContext: 'adult',
|
package/src/lexicon/lexicons.ts
CHANGED
|
@@ -11589,6 +11589,14 @@ export const schemaDict = {
|
|
|
11589
11589
|
ref: 'lex:app.bsky.unspecced.defs#ageAssuranceState',
|
|
11590
11590
|
},
|
|
11591
11591
|
},
|
|
11592
|
+
errors: [
|
|
11593
|
+
{
|
|
11594
|
+
name: 'InvalidEmail',
|
|
11595
|
+
},
|
|
11596
|
+
{
|
|
11597
|
+
name: 'DidTooLong',
|
|
11598
|
+
},
|
|
11599
|
+
],
|
|
11592
11600
|
},
|
|
11593
11601
|
},
|
|
11594
11602
|
},
|