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
@@ -4,31 +4,25 @@ export interface AuthPlugin {
email: string;
token: string;
clientNonce?: string;
}): Promise<{ token: string }>;
}): Promise<void>;
signInOauth(options: {
endpoint: string;
code: string;
state: string;
clientNonce?: string;
}): Promise<{ token: string }>;
}): Promise<void>;
signInPassword(options: {
endpoint: string;
email: string;
password: string;
verifyToken?: string;
challenge?: string;
}): Promise<{ token: string }>;
signInOpenApp(options: {
endpoint: string;
code: string;
}): Promise<{ token: string }>;
signOut(options: { endpoint: string; token?: string | null }): Promise<void>;
readEndpointToken(options: {
}): Promise<void>;
signInOpenApp(options: { endpoint: string; code: string }): Promise<void>;
signOut(options: { endpoint: string }): Promise<void>;
getValidAccessToken(options: {
endpoint: string;
}): Promise<{ token?: string | null }>;
writeEndpointToken(options: {
endpoint: string;
token: string;
}): Promise<void>;
deleteEndpointToken(options: { endpoint: string }): Promise<void>;
refreshAccessToken(options: { endpoint: string }): Promise<{ token: string }>;
clearEndpointSession(options: { endpoint: string }): Promise<void>;
}