From 549108bed961d8b3823e6818394773e1b02fef9b Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Sat, 20 Jun 2026 00:40:28 -0400 Subject: [PATCH] fix: package DeviceActivityReport extension as ExtensionKit to pass App Store validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit App Store Connect validation (and Xcode Cloud, which runs the same archive → validate path) rejected the build with two cascading errors on the report extension: 1. Error 90349 — NSExtensionPointIdentifier value "com.apple.deviceactivity.report-extension" was invalid. The report extension point lives in DeviceActivityUI, so the identifier needs the "ui": "com.apple.deviceactivityui.report-extension". (The monitor extension's "com.apple.deviceactivity.monitor-extension" is correct and was unaffected; the report value had simply been pattern-matched off it and dropped the "ui".) 2. Error 91179 — once the identifier was correct, validation reported the appex was "built like an NSExtension" but its extension point requires an ExtensionKit extension: it must live in the Extensions/ directory and declare EXAppExtensionAttributes, not NSExtension in PlugIns/. Fix migrates OpenAppLockReport from a legacy PlugIns app-extension to an ExtensionKit extension: - Info.plist: NSExtension/NSExtensionPointIdentifier -> EXAppExtensionAttributes/EXExtensionPointIdentifier with the ...ui... id. - project.pbxproj: product type app-extension -> extensionkit-extension; file reference wrapper.app-extension -> wrapper.extensionkit-extension; appex moved out of "Embed Foundation Extensions" (PlugIns, dstSubfolderSpec 13) into a new "Embed ExtensionKit Extensions" phase (Extensions, dstSubfolderSpec 16, dstPath $(EXTENSIONS_FOLDER_PATH)). The @main DeviceActivityReportExtension SwiftUI entry point is unchanged and correct for both packagings; no principal class is added (the runtime rejects it for this extension point). Verified by archiving and running App Store validation in Xcode: "OpenAppLock 1.0.0 (1) validated — Your app successfully passed all validation checks." Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_017CGu4VBWwg6he3zeZdLNGe --- OpenAppLock.xcodeproj/project.pbxproj | 19 +++++++++++++++---- OpenAppLockReport/Info.plist | 13 ++++++++++--- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/OpenAppLock.xcodeproj/project.pbxproj b/OpenAppLock.xcodeproj/project.pbxproj index 7f77c6a..3736753 100644 --- a/OpenAppLock.xcodeproj/project.pbxproj +++ b/OpenAppLock.xcodeproj/project.pbxproj @@ -10,7 +10,7 @@ F10000000000000000000001 /* OpenAppLockMonitor.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = B10000000000000000000001 /* OpenAppLockMonitor.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; F10000000000000000000002 /* OpenAppLockShieldConfig.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = B10000000000000000000002 /* OpenAppLockShieldConfig.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; F10000000000000000000003 /* OpenAppLockShieldAction.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = B10000000000000000000003 /* OpenAppLockShieldAction.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - F10000000000000000000004 /* OpenAppLockReport.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = B10000000000000000000004 /* OpenAppLockReport.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + F10000000000000000000004 /* OpenAppLockReport.appex in Embed ExtensionKit Extensions */ = {isa = PBXBuildFile; fileRef = B10000000000000000000004 /* OpenAppLockReport.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -68,11 +68,21 @@ F10000000000000000000001 /* OpenAppLockMonitor.appex in Embed Foundation Extensions */, F10000000000000000000002 /* OpenAppLockShieldConfig.appex in Embed Foundation Extensions */, F10000000000000000000003 /* OpenAppLockShieldAction.appex in Embed Foundation Extensions */, - F10000000000000000000004 /* OpenAppLockReport.appex in Embed Foundation Extensions */, ); name = "Embed Foundation Extensions"; runOnlyForDeploymentPostprocessing = 0; }; + E10000000000000000000002 /* Embed ExtensionKit Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(EXTENSIONS_FOLDER_PATH)"; + dstSubfolderSpec = 16; + files = ( + F10000000000000000000004 /* OpenAppLockReport.appex in Embed ExtensionKit Extensions */, + ); + name = "Embed ExtensionKit Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ @@ -82,7 +92,7 @@ B10000000000000000000001 /* OpenAppLockMonitor.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = OpenAppLockMonitor.appex; sourceTree = BUILT_PRODUCTS_DIR; }; B10000000000000000000002 /* OpenAppLockShieldConfig.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = OpenAppLockShieldConfig.appex; sourceTree = BUILT_PRODUCTS_DIR; }; B10000000000000000000003 /* OpenAppLockShieldAction.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = OpenAppLockShieldAction.appex; sourceTree = BUILT_PRODUCTS_DIR; }; - B10000000000000000000004 /* OpenAppLockReport.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = OpenAppLockReport.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + B10000000000000000000004 /* OpenAppLockReport.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.extensionkit-extension"; includeInIndex = 0; path = OpenAppLockReport.appex; sourceTree = BUILT_PRODUCTS_DIR; }; E60000000000000000000001 /* Shared.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = ""; }; E60000000000000000000002 /* CI.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = CI.xcconfig; sourceTree = ""; }; E60000000000000000000003 /* DeveloperSettings.sample.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = DeveloperSettings.sample.xcconfig; sourceTree = ""; }; @@ -288,6 +298,7 @@ 20A7EDCB2E47B7CD0097608D /* Frameworks */, 20A7EDCC2E47B7CD0097608D /* Resources */, E10000000000000000000001 /* Embed Foundation Extensions */, + E10000000000000000000002 /* Embed ExtensionKit Extensions */, ); buildRules = ( ); @@ -444,7 +455,7 @@ ); productName = OpenAppLockReport; productReference = B10000000000000000000004 /* OpenAppLockReport.appex */; - productType = "com.apple.product-type.app-extension"; + productType = "com.apple.product-type.extensionkit-extension"; }; /* End PBXNativeTarget section */ diff --git a/OpenAppLockReport/Info.plist b/OpenAppLockReport/Info.plist index afa8fd2..06818b8 100644 --- a/OpenAppLockReport/Info.plist +++ b/OpenAppLockReport/Info.plist @@ -2,10 +2,17 @@ - NSExtension + + EXAppExtensionAttributes - NSExtensionPointIdentifier - com.apple.deviceactivity.report-extension + EXExtensionPointIdentifier + com.apple.deviceactivityui.report-extension