# KeyManager Component The KeyManager is the central coordinator for the Keys for All system. It manages key activation, inventory, and coordinates with other components. Based on the comprehensive architecture, it includes advanced features like undo mechanisms, bulk operations, and enhanced security. ## Pseudocode ```swift class KeyManager { // Singleton instance static shared = KeyManager() // Current state @Published currentLicenseLevel: LicenseLevel = .free @Published keyInventory: [String] = [] @Published isActivating: Bool = false // Dependencies private validator: KeyValidator private storage: KeyStorage private featureGating: FeatureGating private analytics: KeyAnalytics private undoManager: KeyUndoManager // MARK: - Key Activation func activate(key: String) async -> Result { isActivating = true defer { isActivating = false } // Step 1: Validate key format let validationResult = await validator.validate(key) if !validationResult.isValid { analytics.trackKeyEvent(KeyEvent( type: .activation, level: nil, success: false, error: validationResult.error )) return .failure(validationResult.error) } // Step 2: Check if key already used if storage.isKeyUsed(key) { analytics.trackKeyEvent(KeyEvent( type: .activation, level: validationResult.level, success: false, error: .alreadyActivated )) return .failure(.alreadyActivated) } // Step 3: Extract license level from key guard let level = validationResult.level else { return .failure(.invalidLevel) } // Step 4: Store previous state for undo let previousState = LicenseState( level: currentLicenseLevel, activatedDate: Date() ) // Step 5: Store the key securely do { try storage.storeKey(key, level: level) } catch { return .failure(.storageFailed) } // Step 6: Update current license level currentLicenseLevel = level // Step 7: Update feature gating featureGating.updateAvailableFeatures(for: level) // Step 8: Setup undo mechanism undoManager.registerUndo( key: key, previousState: previousState, duration: 3600 // 1 hour ) // Step 9: Track successful activation analytics.trackKeyEvent(KeyEvent( type: .activation, level: level, success: true, error: nil )) // Step 10: Post notification for UI updates NotificationCenter.post("KeysForAllLicenseChanged", level) return .success(License(key: key, level: level)) } // MARK: - Key Inventory Management func addToInventory(keys: [String]) { keyInventory.append(contentsOf: keys) storage.saveInventory(keyInventory) } func shareKey(at index: Int) -> String? { guard index < keyInventory.count else { return nil } let key = keyInventory.remove(at: index) storage.saveInventory(keyInventory) return key } // MARK: - License Queries func hasFeature(_ feature: Feature) -> Bool { return currentLicenseLevel.rawValue >= feature.requiredLevel.rawValue } func keysNeededFor(_ feature: Feature) -> Int { let current = currentLicenseLevel.rawValue let required = feature.requiredLevel.rawValue return max(0, required - current) } // MARK: - Demo Mode func enableDemoMode(for feature: Feature, duration: TimeInterval = 30) { guard currentLicenseLevel < feature.requiredLevel else { return } featureGating.temporarilyUnlock(feature, for: duration) // Track demo usage analytics.trackKeyEvent(KeyEvent( type: .demo, level: currentLicenseLevel, success: true, error: nil )) } // MARK: - Undo System func canUndo() -> Bool { return undoManager.canUndo() } func timeRemainingForUndo() -> TimeInterval? { return undoManager.timeRemaining() } func undoLastActivation() async -> Result { guard let undoAction = undoManager.getUndoAction() else { return .failure(.noUndoAvailable) } // Restore previous state currentLicenseLevel = undoAction.previousState.level // Update feature gating featureGating.updateAvailableFeatures(for: currentLicenseLevel) // Remove key from storage try? storage.removeKey(undoAction.key) // Track undo event analytics.trackKeyEvent(KeyEvent( type: .undo, level: currentLicenseLevel, success: true, error: nil )) // Post notification NotificationCenter.post("KeysForAllLicenseChanged", currentLicenseLevel) return .success(()) } // MARK: - Bulk Operations func activateMultipleKeys(_ keys: [String]) async -> [Result] { var results: [Result] = [] for key in keys { let result = await activate(key: key) results.append(result) // Brief delay to prevent overwhelming the system try? await Task.sleep(nanoseconds: 100_000_000) // 0.1 second } return results } } // Supporting Types enum LicenseLevel: Int { case free = 0 case level1 = 1 case level2 = 2 } struct License { let key: String let level: LicenseLevel let activatedDate: Date = Date() } enum KeyError: Error { case invalidFormat case checksumMismatch case alreadyActivated case unsupportedLevel case invalidLevel case storageFailed case noUndoAvailable case networkError case temporaryFailure } struct LicenseState { let level: LicenseLevel let activatedDate: Date } struct KeyEvent { let type: KeyEventType let level: LicenseLevel? let success: Bool let error: KeyError? let timestamp: Date = Date() } enum KeyEventType { case activation case demo case undo case sharing case validation } // MARK: - Key Undo Manager class KeyUndoManager { private var undoAction: UndoAction? private var undoTimer: Timer? struct UndoAction { let key: String let previousState: LicenseState let expiryDate: Date } func registerUndo(key: String, previousState: LicenseState, duration: TimeInterval) { // Cancel any existing undo undoTimer?.invalidate() // Create new undo action undoAction = UndoAction( key: key, previousState: previousState, expiryDate: Date().addingTimeInterval(duration) ) // Setup expiry timer undoTimer = Timer.scheduledTimer(withTimeInterval: duration, repeats: false) { _ in self.undoAction = nil } } func canUndo() -> Bool { guard let action = undoAction else { return false } return Date() < action.expiryDate } func timeRemaining() -> TimeInterval? { guard let action = undoAction else { return nil } let remaining = action.expiryDate.timeIntervalSince(Date()) return remaining > 0 ? remaining : nil } func getUndoAction() -> UndoAction? { guard canUndo() else { return nil } let action = undoAction undoAction = nil undoTimer?.invalidate() return action } } // MARK: - Key Analytics class KeyAnalytics { private let telemetry = TelemetryService() func trackKeyEvent(_ event: KeyEvent) { // Anonymous tracking only let anonymizedEvent = AnonymizedKeyEvent( type: event.type, level: event.level, timestamp: event.timestamp.timeIntervalSince1970, success: event.success ) telemetry.record(anonymizedEvent) } func generateUsageReport() async -> KeyUsageReport { let events = await telemetry.fetchEvents() return KeyUsageReport( totalActivations: countActivations(events), activationsByLevel: groupByLevel(events), successRate: calculateSuccessRate(events), demoUsage: countDemoUsage(events), undoUsage: countUndoUsage(events) ) } private func countActivations(_ events: [AnonymizedKeyEvent]) -> Int { return events.filter { $0.type == .activation && $0.success }.count } private func groupByLevel(_ events: [AnonymizedKeyEvent]) -> [LicenseLevel: Int] { var counts: [LicenseLevel: Int] = [:] for event in events { if event.type == .activation && event.success, let level = event.level { counts[level, default: 0] += 1 } } return counts } private func calculateSuccessRate(_ events: [AnonymizedKeyEvent]) -> Double { let activations = events.filter { $0.type == .activation } let successful = activations.filter { $0.success } return activations.isEmpty ? 0 : Double(successful.count) / Double(activations.count) } private func countDemoUsage(_ events: [AnonymizedKeyEvent]) -> Int { return events.filter { $0.type == .demo }.count } private func countUndoUsage(_ events: [AnonymizedKeyEvent]) -> Int { return events.filter { $0.type == .undo }.count } } struct AnonymizedKeyEvent { let type: KeyEventType let level: LicenseLevel? let timestamp: TimeInterval let success: Bool } struct KeyUsageReport { let totalActivations: Int let activationsByLevel: [LicenseLevel: Int] let successRate: Double let demoUsage: Int let undoUsage: Int } // MARK: - Telemetry Service class TelemetryService { func record(_ event: AnonymizedKeyEvent) { // Store events locally for analytics var events = loadEvents() events.append(event) // Keep only last 1000 events if events.count > 1000 { events = Array(events.suffix(1000)) } saveEvents(events) } func fetchEvents() async -> [AnonymizedKeyEvent] { return loadEvents() } private func loadEvents() -> [AnonymizedKeyEvent] { guard let data = UserDefaults.standard.data(forKey: "telemetry.events"), let events = try? JSONDecoder().decode([AnonymizedKeyEvent].self, from: data) else { return [] } return events } private func saveEvents(_ events: [AnonymizedKeyEvent]) { let data = try? JSONEncoder().encode(events) UserDefaults.standard.set(data, forKey: "telemetry.events") } } ``` ## Component Responsibilities 1. **Central Coordination** - Acts as the main entry point for all key operations - Coordinates between validator, storage, and UI components - Manages complex workflows and state transitions 2. **State Management** - Maintains current license level - Tracks key inventory - Manages activation state - Handles undo state and timers 3. **Business Logic** - Determines feature availability - Calculates keys needed for features - Handles demo mode timing - Manages bulk operations 4. **Event Broadcasting** - Notifies UI of license changes - Updates feature gating system - Tracks analytics events 5. **Advanced Features** - 1-hour undo mechanism - Bulk key activation - Usage analytics - Error recovery 6. **Security & Privacy** - Secure key handling - Anonymous telemetry - Proper error handling - Timing attack prevention ## Integration Points - **Inputs**: Raw key strings from UI, purchase receipts, bulk operations - **Outputs**: License status, feature availability, UI updates, analytics - **Dependencies**: KeyValidator, KeyStorage, FeatureGating, KeyAnalytics, KeyUndoManager - **Observers**: UI components, feature-gated views, analytics dashboard - **Timers**: Undo expiration, demo mode expiration - **Notifications**: License changes, undo availability, error states