From ac5793c39f6d660c3db52c3c30f86a6cfd02149f Mon Sep 17 00:00:00 2001 From: dbuskariol <32349796+dbuskariol@users.noreply.github.com> Date: Mon, 20 Jul 2026 01:35:28 +1000 Subject: [PATCH] Deduplicate Login Items recovery action --- Delta.xcodeproj/project.pbxproj | 12 +++---- Documentation/RELEASE_NOTES.md | 1 + Documentation/VERIFICATION_REPORT.md | 9 +++--- Scripts/lib/delta-release.sh | 11 ++++++- Scripts/manual-acceptance-items.sh | 2 +- Sources/Delta/ContentView.swift | 25 +++++++++++---- .../DeltaCore/SettingsSurfaceContract.swift | 21 ++++++++++++ .../SettingsSurfaceContractTests.swift | 32 +++++++++++++++++++ docs/PRODUCTION_READINESS.md | 2 +- project.yml | 6 ++-- 10 files changed, 99 insertions(+), 22 deletions(-) diff --git a/Delta.xcodeproj/project.pbxproj b/Delta.xcodeproj/project.pbxproj index c730294..b360561 100644 --- a/Delta.xcodeproj/project.pbxproj +++ b/Delta.xcodeproj/project.pbxproj @@ -992,7 +992,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = Packaging/Delta.entitlements; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 13; + CURRENT_PROJECT_VERSION = 14; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = Packaging/Delta.app.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; @@ -1010,7 +1010,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = Packaging/Delta.entitlements; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 13; + CURRENT_PROJECT_VERSION = 14; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = Packaging/Delta.app.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; @@ -1122,7 +1122,7 @@ APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_ENTITLEMENTS = "$(DELTA_FSKIT_CODE_SIGN_ENTITLEMENTS)"; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 13; + CURRENT_PROJECT_VERSION = 14; DELTA_FSKIT_CODE_SIGN_ENTITLEMENTS = Packaging/DeltaTimeMachineFS.entitlements; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = Packaging/DeltaTimeMachineFS.Info.plist; @@ -1238,7 +1238,7 @@ buildSettings = { COMBINE_HIDPI_IMAGES = YES; CREATE_INFOPLIST_SECTION_IN_BINARY = YES; - CURRENT_PROJECT_VERSION = 13; + CURRENT_PROJECT_VERSION = 14; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = Packaging/DeltaTimeMachineHelper.Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -1274,7 +1274,7 @@ APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_ENTITLEMENTS = "$(DELTA_FSKIT_CODE_SIGN_ENTITLEMENTS)"; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 13; + CURRENT_PROJECT_VERSION = 14; DELTA_FSKIT_CODE_SIGN_ENTITLEMENTS = Packaging/DeltaTimeMachineFS.entitlements; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = Packaging/DeltaTimeMachineFS.Info.plist; @@ -1309,7 +1309,7 @@ buildSettings = { COMBINE_HIDPI_IMAGES = YES; CREATE_INFOPLIST_SECTION_IN_BINARY = YES; - CURRENT_PROJECT_VERSION = 13; + CURRENT_PROJECT_VERSION = 14; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = Packaging/DeltaTimeMachineHelper.Info.plist; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/Documentation/RELEASE_NOTES.md b/Documentation/RELEASE_NOTES.md index b05c277..282a782 100644 --- a/Documentation/RELEASE_NOTES.md +++ b/Documentation/RELEASE_NOTES.md @@ -29,6 +29,7 @@ Delta 0.4.0 adds native Time Machine-format destinations: - Keeps a partial FSKit/APFS mount in an explicit cleanup-only state: storage telemetry can no longer erase a system-connection failure, and no UI or command surface offers Back Up Now until macOS returns the exact Time Machine destination identity. - Places the privileged setup daemon in Apple's current `SMAppService` executable layout and rejects the obsolete `SMJobBless` helper location, preventing update-time launch constraints from being bound to a legacy bundle structure. - Adds a fail-closed clean-install release gate for the exact notarized app: after native administrator approval, Delta must launch and authenticate the embedded privileged helper by Security code hash, and candidate-bound evidence must match the app, helper, source commit, immutable build, and canonical `/Applications/Delta.app` path before publishing. +- Shows one authoritative Review Login Items action in Permissions when Time Machine system support and scheduled backups need the same macOS recovery surface. This release also restores live Activity output following: diff --git a/Documentation/VERIFICATION_REPORT.md b/Documentation/VERIFICATION_REPORT.md index 0be9813..4e083e7 100644 --- a/Documentation/VERIFICATION_REPORT.md +++ b/Documentation/VERIFICATION_REPORT.md @@ -1,16 +1,16 @@ # Delta Verification Report -Date: 19 July 2026 +Date: 20 July 2026 Host: macOS 26.5.2 (25F84) -Candidate: Delta 0.4.0 (13) +Candidate: Delta 0.4.0 (14) Status: exact-candidate verification contract ## Outcome -Delta's source, deterministic acceptance harnesses, Developer ID build, stable installer, notarization flow, Sparkle packaging, privacy controls, and production-readiness checks are covered by the release contract below. The source identifies the next candidate as `0.4.0` (13). +Delta's source, deterministic acceptance harnesses, Developer ID build, stable installer, notarization flow, Sparkle packaging, privacy controls, and production-readiness checks are covered by the release contract below. The source identifies the next candidate as `0.4.0` (14). A release must not be merged, tagged, or published until the complete exact-commit gate, separate app and DMG notarization, stapling, Gatekeeper checks, signed-update installation, manual acceptance matrix, and required genuine external-provider evidence have all passed for this version. Generated evidence under `dist/` is authoritative for the commit, installed path, CDHash, notarization IDs, artifact hashes, command results, and acceptance status; this tracked report deliberately does not duplicate volatile identity values or claim that an unverified source commit has passed. @@ -35,6 +35,7 @@ A release must not be merged, tagged, or published until the complete exact-comm - Removed Intel-sensitive `pipefail` handling from bundled-tool validation and made the crash-marker scan portable to clean macOS runners without ripgrep. - Added Delta-managed Time Machine-format destinations backed by a provisioned FSKit extension, bounded local cache, authenticated remote generations, verified recovery-key retention, safe reconnect and removal, and the existing native Permissions guidance. - Added a clean first-registration Time Machine system-support acceptance gate that uses the production Service Management and authenticated XPC path, binds evidence to the exact notarized installed candidate and helper code hashes, and prevents publishing from treating retained development registration state or a transient build location as release proof. +- Kept the Permissions surface to one authoritative Review Login Items action when Time Machine system support and scheduled backups both need attention, and bound the generated Xcode project and its source specification to the same immutable build identity. ## Automated verification contract @@ -69,7 +70,7 @@ Finalization requires separate accepted Apple submissions for the app archive an ## Required release handoff -1. Build, install, and complete all exact-commit automated, signing, Apple notarization, stapling, Gatekeeper, and evidence checks for `0.4.0` (13). +1. Build, install, and complete all exact-commit automated, signing, Apple notarization, stapling, Gatekeeper, and evidence checks for `0.4.0` (14). 2. Complete every row of the exact-candidate manual acceptance matrix, including a real signed Sparkle upgrade and system-delivered notifications. 3. Provide and exercise genuine external mounted SMB or NFS, non-local SFTP, and non-local S3-compatible fixtures, plus any additional backend families intended for this release. 4. Obtain a fully passing production-readiness result before merging, tagging `v0.4.0`, or publishing. diff --git a/Scripts/lib/delta-release.sh b/Scripts/lib/delta-release.sh index a3267aa..bf42d55 100644 --- a/Scripts/lib/delta-release.sh +++ b/Scripts/lib/delta-release.sh @@ -293,7 +293,7 @@ delta_assert_clean_worktree() { delta_assert_release_metadata() { local root="$1" - local settings version build notes_heading tag + local settings version build project_versions project_builds notes_heading tag settings="$(/usr/bin/xcodebuild \ -project "$root/Delta.xcodeproj" \ -scheme Delta \ @@ -307,6 +307,15 @@ delta_assert_release_metadata() { [[ "$build" =~ ^[1-9][0-9]*$ ]] \ || delta_fail "CURRENT_PROJECT_VERSION must be a positive integer: ${build:-missing}" + if [[ -f "$root/project.yml" ]]; then + project_versions="$(/usr/bin/awk '/MARKETING_VERSION:/ { print $2 }' "$root/project.yml" | /usr/bin/sort -u)" + project_builds="$(/usr/bin/awk '/CURRENT_PROJECT_VERSION:/ { print $2 }' "$root/project.yml" | /usr/bin/sort -u)" + [[ "$project_versions" == "$version" ]] \ + || delta_fail "project.yml MARKETING_VERSION values must all match $version" + [[ "$project_builds" == "$build" ]] \ + || delta_fail "project.yml CURRENT_PROJECT_VERSION values must all match $build" + fi + notes_heading="$(/usr/bin/sed -n '1p' "$root/Documentation/RELEASE_NOTES.md" 2>/dev/null || true)" [[ "$notes_heading" == "# Delta $version" ]] \ || delta_fail "release notes must start with '# Delta $version'" diff --git a/Scripts/manual-acceptance-items.sh b/Scripts/manual-acceptance-items.sh index 4d1733e..034b477 100644 --- a/Scripts/manual-acceptance-items.sh +++ b/Scripts/manual-acceptance-items.sh @@ -3,7 +3,7 @@ manual_acceptance_items() { cat <<'EOF' install_identity Install identity and privacy stability Install /Applications/Delta.app, launch it, quit, relaunch, and confirm macOS privacy prompts remain stable across rebuilds signed by the same identity. -settings_surface Settings surface Confirm Settings shows plain-language Scheduled Backups status, not raw LaunchAgent or implementation status; the compact status summary matches Full Disk Access, schedules, Pause automatic runs, Password Access, updates, notifications, idle-sleep protection, and bundled backup-tool state; expand How Scheduled Backups Work and confirm it explains closed-window scheduling, macOS approval, user-level permissions, and policy checks without raw implementation status; Password Access exposes status, refresh, and Repair Password Access; Run Due Now uses the same rules as automatic scheduled runs when they are not paused; Open Activity jumps to live and saved job output for scheduled-run troubleshooting; Start at Login uses macOS Login Items separately from scheduled backups; Sparkle automatic checks and background downloads are configurable; reset buttons restore recommended backup and restore defaults; new-profile schedule defaults are configurable and seed new profiles without rewriting existing ones; backup freshness warnings, source-access warnings, destination-check warnings, local/mounted destination free-space warnings, and activity history retention are configurable or visible where appropriate. +settings_surface Settings surface Confirm Settings shows plain-language Scheduled Backups status, not raw LaunchAgent or implementation status; the compact status summary matches Full Disk Access, schedules, Pause automatic runs, Password Access, updates, notifications, idle-sleep protection, and bundled backup-tool state; expand How Scheduled Backups Work and confirm it explains closed-window scheduling, macOS approval, user-level permissions, and policy checks without raw implementation status; Password Access exposes status, refresh, and Repair Password Access; Run Due Now uses the same rules as automatic scheduled runs when they are not paused; Open Activity jumps to live and saved job output for scheduled-run troubleshooting; Start at Login uses macOS Login Items separately from scheduled backups; when Time Machine system support and Scheduled Backups both need Login Items attention, confirm the System Access card shows exactly one Review Login Items action; Sparkle automatic checks and background downloads are configurable; reset buttons restore recommended backup and restore defaults; new-profile schedule defaults are configurable and seed new profiles without rewriting existing ones; backup freshness warnings, source-access warnings, destination-check warnings, local/mounted destination free-space warnings, and activity history retention are configurable or visible where appropriate. full_disk_access Full Disk Access From Settings, open Privacy & Security, add Delta manually when required, recheck access, and confirm the dashboard only shows Readiness when action is needed. With access off, confirm a Time Machine Connect action routes to Permissions before FSKit, DiskImages, or remote writes begin; with access on, confirm the exact installed app/helper arrangement can add and remove the verified destination through public `tmutil`. scheduled_backups Scheduled Backups Confirm the automated scheduler acceptance report passed, then create an enabled scheduled profile in the UI, approve Delta in Login Items if macOS asks, turn on Pause automatic runs and confirm due runs do not start, resume automatic runs, quit the main window, wait for the scheduler interval, and confirm the scheduled run appears in Dashboard, Activity, and menu bar state after relaunch. password_access Password access Use an app-managed destination and a destination with backend credentials. Confirm Settings and diagnostics show Password Access as Ready, then confirm a scheduled backup does not show interactive Keychain prompts after Repair Password Access has been run when needed. diff --git a/Sources/Delta/ContentView.swift b/Sources/Delta/ContentView.swift index e60d1f1..7eb0525 100644 --- a/Sources/Delta/ContentView.swift +++ b/Sources/Delta/ContentView.swift @@ -3725,6 +3725,15 @@ struct SettingsView: View { } } + private var loginItemsActionPlacement: SettingsLoginItemsActionPlacement { + .resolve( + timeMachineSystemSupportNeedsAttention: + hasTimeMachineDestinations && !model.timeMachineSystemSupportIsCurrent, + scheduledBackupsNeedAttention: + scheduledBackupsPermissionPresentation == .needsAttention + ) + } + private var passwordAccessPermissionPresentation: SettingsPermissionPresentation { switch backgroundSecretAccessSummary.state { case .ready: @@ -3768,8 +3777,8 @@ struct SettingsView: View { model.requestTimeMachineSystemAccess() } .buttonStyle(.borderedProminent) - Button("Review Login Items") { - model.openLoginItemsSettings() + if loginItemsActionPlacement == .timeMachineSystemSupport { + reviewLoginItemsPermissionAction } } } @@ -3797,10 +3806,14 @@ struct SettingsView: View { @ViewBuilder private var scheduledBackupsPermissionActions: some View { - if scheduledBackupsPermissionPresentation == .needsAttention { - Button("Review Login Items") { - model.openLoginItemsSettings() - } + if loginItemsActionPlacement == .scheduledBackups { + reviewLoginItemsPermissionAction + } + } + + private var reviewLoginItemsPermissionAction: some View { + Button("Review Login Items") { + model.openLoginItemsSettings() } } diff --git a/Sources/DeltaCore/SettingsSurfaceContract.swift b/Sources/DeltaCore/SettingsSurfaceContract.swift index 077df39..4975693 100644 --- a/Sources/DeltaCore/SettingsSurfaceContract.swift +++ b/Sources/DeltaCore/SettingsSurfaceContract.swift @@ -1,5 +1,24 @@ import Foundation +public enum SettingsLoginItemsActionPlacement: Equatable, Sendable { + case timeMachineSystemSupport + case scheduledBackups + case hidden + + public static func resolve( + timeMachineSystemSupportNeedsAttention: Bool, + scheduledBackupsNeedAttention: Bool + ) -> Self { + if timeMachineSystemSupportNeedsAttention { + return .timeMachineSystemSupport + } + if scheduledBackupsNeedAttention { + return .scheduledBackups + } + return .hidden + } +} + public enum SettingsSurfaceContract { public static let categoryGeneral = "General" public static let categoryPermissions = "Permissions" @@ -119,6 +138,7 @@ public enum SettingsSurfaceContract { "Compact status summary", "Run Due Now scheduled-backup action", "Start at Login separate from Scheduled Backups", + "One Login Items recovery action per settings context", "Sparkle automatic check and download controls", "Idle-sleep protection", "Expandable Scheduled Backups explanation", @@ -183,6 +203,7 @@ public enum SettingsSurfaceContract { require(requiredManualAcceptanceCoverage, contains: "No raw system service terminology", in: "manual coverage", failures: &failures) require(requiredManualAcceptanceCoverage, contains: "Scheduled Backups activity shortcut", in: "manual coverage", failures: &failures) require(requiredManualAcceptanceCoverage, contains: "Password access repair", in: "manual coverage", failures: &failures) + require(requiredManualAcceptanceCoverage, contains: "One Login Items recovery action per settings context", in: "manual coverage", failures: &failures) require(requiredManualAcceptanceCoverage, contains: "Destination free-space warning control", in: "manual coverage", failures: &failures) require(requiredManualAcceptanceCoverage, contains: "Configurable new-profile schedule defaults", in: "manual coverage", failures: &failures) require(requiredManualAcceptanceCoverage, contains: "Expandable Scheduled Backups explanation", in: "manual coverage", failures: &failures) diff --git a/Tests/DeltaCoreTests/SettingsSurfaceContractTests.swift b/Tests/DeltaCoreTests/SettingsSurfaceContractTests.swift index bee2105..94da9d2 100644 --- a/Tests/DeltaCoreTests/SettingsSurfaceContractTests.swift +++ b/Tests/DeltaCoreTests/SettingsSurfaceContractTests.swift @@ -2,6 +2,37 @@ import XCTest @testable import DeltaCore final class SettingsSurfaceContractTests: XCTestCase { + func testLoginItemsActionHasOneAuthoritativePermissionRow() { + XCTAssertEqual( + SettingsLoginItemsActionPlacement.resolve( + timeMachineSystemSupportNeedsAttention: true, + scheduledBackupsNeedAttention: true + ), + .timeMachineSystemSupport + ) + XCTAssertEqual( + SettingsLoginItemsActionPlacement.resolve( + timeMachineSystemSupportNeedsAttention: true, + scheduledBackupsNeedAttention: false + ), + .timeMachineSystemSupport + ) + XCTAssertEqual( + SettingsLoginItemsActionPlacement.resolve( + timeMachineSystemSupportNeedsAttention: false, + scheduledBackupsNeedAttention: true + ), + .scheduledBackups + ) + XCTAssertEqual( + SettingsLoginItemsActionPlacement.resolve( + timeMachineSystemSupportNeedsAttention: false, + scheduledBackupsNeedAttention: false + ), + .hidden + ) + } + func testSettingsSurfaceContractCoversRequiredCategoriesAndSummary() { XCTAssertEqual( SettingsSurfaceContract.categoryTitles, @@ -58,6 +89,7 @@ final class SettingsSurfaceContractTests: XCTestCase { XCTAssertTrue(SettingsSurfaceContract.requiredManualAcceptanceCoverage.contains("Password access repair")) XCTAssertTrue(SettingsSurfaceContract.requiredManualAcceptanceCoverage.contains("Compact status summary")) XCTAssertTrue(SettingsSurfaceContract.requiredManualAcceptanceCoverage.contains("Run Due Now scheduled-backup action")) + XCTAssertTrue(SettingsSurfaceContract.requiredManualAcceptanceCoverage.contains("One Login Items recovery action per settings context")) XCTAssertTrue(SettingsSurfaceContract.requiredManualAcceptanceCoverage.contains("Expandable Scheduled Backups explanation")) XCTAssertTrue(SettingsSurfaceContract.requiredManualAcceptanceCoverage.contains("Sparkle automatic check and download controls")) XCTAssertTrue(SettingsSurfaceContract.requiredManualAcceptanceCoverage.contains("Idle-sleep protection")) diff --git a/docs/PRODUCTION_READINESS.md b/docs/PRODUCTION_READINESS.md index 32a293b..2d40c0c 100644 --- a/docs/PRODUCTION_READINESS.md +++ b/docs/PRODUCTION_READINESS.md @@ -188,7 +188,7 @@ Use the local acceptance probe report as supporting evidence while filling this | Area | Required evidence | | --- | --- | | Install identity and privacy stability | Install /Applications/Delta.app, launch it, quit, relaunch, and confirm macOS privacy prompts remain stable across rebuilds signed by the same identity. | -| Settings surface | Confirm Settings shows plain-language Scheduled Backups status, not raw LaunchAgent or implementation status; the compact status summary matches Full Disk Access, schedules, Pause automatic runs, Password Access, updates, notifications, idle-sleep protection, and bundled backup-tool state; expand How Scheduled Backups Work and confirm it explains closed-window scheduling, macOS approval, user-level permissions, and policy checks without raw implementation status; Password Access exposes status, refresh, and Repair Password Access; Run Due Now uses the same rules as automatic scheduled runs when they are not paused; Open Activity jumps to live and saved job output for scheduled-run troubleshooting; Start at Login uses macOS Login Items separately from scheduled backups; Sparkle automatic checks and background downloads are configurable; reset buttons restore recommended backup and restore defaults; new-profile schedule defaults are configurable and seed new profiles without rewriting existing ones; backup freshness warnings, source-access warnings, destination-check warnings, local/mounted destination free-space warnings, and activity history retention are configurable or visible where appropriate. | +| Settings surface | Confirm Settings shows plain-language Scheduled Backups status, not raw LaunchAgent or implementation status; the compact status summary matches Full Disk Access, schedules, Pause automatic runs, Password Access, updates, notifications, idle-sleep protection, and bundled backup-tool state; expand How Scheduled Backups Work and confirm it explains closed-window scheduling, macOS approval, user-level permissions, and policy checks without raw implementation status; Password Access exposes status, refresh, and Repair Password Access; Run Due Now uses the same rules as automatic scheduled runs when they are not paused; Open Activity jumps to live and saved job output for scheduled-run troubleshooting; Start at Login uses macOS Login Items separately from scheduled backups; when Time Machine system support and Scheduled Backups both need Login Items attention, confirm the System Access card shows exactly one Review Login Items action; Sparkle automatic checks and background downloads are configurable; reset buttons restore recommended backup and restore defaults; new-profile schedule defaults are configurable and seed new profiles without rewriting existing ones; backup freshness warnings, source-access warnings, destination-check warnings, local/mounted destination free-space warnings, and activity history retention are configurable or visible where appropriate. | | Full Disk Access | From Settings, open Privacy & Security, add Delta manually when required, recheck access, and confirm the dashboard only shows Readiness when action is needed. With access off, confirm a Time Machine Connect action routes to Permissions before FSKit, DiskImages, or remote writes begin; with access on, confirm the exact installed app/helper arrangement can add and remove the verified destination through public `tmutil`. | | Scheduled Backups | Confirm the automated scheduler acceptance report passed, then create an enabled scheduled profile in the UI, approve Delta in Login Items if macOS asks, turn on Pause automatic runs and confirm due runs do not start, resume automatic runs, quit the main window, wait for the scheduler interval, and confirm the scheduled run appears in Dashboard, Activity, and menu bar state after relaunch. | | Password access | Use an app-managed destination and a destination with backend credentials. Confirm Settings and diagnostics show Password Access as Ready, then confirm a scheduled backup does not show interactive Keychain prompts after Repair Password Access has been run when needed. | diff --git a/project.yml b/project.yml index 8aa42cf..07e2ca2 100644 --- a/project.yml +++ b/project.yml @@ -95,7 +95,7 @@ targets: settings: base: CREATE_INFOPLIST_SECTION_IN_BINARY: YES - CURRENT_PROJECT_VERSION: 10 + CURRENT_PROJECT_VERSION: 14 GENERATE_INFOPLIST_FILE: NO INFOPLIST_FILE: Packaging/DeltaTimeMachineHelper.Info.plist MARKETING_VERSION: 0.4.0 @@ -115,7 +115,7 @@ targets: base: APPLICATION_EXTENSION_API_ONLY: YES CODE_SIGN_ENTITLEMENTS: "$(DELTA_FSKIT_CODE_SIGN_ENTITLEMENTS)" - CURRENT_PROJECT_VERSION: 10 + CURRENT_PROJECT_VERSION: 14 DELTA_FSKIT_CODE_SIGN_ENTITLEMENTS: Packaging/DeltaTimeMachineFS.entitlements GENERATE_INFOPLIST_FILE: YES INFOPLIST_FILE: Packaging/DeltaTimeMachineFS.Info.plist @@ -210,7 +210,7 @@ targets: settings: base: CODE_SIGN_ENTITLEMENTS: Packaging/Delta.entitlements - CURRENT_PROJECT_VERSION: 10 + CURRENT_PROJECT_VERSION: 14 GENERATE_INFOPLIST_FILE: NO INFOPLIST_FILE: Packaging/Delta.app.plist LD_RUNPATH_SEARCH_PATHS: "$(inherited) @executable_path/../Frameworks"