RootHeraldKit Swift Package
Swift package built on DCAppAttestService (App Attest) for hardware-backed device claims on iOS 14+ / iPadOS 14+. Like every other platform SDK it is a keyless evidence collector — it holds no RootHerald key and never renders a verdict. It collects an evidence blob over a nonce your backend issued; your backend relays that blob to the verify API, which appraises it.
This SDK is planned and not yet available. Until it ships, mint attestation tokens on the device and verify them server-side with @rootherald/node (or any available server SDK). The API shown below is the planned surface and may change before release.
Install (Swift Package Manager)
dependencies: [
.package(url: "https://github.com/rootherald/rootherald-ios.git",
from: "1.0.0")
],
targets: [
.target(
name: "MyApp",
dependencies: [
.product(name: "RootHeraldKit", package: "rootherald-ios")
]
)
]Attest a sign-up
The client is keyless — the initializer takes no key and no endpoint. It collects an evidence blob over a nonce your backend issued; your backend relays that blob to POST /api/v1/attestations/verify (using its rh_sk_ secret via a server SDK) and enforces the verdict. The verdict never travels through the app.
import RootHeraldKit
@MainActor
final class SignupViewModel: ObservableObject {
// Keyless: no api_key, no endpoint — nothing to connect to.
private let client = RootHeraldClient()
func submit(email: String, password: String) async {
do {
// 1. Ask YOUR backend for a fresh challenge nonce (it called
// POST /api/v1/attestations/challenge with its rh_sk_ secret).
let nonce = try await api.challengeNonce(action: "signup")
// 2. Collect a keyless evidence blob on-device — no verdict, no
// call to RootHerald.
let evidence = try await client.collectEvidence(nonce: nonce)
// 3. Relay the opaque blob to your backend, which POSTs it to
// /attestations/verify and enforces the returned verdict.
try await api.signup(email: email, password: password,
evidence: evidence)
} catch {
showError("Evidence collection failed: \(error)")
}
}
}Your app must enable the App Attest capability under Signing & Capabilities. Without the entitlement, DCAppAttestService.isSupported returns false and collectEvidence throws RootHeraldError.unsupported with the reason App Attest unsupported.
Where the evidence goes
The client opens no socket to RootHerald and carries no secret — it always hands the collected blob back to your own app code, which relays it to your backend. Your backend issues the nonce, POSTs the evidence to POST /api/v1/attestations/verify, and enforces the verdict — all authenticated with its rh_sk_ secret via a server SDK such as @rootherald/node. The secret must never reach the device.
XCFramework distribution
For consumers who don't use SPM, ship an XCFramework. Build script in src/clients/ios/BUILD.md wraps the device-slice + simulator-slice archive into a single RootHeraldKit.xcframework ready to vendor.
Sample app
A single-file SwiftUI sample ships alongside the SDK when it is released, so you can run a working end-to-end sign-up flow without writing the integration from scratch.