import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# Upgrading from 2.x

3.0 was a major release. This page lists what changes for an app moving from 2.0.0 to 3.1.2, breaking changes first. The 2.0 docs stay at [/docs/v2.0/](/docs/v2.0/). [What's new in 3.0](/docs/v3.0/whats-new/) has the full 3.0 list, and [What's new in 3.1](/docs/mobile/whats-new/) what 3.1 adds.

## 1. Update the version

<Tabs groupId="platform">
  <TabItem value="swift" label="Swift (iOS)">

```swift
.package(url: "https://github.com/octetproof/octet-sdk-ios", exact: "3.1.2")
```

  </TabItem>
  <TabItem value="kotlin" label="Kotlin (Android)">

```kotlin
implementation("com.octetproof:sdk:3.1.2")
```

  </TabItem>
</Tabs>

If you verify proofs yourself with `octet-verify`, run 1.5.0 or later for 3.1 proofs. Checking content commitments needs 1.8.0.

## 2. Review the breaking changes

### Usage reporting is always on

After the first proof of each UTC day, the SDK sends one `device_active` usage record with the next background heartbeat, so Octet can count active devices for billing. The record carries no location, no proof data, no user or account identity and no new device identifier. It never blocks or delays a proof.

`OctetConfig.creditServiceUrl` is only for testing. Leaving it unset, or setting it to `nil` / `null`, does not turn reporting off.

Update your app's privacy disclosures to include the daily usage record. See [Data collection](/docs/mobile/concepts/data-collection/) and [Metrics and usage reporting](/docs/mobile/concepts/metrics/).

### A pinned `claimedRegion` must be an assigned ISO 3166 code

A pinned `claimedRegion` whose code is malformed or not assigned in ISO 3166 produces no proof, and the verdict reason is `regionUnresolved`. 2.0.0 produced a signed proof in this case.

### Android: debugger refusal outside a sandbox session

With a debugger or native tracer attached, the SDK now refuses a proof with `TAMPERING`, as on iOS. A sandbox session (`sandboxBypassToken` set) still allows one, so debugging against the sandbox keeps working.

### Android: `BootstrapReason.NewDevicesBlocked`

`BootstrapReason` gains `NewDevicesBlocked`. A `when (reason)` over `BootstrapReason` without an `else` branch no longer compiles. Add the new case or an `else` branch:

```kotlin
try {
    val sdk = Octet.start(context = applicationContext, config = config)
} catch (e: LicenseError.BootstrapFailed) {
    when (e.reason) {
        // Open the server-signed link exactly as received.
        BootstrapReason.NewDevicesBlocked -> e.upgradeUrl?.let { openInBrowser(it) }
        else -> showStartupError(e)
    }
}
```

On iOS the new case is `.newDevicesBlocked(upgradeUrl:)`. A `switch` with a `default` keeps compiling. See [License Types](/docs/mobile/api-reference/license-types/#bootstrapreason).

### Android: Kotlin binary compatibility

`AdvancedConfig` and `LicenseStatus` gained constructor parameters with defaults. Source that uses named arguments compiles unchanged. Code compiled against 2.0.0 that calls their constructors or `copy` must be recompiled.

## 3. Check the behavior changes

- **The first proof after `Octet.start` waits.** Two changes add up here. Since 3.0, a proof asked for while the SDK is still starting waits for startup to finish, for up to 30 seconds, instead of returning `noFix` / `NO_FIX`. Since 3.1, a fresh proof asked for once it has started also waits for a usable fix while positioning warms up, for up to 30 seconds. If your app applies its own timeout to the first call, allow for this.
- **TLS pins.** The built-in pins for Octet's hosts are updated. If you turned on certificate pinning with 2.0.0, upgrade to 3.1.2.

## 4. Adopt what is new

- **Gateway routing.** Route every SDK network call through your own HTTPS host or through Octet's hosted gateway with `OctetConfig.advanced.transport`. See [Gateway routing](/docs/mobile/concepts/gateway-routing/).
- **`PLAUSIBLE` containment.** Turn on `OctetConfig.advanced.acceptPlausibleContainment` to let disc queries answer from a `PLAUSIBLE` proof. See [Predicates](/docs/mobile/api-reference/predicates/#plausible-containment).
- **Upgrade link on new-device refusal.** Handle `newDevicesBlocked` and open its `upgradeUrl`. See [License Types](/docs/mobile/api-reference/license-types/#bootstrapreason).
