New SDK components extracted from product apps: - BLBlobClient — Azure Blob Storage upload via SAS tokens (from LysnrAI BlobService) - BLKillSwitchClient — Kill switch check from platform-service (from LysnrAI KillSwitchService) - BLLicenseClient — License key activation + status (from LysnrAI LicenseService) - BLBiometricAuth — Face ID / Touch ID wrapper (from LysnrAI BiometricAuth) - BLCrashReporter — MetricKit crash reporting (from ChronoMind CrashReporter) - BLAuditLogger — Local rotating JSON audit log (from LysnrAI AuditLogger) SDK now has 13 source files. Updated README with full component table and migration status (3 apps fully migrated, 18 wrappers total).
59 lines
2.1 KiB
Swift
59 lines
2.1 KiB
Swift
// ── Kill Switch Client ──────────────────────────────────────
|
|
// Checks platform-service kill switch at app launch.
|
|
// If the app is disabled server-side, surfaces a maintenance message.
|
|
// Fails open — network errors allow the app to run.
|
|
|
|
import Foundation
|
|
|
|
/// Generic kill switch client for all ByteLyst iOS apps.
|
|
/// Checks GET /api/settings/kill-switch?productId=X at launch.
|
|
public final class BLKillSwitchClient {
|
|
|
|
private let config: BLPlatformConfig
|
|
|
|
/// Whether the app is disabled by the server.
|
|
public private(set) var isDisabled = false
|
|
|
|
/// Maintenance message from the server (empty if not disabled).
|
|
public private(set) var maintenanceMessage = ""
|
|
|
|
public init(config: BLPlatformConfig) {
|
|
self.config = config
|
|
}
|
|
|
|
/// Check kill switch status. Non-blocking — defaults to enabled on failure (fail open).
|
|
public func check() async {
|
|
guard let url = URL(string: "\(config.baseURL)/api/settings/kill-switch?productId=\(config.productId)") else { return }
|
|
|
|
var request = URLRequest(url: url)
|
|
request.timeoutInterval = 5
|
|
|
|
do {
|
|
let (data, response) = try await URLSession.shared.data(for: request)
|
|
guard let http = response as? HTTPURLResponse, http.statusCode == 200 else { return }
|
|
|
|
struct KillSwitchResponse: Codable {
|
|
let enabled: Bool?
|
|
let disabled: Bool?
|
|
let message: String?
|
|
}
|
|
|
|
let result = try JSONDecoder().decode(KillSwitchResponse.self, from: data)
|
|
|
|
// Support both `enabled: false` and `disabled: true` patterns
|
|
if result.disabled == true || result.enabled == false {
|
|
isDisabled = true
|
|
maintenanceMessage = result.message ?? "\(config.productId) is temporarily unavailable for maintenance."
|
|
}
|
|
} catch {
|
|
// Network error — allow the app to run (fail open)
|
|
}
|
|
}
|
|
|
|
/// Reset the kill switch state (e.g. for retry).
|
|
public func reset() {
|
|
isDisabled = false
|
|
maintenanceMessage = ""
|
|
}
|
|
}
|