Getting Started
Getting Started
Section titled “Getting Started”SDK Requirements
Section titled “SDK Requirements”iOS Requirements:
- iOS 15.0+
- Xcode 15.0+
Permissions Required: The SDK needs no entitlements and adds no privacy prompt to your app. It uses no location, camera, microphone or contacts API, and the Secure Enclave keys it creates are not gated on biometry, so nothing it does raises a Face ID or passcode dialog.
It does need the Info.plist keys below. alphyn-cli integrate merges them for you; add them by
hand only when you integrate without the CLI.
<!-- Background Task Scheduler Permitted Identifiers --><key>BGTaskSchedulerPermittedIdentifiers</key><array> <string>com.byterialab.backgroundcheck</string></array>
<!-- Background Modes --><key>UIBackgroundModes</key><array> <string>fetch</string></array>
<!-- URL schemes the jailbreak detector probes --><key>LSApplicationQueriesSchemes</key><array> <string>cydia</string> <string>sileo</string> <string>zbra</string> <string>filza</string> <string>undecimus</string> <string>installer</string> <string>taig</string> <string>dopamine</string> <string>trollstore</string> <string>trollstorehelper</string></array>
<!-- Network Security Configuration (App Transport Security) --><key>NSAppTransportSecurity</key><dict> <key>NSAllowsArbitraryLoads</key> <false/> <key>NSExceptionDomains</key> <dict> <key>alphyn-attestation-api.byterialab.com</key> <dict> <key>NSExceptionAllowsInsecureHTTPLoads</key> <true/> <key>NSExceptionRequiresForwardSecrecy</key> <false/> <key>NSIncludesSubdomains</key> <true/> </dict> </dict></dict>Important Notes for Info.plist:
- The
BGTaskSchedulerPermittedIdentifierskey is required and must includecom.byterialab.backgroundcheck. - The
fetchbackground mode is required forBGAppRefreshTaskto allow background security checks. - The
LSApplicationQueriesSchemeslist is what the jailbreak detector probes.canOpenURLreturns false for any scheme the host app has not declared, so a shortened list silently narrows detection and produces no error. - The
NSAppTransportSecurityexception is required; the SDK cannot reach the backend without it. The attestation host presents a certificate from a private CA (CN=Byteria Root CA) that the system trust store does not carry, so without the exception the connection is refused inside ATS with TLS error-9802and the SDK’s own certificate check is never reached, so init fails at launch.NSExceptionAllowsInsecureHTTPLoadsis the key that carries the connection past ATS; the SDK then validates the chain itself against a root anchor bundled inAlphyn.framework, and that pinning stays the effective transport control. The exception is scoped to that one domain and weakens nothing else. - After adding these configurations, clean and rebuild your project. If you encounter registration errors related to background tasks, delete the app from your device/simulator and reinstall it.
Background Task Registration (Required)
Section titled “Background Task Registration (Required)”Call AlphynSDK.register() synchronously in application(_:didFinishLaunchingWithOptions:) - it registers the SDK’s background tasks with iOS and cannot be deferred:
import Alphynimport UIKit
@mainclass AppDelegate: UIResponder, UIApplicationDelegate { func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { do { try AlphynSDK.register() } catch { print("AlphynSDK.register() failed: \(error.localizedDescription)") } return true }}Install the SDK
Section titled “Install the SDK”There are three ways to add the framework. Pick one; the Info.plist keys and the register() call above, and Initialize the SDK below, are the same whichever you choose.
- Option 1, the Alphyn CLI: one command wires everything. Recommended.
- Option 2, from the registry by hand: you add a Swift Package
binaryTargetyourself and the registry serves the framework. Nothing is committed into your repo. - Option 3, offline: an
Alphyn.xcframeworkyou download and embed, for build machines that cannot reach the registry.
Option 1: Install with the Alphyn CLI (recommended)
Section titled “Option 1: Install with the Alphyn CLI (recommended)”alphyn-cli integrate --ios-api-key <IOS_APP_KEY>It generates a local Swift package that resolves Alphyn.xcframework from the Alphyn package registry as a checksum-pinned binaryTarget, wires it into your Xcode project, merges the required Info.plist keys, adds the launch hook, and installs the archive post-action that registers each build. Swift Package Manager authenticates to the registry with your app API key through ~/.netrc; see SDK Registry Access and CLI: iOS.
For the development loop, pin your app’s debug hash from the dashboard under App Details. An iOS app’s hash changes on every build and only archives register, so debug and simulator builds cannot initialize the SDK without it:
alphyn-cli integrate --ios-api-key <IOS_APP_KEY> --ios-debug-hash <64-HEX>Option 2: Install from the registry, by hand (no CLI)
Section titled “Option 2: Install from the registry, by hand (no CLI)”Add Alphyn.xcframework as a checksum-pinned Swift Package binaryTarget yourself and let the registry serve it. Nothing is downloaded into your repo.
Before you start: register your iOS app and generate its API key (see How to Register Your App).
Step 1. Let Swift Package Manager authenticate to the registry. Add one line to your ~/.netrc (the login is the literal x, the password is your app API key); see SDK Registry Access:
machine packages.byterialab.com login x password <YOUR_APP_API_KEY>Step 2. Ask the registry for the latest framework. One call returns the version, the zip URL, and the checksum (the user is x, the password is your key):
curl -u "x:<YOUR_APP_API_KEY>" https://packages.byterialab.com/spm/latest# -> {"version":"...","url":"https://packages.byterialab.com/spm/<version>/Alphyn.xcframework.zip","checksum":"<sha256>"}Step 3. Declare the binary target. Put a local Package.swift in your project with the url and checksum from Step 2:
// swift-tools-version:5.9import PackageDescription
let package = Package( name: "AlphynLocal", products: [.library(name: "Alphyn", targets: ["Alphyn"])], targets: [ .binaryTarget( name: "Alphyn", url: "https://packages.byterialab.com/spm/<version>/Alphyn.xcframework.zip", checksum: "<checksum from /spm/latest>" ) ])Step 4. Add the package to Xcode. In Xcode: File -> Add Package Dependencies -> Add Local, select the folder that holds this Package.swift, and add the Alphyn product to your app target.
Expected result: Xcode resolves Alphyn and verifies the download against your checksum. If it cannot authenticate, recheck the ~/.netrc line in Step 1.
Then add the Info.plist keys and the register() call above, Initialize the SDK below, and register your builds with the Xcode archive post-action.
Option 3: Install offline (embedded XCFramework)
Section titled “Option 3: Install offline (embedded XCFramework)”If your build cannot reach the registry, embed the self-contained Alphyn.xcframework directly. It carries the native inside it and needs no registry access at build time.
Step 1. Download Alphyn.xcframework from your app’s SDK Downloads page in the Alphyn dashboard. The download is gated by your app API key.
Step 2. Drag Alphyn.xcframework into your Xcode project’s “Frameworks, Libraries, and Embedded Content” section, and set it to Embed & Sign.
Step 3. Register each build. Without the archive post-action the CLI installs, a build is never enrolled and the app fails attestation at runtime with no build-time error. See Register via Xcode post-action.
Quick Start Integration
Section titled “Quick Start Integration”Basic Integration Example:
import SwiftUIimport Alphyn
// It is highly recommended to initialize AlphynSDK in your App's entry point// (e.g., in your App.swift struct or AppDelegate) for best performance// and consistent lifecycle management.
// Example (in your App.swift):// @main// struct YourApp: App {// @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate// var body: some Scene {// WindowGroup {// ContentView()// }// }// }//// In your AppDelegate.swift:// class AppDelegate: UIResponder, UIApplicationDelegate {// func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {// // 1. Register Alphyn background tasks (synchronous, must run at launch).// do {// try AlphynSDK.register()// } catch {// print("AlphynSDK.register() failed: \(error.localizedDescription)")// }// // 2. Initialize the SDK (async). `initialize` is `async throws` - call it with `try await`.// Task {// do {// try await AlphynSDK.initialize(interval: 45) // seconds, must be > 8// } catch {// print("AlphynSDK initialization failed: \(error)")// }// }// return true// }// }
final class QuickStartSecurityListener: AlphynSecurityListener { private let onThreatDetectedAction: (String) -> Void
init(onThreatDetectedAction: @escaping (String) -> Void) { self.onThreatDetectedAction = onThreatDetectedAction }
func onSuccess(_ result: AlphynCallbackResult) { print("Alphyn Success: \(result.message)") if result.originalEventType == .initComplete { print("AlphynSDK initialized successfully") } }
func onFailure(_ result: AlphynCallbackResult) { print("Alphyn Failure: \(result.message)") }
func onThreatDetected(_ result: AlphynCallbackResult) { print("Alphyn Threat detected: \(result.message)") onThreatDetectedAction(result.message) }}
struct ContentView: View { @State private var showingThreatAlert = false @State private var threatMessage: String = "" @State private var securityListener: QuickStartSecurityListener?
var body: some View { VStack { Text("Alphyn SDK Integration Example") .font(.largeTitle) .padding()
Text("App is running. Check console for Alphyn SDK events.") .padding() } .onAppear { // Initialize SDK (if not done in AppDelegate). // For production apps, initialization should ideally happen once at the app's entry point. if !AlphynSDK.isInitialized() { Task { do { try await AlphynSDK.initialize(interval: 45) print("AlphynSDK initialized in ContentView.onAppear") } catch { print("AlphynSDK initialization failed: \(error)") } } }
// Create and add the security listener when the view appears securityListener = QuickStartSecurityListener { message in self.threatMessage = message self.showingThreatAlert = true }
if let listener = securityListener { AlphynSDK.addSecurityListener(listener) } } .onDisappear { // Remove the security listener when the view disappears if let listener = securityListener { AlphynSDK.removeSecurityListener(listener) self.securityListener = nil } } .alert("Security Alert", isPresented: $showingThreatAlert) { Button("OK") { threatMessage = "" showingThreatAlert = false } } message: { Text(threatMessage.isEmpty ? "A security threat has been detected." : threatMessage) } }}