fix(account): merge durable session refresh
CI / Validate manifests (push) Has been cancelled
CI / SwiftLint (push) Has been cancelled
CI / iOS / Extension (push) Has been cancelled
CI / macOS (push) Has been cancelled

Preserve refresh idempotency and Apple credential revocation handling alongside the consolidated app updates.
This commit is contained in:
Rocky
2026-08-25 16:44:51 +08:00
16 changed files with 438 additions and 33 deletions
@@ -540,6 +540,36 @@ final class AccountCenterViewModelTests: XCTestCase {
XCTAssertEqual(managedGatewayClearCount, 1)
}
@MainActor
func testRevokedAppleCredentialClearsSignedInAccountState() async {
let account = AccountSession(
accountID: UUID(),
createdAtEpochSeconds: 1_700_000_000
)
let service = AccountServiceSpy(
restoredSession: account,
snapshot: makeSnapshot(account: account),
appleCredentialState: .revoked
)
let coordinator = AccountSessionCoordinator(
dependencies: AccountDependencies(
sessionService: service,
centerService: service
),
pendingReferralStore: InMemoryPendingReferralStore()
)
await coordinator.restoreIfNeeded()
XCTAssertTrue(coordinator.isSignedIn)
await coordinator.validateAppleCredentialState()
XCTAssertEqual(coordinator.sessionPhase, .signedOut)
XCTAssertEqual(coordinator.snapshotPhase, .idle)
XCTAssertEqual(coordinator.operationErrorKey, "account.error.sessionExpired")
let signOutCount = await service.signOutCount()
XCTAssertEqual(signOutCount, 1)
}
private func makeReferral(status: AccountReferralStatus) -> AccountReferral {
AccountReferral(
id: UUID(),
@@ -616,6 +646,7 @@ private actor AccountServiceSpy: AccountSessionServicing, AccountCenterServicing
private let signInDelayNanoseconds: UInt64
private let accountLoadDelayNanoseconds: UInt64
private var remainingRestoreFailures: Int
private let storedAppleCredentialState: AccountAppleCredentialState
private var redeemed: [String] = []
private var centerLoadCount = 0
private var logoutCount = 0
@@ -634,7 +665,8 @@ private actor AccountServiceSpy: AccountSessionServicing, AccountCenterServicing
signOutDelayNanoseconds: UInt64 = 0,
signInDelayNanoseconds: UInt64 = 0,
restoreFailureCount: Int = 0,
accountLoadDelayNanoseconds: UInt64 = 0
accountLoadDelayNanoseconds: UInt64 = 0,
appleCredentialState: AccountAppleCredentialState = .unknown
) {
restored = restoredSession
signedInAccount = signInSession ?? restoredSession
@@ -646,6 +678,7 @@ private actor AccountServiceSpy: AccountSessionServicing, AccountCenterServicing
self.signInDelayNanoseconds = signInDelayNanoseconds
remainingRestoreFailures = restoreFailureCount
self.accountLoadDelayNanoseconds = accountLoadDelayNanoseconds
self.storedAppleCredentialState = appleCredentialState
}
func restoreSession() async throws -> AccountSession? {
@@ -676,6 +709,10 @@ private actor AccountServiceSpy: AccountSessionServicing, AccountCenterServicing
accountDeleteCount += 1
}
func appleCredentialState() async -> AccountAppleCredentialState {
storedAppleCredentialState
}
func clearManagedGateway() async {
gatewayClearCount += 1
}