Return an object from device-signals age data helper
Rename getAssuredAgeFromDeviceSignals to getAgeAssuranceDataFromDeviceSignals and return an object instead of a bare number, leaving room to derive more rule-engine inputs from the native response (declared vs. guardian-declared, parental controls, platform verification status) as the rules grow. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -42,7 +42,7 @@ import {
|
|||||||
import {logger} from '#/ageAssurance/logger'
|
import {logger} from '#/ageAssurance/logger'
|
||||||
import {useComputeAgeAssuranceRegionAccess} from '#/ageAssurance/useComputeAgeAssuranceRegionAccess'
|
import {useComputeAgeAssuranceRegionAccess} from '#/ageAssurance/useComputeAgeAssuranceRegionAccess'
|
||||||
import {
|
import {
|
||||||
getAssuredAgeFromDeviceSignals,
|
getAgeAssuranceDataFromDeviceSignals,
|
||||||
isLegacyBirthdateBug,
|
isLegacyBirthdateBug,
|
||||||
regionAllowsDeviceVerification,
|
regionAllowsDeviceVerification,
|
||||||
useAgeAssuranceRegionConfig,
|
useAgeAssuranceRegionConfig,
|
||||||
@@ -360,7 +360,10 @@ function AccessSection() {
|
|||||||
setIsVerifyingDevice(false)
|
setIsVerifyingDevice(false)
|
||||||
}
|
}
|
||||||
if (signals && did) {
|
if (signals && did) {
|
||||||
const assuredAge = getAssuredAgeFromDeviceSignals(region, signals)
|
const {assuredAge} = getAgeAssuranceDataFromDeviceSignals(
|
||||||
|
region,
|
||||||
|
signals,
|
||||||
|
)
|
||||||
if (assuredAge !== undefined) {
|
if (assuredAge !== undefined) {
|
||||||
// Sufficient device signals: persist (keyed by this region) and let
|
// Sufficient device signals: persist (keyed by this region) and let
|
||||||
// the AA state recompute from the cache write unlock access. Nothing
|
// the AA state recompute from the cache write unlock access. Nothing
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ import {
|
|||||||
} from '#/ageAssurance/types'
|
} from '#/ageAssurance/types'
|
||||||
import {
|
import {
|
||||||
computeAgeAssuranceFlags,
|
computeAgeAssuranceFlags,
|
||||||
|
getAgeAssuranceDataFromDeviceSignals,
|
||||||
getAgeAssuranceRegionConfigWithFallback,
|
getAgeAssuranceRegionConfigWithFallback,
|
||||||
getAssuredAgeFromDeviceSignals,
|
|
||||||
} from '#/ageAssurance/util'
|
} from '#/ageAssurance/util'
|
||||||
import {type Geolocation, useGeolocation} from '#/geolocation'
|
import {type Geolocation, useGeolocation} from '#/geolocation'
|
||||||
import {device} from '#/storage'
|
import {device} from '#/storage'
|
||||||
@@ -103,7 +103,10 @@ function computeAgeAssuranceState({
|
|||||||
* is treated as an assured age and fed into the rule engine, where it
|
* is treated as an assured age and fed into the rule engine, where it
|
||||||
* matches `IfAssuredOverAge`/`IfAssuredUnderAge` rules.
|
* matches `IfAssuredOverAge`/`IfAssuredUnderAge` rules.
|
||||||
*/
|
*/
|
||||||
const assuredAge = getAssuredAgeFromDeviceSignals(region, deviceSignals)
|
const {assuredAge} = getAgeAssuranceDataFromDeviceSignals(
|
||||||
|
region,
|
||||||
|
deviceSignals,
|
||||||
|
)
|
||||||
const result = computeAgeAssuranceRegionAccess(region, {
|
const result = computeAgeAssuranceRegionAccess(region, {
|
||||||
accountCreatedAt: metadata?.accountCreatedAt,
|
accountCreatedAt: metadata?.accountCreatedAt,
|
||||||
declaredAge: metadata?.declaredAge,
|
declaredAge: metadata?.declaredAge,
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export type AgeAssuranceConfigRegion = AppBskyAgeassuranceDefs.ConfigRegion & {
|
|||||||
* attestation, only age bounds), so we persist it client-side only and bind it
|
* attestation, only age bounds), so we persist it client-side only and bind it
|
||||||
* to its capture region via the key. A grant captured in TX is only ever read
|
* to its capture region via the key. A grant captured in TX is only ever read
|
||||||
* back for TX — it can't silently unlock another region. See
|
* back for TX — it can't silently unlock another region. See
|
||||||
* `getAssuredAgeFromDeviceSignals`.
|
* `getAgeAssuranceDataFromDeviceSignals`.
|
||||||
*/
|
*/
|
||||||
export type AgeAssuranceDeviceSignals = {
|
export type AgeAssuranceDeviceSignals = {
|
||||||
[regionKey: string]: AgeRange.AgeRangeResponse
|
[regionKey: string]: AgeRange.AgeRangeResponse
|
||||||
|
|||||||
+15
-10
@@ -79,26 +79,31 @@ export function createRegionKey(region: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Derives an assured age from native device signals for the given region, but
|
* Derives age assurance data from native device signals for the given region,
|
||||||
* only when the region permits device verification. The signals are expected to
|
* but only when the region permits device verification. The signals are
|
||||||
* already be resolved to the user's current region (see
|
* expected to already be resolved to the user's current region (see
|
||||||
* `getDeviceSignalsFromCacheForCurrentRegion`), so a grant captured in another
|
* `getDeviceSignalsFromCacheForCurrentRegion`), so a grant captured in another
|
||||||
* region won't reach here.
|
* region won't reach here.
|
||||||
*
|
*
|
||||||
* The OS-provided `lowerBound` is the minimum age the platform will attest to,
|
* The OS-provided `lowerBound` is the minimum age the platform will attest to,
|
||||||
* which maps directly onto the `assuredAge` input of the rule engine (i.e.
|
* which maps onto the `assuredAge` input of the rule engine (i.e.
|
||||||
* `IfAssuredOverAge`/`IfAssuredUnderAge` rules).
|
* `IfAssuredOverAge`/`IfAssuredUnderAge` rules).
|
||||||
*
|
*
|
||||||
* Returns undefined when device verification doesn't apply or the OS didn't
|
* Always returns an object (so callers can spread it unconditionally); fields
|
||||||
* provide a usable lower bound.
|
* are populated only when device verification applies and the OS provided
|
||||||
|
* usable data.
|
||||||
*/
|
*/
|
||||||
export function getAssuredAgeFromDeviceSignals(
|
export function getAgeAssuranceDataFromDeviceSignals(
|
||||||
region: AppBskyAgeassuranceDefs.ConfigRegion,
|
region: AppBskyAgeassuranceDefs.ConfigRegion,
|
||||||
deviceSignals: AgeRange.AgeRangeResponse | undefined,
|
deviceSignals: AgeRange.AgeRangeResponse | undefined,
|
||||||
): number | undefined {
|
): {
|
||||||
if (!regionAllowsDeviceVerification(region)) return undefined
|
assuredAge?: number
|
||||||
|
} {
|
||||||
|
if (!regionAllowsDeviceVerification(region)) return {}
|
||||||
const lowerBound = deviceSignals?.lowerBound
|
const lowerBound = deviceSignals?.lowerBound
|
||||||
return typeof lowerBound === 'number' ? lowerBound : undefined
|
return {
|
||||||
|
assuredAge: typeof lowerBound === 'number' ? lowerBound : undefined,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user