> ## Documentation Index
> Fetch the complete documentation index at: https://docs.compliance.legaltalent.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Device signals

> Technical device, connection and capture signals the SDK records for fraud prevention

To help detect fraud, the SDK records **technical** signals about the device, the connection and each capture, and sends them with the requests the flow already makes. It is capture only: nothing here changes a decision, a validation or what the applicant sees, and no extra endpoint or backend work is needed on your side.

Signals are on by default on iOS and Android.

## What is sent

| Where                                                       | What                                                                                                                                                                                                                                                                                                                                                                  |
| ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `client_metadata` on every public call the flow makes       | SDK and OS versions, device model, a hashed device identifier, locale and time zone, clock skew against the server, screen and hardware summary, network type, integrity checks, platform attestation, and session behavior (time per step, retries, interruptions, typing cadence as counts). The first request carries the full block; later ones only what changed |
| `capture_context` next to each captured document and selfie | Which camera was used, motion sensor summary while framing, exposure / focus behavior, frame cadence, and the selfie depth and light checks. A few KB per capture; no frames                                                                                                                                                                                          |
| Headers on every request                                    | `X-LT-SDK`, `X-LT-SDK-Version`, `X-LT-Platform`                                                                                                                                                                                                                                                                                                                       |

Identifiers never leave the device raw: the device identifier (`identifierForVendor` on iOS, `ANDROID_ID` on Android) is sent only as a salted SHA-256 hash.

**Not collected:** location (GPS), advertising identifiers (IDFA / advertising ID), lists of installed apps, Wi-Fi network names, clipboard or typed content. There is no App Tracking Transparency prompt and no new runtime permission.

<Tabs>
  <Tab title="iOS">
    Integrity checks cover jailbreak, simulator, debugger, hooking frameworks, signing / distribution, screen recording and active calls.
  </Tab>

  <Tab title="Android">
    Integrity checks cover root, emulator, debugger, hooking (Frida / Xposed), developer options / ADB, installer, extra displays, non-system accessibility services, user CA certificates, and optionally the signing certificate and Play Integrity. Network transport is reported only if your app already holds `ACCESS_NETWORK_STATE`.
  </Tab>
</Tabs>

## Consent

The entry gate shows one informational line under the terms and privacy links, localized in en / es / pt. When the applicant continues, the SDK records `consent.device_signals = "accepted_with_terms"` with the text version (`v1`). There is no extra checkbox.

## Turn it off

Pass `collectsDeviceSignals: false` to switch everything off: the consent line disappears, no `capture_context` is sent, and `client_metadata` shrinks to the SDK identity and the consent record.

<CodeGroup>
  ```swift iOS theme={null}
  LegalTalentFlowView(
      accessToken: token,
      environment: .production,
      collectsDeviceSignals: false
  )
  ```

  ```kotlin Android theme={null}
  LegalTalentFlowView(
      accessToken = token,
      environment = KYCEnvironment.PRODUCTION,
      collectsDeviceSignals = false,
  )
  ```
</CodeGroup>

## Platform attestation (recommended)

Attestation lets the platform check that captures came from a genuine copy of your app on a genuine device. It is best effort on both platforms: it never blocks a capture and is reported as unavailable when it cannot run.

<Tabs>
  <Tab title="iOS: App Attest">
    The SDK creates an App Attest key per install, attests it once, and signs one assertion per captured image over `sha256(session_id ‖ step_id ‖ image_sha256)`.

    To enable it, turn on the App Attest capability for your App ID and add the entitlement:

    ```xml theme={null}
    <key>com.apple.developer.devicecheck.appattest-environment</key>
    <string>development</string>
    ```

    TestFlight and App Store builds always use the production environment.
  </Tab>

  <Tab title="Android: Play Integrity">
    Pass `deviceSignalsOptions` to enable a Play Integrity request at flow start (nonce `base64url(sha256(session_id))`) and signing-certificate checks:

    ```kotlin theme={null}
    LegalTalentFlowView(
        accessToken = token,
        environment = KYCEnvironment.PRODUCTION,
        deviceSignalsOptions =
            LegalTalentDeviceSignalsOptions(
                // Google Cloud project number linked to the app in Play Console.
                cloudProjectNumber = 123456789012L,
                // Optional: SHA-256 of the Play App Signing and upload certificates.
                expectedSigningCertSha256 = listOf("AB:CD:..."),
                // Optional: your genuine application id.
                expectedPackageName = "com.example.app",
            ),
    )
    ```

    Without `cloudProjectNumber`, attestation is reported as `not_configured`. The app must be linked to that Cloud project in Play Console.
  </Tab>
</Tabs>

## Store declarations

<Tabs>
  <Tab title="Apple privacy manifest">
    `LegalTalentCore` and `LegalTalentUI` ship privacy manifests that declare the collected data types (Device ID and Product Interaction: linked to the user, not used for tracking, purpose App Functionality) and the required-reason APIs they use. Xcode merges them into your app's privacy report; review it before submitting.

    The capture views read device motion without a permission prompt; declaring `NSMotionUsageDescription` in your `Info.plist` is still recommended.
  </Tab>

  <Tab title="Google Play Data safety">
    Declare as collected, not shared, processed for fraud prevention and security:

    * **Device or other IDs**: hashed `ANDROID_ID`, Play Integrity token.
    * **App activity**: app interactions (step timing, retries, typing cadence as counts).
    * **App info and performance → Diagnostics**: device and integrity state, camera and sensor summaries.

    Location is not collected. With `collectsDeviceSignals = false` only the SDK identity and the consent record are sent.
  </Tab>
</Tabs>

## Headless integrations

On iOS, pass a collector to the client and forward its output on each call:

```swift theme={null}
let client = LegalTalentClient(
    accessToken: token,
    environment: .production,
    deviceSignalsCollector: UIKitDeviceSignalsCollector()
)
```

The collector is exposed as `client.deviceSignalsCollector`, and every public call takes a `clientMetadata:` argument. `LegalTalentCapturedFace.captureContext` carries the selfie capture summary.
