Files
luma/Sources/LumaCore/APNsRegistration.swift
Ole André Vadla Ravnås 8c6de884f2 ci: Embed Developer ID provisioning profile
The 0.1.0 DMG refused to launch with "The application Luma.app
can't be opened." because the signed entitlements declared
aps-environment but no provisioning profile was embedded to
authorize it; amfid kills the process before main().

Split out Luma-Release.entitlements that asks for production
(matching APNsRegistration.environment in release builds), wire
a new APPLE_DEVELOPER_ID_PROFILE secret into CI, copy it into
Contents/embedded.provisionprofile before codesigning, and
verify after the fact that both the sealed entitlements and the
profile itself say aps-environment=production so a future
regression fails the build instead of silently shipping.

Luma.entitlements stays with aps-environment=development for
local Xcode dev and iOS builds.
2026-04-21 18:53:40 +02:00

52 lines
1.6 KiB
Swift

import Foundation
/// Holds the APNs device token that `registerForRemoteNotifications()`
/// hands back via the app delegate, so `Engine` can forward it to the
/// portal when an authenticated session is established.
///
/// The token is per-installation, not per-user, so we keep a single
/// shared instance. `Engine` subscribes once and re-pushes on every
/// authenticated `+welcome` so a signed-in user always has this device's
/// APNs subscription on file.
@MainActor
public final class APNsRegistration {
public static let shared = APNsRegistration()
public private(set) var deviceToken: Data?
public private(set) var lastError: String?
private var observers: [(Data) -> Void] = []
private init() {}
public func setToken(_ data: Data) {
deviceToken = data
lastError = nil
for observer in observers { observer(data) }
}
public func setError(_ message: String) {
lastError = message
}
public func observe(_ handler: @escaping (Data) -> Void) {
observers.append(handler)
if let deviceToken { handler(deviceToken) }
}
public var deviceTokenHex: String? {
deviceToken?.map { String(format: "%02x", $0) }.joined()
}
/// Which APNs endpoint the token is valid against: sandbox for
/// debug builds (signed with `aps-environment = development`) and
/// production for release builds (`aps-environment = production`).
public static var environment: String {
#if DEBUG
return "sandbox"
#else
return "production"
#endif
}
}