Skip to main content

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 .onOpenURL and .onContinueUserActivity(NSUserActivityTypeBrowsingWeb) (iOS picks the delivery route per launch; URLs arriving before initialization finish are parked, latest wins), surfaced on the links: AsyncStream<OptoLinkData> (fresh stream per access with replay-last, never errors).
  • Deferred deep linking: one bulk POST /match with the clipboard token and the fingerprint fields (timezone deliberately omitted — Safari parity); resolveDeferredLink() re-runs the match manually and returns OptoLinkData?.
  • 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. clipboardEnabled opts out.
  • Device identity: UUID v4 deviceId, persisted in UserDefaults; setIdentity / clearIdentity bind it to an end user; trackEvent reports events.
  • Config: OptoLinkConfig (CLIENT-tier apiKey, orgKey, baseUrl: URL, timeout: 10, maxRetries: 2, clipboardEnabled, optional logger).
  • Error model: OptoLinkError protocol with two conformers: OptoLinkApiError (status, requestId, details, retryAfterSeconds, raw) and OptoLinkConnectionError.
  • Retry matrix: /match and link resolution retry on connection errors, 429 (sleeping the body-communicated retryAfterSeconds), and 5xx; events never retry on 5xx; the session ping is fire-and-forget.
  • Logging: OptoLinkLogLevel.info (alongside warning/error) — the SDK logs its decision trail at info (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's matchScore (present only on FINGERPRINT_SCORED matches) surfaces instead of being dropped; nil everywhere 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.