b34697660d
- 新增 AuthSessionInvalidated 事件处理 token 失效场景 - ApiInterceptor 新增 authFailureCallback 单飞机制 - AuthBloc 区分 manual logout 与 auto expiry 语义 - 新增 startup recovery fallback 防止启动卡死 feat: 重构 Calendar DayWeek 视图事件布局引擎 - 新增 DayEventLayoutEngine 解耦事件计算与渲染 - 新增 DayTimelineMetrics 统一时间轴常量 - 新增 DayViewScale 支持捏合缩放 feat: 新增 Settings 页面共享 UI 组件 - 新增 BackTitlePageHeader 统一页面 header - 新增 DetailHeaderActionMenu 统一操作菜单 - 新增 DestructiveActionSheet 统一删除确认 - 新增 AppToggleSwitch 统一开关组件 feat: Chat UI Schema 支持导航操作 - 支持 navigation 类型 action 触发内部路由跳转 - 新增路径验证与参数处理 chore: 更新相关测试覆盖 auth 失效路径
3.4 KiB
3.4 KiB
Auth 全局模块重写设计(跨端并存、同端互斥)
1. 目标
- 彻底消除 Auth 分裂状态:
token状态与AuthBloc状态必须单一真相源。 - 会话策略升级为:
- 同账号允许跨端并存:
mobile + web + desktop - 同账号同端互斥:同端新登录会挤下线旧设备
- 同账号允许跨端并存:
- 保证任何 401 链路在刷新失败后都能统一收敛为“未登录 + 清理本地 + 路由回到登录页”。
- 消除设备差异导致的不一致行为(部分机型“假登录”或“卡死页”)。
2. 边界与约束
- 仅重写
apps/**的 Auth 客户端架构与规则,不改后端协议语义。 - 保持现有登录/注册 UI 路由入口,避免用户操作路径变化。
- 认证属于高风险域,重写必须覆盖:
- 启动恢复
- 运行时 token 过期
- 并发 401
- 手动登出与自动过期登出的差异行为
3. 核心架构
3.1 单一真相源(Single Source of Truth)
AuthBloc成为唯一认证状态源。ApiInterceptor只负责协议级拦截与刷新,不直接做路由跳转。- 401 刷新失败时,
ApiInterceptor -> ApiClient callback -> AuthBloc(AuthSessionInvalidated)。 - 路由守卫只看
AuthBloc状态,不再做隐式 token 判定。
3.2 会话状态机
AuthInitialAuthLoading(启动恢复/会话检查)AuthAuthenticated(user)AuthUnauthenticated(reason)
reason 取值:
signedOutexpiredstartupRecoveryFailed
3.3 登出语义分离
- 手动登出:
deleteSession()- 尝试调用后端注销
- 最终清本地
- 自动过期:
clearSessionLocalOnly()- 仅清本地
- 不调用后端注销接口
3.4 并发与抖动控制
ApiInterceptor继续使用 refresh singleflight。- 新增 auth failure singleflight:多并发 401 刷新失败,只触发一次全局会话失效事件。
3.5 设备差异治理
- 启动时 token 读取异常必须兜底:进入
AuthUnauthenticated(startupRecoveryFailed),避免卡死在 Boot。 FlutterSecureStorage显式平台配置:- Android 使用
encryptedSharedPreferences - iOS 指定 keychain accessibility(保证行为稳定)
- Android 使用
4. 数据流
4.1 冷启动
main触发AuthStartedAuthBloc读取 refresh token- 有 refresh token -> 刷新会话 -> 成功进入
AuthAuthenticated - 无 token 或异常 ->
AuthUnauthenticated(startupRecoveryFailed)
4.2 运行时 API 请求
- 请求携带 access token
- 401 -> 触发 refresh
- refresh 成功 -> 自动重试原请求
- refresh 失败 -> 触发一次全局 auth failure
AuthBloc收到AuthSessionInvalidated(expired)-> 清本地 ->AuthUnauthenticated(expired)- Router 根据状态回登录页
5. 测试策略
AuthBloc:- 启动读取 refresh token 异常兜底
- session invalidated 事件导致统一未登录
ApiInterceptor:- 并发 401 refresh 失败仅触发一次 auth failure
AuthRepository:- 手动登出 vs 自动过期清理行为差异
6. 迁移计划
- 先引入新事件/新回调/新状态原因,不改 UI 交互。
- 再改路由守卫识别未登录原因。
- 最后补齐
apps/AGENTS.mdAuth 强约束,防止后续回归为“各处乱写”。
7. 风险与回滚
- 风险:回调链路接错导致频繁误登出。
- 规避:并发 singleflight + 精确触发条件(仅 401 refresh 失败)。
- 回滚:保留旧事件兼容层,出现异常可快速退回旧路由判定。