Files
cursor/plans/SR-3 internal-23416728.plan.md
ray zhou 2dd9f17da9 ok
2026-06-29 14:51:55 +08:00

122 lines
6.1 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.

<!-- 23416728-def1-424f-ba2f-16a110d1f084 -->
---
todos:
- id: "internal-layer"
content: "新建 internal DeviceController + 迁移 logic/dto/validateDTO 含 user_id"
status: pending
- id: "cleanup-api"
content: "从 api DeviceController 移除绑定三接口并删除 api 侧绑定文件"
status: pending
- id: "remove-user-auth"
content: "删除 UserAuth、UserRequestContext 及无引用错误码"
status: pending
- id: "docs-update"
content: "更新 device.md §10、03-user-binding.md、06-internal-api.md 路径与调用方说明"
status: pending
- id: "verify"
content: "docker php -l + slot-backend-completion-report"
status: pending
isProject: false
---
# SR-3 设备绑定迁入 internal 应用
## 架构判断(同意你的方向)
与 [device.md](device/docs/requirements/device.md) 中已有分层一致:
| 应用 | 调用方 | 鉴权 | 职责 |
|------|--------|------|------|
| **api** | 物理设备 | `device_sn` + 签名 | 激活、心跳、OTA 入口 |
| **admin** | 后台 BFF / admin-service | `Authorization`(骨架) | 产品/型号/设备档案管理 |
| **internal** | user-service、message-service、ota-service 等 | `X-Internal-Token` | 跨服务读写设备主数据 |
绑定关系是 **device-service 的领域数据**,但 **用户登录态不应在本服务校验**——应由 user-service或 App BFF完成 session/JWT 校验后,再调用 device-service 的 internal 接口写入绑定。这与 §4.3「后台 → BFF → device-service」模式同构。
```mermaid
sequenceDiagram
participant User as 用户App
participant UserSvc as user_service_BFF
participant Device as device_service_internal
User->>UserSvc: 扫码绑定 device_sn
Note over UserSvc: 校验登录态,解析 user_id
UserSvc->>Device: POST /internal/device/bind
Note over Device: X-Internal-Token + user_id + device_sn
Device-->>UserSvc: code=0
UserSvc-->>User: 绑定成功
```
**结论**SR-3 应落在 **internal**,而不是 api当前 [DeviceController.php](device/app/api/controller/DeviceController.php) 上的 `#[Middleware(UserAuth)]` + `UserRequestContext` 应移除。
---
## 目标接口默认路由id 走 body/query
| 方法 | 路径 | 入参 |
|------|------|------|
| POST | `/internal/device/bind` | `user_id`, `device_sn` |
| POST | `/internal/device/unbind` | `user_id`, `device_id` |
| GET | `/internal/device/list` | `user_id`query |
鉴权:应用级 [InternalTokenAuth](device/app/middleware/InternalTokenAuth.php)(已挂在 `internal`**不再**使用 [UserAuth](device/app/middleware/UserAuth.php)。
---
## 代码迁移步骤
### 1. 新建 internal 分层(从 api 平移)
- 新增 [app/internal/controller/DeviceController.php](device/app/internal/controller/DeviceController.php)`extends InternalController`
- `bind` / `unbind` / `list` 三个 action
- 将以下文件 **改 namespace 为 `app\internal\*`**(逻辑基本不变):
- [app/api/logic/DeviceBindLogic.php](device/app/api/logic/DeviceBindLogic.php) → `app/internal/logic/DeviceBindLogic.php`
- [app/api/dto/DeviceBindDTO.php](device/app/api/dto/DeviceBindDTO.php) → 增加 `userId` 字段
- [app/api/dto/DeviceUnbindDTO.php](device/app/api/dto/DeviceUnbindDTO.php) → 增加 `userId` 字段
- [app/api/validate/DeviceBindValidate.php](device/app/api/validate/DeviceBindValidate.php) → 增加 `user_id` 规则(`require|integer|gt:0`)及 validation 文案
Controller 从 DTO 读取 `userId`**不再**调用 `UserRequestContext::getUserId()`
### 2. 清理 api 应用
- 从 [app/api/controller/DeviceController.php](device/app/api/controller/DeviceController.php) 删除 `bind` / `unbind` / `list``DeviceBindLogic``DeviceBindValidate``UserAuth` 相关 use/构造注入
- 删除 api 侧已迁移的 logic/dto/validate 文件
### 3. 删除用户鉴权骨架(若无其它引用)
- 删除 [app/middleware/UserAuth.php](device/app/middleware/UserAuth.php)
- 删除 [app/support/UserRequestContext.php](device/app/support/UserRequestContext.php)
- `OtaErrorCode::USER_AUTH_FAILED (1004)` 可保留翻译条目(无害),或一并移除——以「无引用」为准
### 4. Logic 行为
[DeviceBindLogic](device/app/api/logic/DeviceBindLogic.php) 业务规则 **不变**(幂等、唯一约束、状态校验);仅入参来源从「上下文 user_id」改为「请求体/Query 显式 `user_id`」。
**安全说明**(写入 SR-3/SR-6 文档internal 信任「调用方已在网关/BFF 完成用户鉴权」;`user_id` 由调用方传入device-service 只负责绑定域规则。与 SR-6 §5「服务间 token」一致。
### 5. 需求文档同步
- [03-user-binding.md](device/docs/requirements/device/03-user-binding.md):路径改为 `/internal/device/*`,注明调用方为 user-service/BFF
- [device.md](device/docs/requirements/device.md) §10同上§10 标题可改为「用户绑定(内部接口,由 user-service 暴露给 App
- [06-internal-api.md](device/docs/requirements/device/06-internal-api.md):补充 bind/unbind/list 三条(扩展 SR-6 范围或交叉引用 SR-3
### 6. 调用方 SDK可选本仓库外
按 [cross-service-sdk](.cursor/rules/cross-service-sdk.mdc),若 user-service 在 monorepo 内,后续在 `slot_sdk` 增加 `DeviceClient`(或 `DeviceBindService`)方法指向上述三条 internal 路径;**本次 device 仓库内可不实现**,仅在计划中标注为调用方跟进项。
---
## 不涉及
- `DeviceBindModel`、错误码 `4208`/`4209`、翻译文案:已存在,无需改业务码
- SR-6 只读查询(单设备档案/批量/在线状态):可另 PR 实现,与本次迁移独立
- 「查询设备绑定用户」admin 详情已只读;若 internal 需要可加 `GET /internal/device/bind-owner?device_id=`**非本次必须**,除非你要求一并做
---
## 验收
1. `api` 仅保留 `activate``heartbeat`(及后续 OTA
2. `internal` 三条绑定接口带 `X-Internal-Token` 可通,缺 token 返回 `1001` + HTTP 403
3. 绑定/解绑/列表业务行为与现 SR-3 验收要点一致
4. `docker php -l` + completion-report 通过