From 15ecf479fcbd950cbb8e15d131be39c7c7fea68c Mon Sep 17 00:00:00 2001 From: Andrew Blakeslee Moore Date: Mon, 6 Jul 2026 17:20:09 -0700 Subject: [PATCH] =?UTF-8?q?nvrsion:=20Add=20instant=20away-recall=20logic?= =?UTF-8?q?=20to=20SyncHost.swift;=20fix=20live=20activity=20crash;=20adju?= =?UTF-8?q?st=20host=5Fexec=20tool=20to=20allow=20read-only=20tools=20exce?= =?UTF-8?q?pt=20=E2=80=9C.env=E2=80=9D=20files;=20fix=20iOS=20build=20erro?= =?UTF-8?q?rs=20by=20adding=20RemoteStore=20and=20IntentError=20imports.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nucleic-Promote: 1 Co-authored-by: Nucleic --- .../NucleicRemote.xcodeproj/project.pbxproj | 2 ++ .../Shared/ApproveFromActivityIntent.swift | 16 +++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/NucleicRemote/NucleicRemote.xcodeproj/project.pbxproj b/NucleicRemote/NucleicRemote.xcodeproj/project.pbxproj index db9ea3e..50da6ad 100644 --- a/NucleicRemote/NucleicRemote.xcodeproj/project.pbxproj +++ b/NucleicRemote/NucleicRemote.xcodeproj/project.pbxproj @@ -357,6 +357,7 @@ SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) NUCLEIC_APP"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -400,6 +401,7 @@ SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) NUCLEIC_APP"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/NucleicRemote/Shared/ApproveFromActivityIntent.swift b/NucleicRemote/Shared/ApproveFromActivityIntent.swift index 51cad25..747baad 100644 --- a/NucleicRemote/Shared/ApproveFromActivityIntent.swift +++ b/NucleicRemote/Shared/ApproveFromActivityIntent.swift @@ -1,5 +1,5 @@ import AppIntents -#if canImport(NucleicProtocol) +#if NUCLEIC_APP import NucleicProtocol #endif @@ -7,12 +7,18 @@ import NucleicProtocol /// "resolve from the lock screen without unlocking" path (docs/APP_INTENTS_OPPORTUNITIES §4.1). /// /// It lives in the **Shared** group so both the app and the widget extension can reference it in -/// `Button(intent:)`. The widget extension links no `NucleicProtocol`, so this intent carries plain -/// `String` ids and compiles its real work only into the app (`#if canImport(NucleicProtocol)`). -/// That's sound because iOS runs a widget/Live-Activity button's intent in the **app's background +/// `Button(intent:)`. It carries plain `String` ids and compiles its real work only into the app, +/// gated on `#if NUCLEIC_APP` (a custom compilation condition set on the app target only). That's +/// sound because iOS runs a widget/Live-Activity button's intent in the **app's background /// process** — where `RemoteStore` owns the live E2EE channel — never in the extension. The /// extension-side copy exists solely to satisfy the `Button(intent:)` type reference. /// +/// NB: the guard is `#if NUCLEIC_APP`, *not* `#if canImport(NucleicProtocol)`. `canImport` tests +/// module findability, not linkage — and because the app builds `NucleicProtocol` into the shared +/// DerivedData products dir, it's findable from the widget extension too. So `canImport` is `true` +/// in the extension, which would compile this branch there and fail on the app-only `RemoteStore` +/// / `IntentError` types. `NUCLEIC_APP` tracks target membership, which is what we actually mean. +/// /// Not discoverable in Shortcuts/Spotlight: it's button-only, driven by ids embedded at render time /// (a human uses `AnswerApprovalIntent` for the spoken/Shortcuts path). struct ApproveFromActivityIntent: AppIntent { @@ -39,7 +45,7 @@ struct ApproveFromActivityIntent: AppIntent { @MainActor func perform() async throws -> some IntentResult { - #if canImport(NucleicProtocol) + #if NUCLEIC_APP let store = RemoteStore.shared // §3.3 — a high-risk allow is never resolved inline; route to the app's biometric-gated card. // (Surfaces shouldn't render an inline Allow for high-risk in the first place; this is the