1
T-266
ila edited this page 2026-08-07 16:37:07 +08:00
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.

同步来源:docs/tasks/T-266.md · commit afc651f75a3a


id: T-266 title: 将设备 Bearer token 固定有效期延长为30天 phase: 2 deps:

  • T-204
  • T-206 status: DONE created: 2026-07-31 context_ref: 200e263 work_branch: null write_paths:
  • docs/tasks/T-266.md
  • docs/current-state.md
  • docs/02-requirements.md
  • docs/03-tech-stack.md
  • docs/04-architecture.md
  • docs/api.md
  • backend-api/internal/usecase/**
  • backend-api/internal/transport/httpapi/**
  • android-buyer/app/src/test/java/com/roubao/autopilot/procurement/ProcurementApiClientTest.kt

问题 / 背景

内部采购手机当前每次登录取得固定 1 小时 BUYER 设备 Bearer token。采购设备是预授权 设备,token 由 Android Keystore-backed 安全存储保存;1 小时到期会增加频繁重新登录 和无人值守任务中断成本。需求将有效期延长为 1 个月。

Go time.Duration 不表达自然月,本任务把“1个月”固定定义为 30 天,即 720 小时、 2,592,000 秒,避免不同月份导致 API 与设备本地到期时间不确定。

行为契约

  • 新签发 BUYER 设备 access token 的绝对有效期固定为 30 * 24 * time.Hour。
  • POST /api/v1/auth/token 成功响应的 expires_in 固定为 2592000。
  • 已签发 token 保留数据库中的原 expires_at,不批量延长;部署后设备需重新登录一次 才能取得30天 token。
  • token 不因 heartbeat、claim、start、任务执行或 API 请求滚动续期;仍不增加 refresh token。
  • 用户禁用、设备禁用、token 撤销、设备绑定不匹配和角色错误仍在下一次请求立即失败, 不等待30天到期。
  • 数据库仍只保存 token SHA-256;原 token 不写日志、不写 execution event。

不变边界

  • ADMIN 服务端 session 仍为固定8小时。
  • 设备预共享 secret、任务 claim token、claim 租约、execution 授权和幂等 key 的 生命周期均不变。
  • 管理 Cookie 与 BUYER Bearer middleware 继续隔离。
  • 不增加可配置环境变量,避免生产节点出现不一致的鉴权期限。

方案

  1. 将 AccessTokenLifetime 改为 30 * 24 * time.Hour。
  2. 更新 HTTP 契约测试,断言 expires_in=2592000;usecase 测试继续断言数据库到期 时间严格等于统一常量。
  3. 同步需求、技术栈、架构、API 示例和当前状态文档。
  4. 运行 Go 全量测试、Android 契约消费回归和根 init.ps1。

验收要点

  • 新登录产生的 expires_at - created_at 严格等于30天。
  • 登录响应 expires_in 为 2592000。
  • 过期、撤销、用户禁用和设备禁用测试继续通过。
  • 已有 token 不被迁移或静默延期。
  • Admin session、claim/execution 生命周期无改动。
  • Go 全量测试和根 init.ps1 通过。

执行记录

  • 2026-07-31:将 AccessTokenLifetime 从 time.Hour 改为 30 * 24 * time.Hour;登录响应继续从该统一常量计算 expires_in,现在固定返回 2592000。ADMIN session 常量仍为8小时。
  • 2026-07-31:更新 HTTP handler 测试精确断言 2592000;既有 usecase 测试继续 断言 expires_at - created_at == AccessTokenLifetime,SQLite 鉴权的过期、撤销、 用户禁用、设备禁用与绑定检查测试全部通过。
  • 2026-07-31:Android 登录 mock 改为30天并断言本地计算的 expiresAtEpochMillis 落在登录时刻加30天的窗口内,证明跨端秒/毫秒换算无溢出。
  • 2026-07-31:同步需求、技术栈、架构、API 示例和当前状态。没有新增或修改数据库 migration,因此已有 token 的 expires_at 不变;后端重启后设备必须重新登录一次 才取得30天 token。
  • 2026-07-31:Go 全量测试通过,Android 定向消费测试通过,根 init.ps1 通过 Debug/Release 单测、Debug APK、共享契约、导入工具和全部 Go 后端测试。