# pvtcoms native bindings (UniFFI)

Auto-generated **Kotlin** (Android) and **Swift** (iOS) bindings over the Rust core, produced from the
`pvtcoms-ffi` crate (`../ffi`). This is the FFI layer the architecture calls for — the native apps load
the cdylib built from `pvtcoms-ffi` and call these functions. The desktop app does **not** use this (it
embeds the core directly), so UniFFI never bloats the shipped desktop exe.

## What's exposed (v1 foundation)

The **local, synchronous** crypto/identity operations an app's onboarding / verify / at-rest-storage
screens need, as **typed** UniFFI functions (the secret key never crosses the boundary):

| API | Purpose |
|---|---|
| `version()` | core version string |
| `Identity` (opaque object) | `generate()`, `fromSealed(storageKey, blob)`, `publicKey()`, `fingerprint()`, `sign(msg)`, `toSealed(storageKey)` — the **secret key never leaves Rust** |
| `verify(publicKey, msg, signature)` | check an Ed25519 signature |
| `fingerprint(publicKey)` | short fingerprint for the contact/verify UI |
| `safetyNumber(sessionKey)` | the 16-emoji safety number (verify screen) |
| `seal(key, aad, plaintext)` / `open(...)` | seal/open bytes with the core's audited AEAD |

Bytes are `ByteArray` (Kotlin) / `Data` (Swift) — never hex strings. Errors surface as a Kotlin `FfiException` / Swift `throws`. Transport (Tor), the message session, and
persistent storage are layered on top later — this is the foundation, not the whole app.

## Regenerate the bindings

After changing the `#[uniffi::export]` surface in `ffi/src/lib.rs`:

```bash
cargo build -p pvtcoms-ffi
cargo run -p pvtcoms-ffi --bin uniffi-bindgen -- generate \
    --library target/debug/libpvtcoms_ffi.so --language kotlin --out-dir bindings/kotlin
cargo run -p pvtcoms-ffi --bin uniffi-bindgen -- generate \
    --library target/debug/libpvtcoms_ffi.so --language swift --out-dir bindings/swift
```

(`ktlint` / `swift-format` are used only to pretty-print if installed — their absence is harmless.)

## Build the native library for mobile (needs the platform toolchains — NOT done in CI here)

**Android** — cross-compile the cdylib per ABI with [`cargo-ndk`] (needs the Android NDK):

```bash
cargo install cargo-ndk
rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android
cargo ndk -t arm64-v8a -t armeabi-v7a -t x86_64 -o android/app/src/main/jniLibs build -p pvtcoms-ffi --release
# then drop bindings/kotlin/uniffi/** into android/app/src/main/java/
```

**iOS** — build a static lib per arch and bundle an `.xcframework`:

```bash
rustup target add aarch64-apple-ios aarch64-apple-ios-sim
cargo build -p pvtcoms-ffi --release --target aarch64-apple-ios
# lipo/xcodebuild -create-xcframework ... then add bindings/swift/* to the Xcode project
```

## Use it (examples)

See [`example_usage.kt`](./example_usage.kt) and [`example_usage.swift`](./example_usage.swift).
