feat(core): improve login flow (#15219)

#### PR Dependency Tree


* **PR #15219** 👈

This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added secure, automatic auth session token refresh and request replay
for expired-token responses across Android, iOS, and Electron.
* Updated sign-in flows to manage sessions without returning tokens to
the app layer.
* Added “Devices” management UI with sign out per device and sign out
all.
  * Enabled support for both Hashcash and Turnstile captcha providers.
* **Bug Fixes**
* Improved refresh de-duplication, inflight cancellation/clear behavior,
and recovery from corrupted/invalid sessions.
* **Tests**
* Expanded auth-session, refresh/revoke, and replay coverage (Electron
unit tests, Android instrumentation tests, iOS auth date parser tests).
* **Chores**
* Removed CAPTCHA site key from build-time configuration and adjusted CI
test execution.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
DarkSky
2026-07-12 18:11:02 +08:00
committed by GitHub
parent 02b25e05d8
commit abf37d3dfa
57 changed files with 2919 additions and 789 deletions
@@ -33,6 +33,8 @@
C4C97C7C2D030BE000BC2AD1 /* affine_mobile_native.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C97C6F2D0307B700BC2AD1 /* affine_mobile_native.swift */; };
C4C97C7D2D030BE000BC2AD1 /* affine_mobile_nativeFFI.h in Sources */ = {isa = PBXBuildFile; fileRef = C4C97C702D0307B700BC2AD1 /* affine_mobile_nativeFFI.h */; };
C4C97C7E2D030BE000BC2AD1 /* affine_mobile_nativeFFI.modulemap in Sources */ = {isa = PBXBuildFile; fileRef = C4C97C712D0307B700BC2AD1 /* affine_mobile_nativeFFI.modulemap */; };
AA0000040000000000000000 /* AuthDateParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA0000010000000000000000 /* AuthDateParser.swift */; };
AA0000050000000000000000 /* AuthDateParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA0000020000000000000000 /* AuthDateParserTests.swift */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@@ -83,6 +85,9 @@
C4C97C712D0307B700BC2AD1 /* affine_mobile_nativeFFI.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = affine_mobile_nativeFFI.modulemap; sourceTree = "<group>"; };
E5E5070D1CA1200D4964D91F /* Pods-AFFiNE.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AFFiNE.release.xcconfig"; path = "Pods/Target Support Files/Pods-AFFiNE/Pods-AFFiNE.release.xcconfig"; sourceTree = "<group>"; };
FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.debug.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.debug.xcconfig"; sourceTree = "<group>"; };
AA0000010000000000000000 /* AuthDateParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ../App/Plugins/Auth/AuthDateParser.swift; sourceTree = "<group>"; };
AA0000020000000000000000 /* AuthDateParserTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthDateParserTests.swift; sourceTree = "<group>"; };
AA0000030000000000000000 /* AFFiNETests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AFFiNETests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFileSystemSynchronizedRootGroup section */
@@ -94,6 +99,13 @@
/* End PBXFileSystemSynchronizedRootGroup section */
/* Begin PBXFrameworksBuildPhase section */
AA0000070000000000000000 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
504EC3011FED79650016851F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -127,6 +139,7 @@
children = (
C4C97C722D0307B700BC2AD1 /* uniffi */,
9D90BE242CCB9876006677DB /* App */,
AA00000D0000000000000000 /* AppTests */,
50802D5F2D112F7D00694021 /* Packages */,
504EC3051FED79650016851F /* Products */,
7F8756D8B27F46E3366F6CEA /* Pods */,
@@ -140,6 +153,7 @@
isa = PBXGroup;
children = (
504EC3041FED79650016851F /* AFFiNE.app */,
AA0000030000000000000000 /* AFFiNETests.xctest */,
);
name = Products;
sourceTree = "<group>";
@@ -192,6 +206,15 @@
path = App;
sourceTree = "<group>";
};
AA00000D0000000000000000 /* AppTests */ = {
isa = PBXGroup;
children = (
AA0000010000000000000000 /* AuthDateParser.swift */,
AA0000020000000000000000 /* AuthDateParserTests.swift */,
);
path = AppTests;
sourceTree = "<group>";
};
C4C97C722D0307B700BC2AD1 /* uniffi */ = {
isa = PBXGroup;
children = (
@@ -206,6 +229,23 @@
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
AA0000090000000000000000 /* AFFiNETests */ = {
isa = PBXNativeTarget;
buildConfigurationList = AA00000C0000000000000000 /* Build configuration list for PBXNativeTarget "AFFiNETests" */;
buildPhases = (
AA0000060000000000000000 /* Sources */,
AA0000070000000000000000 /* Frameworks */,
AA0000080000000000000000 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = AFFiNETests;
productName = AFFiNETests;
productReference = AA0000030000000000000000 /* AFFiNETests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
504EC3031FED79650016851F /* AFFiNE */ = {
isa = PBXNativeTarget;
buildConfigurationList = 504EC3161FED79650016851F /* Build configuration list for PBXNativeTarget "AFFiNE" */;
@@ -240,6 +280,9 @@
LastSwiftUpdateCheck = 0920;
LastUpgradeCheck = 2600;
TargetAttributes = {
AA0000090000000000000000 = {
CreatedOnToolsVersion = 26.0;
};
504EC3031FED79650016851F = {
CreatedOnToolsVersion = 9.2;
LastSwiftMigration = 1600;
@@ -260,11 +303,19 @@
projectRoot = "";
targets = (
504EC3031FED79650016851F /* AFFiNE */,
AA0000090000000000000000 /* AFFiNETests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
AA0000080000000000000000 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
504EC3021FED79650016851F /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@@ -340,6 +391,15 @@
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
AA0000060000000000000000 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
AA0000040000000000000000 /* AuthDateParser.swift in Sources */,
AA0000050000000000000000 /* AuthDateParserTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
504EC3001FED79650016851F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -373,6 +433,38 @@
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
AA00000A0000000000000000 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGNING_ALLOWED = NO;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 16.5;
PRODUCT_BUNDLE_IDENTIFIER = app.affine.pro.tests;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
AA00000B0000000000000000 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGNING_ALLOWED = NO;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 16.5;
PRODUCT_BUNDLE_IDENTIFIER = app.affine.pro.tests;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
504EC3141FED79650016851F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -574,6 +666,15 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
AA00000C0000000000000000 /* Build configuration list for PBXNativeTarget "AFFiNETests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
AA00000A0000000000000000 /* Debug */,
AA00000B0000000000000000 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
504EC2FF1FED79650016851F /* Build configuration list for PBXProject "App" */ = {
isa = XCConfigurationList;
buildConfigurations = (