Changelog
The SDK runs its own semver clock: 0.x while pre-stable, 1.0 when confident. A breaking change in the backend surface also forces an SDK major.
0.1.0
Initial release.
OptoLink.initialize(config:): idempotent, concurrency-safe; runs the once-per-install deferred match and never throws on network failure.- Universal Links and custom-scheme handling: one ingestion point,
handle(url:), fed from.onOpenURLand.onContinueUserActivity(NSUserActivityTypeBrowsingWeb)(iOS picks the delivery route per launch; URLs arriving before initialization finish are parked, latest wins), surfaced on thelinks: AsyncStream<OptoLinkData>(fresh stream per access with replay-last, never errors). - Deferred deep linking: one bulk
POST /matchwith the clipboard token and the fingerprint fields (timezone deliberately omitted — Safari parity);resolveDeferredLink()re-runs the match manually and returnsOptoLinkData?. - Clipboard gate: on iOS 16+ the pasteboard is probed silently (
detectPatterns) before reading, so organic installs never trigger the paste prompt; on iOS 15 the read surfaces the non-blocking paste banner.clipboardEnabledopts out. - Device identity: UUID v4
deviceId, persisted inUserDefaults;setIdentity/clearIdentitybind it to an end user;trackEventreports events. - Config:
OptoLinkConfig(CLIENT-tierapiKey,orgKey,baseUrl: URL,timeout: 10,maxRetries: 2,clipboardEnabled, optional logger). - Error model:
OptoLinkErrorprotocol with two conformers:OptoLinkApiError(status,requestId,details,retryAfterSeconds,raw) andOptoLinkConnectionError. - Retry matrix:
/matchand link resolution retry on connection errors,429(sleeping the body-communicatedretryAfterSeconds), and5xx; events never retry on5xx; the session ping is fire-and-forget. - Logging:
OptoLinkLogLevel.info(alongsidewarning/error) — the SDK logs its decision trail atinfo(init summary with a redacted key, match attempt/response, per-rung deferred-leg decisions, per-attempt request lines, link emissions, telemetry successes) for live-test observability. OptoLinkData.score: Int?— the backend'smatchScore(present only onFINGERPRINT_SCOREDmatches) surfaces instead of being dropped;nileverywhere else.- Zero third-party dependencies (Foundation/
URLSession, native async/await); iOS 15 floor; distributed via Swift Package Manager as a binary package with an Apple privacy manifest included.
Compatible with OptoLink backend v2.1.0+.
Install via Swift Package Manager: install & initialize.