Files
makelore/.project-docs/30-worklog/tasks/20260807-client-login-sliding-7d2a.md
brother7 86ece3a430 实现客户端登录七天滑动续期
需求:解决短效访问令牌到期后客户端一小时掉登录的问题。

实现:由 Electron Main 加密管理并轮换刷新凭据,按真实用户活动续期,七天闲置后清理会话,并补齐并发、迁移和终态回归测试。
2026-08-07 16:11:10 +08:00

75 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Task: 客户端登录滑动续期与七天闲置失效
## Identity
- Task ID: 20260807-client-login-sliding-7d2a
- Mode: Feature
- Branch: codex/login-sliding-7d2a
- Worktree: D:\Datas\OthersProjects\makelore-login-sliding-7d2a
- Base commit: 7b23cce67a1b9e61a48d89dedbd088d37b10ecd4
- Owner: codex
- Status: Done
## Scope
- 修复客户端启动时 access token 过期即清空整个会话的问题。
- 由 Electron Main 统一执行 refresh token 换取、轮换保存与并发单飞。
- 记录真实用户活跃时间;每天使用可持续续期,连续 7 天未使用则要求重新授权。
- 后台保活不计入用户活跃,并补齐 Main、Host API、Renderer Store 聚焦测试。
## Intent And Constraints
- access token 保持短效,不把 7 天直接改成长效 Bearer token。
- 真实前台使用才推进滑动窗口;后台定时刷新不能无限延长登录。
- 先判断 7 天闲置,再允许刷新,过期后不得被一次迟到的活动复活。
- 保留 OAuth 返回的旋转 refresh token并在 Electron Main 中加密、原子持久化Renderer 不保存新 refresh token。
- 所有代码与 Git 操作仅限隔离工作区,不触碰原 Makelore 工作区未提交改动。
## Plan
1. 用失败测试固定每日活跃、7 天边界、后台刷新和并发单飞语义。
2. 扩展 Main 会话模型与 Host API使刷新和活跃状态由 Main 统一管理。
3. 调整 Renderer 启动恢复、持久化和前台/定时维护逻辑。
4. 运行聚焦测试、类型检查、Lint、构建与文档漂移检查。
## Outcome
- 新增 Main-owned 会话服务:使用系统安全存储加密 refresh token启动恢复、刷新单飞、
轮换凭据落盘屏障与恢复失败保护均在 Main 内完成。
- 真实键盘、鼠标、触摸活动每分钟至多推进一次 `lastActiveAt`,并在 access token 临近过期时
触发刷新;后台令牌消费者不推进用户活跃时间。
- 连续 7 天无真实活动后终止会话,并由 Main 统一清理 AI gateway 凭据、Provider key、
OpenCode 运行时和绘画事件会话;清理与新登录串行,避免跨账号代际竞态。
- Renderer 只持久化公开会话;旧版本已存在的 refresh token 仅在 Main 安全落盘成功前保留在
原 localStorage接管成功后立即移除新 refresh token 从不返回或写入 Renderer。Linux
`basic_text` 等不受保护的存储后端不会落盘 refresh token。
- 临时密钥库/磁盘故障返回 503 并保留可恢复状态,不再误判为授权失效;过期、退出和并发刷新
的终态/跨代边界均有回归测试。
- Electron Store 外层 JSON 损坏会安全重建;密文暂时不可读时先保留,用户显式重新授权可清除
不可恢复记录后继续登录,不会因坏记录永久卡在启动或 503。
- 登出及终态清理会先撤销本地派生凭据,并使用清理前捕获的 Main access token 尝试关闭远端绘画
事件会话;无论远端结果都轮换本地幂等键,显式登出仍会对远端关闭失败返回错误。
## Verification
- `pnpm exec vitest run tests/unit/auth-routes.test.ts tests/unit/works-square-session-persistence.test.ts tests/unit/works-square-session.test.ts tests/unit/auth-store.test.ts tests/unit/login-page.test.tsx tests/unit/works-square-design-workspace.test.ts`
- 通过6 files85 tests。
- `pnpm run typecheck`
- 通过。
- 针对本次变更文件运行 ESLint
- 通过。
- `pnpm run build:vite`
- 通过;仅保留既有 chunk size/dynamic import 警告。
- 全量 `npm test -- --reporter=dot`
- 未全绿21 项失败集中在隔离工作树缺少外部 `zip`、未检出的 `.opencode/agent` 资源及既有
project progress sync 用例;认证聚焦测试全部通过。
## Follow-ups
- 服务端与客户端需协调上线;先发布支持旋转凭据原子落盘的兼容版本并确认共享 `app` 客户端的
所有使用方,再应用 OAuth 数据迁移并刷新 RegisteredClient Redis 缓存。
## Promotion Candidates
- None recorded.