Skip to content

Commit fce599a

Browse files
Port forcedotcom#4096: bump SQLCipher 4.16.0 -> 4.17.0 (unit 42/49)
Semantic re-implementation FROM forcedotcom/dev 303013d INTO the ObjC->Swift migration branch. Dependency version bump; PRE-APPROVED gate (still PR-flagged). SQLCipher 4.16.0 -> 4.17.0 (bundled SQLite 3.53.1 -> 3.53.3 at runtime) across the four dependency-declaration sites: - SmartStore.podspec (CocoaPods dependency) - mobilesdk_pods.rb (consuming-app Podfile helper) - SmartStore.xcodeproj + MobileSyncExplorer.xcodeproj SPM exactVersion pins Version-assertion tests updated in the compiled Swift twin SFSmartStoreTests.swift (testSqliteVersion 3.53.3, testSqlCipherVersion 4.17.0 community); de-referenced ObjC SFSmartStoreTests.m ref-synced verbatim. update-sqlcipher SKILL.md synced byte-identical to upstream (typo + template placeholder). SmartStore and MobileSync (top of the dependency chain) TEST BUILD SUCCEEDED; 3 version tests pass (runtime-confirmed 4.17.0 community / SQLite 3.53.3). Marker advanced 41->42 (303013d). Escalation: SQLCipher dependency bump -- flag in PR (pre-approved).
1 parent a9ef244 commit fce599a

10 files changed

Lines changed: 30 additions & 15 deletions

File tree

.claude/pr-escalation-digest.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,8 +240,23 @@ Pre-approved gates (still PR-flag, do NOT re-ask): SQLCipher #4096; Localizable.
240240
MobileSync build green (0 new warnings in diff); 19 SDKCore tests pass (10 validation + 9 recovery). Escalation =
241241
login-UI + login-host failure-recovery behavior + L10n — flag in PR.
242242

243+
### Unit 42 · #4096 — SQLCipher 4.16.0 → 4.17.0 (dependency bump, gate PRE-APPROVED)
244+
**Escalation class: dependency version bump (SQLCipher / SmartStore encryption stack).** Gate was PRE-APPROVED
245+
(Feedback #4) — no re-ask — but per policy every SQLCipher/dependency change is flagged for PR review.
246+
**What changed:** SQLCipher `4.16.0 → 4.17.0` (bundled SQLite `3.53.1 → 3.53.3` at runtime), a mechanical version bump
247+
across the four dependency-declaration sites — `SmartStore.podspec` (CocoaPods), `mobilesdk_pods.rb` (consuming-app
248+
Podfile helper), and the two SPM `XCRemoteSwiftPackageReference` pins (`SmartStore.xcodeproj`, `MobileSyncExplorer.xcodeproj`,
249+
`kind = exactVersion`) — plus the version-assertion tests and the maintenance skill doc.
250+
**Reviewer notes:** (1) No API changes in the SQLCipher 4.17 bump for our usage — SmartStore + MobileSync (top of the
251+
dependency chain) both build clean and the SQLCipher-linked encryption path is unchanged. (2) The version assertions live
252+
in the **compiled Swift twin** `SFSmartStoreTests.swift` (`testSqliteVersion``3.53.3`, `testSqlCipherVersion`
253+
`4.17.0 community`); the de-referenced ObjC `SFSmartStoreTests.m` (0-in-Sources) was ref-synced verbatim for clean future
254+
merges. (3) `SKILL.md` update is byte-identical to upstream (`SQLLite``SQLite` typo + a template-placeholder assertion).
255+
(4) The version swap required a one-time full DerivedData Build-dir wipe (stale precompiled `sqlite3.h` module) — a local
256+
build-cache artifact, not a code issue. SmartStore/MobileSync TEST BUILD green; 3 version tests pass (runtime-confirmed
257+
`4.17.0 community` / SQLite `3.53.3`). **Escalation = SQLCipher dependency bump — flag in PR (pre-approved).**
258+
243259
## Pending escalation units (upcoming — port in order)
244-
- **42 · #4096 — dependency bump (gate PRE-APPROVED):** SQLCipher 4.16 → 4.17 (SmartStore.podspec, mobilesdk_pods.rb).
245260
- **43 · #4098 — OAuth/scene:** nil-sceneId crash fix on advanced-auth browser callback.
246261
- **44 · #4087 — OAuth/token (LIVE-AUTH UNBLOCKER):** token-refresh coordinator; 18 files. Unblocks Phase 2.
247262
- **45 · #4102 — OAuth/token:** improve token-refresh error handling.

.claude/skills/update-sqlcipher/SKILL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,10 @@ Update the cipher provider version test:
9494

9595
Note: The OpenSSL version format is typically like "OpenSSL 3.0.17 1 Jul 2025" and the LibTomCrypt format is like "1.18.2" - check the actual runtime value or SQLCipher release notes.
9696

97-
Update the SQLLite version test:
97+
Update the SQLite version test:
9898
- (void) testSqliteVersion {
9999
NSString* version = [NSString stringWithUTF8String:sqlite3_libversion()];
100-
XCTAssertEqualObjects(version, @"3.50.4");
100+
XCTAssertEqualObjects(version, @"NEW_SQLITE_VERSION");
101101
}
102102

103103
### 4. Check for API Changes

.claude/upstream-sync-backlog.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Upstream Sync Backlog Ledger
22

3-
Marker (done floor): `e4bdf6397` (units 1-41 done) · forcedotcom/dev HEAD (target): `b5d37d807` · **8 units remaining** · Re-seeded: 2026-07-19 (Phase 0 of the resume-porting plan).
3+
Marker (done floor): `303013dd7` (units 1-42 done) · forcedotcom/dev HEAD (target): `b5d37d807` · **7 units remaining** · Re-seeded: 2026-07-19 (Phase 0 of the resume-porting plan).
44

55
> **Direction:** we port changes **FROM** `forcedotcom/dev` **INTO** our ObjC→Swift migration branch
66
> (`feature/objc-to-swift-test-migration`). Each unit is a *semantic re-implementation* against the current
@@ -17,7 +17,7 @@ Marker (done floor): `e4bdf6397` (units 1-41 done) · forcedotcom/dev HEAD (ta
1717
> non-libs (CI, docs, skills, sample apps). Live progress bar = subject of lead task #9.
1818
1919
## Migration status
20-
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░ 41/49 units done (84%) · libs-production-impacting: 15/21 · Phase 1 porting (units 1-41 ✅)
20+
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░ 42/49 units done (86%) · libs-production-impacting: 15/21 · Phase 1 porting (units 1-42 ✅)
2121

2222
| Bucket | Count | Notes |
2323
|--------|-------|-------|
@@ -72,7 +72,7 @@ Marker (done floor): `e4bdf6397` (units 1-41 done) · forcedotcom/dev HEAD (ta
7272
| 39 | #4093 make advanced-auth default + deprecate forceAdvancedAuthentication | a2c4ee4d5 | B | ⚠⚠⚠ PUBLIC API + advanced-auth + L10n(pre-appr) | ✅ ported fa450e82ca3e45d29c4411f573c59ff20f44a61b | Advanced Auth is now the DEFAULT; `SalesforceManager.forceAdvancedAuthentication` deprecated (14.0→remove 15.0). Ported into compiled Swift twins: **SalesforceSDKManager.swift** (deprecated `@objc` prop backed by non-deprecated `forceAdvancedAuthenticationInternal` = default `true`, mirrors the migration's `showAuthWindowWhileLoading` precedent & upstream's `sdk_forceAdvancedAuthentication`; devActions host-list-as-login-screen routing; devInfo line), **SFOAuthCoordinator.swift** (OR force flag into native-browser decision), **SFSDKLoginHostListViewController.swift** (`presentedAsLoginScreen` + forced-adv-auth chrome: back button/gear via `shouldShowBackButton`/`createBackButton`/`handleBackButtonAction`/`loginOptionsButton`, mirrors SFLoginViewController.swift; `delegateDidChangeLoginOptions`), **SFUserAccountManager.swift** (`presentedAsLoginScreen=true` on cancel-browser host list + new `hostListViewControllerDidChangeLoginOptions`), **AuthFlowTypesView.swift** (force-adv toggle via `forceAdvancedAuthenticationInternal`, warning-free). Compiled header **SFSDKLoginHostDelegate.h** overwritten verbatim (real protocol, matched pre-image → adds optional method). L10n `LOGIN_OPTIONS_FORCE_ADVANCED_AUTH` (pre-approved). De-ref ref-sync: `SFSDKLoginHostListViewController.m` verbatim (matched pre-image); `SalesforceSDKManager.m` + `SFOAuthCoordinator.m` surgical (import + accessor + init default + isShowingLogin + decision + devInfo). Tombstone/stub SKIPS (no compiled region, documented): `SalesforceSDKManager.h`, `SalesforceSDKManager+Internal.h`, `SFSDKLoginHostListViewController.h`, `SFUserAccountManager.m` (79-line stub). Tests: 2 ObjC test files (`SFSDKLoginHostTests.m`/`SalesforceSDKManagerTests.m`) ported to their Swift twins (15 chrome tests + 8 forced-adv-auth incl. capturing-coordinator subclass over now-`internal` `beginNativeBrowserFlow`/`beginWebViewFlow`/`approvalURL`/`brandedAuthorizeURL`, PKCE security-invariant); 3 SDKCore Swift test files hunked (JSON round-trip, session recreate, discovery-gate) — all deprecated-touching helpers `@available(*,deprecated)`-guarded → 0 deprecation warnings. 8 AuthFlowTester UI-test files verbatim + NEW `ForceAdvancedAuthTests.swift` (filesystem-synced group, no pbxproj wiring; build gated on CocoaPods, like #4092). SDKCore/SmartStore/MobileSync TEST BUILD ✓ (0 errors, 0 new warnings in diff); 135 tests across the 5 SDKCore classes PASS (incl. 25 new). ⚠⚠⚠ escalation: PUBLIC-API deprecation + advanced-auth default behavior flip + login-UI + L10n — flag in PR. |
7373
| 40 | #4088 invalid login-host recovery | a2a271cca | B | ⚠ login-host + L10n(pre-appr) | ✅ ported 6263a436e4127e450592d5be35410ecbce8d9f53 | Validate login-host input; recover to previous host when the current one fails. Ported into compiled Swift twins: **NewLoginHostView.swift** (per-field inline error UI: `NewLoginHostField.errorMessage`/`errorAccessibilityID`; `save(...)` validates non-empty + contains `.` + no whitespace + parseable `https://` URL, sets `hostError`=`LOGIN_INVALID_HOST` and bails on invalid; `.onChange(of: host)` clears error) — twin diverged from pre-image only in 2 `init` API-parity lines (outside change regions) so applied hunks surgically. **SFUserAccountManager.swift** (new `internal var previousLoginHost`; set in `hostListViewController(_:didChange:)`; recovery rewrite in `hostConnectionErrorHandlerBlock` completion: only auto-remove a *deletable* failing host on a **strong-bad-host** signal [`kSFOAuthErrorInvalidURL` / `NSURLErrorBadURL`/`UnsupportedURL`/`AppTransportSecurityRequiresSecureConnection`], NOT on ambiguous DNS/timeout [captive-portal safety]; recovery host = `previousLoginHost` if still in storage else `loginHost(at:0)` guarded by `numberOfLoginHosts>0` to avoid range trap on empty storage). L10n `LOGIN_INVALID_HOST` (pre-approved). Test-visibility: relaxed `SFSDKLoginHostStorage.loginHostList` `private`→`internal` (mirrors ObjC test's KVC reach into the private ivar; no new public API). De-ref ref-sync: `SFUserAccountManager+Internal.h` — added `previousLoginHost` @property to the `#if !defined(SWIFT_CLASS)` ObjC class-extension region verbatim (anchor `nativeLoginEnabled`→`setCurrentUserInternal` matched pre-image; header has NO compiled consumer — all 7 importer `.m` de-referenced — but kept in sync for clean future merges). Stub SKIP (no matching region): `SFUserAccountManager.m` (79-line stub). Tests: NEW ObjC `SFUserAccountManagerLoginHostRecoveryTests.m` (357 lines, `method_exchangeImplementations` swizzle + KVC) ported to a **Swift twin** `SFUserAccountManagerLoginHostRecoveryTests.swift` (9 tests: previousLoginHost capture, restore-to-previous, index-0 fallback ×2, strong-signal removal, ambiguous/DNS keep, empty-storage guard, non-deletable keep) — swizzles `restartAuthentication:` via `method_exchangeImplementations` (mirrors `SFSDKLogoutBlocker.swift`), snapshots the now-`internal` `loginHostList` for the empty-storage case, and attaches the running app's `UIScene` to the request (the migrated `showErrorAlert` skips presentation on nil scene, unlike upstream ObjC — this is why the first test run timed out; fix = set `request.scene`); wired into pbxproj as **Swift** (2 fresh IDs `E40A1C01/02…`), NOT ObjC. `NewLoginHostTests.swift` +6 validation tests (verbatim, matched pre-image). SDKCore/SmartStore/MobileSync TEST BUILD ✓ (0 errors, 0 new warnings in diff); 19 SDKCore tests PASS (10 NewLoginHost + 9 recovery, fixture-based/not live-gated). ⚠ escalation: login-UI + login-host recovery behavior + L10n — flag in PR. |
7474
| 41 | #4095 token-exchange error tests | e4bdf6397 | A | — | ✅ ported fd0fde64acb2d2a1ba828deffa7262a5449facfd | OAuth2 token-endpoint error classification tests. NEW **SFSDKOAuth2TokenExchangeErrorTests.swift** (7 tests: invalid_grant family ×3 descriptions, invalid_client_id, invalid_client, unsupported_grant_type, invalid_request, enum-mapping lock-in for the 5 wire values, success-response control) ported byte-faithful except two migration adaptations forced by the unit-38 Swift port: (1) `SFSDKOAuthTokenEndpointErrorResponse.errorCode` is the **typed `SFOAuthErrorCode` enum** in the Swift twin (was `NSInteger` in ObjC), so the assertion compares enum-to-enum (`expectedEnum`) instead of `expectedEnum.rawValue`; (2) the Swift `SFSDKOAuthTokenEndpointResponse(dictionary:parseAdditionalFields:)` init is **non-failable** and takes **`NSDictionary`** (was an implicitly-optional ObjC init), so call sites bind directly (no `guard let`) with `let params: NSDictionary`. Wired into SDKCore-test pbxproj as Swift (2 fresh IDs `E40A1C03/04…`). Test-only, SDKCore-scoped — no production change. SDKCore TEST BUILD ✓ (0 errors, 0 new warnings); 7 tests PASS. No escalation. |
75-
| 42 | #4096 SQLCipher 4.17.0 | 303013dd7 | C | ⚠⚠ dependency bump (PRE-APPROVED gate) | ⬜ pending | `SmartStore.podspec`, `mobilesdk_pods.rb`, SmartStore pbxproj, MobileSyncExplorer pbxproj, `SFSmartStoreTests.m`, skill. SQLCipher 4.16→4.17. Gate PRE-APPROVED (Feedback #4). |
75+
| 42 | #4096 SQLCipher 4.17.0 | 303013dd7 | C | ⚠⚠ dependency bump (PRE-APPROVED gate) | ✅ ported 2e54cc1c8d37293aa0514f9d9fda7fd101e06df8 | SQLCipher **4.16.0 → 4.17.0** (SQLite 3.53.1 → **3.53.3** runtime). Mechanical version bump across 7 files: **SmartStore.podspec** (`smartstore.dependency 'SQLCipher', '~> 4.17.0'`), **mobilesdk_pods.rb** (`pod 'SQLCipher', '4.17.0'`), **SmartStore pbxproj** + **MobileSyncExplorer pbxproj** (SPM `XCRemoteSwiftPackageReference` exactVersion `4.17.0`, tab-indented, single occurrence each, `plutil` clean), **SFSmartStoreTests.swift** (the COMPILED twin — `testSqliteVersion` `3.53.3`, `testSqlCipherVersion` `4.17.0 community`) + de-ref **SFSmartStoreTests.m** ref-synced verbatim (`.m` is 0-in-Sources; `.swift` twin at pbxproj line 856 is compiled), **`.claude/skills/update-sqlcipher/SKILL.md`** (byte-identical to upstream post-image `79b7335f`: `SQLLite`→`SQLite` typo + example-placeholder assert → `NEW_SQLITE_VERSION`). SPM resolved+checked-out 4.17.0; a stale precompiled-module cache (`sqlite3.h` changed under the version swap) forced a **full Build-dir wipe** (SourcePackages retained) — clean rebuild GREEN. SmartStore + MobileSync (top-of-chain) TEST BUILD ✓ 0 errors; 3 version tests PASS (runtime confirmed `4.17.0 community` / SQLite `3.53.3`). ⚠⚠ dependency bump — PRE-APPROVED (Feedback #4), still flag in PR. |
7676
| 43 | #4098 fix nil-sceneId crash on advanced-auth browser callback | e4e838863 | B | ⚠ OAuth/scene | ⬜ pending | `SFOAuthCoordinator+Internal.h/.m`, `SFSDKAuthSession.m` + test. |
7777
| 44 | #4087 token refresh coordinator | 6e0967833 | B+D | ⚠⚠⚠ OAuth/token (LIVE-AUTH UNBLOCKER) | ⬜ pending | 18 files: NEW `SFSDKTokenRefreshCoordinator.h/.m`, `SFOAuthErrorCode.swift`(via #4094), `SFOAuthSessionRefresher.*`, `SFIdentityCoordinator.m`, `SFRestAPI.m`, `UserAccountManager.swift`, `SFSDKOAuth2.m` + tests. **THIS unblocks the 51 SKIP-gated live-org tests → enables Phase 2.** |
7878
| 45 | #4102 improve token-refresh error handling | 19d4436ab | B | ⚠ OAuth/token | ⬜ pending | `SFRestAPI.m`, `SFSDKOAuth2.h/.m` + tests + pbxproj. |

.claude/upstream-sync-marker

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
e4bdf6397b09a00fbe30a50a76d0f804e50f0455
1+
303013dd7d3a05234559947ab188c6647c26c296

SmartStore.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Pod::Spec.new do |s|
2121

2222
smartstore.dependency 'SalesforceSDKCore', "~>#{s.version}"
2323
smartstore.dependency 'FMDB/SQLCipher', '~> 2.7.12'
24-
smartstore.dependency 'SQLCipher', '~> 4.16.0'
24+
smartstore.dependency 'SQLCipher', '~> 4.17.0'
2525
smartstore.source_files = 'libs/SmartStore/SmartStore/Classes/**/*.swift', 'libs/SmartStore/SmartStore/SmartStore.h'
2626
smartstore.public_header_files = 'libs/SmartStore/SmartStore/SmartStore.h'
2727
smartstore.exclude_files = 'libs/SmartStore/SmartStore/Classes/**/*.{h,m}'

libs/SmartStore/SmartStore.xcodeproj/project.pbxproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1291,7 +1291,7 @@
12911291
repositoryURL = "https://github.com/sqlcipher/SQLCipher.swift";
12921292
requirement = {
12931293
kind = exactVersion;
1294-
version = 4.16.0;
1294+
version = 4.17.0;
12951295
};
12961296
};
12971297
/* End XCRemoteSwiftPackageReference section */

libs/SmartStore/SmartStoreTests/SFSmartStoreTests.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,13 @@ - (void) testRuntimeSettings
103103
- (void) testSqliteVersion
104104
{
105105
NSString* version = [NSString stringWithUTF8String:sqlite3_libversion()];
106-
XCTAssertEqualObjects(version, @"3.53.1");
106+
XCTAssertEqualObjects(version, @"3.53.3");
107107
}
108108

109109
- (void) testSqlCipherVersion
110110
{
111111
NSString* version = [self.store getSQLCipherVersion];
112-
XCTAssertEqualObjects(version, @"4.16.0 community");
112+
XCTAssertEqualObjects(version, @"4.17.0 community");
113113
}
114114

115115
- (void) testCipherProviderVersion

libs/SmartStore/SmartStoreTests/SFSmartStoreTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,13 @@ class SFSmartStoreTests: SFSmartStoreTestCase {
9393

9494
func testSqliteVersion() {
9595
let version = String(cString: sqlite3_libversion())
96-
XCTAssertEqual(version, "3.53.1")
96+
XCTAssertEqual(version, "3.53.3")
9797
}
9898

9999
func testSqlCipherVersion() {
100100
guard let store = store else { return XCTFail("Store should not be nil") }
101101
let version = store.versionOfSQLCipher()
102-
XCTAssertEqual(version, "4.16.0 community")
102+
XCTAssertEqual(version, "4.17.0 community")
103103
}
104104

105105
func testCipherProviderVersion() {

mobilesdk_pods.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def use_mobile_sdk!(options={})
2525

2626
source 'https://www.github.com/forcedotcom/SalesforceMobileSDK-iOS-Specs'
2727

28-
pod 'SQLCipher', '4.16.0'
28+
pod 'SQLCipher', '4.17.0'
2929
pod 'SalesforceSDKCommon', :path => path
3030
pod 'SalesforceAnalytics', :path => path
3131
pod 'SalesforceSDKCore', :path => path

native/SampleApps/MobileSyncExplorer/MobileSyncExplorer.xcodeproj/project.pbxproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1220,7 +1220,7 @@
12201220
repositoryURL = "https://github.com/sqlcipher/SQLCipher.swift";
12211221
requirement = {
12221222
kind = exactVersion;
1223-
version = 4.16.0;
1223+
version = 4.17.0;
12241224
};
12251225
};
12261226
/* End XCRemoteSwiftPackageReference section */

0 commit comments

Comments
 (0)