## Context 依据 `docs/engineering/轮询按运营商账户限流技术方案.md` 第一部分第 6 节、第四部分"保护期整套机制"。 现状:后台设备停复机设置 `protect:device:{id}:stop|start`(1 小时,互斥,`internal/service/device/service.go:1506,1663`);保护期内拒绝相反人工操作;`polling:protect` 轮询(`internal/task/polling_protect_handler.go`)方向不一致时 `ForceStopCard` / `ForceStartCard`;自动停复机 `EvaluateAndAct` 不看保护期,造成反复翻转。`ProtectCheckSkipsForRealname`(`stop_resume_unified.go`)仅保护期轮询使用。资产 DTO 有 `device_protect_status`(`asset_dto.go:38,144`、`client_asset_dto.go:75`)。 ## Goals / Non-Goals **Goals:** 删除保护期的设置、检查、轮询与展示逻辑;不破坏现有客户端;数据库只加不删。 **Non-Goals:** 不改停复机业务规则(第 4、6 个 Change);不删 `protect_period` 常量与历史数据;不删数据库列。 ## Decisions 1. **字段保留、固定返回 `none`**:直接删字段会让读取该字段的老版本小程序出错;固定值兼容成本最低。备选"字段 omitempty 后不返回":老客户端读不到同样可能出错,放弃。 2. **数据库列只改注释**:遵循"数据库只加不删";`protect_check_interval`、`last_protect_check_at` 列注释标记已废弃,代码中去掉读写。 3. **存量 Redis 保护期 key 不清理**:TTL 只有 1 小时,上线后自然过期;代码不再读取,即使残留也无影响。 4. **Asynq 中已排队的 `polling:protect` 任务**:保留一个空处理函数直接返回成功一个发布周期,避免"未注册任务类型"错误堆积,下一次发布再移除;或上线前确认队列为空。选择保留空处理函数,更稳妥。 ## Risks / Trade-offs - [运营依赖保护期防止误操作] → 已定"规则优先、人工停机无豁免",需要保持停机的关闭轮询(第 7 个 Change 提供批量操作)。 - [前端仍展示保护期] → 固定 `none` 时前端显示"无",不报错;前端随后去掉展示。 ## Migration Plan 1. 迁移只改列注释。2. 测试环境验证后由维护者发布生产。3. 回退:代码回退即可恢复保护期逻辑,数据库无需回退。