Files
cmbuyer/docs/tasks/T-301.md
T

92 lines
6.9 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.
---
id: T-301
title: 设备凭据与身份隔离(F-013)
phase: 3
deps: [T-201, T-204]
status: DOING
created: 2026-08-04
vikunja_task_id: 33
context_ref: a6ad560
work_branch: task/t-301-device-auth
needs_device: false
needs_human_review: false
write_paths:
- docs/tasks/T-301.md
- admin/migrations/00004_device_credentials.sql
- admin/internal/migrations/migrations_test.go
- admin/internal/deviceauth/**
- admin/internal/evidence/**
- admin/internal/storage/evidence/**
- admin/internal/server/**
- admin/cmd/device-credentials/**
- admin/cmd/server/**
- admin/README.md
- docs/api.md
- docs/04-architecture.md
---
<!-- BEGIN VIKUNJA EXPORT id=33 synced=2026-08-04T12:06:22Z sha256=1d572a2bf01628ca25aa153baa6d51443535eb399c006f1f0c7cc2b99edc1d6b -->
## 问题 / 背景
T-204 已提供设备认证注入点,但生产实现固定拒绝全部设备请求。T-301 为采购工具建立可签发、可撤销、服务端逐请求校验的设备凭据,并把管理员会话与设备 Bearer 能力严格隔离;不提前实现领取、租约或客户端 HTTP 适配。
## 关联需求与交互
- 功能:F-013。
- 用户故事:US-007。
- 依赖:T-201、T-204;复用 T-204 的证据上传认证入口。
- 后续消费者:T-302 领取/租约、T-303 客户端 HTTP 适配。
## 方案
1. 新增通用 `deviceauth` 包,提供设备主体和认证接口;把 T-204 位于 evidence 包内的临时接口迁出,证据上传改用通用主体,避免后续设备路由重复定义身份。
2. SQLite 新增设备凭据表:设备 id 为规范小写 UUID,显示名为非秘密元数据,token 只保存 32 字节 SHA-256 BLOB,状态仅 ACTIVE/REVOKED,并用时间字段约束撤销状态一致性。
3. 凭据签发生成 32 字节加密随机 token,对外只显示一次 64 位小写十六进制明文;数据库、日志、错误、HTTP 响应均不得保存或回显 token 明文。提供显式数据库路径的管理 CLI,支持 issue、list、revoke;list 不显示 token/hash,重复 revoke 不得恢复凭据。
4. 设备请求必须同时提供且只提供一个 `Authorization: Bearer <64位小写十六进制token>` 与一个 `X-CMBuyer-Device-ID: <小写UUID>`;格式、重复头、空白、未知、token/device 不匹配和已撤销统一 401,不区分原因。
5. 认证器每次请求查询 SQLite,不缓存 ACTIVE 结果,确保撤销立即生效;比较使用常量时间。请求头非法、未知、错配或已撤销统一返回空 401;SQLite 查询/连接故障返回空 503。两类都在读取请求体前失败闭合且不泄露内部信息。
6. 服务启动改用真实 SQLite 设备认证器;空凭据库仍拒绝全部。管理员 cookie 单独不能调用设备上传;Bearer 单独或与 cookie 并存均不能调用管理建单/开始采购,因为管理端仍只接受管理员 session + CSRF。
7. MVP 的采购服务与采购工具部署在同一运营电脑,服务进程只监听 127.0.0.1:8080;本机 HTTP 不经过网络。未来若开放非回环访问,必须先建立并验收 HTTPS/TLS 终止与代理信任边界,设备 Bearer 不得经过明文局域网。
8. 本任务只接通现有证据上传认证,不新增 heartbeat、claim、lease、event、fence、result 路由,不实现客户端保存/发送凭据,不接触真机选择器、提交订单或付款。
## 验收要点
- 迁移升级/重开/约束/回滚安全测试通过;数据库中不存在 token 明文。
- 覆盖签发随机性与一次显示、规范格式、错误头矩阵、token/device 绑定、撤销即时生效、重复撤销、并发认证/撤销,以及数据库故障在 body 零读取下返回空 503。
- 覆盖身份隔离:管理员 cookie 不能上传证据;设备 Bearer 不能建单或开始采购;混合凭据不扩大任一身份权限。
- 现有证据上传在有效设备身份下保持原幂等/归属语义,认证仍先于 Content-Type 和 body 读取。
- `go test ./...`、`go test -race ./...`、`go vet ./...`、`go build ./...`、完整 init、上下文校验与 diff-check 全部通过。
## 执行记录
### 2026-08-04T12:00:56Z · ila
2026-08-04 开始 T-301:依赖 T-201 已完成,任务定义提交 a6ad560。实现范围严格限于设备凭据签发/撤销、逐请求 Bearer+设备 id 认证、身份隔离及接通 T-204 证据上传;不新增领取/租约/事件/围栏/结果接口,不接触真机或提交/付款。工作分支 task/t-301-device-auth。
### 2026-08-04T12:04:54Z · ila
2026-08-04 编码前安全收紧:T-301 实际复用 T-204 认证注入点和 00003 后续迁移,依赖补为 T-201、T-204。MVP 已定为单机部署,生产服务改为仅监听 127.0.0.1:8080;未来非回环访问必须先建立 HTTPS/TLS 终止与代理信任边界,设备 Bearer 不得经过明文局域网。
### 2026-08-04T12:06:14Z · ila
2026-08-04 编码前错误语义定值:请求头非法、未知、token/device 错配和已撤销统一空 401;SQLite 查询/连接故障统一空 503。两类都必须在读取 body 和调用业务处理器前失败闭合,响应不含内部原因。token_sha256 采用 32 字节 BLOB。
<!-- END VIKUNJA EXPORT -->
## 边界
- 设备身份与管理员身份必须保持能力隔离:设备 Bearer 不得建单、开始采购、重置或调和;管理员
session 不得代替设备领取、上传或调用后续设备接口。两类凭据同时出现也不得扩大任何一方权限。
- 设备 token 必须由加密安全随机源生成,只在签发成功时向操作者显示一次;SQLite、日志、错误响应、
HTTP 响应、Git、Vikunja 和测试 fixture 均不得保存或回显明文 token。数据库只保存 token SHA-256。
- 认证必须同时绑定规范设备 id 与 token,并在解析请求体之前完成。格式错误、重复头、未知凭据、
token/device 不匹配和已撤销统一返回空 `401`;认证存储异常返回空 `503`。两类失败都必须
fail closed、不得调用业务处理器或读取请求体,也不得泄露具体原因。
- MVP 的采购服务与采购工具部署在同一运营电脑,生产服务必须只监听回环地址;只允许
`http://127.0.0.1` / `http://localhost` 的本机通信。未来若开放非回环访问,必须先单独建立并验收
HTTPS/TLS 终止与代理信任边界,不得让设备 Bearer 经过明文局域网。
- 撤销必须逐请求立即生效,不得缓存已认证结果,不得通过重复签发或重复撤销恢复旧 token。轮换属于
后续任务,本任务不提供会让旧 token 重新生效的路径。
- 本任务只把真实设备认证接到 T-204 已有截图上传入口;不得新增 heartbeat、claim、lease、event、
submission-fence 或 result 路由,不实现客户端凭据持久化和 HTTP 适配。
- 不接触拼多多页面判据、规格选择、数量、确认页或真机流程;不编写点击“提交订单”、支付、免密支付、
先用后付或任何扣款控件的代码。