交付单元 Server + Web;Android、采集器、全局菜单权限、采购流程、付款/下单及历史采购快照不改。服务端必须按当前登录用户过滤并校验 deviceId,不能只依赖前端;越权、未归属、停用设备返回明确错误。采购员只使用本人归属设备;管理员范围按前置单确认的规则执行,不能在本单自行扩大。继续复用现有行内小下拉,不增加顶部设备选择或新流程。实施时核对设备模型是否已有归属字段;没有则另提最小迁移方案,未经授权不实施。
验收:A 看不到且不能改请求使用 B 的设备;多台时只能选自己的设备;候选是选定设备最近一次可用采集;点击后冻结上下文;不完整不回退;关联和替换同样校验;补充契约、越权、排序、并发和 Web 测试,不执行真实采购/下单/付款。长期设备归属/API事实变化时更新 Wiki 并 sync/check,否则说明无影响。
不根据历史记录推断归属,不以全局最近采集兜底;设备转移、批量归属和菜单权限另建工单。本单创建后待实施。前置归属单未完成时本单明确阻塞;本单不自行创建归属数据、不执行迁移或权限写入。实施、发布或重启仍需明确授权。Gitea MCP 不可用,使用项目安全配置 API 回退创建。
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
需求与确认方案
多人同时使用系统、每个采购员账号拥有自己的一个或多个 Android 手机且不混用时,SYB 商品行“一键关联/一键替换”不得取到其他采购员的临时采集结果。
前置依赖(未满足前不得实施)
rnrn本单是设备归属数据的消费方,依赖一个前置单完成:rn- 设备归属数据模型/迁移;rn- 管理员维护采购员与手机归属的入口及已确认原型;rn- 现存 8 台设备的明确初始化归属;rn- 管理员可见范围和归属变更规则。rnrn前置单完成并验收前,本单保持待实施;不得用设备名称、历史采集记录或浏览器偏好推断归属,也不得用全局设备列表作为兜底。rnrn## 基线与范围基线 main:8d9c3d47e084e6b0e6db013024c9f38aedd3d0a7(2026-09-21)。#253 一键关联、#258 一键替换已上线,为依赖。当前 quick-link.js 请求 listDevices 后展示全部 online/offline 手机;偏好按登录用户保存,但选择不是服务端归属授权。前置归属数据完成后,本单才补充按当前登录用户过滤和服务端最终校验。请求已带 deviceId 和 latestCollection 上下文。本单只补归属范围和服务端最终校验,不改变现有匹配、替换确认、并发冻结和失败回读。
交付单元 Server + Web;Android、采集器、全局菜单权限、采购流程、付款/下单及历史采购快照不改。服务端必须按当前登录用户过滤并校验 deviceId,不能只依赖前端;越权、未归属、停用设备返回明确错误。采购员只使用本人归属设备;管理员范围按前置单确认的规则执行,不能在本单自行扩大。继续复用现有行内小下拉,不增加顶部设备选择或新流程。实施时核对设备模型是否已有归属字段;没有则另提最小迁移方案,未经授权不实施。
设计门禁、验收与风险
如需新增设备归属管理界面或改变设备列表交互,先制作并确认 QuantUX/低保真原型,覆盖正常、空、加载、失败、禁用和权限边界。数据库迁移、权限写入、并发/安全策略、发布均需实施前明确授权。
验收:A 看不到且不能改请求使用 B 的设备;多台时只能选自己的设备;候选是选定设备最近一次可用采集;点击后冻结上下文;不完整不回退;关联和替换同样校验;补充契约、越权、排序、并发和 Web 测试,不执行真实采购/下单/付款。长期设备归属/API事实变化时更新 Wiki 并 sync/check,否则说明无影响。
不根据历史记录推断归属,不以全局最近采集兜底;设备转移、批量归属和菜单权限另建工单。本单创建后待实施。前置归属单未完成时本单明确阻塞;本单不自行创建归属数据、不执行迁移或权限写入。实施、发布或重启仍需明确授权。Gitea MCP 不可用,使用项目安全配置 API 回退创建。
范围核查(2026-09-21,只读核验,未改动代码)
结论:问题真实、方向正确、安全考虑到位,但当前范围不可实施——工单把一个不存在的前提写成了「实施时核对」项。
一、已核验属实的部分
8d9c3d47e084e6b0e6db013024c9f38aedd3d0a7web/src/views/goauto/syb-products/quick-link.js:57按status === 'online' || status === 'offline'过滤,等于全量展示web/src/utils/quick-link-device-preference.js存于浏览器localStorageserver/app/goauto/shopeeproduct/latest_collection.go:99直接按请求传入的 ID 加锁查agent_device,:109按device_id查采集任务,全程无归属或用户校验sys_user3 个账号(admin/zhangwj、caigou1/采购1、caigou2);agent_device8 台「不能只依赖前端」的要求符合项目安全规则;点击后冻结 taskId/deviceId/规格上下文以防漂移是合理设计;非目标(不改采购流程、不碰付款下单、设备转移与批量归属另建工单)划分清楚。
二、关键问题:设备归属字段不存在,且不是可选项
核验
server/app/goauto/models/schema.go的AgentDevice,全部字段为:没有任何
UserID/OwnerID/PurchaserID字段;全库也不存在任何 user↔device 关联表(已按UserDevice/DeviceUser/DeviceOwner/DeviceAssign等命名检索,无结果)。工单将此写为「实施时核对设备模型是否已有归属字段;没有则另提最小迁移方案,未经授权不实施」,即当作待核对的条件分支。但核验结果是确定的——它不存在,因此它不是条件,而是整个功能的地基。
据此,工单正文中这一句不成立:
实际需要新增一个领域概念(设备归属),连带数据库迁移、归属维护界面,以及该界面按本工单自身门禁所要求的原型确认。
三、由此产生的三个自洽性缺口
四、建议
拆为两单,使本单的「只补范围和校验」真正成立:
说明
本次核查为只读:未修改任何代码、未创建迁移、未改动工单正文。以上结论中,第一节与第二节为代码与生产数据的直接核验结果,第三、四节为在此之上的判断。
实施完成,待验收(2026-09-21)
实现提交:
0661b22;文档提交:2491a85,均已推送 main。已实现
DEVICE_OWNERSHIP_FORBIDDEN,不会写入关联。验证
go test ./app/goauto/device ./app/goauto/shopeeproduct通过。文档
已更新长期业务规则并同步 Wiki,记录设备归属和一键关联/替换按所选设备取最新采集的规则。
本地迁移已完成:owner_user_id 已创建并记录迁移版本 1789800300000,重复执行无新增迁移。当前需在本地设备列表为手机分配采购员后,#328 才能进行采购员范围验证。
范围追加:手动关联/更换 PDD 搜索列表(2026-09-21)
用户确认:采购员登录后,在 SYB 商品详情中手动“关联/更换 PDD 商品”的搜索列表,也必须限制为当前账号归属手机采集过的 PDD 商品;Admin 账号仍可查看全部商品。
规则:
本次追加只涉及 Server/Web 查询过滤和越权测试,不改 Android、数据库模型、采集流程、采购流程或付款。
手动关联/更换列表过滤已实现(2026-09-21)
提交:4261a54,已推送 main。
验证:go test ./app/goauto/product ./app/goauto/shopeeproduct ./app/goauto/device 通过;新增归属设备/来源/状态过滤回归测试通过。无需新增数据库迁移。当前待验收,未发布或重启线上服务。
线上发布完成(2026-09-22)
已按授权发布 main 提交
5e0a9d1,发布标识20260922-5e0a9d1-328-330。/home/goauto/current已原子切换到该 release。1789800300000),其余 53 个已应用;未修改定时任务启停状态。goauto.service状态为 active,Nginx reload 成功。4a6806759108901808acaf162959909ece6c46d5dab02acdd56df30bccd315e8。状态:待线上功能验收。