move age assurance onto the sdk utils and scope regions by platform locally
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,3 @@
|
|||||||
import {
|
|
||||||
ageAssuranceRuleIDs as ids,
|
|
||||||
type AppBskyAgeassuranceDefs,
|
|
||||||
} from '@atproto/api'
|
|
||||||
|
|
||||||
import {AgeAssuranceAccess} from '#/ageAssurance/types'
|
import {AgeAssuranceAccess} from '#/ageAssurance/types'
|
||||||
import {
|
import {
|
||||||
ANDROID_API_LEVEL,
|
ANDROID_API_LEVEL,
|
||||||
@@ -11,6 +6,7 @@ import {
|
|||||||
IS_IOS,
|
IS_IOS,
|
||||||
IS_WEB,
|
IS_WEB,
|
||||||
} from '#/env'
|
} from '#/env'
|
||||||
|
import {app} from '#/lexicons'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Minimum age required to access the app at all.
|
* Minimum age required to access the app at all.
|
||||||
@@ -44,19 +40,17 @@ export const AGE_ASSURANCE_PLATFORM: 'web' | 'ios' | 'android' = IS_WEB
|
|||||||
export const DEVICE_SIGNALS_SUPPORTED: boolean =
|
export const DEVICE_SIGNALS_SUPPORTED: boolean =
|
||||||
(IS_IOS && IOS_MAJOR_VERSION >= 26) || (IS_ANDROID && ANDROID_API_LEVEL >= 23)
|
(IS_IOS && IOS_MAJOR_VERSION >= 26) || (IS_ANDROID && ANDROID_API_LEVEL >= 23)
|
||||||
|
|
||||||
export const FALLBACK_REGION_CONFIG: AppBskyAgeassuranceDefs.ConfigRegion = {
|
export const FALLBACK_REGION_CONFIG: app.bsky.ageassurance.defs.ConfigRegion = {
|
||||||
countryCode: '*',
|
countryCode: '*',
|
||||||
regionCode: undefined,
|
regionCode: undefined,
|
||||||
minAccessAge: MIN_ACCESS_AGE,
|
minAccessAge: MIN_ACCESS_AGE,
|
||||||
rules: [
|
rules: [
|
||||||
{
|
app.bsky.ageassurance.defs.configRegionRuleIfDeclaredOverAge.build({
|
||||||
$type: ids.IfDeclaredOverAge,
|
|
||||||
age: MIN_ACCESS_AGE,
|
age: MIN_ACCESS_AGE,
|
||||||
access: AgeAssuranceAccess.Full,
|
access: AgeAssuranceAccess.Full,
|
||||||
},
|
}),
|
||||||
{
|
app.bsky.ageassurance.defs.configRegionRuleDefault.build({
|
||||||
$type: ids.Default,
|
|
||||||
access: AgeAssuranceAccess.None,
|
access: AgeAssuranceAccess.None,
|
||||||
},
|
}),
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-24
@@ -1,11 +1,5 @@
|
|||||||
import {createContext, useCallback, useContext, useEffect, useMemo} from 'react'
|
import {createContext, useCallback, useContext, useEffect, useMemo} from 'react'
|
||||||
import * as AgeRange from 'expo-age-range'
|
import * as AgeRange from 'expo-age-range'
|
||||||
import {
|
|
||||||
type AppBskyAgeassuranceDefs,
|
|
||||||
type AppBskyAgeassuranceGetConfig,
|
|
||||||
type AppBskyAgeassuranceGetState,
|
|
||||||
type ChatBskyActorDeclaration,
|
|
||||||
} from '@atproto/api'
|
|
||||||
import {type Client} from '@atproto/lex'
|
import {type Client} from '@atproto/lex'
|
||||||
import {getPreferences} from '@bsky.app/sdk'
|
import {getPreferences} from '@bsky.app/sdk'
|
||||||
import {createAsyncStoragePersister} from '@tanstack/query-async-storage-persister'
|
import {createAsyncStoragePersister} from '@tanstack/query-async-storage-persister'
|
||||||
@@ -38,7 +32,7 @@ import {
|
|||||||
} from '#/ageAssurance/util'
|
} from '#/ageAssurance/util'
|
||||||
import {IS_DEV} from '#/env'
|
import {IS_DEV} from '#/env'
|
||||||
import {useGeolocation} from '#/geolocation'
|
import {useGeolocation} from '#/geolocation'
|
||||||
import {app} from '#/lexicons'
|
import {app, chat} from '#/lexicons'
|
||||||
import {device} from '#/storage'
|
import {device} from '#/storage'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -104,12 +98,12 @@ export async function getConfig() {
|
|||||||
*/
|
*/
|
||||||
return (await getPublicAppviewClient().call(
|
return (await getPublicAppviewClient().call(
|
||||||
app.bsky.ageassurance.getConfig,
|
app.bsky.ageassurance.getConfig,
|
||||||
)) as AppBskyAgeassuranceGetConfig.OutputSchema
|
)) as app.bsky.ageassurance.getConfig.$OutputBody
|
||||||
}
|
}
|
||||||
export function getConfigFromCache():
|
export function getConfigFromCache():
|
||||||
| AppBskyAgeassuranceGetConfig.OutputSchema
|
| app.bsky.ageassurance.getConfig.$OutputBody
|
||||||
| undefined {
|
| undefined {
|
||||||
return qc.getQueryData<AppBskyAgeassuranceGetConfig.OutputSchema>(
|
return qc.getQueryData<app.bsky.ageassurance.getConfig.$OutputBody>(
|
||||||
configQueryKey,
|
configQueryKey,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -130,7 +124,7 @@ export function prefetchConfig() {
|
|||||||
try {
|
try {
|
||||||
logger.debug(`prefetchAgeAssuranceConfig: resolving...`)
|
logger.debug(`prefetchAgeAssuranceConfig: resolving...`)
|
||||||
const res = await networkRetry(3, () => getConfig())
|
const res = await networkRetry(3, () => getConfig())
|
||||||
qc.setQueryData<AppBskyAgeassuranceGetConfig.OutputSchema>(
|
qc.setQueryData<app.bsky.ageassurance.getConfig.$OutputBody>(
|
||||||
configQueryKey,
|
configQueryKey,
|
||||||
res,
|
res,
|
||||||
)
|
)
|
||||||
@@ -146,7 +140,7 @@ export function prefetchConfig() {
|
|||||||
export async function refetchConfig() {
|
export async function refetchConfig() {
|
||||||
logger.debug(`refetchConfig: fetching...`)
|
logger.debug(`refetchConfig: fetching...`)
|
||||||
const res = await getConfig()
|
const res = await getConfig()
|
||||||
qc.setQueryData<AppBskyAgeassuranceGetConfig.OutputSchema>(
|
qc.setQueryData<app.bsky.ageassurance.getConfig.$OutputBody>(
|
||||||
configQueryKey,
|
configQueryKey,
|
||||||
res,
|
res,
|
||||||
)
|
)
|
||||||
@@ -216,8 +210,8 @@ export function getServerStateFromCache({
|
|||||||
did,
|
did,
|
||||||
}: {
|
}: {
|
||||||
did: string
|
did: string
|
||||||
}): AppBskyAgeassuranceGetState.OutputSchema | undefined {
|
}): app.bsky.ageassurance.getState.$OutputBody | undefined {
|
||||||
return qc.getQueryData<AppBskyAgeassuranceGetState.OutputSchema>(
|
return qc.getQueryData<app.bsky.ageassurance.getState.$OutputBody>(
|
||||||
createServerStateQueryKey({did}),
|
createServerStateQueryKey({did}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -243,7 +237,7 @@ export async function prefetchServerState({
|
|||||||
logger.debug(`prefetchServerState: resolving...`)
|
logger.debug(`prefetchServerState: resolving...`)
|
||||||
const res = await networkRetry(3, () => getServerState({appviewClient}))
|
const res = await networkRetry(3, () => getServerState({appviewClient}))
|
||||||
if (res) {
|
if (res) {
|
||||||
qc.setQueryData<AppBskyAgeassuranceGetState.OutputSchema>(qk, res)
|
qc.setQueryData<app.bsky.ageassurance.getState.$OutputBody>(qk, res)
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const e = err as Error
|
const e = err as Error
|
||||||
@@ -262,7 +256,7 @@ export async function refetchServerState({
|
|||||||
logger.debug(`refetchServerState: fetching...`)
|
logger.debug(`refetchServerState: fetching...`)
|
||||||
const res = await networkRetry(3, () => getServerState({appviewClient}))
|
const res = await networkRetry(3, () => getServerState({appviewClient}))
|
||||||
if (res) {
|
if (res) {
|
||||||
qc.setQueryData<AppBskyAgeassuranceGetState.OutputSchema>(
|
qc.setQueryData<app.bsky.ageassurance.getState.$OutputBody>(
|
||||||
createServerStateQueryKey({did}),
|
createServerStateQueryKey({did}),
|
||||||
res,
|
res,
|
||||||
)
|
)
|
||||||
@@ -272,16 +266,16 @@ export async function refetchServerState({
|
|||||||
export function usePatchServerState() {
|
export function usePatchServerState() {
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
return useCallback(
|
return useCallback(
|
||||||
(next: AppBskyAgeassuranceDefs.State) => {
|
(next: app.bsky.ageassurance.defs.State) => {
|
||||||
if (!currentAccount) return
|
if (!currentAccount) return
|
||||||
const did = currentAccount.did
|
const did = currentAccount.did
|
||||||
const prev = getServerStateFromCache({did})
|
const prev = getServerStateFromCache({did})
|
||||||
const merged: AppBskyAgeassuranceGetState.OutputSchema = {
|
const merged: app.bsky.ageassurance.getState.$OutputBody = {
|
||||||
metadata: {},
|
metadata: {},
|
||||||
...(prev || {}),
|
...(prev || {}),
|
||||||
state: next,
|
state: next,
|
||||||
}
|
}
|
||||||
qc.setQueryData<AppBskyAgeassuranceGetState.OutputSchema>(
|
qc.setQueryData<app.bsky.ageassurance.getState.$OutputBody>(
|
||||||
createServerStateQueryKey({did}),
|
createServerStateQueryKey({did}),
|
||||||
merged,
|
merged,
|
||||||
)
|
)
|
||||||
@@ -347,7 +341,7 @@ export function useServerStateQuery() {
|
|||||||
|
|
||||||
export type OtherRequiredData = {
|
export type OtherRequiredData = {
|
||||||
birthdate: string | undefined
|
birthdate: string | undefined
|
||||||
actorDeclaration?: ChatBskyActorDeclaration.Main
|
actorDeclaration?: chat.bsky.actor.declaration.Main
|
||||||
}
|
}
|
||||||
export function createOtherRequiredDataQueryKey({did}: {did: string}) {
|
export function createOtherRequiredDataQueryKey({did}: {did: string}) {
|
||||||
return ['otherRequiredData', did]
|
return ['otherRequiredData', did]
|
||||||
@@ -422,7 +416,7 @@ export function setOtherRequiredDataActorDeclarationCache({
|
|||||||
actorDeclaration,
|
actorDeclaration,
|
||||||
}: {
|
}: {
|
||||||
did: string
|
did: string
|
||||||
actorDeclaration: ChatBskyActorDeclaration.Main
|
actorDeclaration: chat.bsky.actor.declaration.Main
|
||||||
}) {
|
}) {
|
||||||
const prev = getOtherRequiredDataFromCache({did})
|
const prev = getOtherRequiredDataFromCache({did})
|
||||||
const next: OtherRequiredData = {
|
const next: OtherRequiredData = {
|
||||||
@@ -564,7 +558,7 @@ export function getDeviceSignalsFromCacheForRegion({
|
|||||||
region,
|
region,
|
||||||
}: {
|
}: {
|
||||||
did: string
|
did: string
|
||||||
region: AppBskyAgeassuranceDefs.ConfigRegion
|
region: app.bsky.ageassurance.defs.ConfigRegion
|
||||||
}): AgeRange.AgeRangeResponse | undefined {
|
}): AgeRange.AgeRangeResponse | undefined {
|
||||||
const regionKey = createRegionKey(region)
|
const regionKey = createRegionKey(region)
|
||||||
return getDeviceSignalsMapFromCache({did})?.[regionKey]
|
return getDeviceSignalsMapFromCache({did})?.[regionKey]
|
||||||
@@ -718,11 +712,11 @@ export type AgeAssuranceServerData = {
|
|||||||
/**
|
/**
|
||||||
* The raw config from the appview.
|
* The raw config from the appview.
|
||||||
*/
|
*/
|
||||||
config: AppBskyAgeassuranceDefs.Config | undefined
|
config: app.bsky.ageassurance.defs.Config | undefined
|
||||||
/**
|
/**
|
||||||
* The raw state from the appview. Must be further processed before being useful.
|
* The raw state from the appview. Must be further processed before being useful.
|
||||||
*/
|
*/
|
||||||
state: AppBskyAgeassuranceDefs.State | undefined
|
state: app.bsky.ageassurance.defs.State | undefined
|
||||||
metadata: AgeAssuranceMetadata | undefined
|
metadata: AgeAssuranceMetadata | undefined
|
||||||
/**
|
/**
|
||||||
* The native on-device age signals for the region the user is currently in,
|
* The native on-device age signals for the region the user is currently in,
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import {useEffect, useMemo, useState} from 'react'
|
import {useEffect, useMemo, useState} from 'react'
|
||||||
import type * as AgeRange from 'expo-age-range'
|
import type * as AgeRange from 'expo-age-range'
|
||||||
import {
|
import {computeAgeAssuranceRegionAccess} from '@bsky.app/sdk/utils'
|
||||||
type AppBskyAgeassuranceDefs,
|
|
||||||
computeAgeAssuranceRegionAccess,
|
|
||||||
} from '@atproto/api'
|
|
||||||
|
|
||||||
|
import {type app} from '#/lexicons'
|
||||||
import {getAge} from '#/lib/strings/time'
|
import {getAge} from '#/lib/strings/time'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
import {
|
import {
|
||||||
@@ -47,8 +45,8 @@ function computeAgeAssuranceState({
|
|||||||
}: {
|
}: {
|
||||||
hasSession: boolean
|
hasSession: boolean
|
||||||
geolocation: Geolocation
|
geolocation: Geolocation
|
||||||
config?: AppBskyAgeassuranceDefs.Config
|
config?: app.bsky.ageassurance.defs.Config
|
||||||
state?: AppBskyAgeassuranceDefs.State
|
state?: app.bsky.ageassurance.defs.State
|
||||||
metadata?: AgeAssuranceMetadata
|
metadata?: AgeAssuranceMetadata
|
||||||
deviceSignals?: AgeRange.AgeRangeResponse
|
deviceSignals?: AgeRange.AgeRangeResponse
|
||||||
}) {
|
}) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type * as AgeRange from 'expo-age-range'
|
import type * as AgeRange from 'expo-age-range'
|
||||||
import {type computeAgeAssuranceRegionAccess} from '@atproto/api'
|
import {type computeAgeAssuranceRegionAccess} from '@bsky.app/sdk/utils'
|
||||||
|
|
||||||
import {logger} from '#/ageAssurance/logger'
|
import {logger} from '#/ageAssurance/logger'
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import {useCallback} from 'react'
|
import {useCallback} from 'react'
|
||||||
import {computeAgeAssuranceRegionAccess} from '@atproto/api'
|
import {computeAgeAssuranceRegionAccess} from '@bsky.app/sdk/utils'
|
||||||
|
|
||||||
import {useAgeAssuranceServerDataContext} from '#/ageAssurance/data'
|
import {useAgeAssuranceServerDataContext} from '#/ageAssurance/data'
|
||||||
import {logger} from '#/ageAssurance/logger'
|
import {logger} from '#/ageAssurance/logger'
|
||||||
|
|||||||
@@ -1,31 +1,48 @@
|
|||||||
import {getAgeAssuranceRegionConfig} from '@atproto/api'
|
|
||||||
|
|
||||||
import {getAgeAssuranceRegionConfigForGeolocation} from '#/ageAssurance/util'
|
import {getAgeAssuranceRegionConfigForGeolocation} from '#/ageAssurance/util'
|
||||||
|
import {type app} from '#/lexicons'
|
||||||
|
|
||||||
jest.mock('#/ageAssurance/data')
|
jest.mock('#/ageAssurance/data')
|
||||||
jest.mock('@atproto/api', () => ({
|
|
||||||
...jest.requireActual('@atproto/api'),
|
|
||||||
getAgeAssuranceRegionConfig: jest.fn(),
|
|
||||||
}))
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Platform-based region filtering itself is implemented and tested in
|
* Platform scoping is applied locally in `util.ts` (the SDK region matcher
|
||||||
* `@atproto/api` (see `getAgeAssuranceRegionConfig`). What we own - and test
|
* takes no platform filter). The jest preset is `jest-expo/ios`, so
|
||||||
* here - is that region resolution passes the current platform through. The
|
* `AGE_ASSURANCE_PLATFORM` resolves to `ios` in these tests.
|
||||||
* jest preset is `jest-expo/ios`, so `AGE_ASSURANCE_PLATFORM` resolves to
|
|
||||||
* `ios` in these tests.
|
|
||||||
*/
|
*/
|
||||||
describe('getAgeAssuranceRegionConfigForGeolocation', () => {
|
describe('getAgeAssuranceRegionConfigForGeolocation', () => {
|
||||||
it('passes the current platform to the SDK region matcher', () => {
|
const region = (
|
||||||
const config = {regions: []}
|
countryCode: string,
|
||||||
getAgeAssuranceRegionConfigForGeolocation(config, {
|
regionCode?: string,
|
||||||
countryCode: 'US',
|
platforms?: string[],
|
||||||
regionCode: 'TX',
|
) =>
|
||||||
})
|
({
|
||||||
expect(getAgeAssuranceRegionConfig).toHaveBeenCalledWith(config, {
|
countryCode,
|
||||||
countryCode: 'US',
|
regionCode,
|
||||||
regionCode: 'TX',
|
platforms,
|
||||||
platform: 'ios',
|
minAccessAge: 13,
|
||||||
})
|
rules: [],
|
||||||
|
}) as app.bsky.ageassurance.defs.ConfigRegion
|
||||||
|
|
||||||
|
it('skips regions for other platforms and continues matching', () => {
|
||||||
|
const web = region('US', undefined, ['web'])
|
||||||
|
const ios = region('US', undefined, ['ios'])
|
||||||
|
|
||||||
|
expect(
|
||||||
|
getAgeAssuranceRegionConfigForGeolocation(
|
||||||
|
{regions: [web, ios]},
|
||||||
|
{countryCode: 'US', regionCode: undefined},
|
||||||
|
),
|
||||||
|
).toBe(ios)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('matches a region-specific config before a later country config', () => {
|
||||||
|
const texas = region('US', 'TX')
|
||||||
|
const us = region('US')
|
||||||
|
|
||||||
|
expect(
|
||||||
|
getAgeAssuranceRegionConfigForGeolocation(
|
||||||
|
{regions: [texas, us]},
|
||||||
|
{countryCode: 'US', regionCode: 'TX'},
|
||||||
|
),
|
||||||
|
).toBe(texas)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
+36
-16
@@ -1,12 +1,13 @@
|
|||||||
import {useMemo} from 'react'
|
import {useMemo} from 'react'
|
||||||
import type * as AgeRange from 'expo-age-range'
|
import type * as AgeRange from 'expo-age-range'
|
||||||
import {
|
import {
|
||||||
AppBskyAgeassuranceDefs,
|
|
||||||
computeAgeAssuranceRegionAccess,
|
computeAgeAssuranceRegionAccess,
|
||||||
getAgeAssuranceRegionConfig,
|
getAgeAssuranceRegionConfig,
|
||||||
} from '@atproto/api'
|
} from '@bsky.app/sdk/utils'
|
||||||
import {type ModerationPrefs} from '@bsky.app/sdk/moderation'
|
import {type ModerationPrefs} from '@bsky.app/sdk/moderation'
|
||||||
|
|
||||||
|
import * as bsky from '#/types/bsky'
|
||||||
|
import {app} from '#/lexicons'
|
||||||
import {getAge} from '#/lib/strings/time'
|
import {getAge} from '#/lib/strings/time'
|
||||||
import {regionName} from '#/locale/helpers'
|
import {regionName} from '#/locale/helpers'
|
||||||
import {DEFAULT_LOGGED_OUT_LABEL_PREFERENCES} from '#/state/queries/preferences/const'
|
import {DEFAULT_LOGGED_OUT_LABEL_PREFERENCES} from '#/state/queries/preferences/const'
|
||||||
@@ -41,13 +42,26 @@ import {USRegionNameToRegionCode} from '#/geolocation/util'
|
|||||||
* risk desyncing the write and read keys and silently losing grants.
|
* risk desyncing the write and read keys and silently losing grants.
|
||||||
*/
|
*/
|
||||||
export function getAgeAssuranceRegionConfigForGeolocation(
|
export function getAgeAssuranceRegionConfigForGeolocation(
|
||||||
config: AppBskyAgeassuranceDefs.Config,
|
config: app.bsky.ageassurance.defs.Config,
|
||||||
geolocation: Geolocation,
|
geolocation: Geolocation,
|
||||||
): AppBskyAgeassuranceDefs.ConfigRegion | undefined {
|
): app.bsky.ageassurance.defs.ConfigRegion | undefined {
|
||||||
return getAgeAssuranceRegionConfig(config, {
|
/*
|
||||||
|
* The SDK's region matcher takes no `platform` filter (and the generated
|
||||||
|
* `ConfigRegion` carries no `platforms` field yet), so platform scoping is
|
||||||
|
* applied here: regions restricted to other platforms are dropped before
|
||||||
|
* matching, which is what passing `platform` to the old api helper did.
|
||||||
|
* Fold this back into the SDK call once it accepts a platform.
|
||||||
|
*/
|
||||||
|
const scoped: app.bsky.ageassurance.defs.Config = {
|
||||||
|
...config,
|
||||||
|
regions: config.regions.filter(region => {
|
||||||
|
const platforms = (region as {platforms?: string[]}).platforms
|
||||||
|
return !platforms || platforms.includes(AGE_ASSURANCE_PLATFORM)
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
return getAgeAssuranceRegionConfig(scoped, {
|
||||||
countryCode: geolocation.countryCode ?? '',
|
countryCode: geolocation.countryCode ?? '',
|
||||||
regionCode: geolocation.regionCode,
|
regionCode: geolocation.regionCode,
|
||||||
platform: AGE_ASSURANCE_PLATFORM,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,9 +73,9 @@ export function getAgeAssuranceRegionConfigForGeolocation(
|
|||||||
* which can return undefined if the geolocation does not match any AA region.
|
* which can return undefined if the geolocation does not match any AA region.
|
||||||
*/
|
*/
|
||||||
export function getAgeAssuranceRegionConfigWithFallback(
|
export function getAgeAssuranceRegionConfigWithFallback(
|
||||||
config: AppBskyAgeassuranceDefs.Config,
|
config: app.bsky.ageassurance.defs.Config,
|
||||||
geolocation: Geolocation,
|
geolocation: Geolocation,
|
||||||
): AppBskyAgeassuranceDefs.ConfigRegion {
|
): app.bsky.ageassurance.defs.ConfigRegion {
|
||||||
return (
|
return (
|
||||||
getAgeAssuranceRegionConfigForGeolocation(config, geolocation) ||
|
getAgeAssuranceRegionConfigForGeolocation(config, geolocation) ||
|
||||||
FALLBACK_REGION_CONFIG
|
FALLBACK_REGION_CONFIG
|
||||||
@@ -74,9 +88,9 @@ export function getAgeAssuranceRegionConfigWithFallback(
|
|||||||
* historical KWS-only behavior).
|
* historical KWS-only behavior).
|
||||||
*/
|
*/
|
||||||
export function getRegionAdditionalVerificationMethods(
|
export function getRegionAdditionalVerificationMethods(
|
||||||
region: AppBskyAgeassuranceDefs.ConfigRegion,
|
region: app.bsky.ageassurance.defs.ConfigRegion,
|
||||||
): NonNullable<
|
): NonNullable<
|
||||||
AppBskyAgeassuranceDefs.ConfigRegion['additionalVerificationMethods']
|
app.bsky.ageassurance.defs.ConfigRegion['additionalVerificationMethods']
|
||||||
> {
|
> {
|
||||||
return region.additionalVerificationMethods ?? []
|
return region.additionalVerificationMethods ?? []
|
||||||
}
|
}
|
||||||
@@ -86,7 +100,7 @@ export function getRegionAdditionalVerificationMethods(
|
|||||||
* age APIs (Apple Declared Age Range / Google Play Age Signals).
|
* age APIs (Apple Declared Age Range / Google Play Age Signals).
|
||||||
*/
|
*/
|
||||||
export function regionAllowsDeviceVerification(
|
export function regionAllowsDeviceVerification(
|
||||||
region: AppBskyAgeassuranceDefs.ConfigRegion,
|
region: app.bsky.ageassurance.defs.ConfigRegion,
|
||||||
): boolean {
|
): boolean {
|
||||||
return getRegionAdditionalVerificationMethods(region).includes('device')
|
return getRegionAdditionalVerificationMethods(region).includes('device')
|
||||||
}
|
}
|
||||||
@@ -122,7 +136,7 @@ export function createRegionKey(region: {
|
|||||||
* usable data.
|
* usable data.
|
||||||
*/
|
*/
|
||||||
export function getAgeAssuranceDataFromDeviceSignals(
|
export function getAgeAssuranceDataFromDeviceSignals(
|
||||||
region: AppBskyAgeassuranceDefs.ConfigRegion,
|
region: app.bsky.ageassurance.defs.ConfigRegion,
|
||||||
deviceSignals: AgeRange.AgeRangeResponse | undefined,
|
deviceSignals: AgeRange.AgeRangeResponse | undefined,
|
||||||
): {
|
): {
|
||||||
assuredAge?: number
|
assuredAge?: number
|
||||||
@@ -183,7 +197,7 @@ export function canBirthdateUpdateIncreaseAccess({
|
|||||||
metadata,
|
metadata,
|
||||||
deviceSignals,
|
deviceSignals,
|
||||||
}: {
|
}: {
|
||||||
region: AppBskyAgeassuranceDefs.ConfigRegion
|
region: app.bsky.ageassurance.defs.ConfigRegion
|
||||||
metadata?: AgeAssuranceMetadata
|
metadata?: AgeAssuranceMetadata
|
||||||
deviceSignals?: AgeRange.AgeRangeResponse
|
deviceSignals?: AgeRange.AgeRangeResponse
|
||||||
}): boolean {
|
}): boolean {
|
||||||
@@ -212,8 +226,14 @@ export function canBirthdateUpdateIncreaseAccess({
|
|||||||
const thresholds = new Set<number>([region.minAccessAge])
|
const thresholds = new Set<number>([region.minAccessAge])
|
||||||
for (const rule of region.rules) {
|
for (const rule of region.rules) {
|
||||||
if (
|
if (
|
||||||
AppBskyAgeassuranceDefs.isConfigRegionRuleIfDeclaredOverAge(rule) ||
|
bsky.isType(
|
||||||
AppBskyAgeassuranceDefs.isConfigRegionRuleIfDeclaredUnderAge(rule)
|
app.bsky.ageassurance.defs.configRegionRuleIfDeclaredOverAge,
|
||||||
|
rule,
|
||||||
|
) ||
|
||||||
|
bsky.isType(
|
||||||
|
app.bsky.ageassurance.defs.configRegionRuleIfDeclaredUnderAge,
|
||||||
|
rule,
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
thresholds.add(rule.age)
|
thresholds.add(rule.age)
|
||||||
}
|
}
|
||||||
@@ -303,7 +323,7 @@ export function computeAgeAssuranceFlags({
|
|||||||
deviceSignals,
|
deviceSignals,
|
||||||
}: {
|
}: {
|
||||||
state: AgeAssuranceState
|
state: AgeAssuranceState
|
||||||
regionConfig: AppBskyAgeassuranceDefs.ConfigRegion
|
regionConfig: app.bsky.ageassurance.defs.ConfigRegion
|
||||||
metadata?: AgeAssuranceMetadata
|
metadata?: AgeAssuranceMetadata
|
||||||
deviceSignals?: AgeRange.AgeRangeResponse
|
deviceSignals?: AgeRange.AgeRangeResponse
|
||||||
}): AgeAssuranceFlags {
|
}): AgeAssuranceFlags {
|
||||||
|
|||||||
Reference in New Issue
Block a user