feat(devices): P2 sessions 表 + 在线/最后登录/客户端版本
ci-pangolin / Lint — shellcheck (push) Successful in 8s
ci-pangolin / OpenAPI Sync Check (push) Successful in 18s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 6s
ci-pangolin / Flutter — analyze + test (push) Successful in 24s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 4s
ci-pangolin / Go — build + test (push) Successful in 11s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 14s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Failing after 4m13s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 14s
ci-pangolin / Lint — shellcheck (push) Successful in 8s
ci-pangolin / OpenAPI Sync Check (push) Successful in 18s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 6s
ci-pangolin / Flutter — analyze + test (push) Successful in 24s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 4s
ci-pangolin / Go — build + test (push) Successful in 11s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 14s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Failing after 4m13s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 14s
migration 000016(mysql+sqlite,含 down):新增 sessions 表(绑 device+refresh JTI) + devices 加 client_version/totp_trusted_until。devices 唯一键改 + platform CHECK 加 linux(需 SQLite 表重建)拆出后续迁移,降风险。 后端:新 internal/sessions Store(Create/Rotate/Revoke/RevokeByDevice/ LastLoginByDevice);TokenManager 外露 refresh JTI(IssueWithJTI/RefreshWithJTI/ ParseRefreshJTI);auth.Service 注入 SessionStore——登录建会话、刷新轮换、登出吊销; DeviceRegistrar 返回 deviceID;ReportUsage 心跳 touch devices.last_seen(在线判定); devices.ListDevices 经 LastLoginSource 注入返回 online(last_seen<3min)/client_version/ last_login;RegisterIfAbsent 存 client_version。 客户端:Device model 加 online/clientVersion/lastLogin(fromJson 自动解析)。 测试:sessions store 3 例 + ListDevices 在线/最后登录 + device model 2 例 + migration v16;全量 go test/flutter test 绿。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -5,32 +5,33 @@
|
||||
|
||||
## 计划文档(先产出)
|
||||
- [x] `docs/superpowers/plans/2026-06-29-device-session-management.md`(本文件)
|
||||
- [ ] `docs/device-session-management-plan.html`(阅读版)
|
||||
- [ ] 登记 `docs/index.html`「实现计划」
|
||||
- [ ] 总方案 `device-session-management-design.html` 加「→ 实现计划」链接
|
||||
- [x] `docs/device-session-management-plan.html`(阅读版)
|
||||
- [x] 登记 `docs/index.html`「实现计划」
|
||||
- [x] 总方案 `device-session-management-design.html` 加「→ 实现计划」链接
|
||||
|
||||
## P1 · 设备注册打通(登录即注册设备)
|
||||
- [ ] 客户端加依赖 `uuid` + `device_info_plus`(`client/pubspec.yaml`)
|
||||
- [ ] 新 `client/lib/services/device_identity.dart`:`deviceId()`(secure storage 读;无则 `Uuid().v4()` 写;读失败 ≠ 没有,不重生成)、`deviceName()`/`platform()`、`clientVersion()`
|
||||
- [ ] 弃用 `connection_provider.dart` 的 `_kDeviceId='mac-001'` → 用 `device_identity`
|
||||
- [ ] `auth_api.dart` login/register 请求体加 `device:{id,name,platform,client_version}`
|
||||
- [ ] `auth/handler.go`:`loginRequest`/`registerRequest` 加 `Device deviceMeta`
|
||||
- [ ] `auth/service.go` Login/Register:成功签发后调 `DeviceRegistrar.RegisterIfAbsent`(consumer-side 接口;`devices.Service` 实现;`RegisterIfAbsent` 增返回 `deviceID`);`MaxDevices` 由 plan 解析
|
||||
- [ ] `normalizePlatform` 加 `linux`
|
||||
- [ ] `main.go` 构造 `devices.Service` 注入 `authSvc`
|
||||
- [ ] 测试:`device_identity` 单测;auth 集成(登录后 devices 落行)
|
||||
- [ ] 验收:登录后 `GET /v1/me/devices` 非空
|
||||
- [x] 客户端加依赖 `uuid` + `device_info_plus`(`client/pubspec.yaml`)
|
||||
- [x] 新 `client/lib/services/device_identity.dart`:`deviceId()`(secure storage 读;无则 `Uuid().v4()` 写;读失败 ≠ 没有,不重生成)、`deviceName()`/`platform()`、`clientVersion()`
|
||||
- [x] 弃用 `connection_provider.dart` 的 `_kDeviceId='mac-001'` → 用 `device_identity`
|
||||
- [x] `auth_api.dart` login/register 请求体加 `device:{id,name,platform,client_version}`
|
||||
- [x] `auth/handler.go`:`loginRequest`/`registerRequest` 加 `Device deviceMeta`
|
||||
- [x] `auth/service.go` Login/Register:成功签发后调 `DeviceRegistrar.RegisterIfAbsent`(consumer-side 接口;`devices.Service` 实现;`RegisterIfAbsent` 增返回 `deviceID`);`MaxDevices` 由 plan 解析
|
||||
- [x] `normalizePlatform` 加 `linux`
|
||||
- [x] `main.go` 构造 `devices.Service` 注入 `authSvc`
|
||||
- [x] 测试:`device_identity` 单测;auth 集成(登录后 devices 落行)
|
||||
- [x] 验收:登录后 `GET /v1/me/devices` 非空
|
||||
|
||||
## P2 · sessions 表 + 在线/最后登录
|
||||
- [ ] migration `000016_sessions_and_device_meta`(mysql+sqlite,含 down):建 sessions 表;devices 加 `client_version`+`totp_trusted_until`;唯一键 `UNIQUE(uuid)`→`UNIQUE(user_id,uuid)`;platform CHECK 加 `linux`
|
||||
- [ ] 新 `server/internal/sessions/`:`Store`(Create/RotateJTI/RevokeByJTI/RevokeByDevice/ActiveByUserWithDevice/LastLoginByDevice)
|
||||
- [ ] `TokenManager.Issue`/`Refresh` 外露 refresh JTI
|
||||
- [ ] `auth.Service` 注入 `sessions.Store`:Login/Register `Create`;Refresh `RotateJTI`+last_active;Logout `RevokeByJTI`
|
||||
- [ ] `nodes/handler_grpc.go: ReportUsage` deviceID>0 时 touch `devices.last_seen`
|
||||
- [ ] `devices.Service.ListDevices`+API struct+store join:增 `client_version`/`online`/`last_login`
|
||||
- [ ] 客户端 `Device` model 加 `clientVersion`/`online`/`lastLogin`;`account_api` 解析
|
||||
- [ ] 测试:sessions store;JTI surface;ReportUsage touch;ListDevices 计算;migration sqlite 实库
|
||||
- [ ] 验收:列表显示在线/版本/最后登录;停 agent ~3min 转离线
|
||||
- [x] migration `000016_sessions_and_device_meta`(mysql+sqlite,含 down):建 sessions 表;devices 加 `client_version`+`totp_trusted_until`
|
||||
- ⏭ **拆出**:devices 唯一键 `UNIQUE(uuid)`→`UNIQUE(user_id,uuid)` + platform CHECK 加 `linux` 需 SQLite 表重建(最高风险 DDL),隔离到单独后续迁移(多账户同机=已知降级,linux 注册 best-effort 失败不阻断登录)
|
||||
- [x] 新 `server/internal/sessions/`:`Store`(Create/Rotate/Revoke/RevokeByDevice/LastLoginByDevice)
|
||||
- [x] `TokenManager.IssueWithJTI`/`RefreshWithJTI`/`ParseRefreshJTI` 外露 refresh JTI
|
||||
- [x] `auth.Service` 注入 `SessionStore`:Login/Register `Create`;Refresh `Rotate`+last_active;Logout `Revoke`
|
||||
- [x] `nodes/handler_grpc.go: ReportUsage` deviceID>0 时 touch `devices.last_seen`
|
||||
- [x] `devices.Service.ListDevices`+API struct+store join:增 `client_version`/`online`/`last_login`(注入 `LastLoginSource`)
|
||||
- [x] 客户端 `Device` model 加 `clientVersion`/`online`/`lastLogin`;`account_api` 解析(fromJson 自动)
|
||||
- [x] 测试:sessions store(3) + ListDevices 计算 + device model(2) + auth 设备/会话;migration sqlite 实库 v16
|
||||
- [ ] 验收:列表显示在线/版本/最后登录(待 P6 UI + 端到端);停 agent ~3min 转离线
|
||||
|
||||
## P3 · 两个操作(强制退出 + 清除增强)
|
||||
- [ ] 新端点 `POST /v1/me/devices/{uuid}/logout`(handler + `Service.ForceLogout`):`sessions.RevokeByDevice` + 逐 jti `TokenManager.Revoke`
|
||||
|
||||
Reference in New Issue
Block a user