// ── Platform Configuration ─────────────────────────────────── // Product-specific config that every BL* service reads from. // Each app creates ONE config at launch and passes it to all services. import Foundation /// Configuration for all ByteLyst platform services. /// Create one instance at app launch and inject into BLTelemetryClient, BLAuthClient, etc. public struct BLPlatformConfig { /// Product identifier (e.g. "chronomind", "lysnrai", "peakpulse", "nomgap", "mindlyst"). public let productId: String /// Platform-service base URL (e.g. "https://api.chronomind.app" or "http://localhost:4003/api"). public let baseURL: String /// Platform string sent in telemetry (e.g. "ios", "watchos", "macos"). public let platform: String /// Channel string sent in telemetry (e.g. "native", "mobile_app"). public let channel: String /// Bundle ID used as Keychain service identifier. public let bundleId: String /// App Group ID for sharing data between app and extensions (optional). public let appGroupId: String? public init( productId: String, baseURL: String, platform: String = "ios", channel: String = "native", bundleId: String, appGroupId: String? = nil ) { self.productId = productId self.baseURL = baseURL self.platform = platform self.channel = channel self.bundleId = bundleId self.appGroupId = appGroupId } /// Convenience: read PLATFORM_SERVICE_URL from Info.plist, fall back to provided default. public static func fromInfoPlist( productId: String, defaultBaseURL: String, platform: String = "ios", channel: String = "native", bundleId: String, appGroupId: String? = nil ) -> BLPlatformConfig { let url = Bundle.main.object(forInfoDictionaryKey: "PLATFORM_SERVICE_URL") as? String ?? defaultBaseURL return BLPlatformConfig( productId: productId, baseURL: url, platform: platform, channel: channel, bundleId: bundleId, appGroupId: appGroupId ) } }