chahinebrini c1edef8abd feat(magic): RebreakMagic device-binding + DNS profile
- backend: /api/magic/{register,devices,profile,release} + AdGuard provisioning + 24h cooldown
- prisma: magic_binding_fields migration (additive on UserDevice)
- mac-app: Phase 2 - Login + MacRegistration + Profile install
- marketing: landing section + /download/rebreakmagic + DMG
- lyra: forbidden phrases + RebreakMagic coach guidance
2026-06-02 09:15:19 +02:00

83 lines
2.5 KiB
Swift

import Foundation
import IOKit
/// Device-Info für den aktuellen Mac.
/// Wird für /api/magic/register benötigt.
struct MacDeviceInfo {
let deviceId: String // IOPlatformUUID
let hostname: String // Host.current().localizedName
let model: String // hw.model via sysctl
let osVersion: String // ProductVersion
}
enum MacDeviceDetectorError: Error, LocalizedError {
case platformUUIDNotFound
case sysctlFailed(String)
var errorDescription: String? {
switch self {
case .platformUUIDNotFound:
return "IOPlatformUUID nicht gefunden"
case .sysctlFailed(let msg):
return "sysctl fehlgeschlagen: \(msg)"
}
}
}
/// Erkennt Mac-Hardware-Infos via IOKit + sysctl.
enum MacDeviceDetector {
/// Liest IOPlatformUUID eindeutige Hardware-ID des Mac.
static func platformUUID() throws -> String {
let service = IOServiceGetMatchingService(
kIOMainPortDefault,
IOServiceMatching("IOPlatformExpertDevice")
)
guard service != 0 else {
throw MacDeviceDetectorError.platformUUIDNotFound
}
defer { IOObjectRelease(service) }
guard let uuidCF = IORegistryEntryCreateCFProperty(
service,
"IOPlatformUUID" as CFString,
kCFAllocatorDefault,
0
)?.takeRetainedValue() as? String else {
throw MacDeviceDetectorError.platformUUIDNotFound
}
return uuidCF
}
/// Liest hw.model via sysctl (z.B. "MacBookPro18,3").
static func hwModel() throws -> String {
var size: size_t = 0
sysctlbyname("hw.model", nil, &size, nil, 0)
var model = [CChar](repeating: 0, count: size)
guard sysctlbyname("hw.model", &model, &size, nil, 0) == 0 else {
throw MacDeviceDetectorError.sysctlFailed("hw.model read failed")
}
return String(cString: model)
}
/// Sammelt alle Infos für /api/magic/register.
static func detect() throws -> MacDeviceInfo {
let deviceId = try platformUUID()
let hostname = Host.current().localizedName ?? "Unknown Mac"
let model = try hwModel()
let osVersion = ProcessInfo.processInfo.operatingSystemVersionString
return MacDeviceInfo(
deviceId: deviceId,
hostname: hostname,
model: model,
osVersion: osVersion
)
}
}