learning_ai_common_plat/packages/swift-platform-sdk/Sources/BLLicenseClient.swift
saravanakumardb1 23d14f33ea feat(swift-sdk): add 6 new components — BLBlobClient, BLKillSwitchClient, BLLicenseClient, BLBiometricAuth, BLCrashReporter, BLAuditLogger
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).
2026-02-28 22:38:43 -08:00

104 lines
3.5 KiB
Swift

// License Client
// Generic license key activation via platform-service.
// Flow: enter key POST /api/licenses/activate receive tokens.
// Product apps configure with BLPlatformConfig.
import Foundation
/// License information returned from platform-service.
public struct BLLicenseInfo: Codable, Sendable {
public let key: String
public let plan: String
public let status: String
public let devicesUsed: Int
public let maxDevices: Int
public let expiresAt: String?
public init(key: String, plan: String, status: String, devicesUsed: Int, maxDevices: Int, expiresAt: String?) {
self.key = key
self.plan = plan
self.status = status
self.devicesUsed = devicesUsed
self.maxDevices = maxDevices
self.expiresAt = expiresAt
}
}
/// Activation result containing tokens + license info.
public struct BLActivationResult: Sendable {
public let accessToken: String
public let refreshToken: String
public let license: BLLicenseInfo
}
/// Generic license client for all ByteLyst iOS apps.
/// Handles license key activation and status checking via platform-service.
public final class BLLicenseClient {
private let config: BLPlatformConfig
private let client: BLPlatformClient
public init(config: BLPlatformConfig, client: BLPlatformClient) {
self.config = config
self.client = client
}
// MARK: - Activate
/// Activate a license key on this device.
/// Returns activation result with tokens and license info.
public func activate(key: String, deviceId: String, deviceName: String) async throws -> BLActivationResult {
let body: [String: String] = [
"key": key.uppercased().trimmingCharacters(in: .whitespaces),
"deviceId": deviceId,
"deviceName": deviceName,
"platform": config.platform,
]
let (data, _) = try await client.rawRequest(path: "/api/licenses/activate", method: "POST", body: body)
struct ActivateResponse: Codable {
let accessToken: String
let refreshToken: String
let license: LicenseDoc
}
struct LicenseDoc: Codable {
let key: String
let plan: String
let status: String
let deviceIds: [String]
let maxDevices: Int
let expiresAt: String?
let userId: String
}
let result = try JSONDecoder().decode(ActivateResponse.self, from: data)
let info = BLLicenseInfo(
key: result.license.key,
plan: result.license.plan,
status: result.license.status,
devicesUsed: result.license.deviceIds.count,
maxDevices: result.license.maxDevices,
expiresAt: result.license.expiresAt
)
return BLActivationResult(
accessToken: result.accessToken,
refreshToken: result.refreshToken,
license: info
)
}
// MARK: - Status
/// Check license status without activating.
public func checkStatus(key: String) async throws -> BLLicenseInfo {
let encodedKey = key.uppercased().trimmingCharacters(in: .whitespaces)
return try await client.request(
path: "/api/licenses/status/\(encodedKey)",
responseType: BLLicenseInfo.self
)
}
}