docs(qy_lty): 启动 Milestone v1.0 通用凭据槽位

PROJECT.md 加入「本期 Milestone」段:全局单例 APP ID + Access Token 凭据存储,
管理端读写 + 客户端读取 + 日志脱敏;前端联动 milestone 在 qy-lty-admin 另起。
STATE.md 切换到 v1.0 状态:当前位置 = 需求定义中(roadmap 待生成)。
This commit is contained in:
pmc 2026-05-07 16:29:10 +08:00
parent 3e8a212e9f
commit ab3d728a08
2 changed files with 93 additions and 60 deletions

View File

@ -1,16 +1,33 @@
# QY LTY Backend洛天依统一后端服务 # QY LTY Backend洛天依统一后端服务
## What This Is ## 项目简介
QY LTY Backend 是「洛天依Luotianyi智能陪伴产品」生态的统一 Django 后端,同时服务于 **3 个客户端**Unity 设备端(`LTY_Project`、Unity 移动 App`LTY_App_Project_URP`、Web 管理后台(`qy-lty-admin`。提供用户认证、AI 对话含语音、设备实时通信WebSocket + RTC、卡片/二维码、成就、订阅等综合能力。 QY LTY Backend 是「洛天依Luotianyi智能陪伴产品」生态的统一 Django 后端,同时服务于 **3 个客户端**Unity 设备端(`LTY_Project`、Unity 移动 App`LTY_App_Project_URP`、Web 管理后台(`qy-lty-admin`。提供用户认证、AI 对话含语音、设备实时通信WebSocket + RTC、卡片/二维码、成就、订阅等综合能力。
## Core Value ## 核心价值
**设备端与手机端通过同一个用户身份实时互通**——`device_{user_id}` 分组模型必须始终成立。一旦绑定/控制权解析、WebSocket 路由、RTC 房间号三者偏离同一 user_id整个产品的"陪伴"价值就坍塌了。其他能力(卡片、成就、订阅)可以暂时降级,这条不行。 **设备端与手机端通过同一个用户身份实时互通**——`device_{user_id}` 分组模型必须始终成立。一旦绑定/控制权解析、WebSocket 路由、RTC 房间号三者偏离同一 user_id整个产品的"陪伴"价值就坍塌了。其他能力(卡片、成就、订阅)可以暂时降级,这条不行。
## Requirements ## 本期 Milestonev1.0 通用凭据槽位APP ID + Access Token
### Validated **启动日期**2026-05-07
**目标**在后端提供一组全局单例的通用凭据存储槽位APP ID + Access Token管理后台可写入手机端 + 设备端可读取。不绑定特定服务商,运营自由填值;前端联动 milestone 在 `qy-lty-admin` 仓库另行启动。
**目标能力**
- 后端单例配置模型(保存 APP ID + Access Token强制全局唯一记录
- 管理端读写接口admin token 鉴权,`/api/v1/admin/` 命名空间GET 时 Access Token 脱敏)
- 客户端读取接口user token 鉴权,复用 `RedisTokenAuthentication`,明文返回供 LTY_App_Project_URP / LTY_Project 实际调用第三方服务)
- 敏感字段脱敏(响应壳层 + 阿里云日志),避免 Access Token 落入生产日志
**关键约束**
- 客户端实际使用 Access Token 调用第三方服务,所以**客户端 GET 接口必须返回明文**;只有管理端 GET 与日志做脱敏
- 单例语义DB 中保证最多一条记录(建议 `pk=1` 固定主键 + `get_or_create` 模式,或单字段唯一约束)
- 与现有 `StandardResponseMiddleware` 响应壳层兼容(`{ success, code, message, data }`
- 不引入新的鉴权体系:管理端走 `admin_token:{token}`,客户端走 `token:{token}`,与现有所有接口对齐
## 需求清单
### 已交付
<!-- 已交付且在生产链路上跑通的能力,从 .planning/codebase/ 推断 --> <!-- 已交付且在生产链路上跑通的能力,从 .planning/codebase/ 推断 -->
@ -76,13 +93,20 @@ QY LTY Backend 是「洛天依Luotianyi智能陪伴产品」生态的统
- ✓ **DEP-03** PostgreSQL主库+ Redis缓存 + Channel Layer— existing - ✓ **DEP-03** PostgreSQL主库+ Redis缓存 + Channel Layer— existing
- ✓ **DEP-04** i18n 双语zh_HAns / envia django-rosetta — existing - ✓ **DEP-04** i18n 双语zh_HAns / envia django-rosetta — existing
### Active ### 进行中
<!-- 当前正在建设的目标。GSD 通过 phase 推动这一段;移到 Validated 才算完成 --> <!-- 当前正在建设的目标。GSD 通过 phase 推动这一段;移到 Validated 才算完成 -->
(暂无 — 本次 `/gsd-new-project` 仅做 brownfield 文档化。下次新增功能 / 子系统时使用 `/gsd-new-milestone` 启动新 milestone把当时要交付的能力加到这一段然后 `/gsd-plan-phase` 拆 phase。 **Milestone v1.0 通用凭据槽位**(启动 2026-05-07
### Out of Scope - [ ] **CRED-01** 单例 `CredentialSlot` 模型 + 迁移(强制 DB 中最多一条)
- [ ] **CRED-02** Django Admin 注册(`Access Token` 字段写入态可见,列表/查看态脱敏)
- [ ] **CRED-03** 管理端 GET `/api/v1/admin/credential-slot/`admin token 鉴权Access Token 字段脱敏掩码返回)
- [ ] **CRED-04** 管理端 PUT `/api/v1/admin/credential-slot/`admin token 鉴权,全字段覆写更新)
- [ ] **CRED-05** 客户端 GET `/api/credential-slot/`user token 鉴权 via `RedisTokenAuthentication`,明文返回 APP ID + Access Token
- [ ] **CRED-06** Access Token 在阿里云日志中过滤(日志格式化器 / 中间件层避免 secret 落生产日志)
### 范围外
<!-- 明确排除项 + 理由。防止后续被无意识地拉回来 --> <!-- 明确排除项 + 理由。防止后续被无意识地拉回来 -->
@ -93,7 +117,7 @@ QY LTY Backend 是「洛天依Luotianyi智能陪伴产品」生态的统
- **多 Redis 实例 / Sentinel 集群** — 当前是单 RedisCONCERNS.md 标记为 HA 风险,但不在本次范畴内;待性能/可用性 milestone 决议。 - **多 Redis 实例 / Sentinel 集群** — 当前是单 RedisCONCERNS.md 标记为 HA 风险,但不在本次范畴内;待性能/可用性 milestone 决议。
- **真正意义的测试套件** — 当前 ≈10 个 test 文件中只有 1 个真正在测,无 mock 基础设施。这是 CONCERNS.md 标的 HIGH-severity 工程债,但需要独立 milestone 系统性修。 - **真正意义的测试套件** — 当前 ≈10 个 test 文件中只有 1 个真正在测,无 mock 基础设施。这是 CONCERNS.md 标的 HIGH-severity 工程债,但需要独立 milestone 系统性修。
## Context ## 背景上下文
**生态位**本服务是「设备—App—管理端」三角的中心节点对所有客户端来说**它是唯一的真理来源**。 **生态位**本服务是「设备—App—管理端」三角的中心节点对所有客户端来说**它是唯一的真理来源**。
@ -117,24 +141,24 @@ QY LTY Backend 是「洛天依Luotianyi智能陪伴产品」生态的统
- `requirements.txt` 不锁版本(无 lockfile—— 部署一致性靠 Docker 镜像保证 - `requirements.txt` 不锁版本(无 lockfile—— 部署一致性靠 Docker 镜像保证
- Python 3.8 已 EOL2024-10需要规划升级 - Python 3.8 已 EOL2024-10需要规划升级
## Constraints ## 约束
- **Tech stack**: Django 4.2.13 + DRF + Channels + Daphne — 已锁定,迁移成本极高 - **技术栈**Django 4.2.13 + DRF + Channels + Daphne — 已锁定,迁移成本极高
- **Tech stack**: Python 3.8EOL— 当前限制,但近期需升级 - **技术栈**Python 3.8EOL— 当前限制,但近期需升级
- **Tech stack**: PostgreSQL+ Redis缓存 + Channel Layer— 不可替换 - **技术栈**PostgreSQL+ Redis缓存 + Channel Layer— 不可替换
- **Tech stack**: ASGI 必须,因为 WebSocket 是核心 — WSGI 路径 (`wsgi.py`) 仅作历史保留 - **技术栈**ASGI 必须,因为 WebSocket 是核心 — WSGI 路径 (`wsgi.py`) 仅作历史保留
- **Compatibility**: WebSocket 消息协议11 种 message type被 2 个 Unity 客户端依赖 — 任何新增字段必须向前兼容,删除字段需协调 3 方排期 - **兼容性**WebSocket 消息协议11 种 message type被 2 个 Unity 客户端依赖 — 任何新增字段必须向前兼容,删除字段需协调 3 方排期
- **Compatibility**: REST API 响应包装格式(`StandardResponseMiddleware` 输出的 `{success, code, message, data}`)被 `qy-lty-admin` 依赖 — 整体结构不可改 - **兼容性**REST API 响应包装格式(`StandardResponseMiddleware` 输出的 `{success, code, message, data}`)被 `qy-lty-admin` 依赖 — 整体结构不可改
- **Compatibility**: `device_{user_id}` 分组命名 + `room_{user_id}` 房间命名是端到端的隐式契约 — 改名要同步 Unity / Volcengine RTC 配置 - **兼容性**`device_{user_id}` 分组命名 + `room_{user_id}` 房间命名是端到端的隐式契约 — 改名要同步 Unity / Volcengine RTC 配置
- **Documentation**: 每次代码改动**必须**追加到 `docs/修改记录.md` 顶部CLAUDE.md 强制规则,结构性文档变更同样适用) - **文档规范**每次代码改动**必须**追加到 `docs/修改记录.md` 顶部CLAUDE.md 强制规则,结构性文档变更同样适用)
- **Communication**: 与用户沟通使用中文CLAUDE.md「沟通语言」章节强制 - **沟通语言**与用户沟通使用中文CLAUDE.md「沟通语言」章节强制
- **Independence**: `qy_lty``qy-lty-admin` 独立维护,**修改记录、planning 工件不混合** - **项目独立**`qy_lty``qy-lty-admin` 独立维护,**修改记录、planning 工件不混合**
- **Security**: `.env` 不入库,所有 SDK secret 必须通过环境变量加载CONCERNS.md 已标 SECRET_KEY / DEBUG / CORS 多处需收紧) - **安全**`.env` 不入库,所有 SDK secret 必须通过环境变量加载CONCERNS.md 已标 SECRET_KEY / DEBUG / CORS 多处需收紧)
## Key Decisions ## 关键决策
| Decision | Rationale | Outcome | | 决策 | 理由 | 结果 |
|----------|-----------|---------| |------|------|------|
| WebSocket 分组用 `device_{user_id}`(不是 `device_{mac}` | 让"同一用户"的多个端点(手机 + 设备)天然共享同一通信空间;同时一个设备同一时刻只能被最新绑定的用户控制,符合"陪伴"产品语义 | ✓ Good — 已支撑生产 | | WebSocket 分组用 `device_{user_id}`(不是 `device_{mac}` | 让"同一用户"的多个端点(手机 + 设备)天然共享同一通信空间;同时一个设备同一时刻只能被最新绑定的用户控制,符合"陪伴"产品语义 | ✓ Good — 已支撑生产 |
| `UserDevice.Meta.ordering = ['-bound_at']` 隐式驱动控制权解析 | 实现"后绑挤先绑"语义无需显式状态机,依赖 ORM 默认排序 | ⚠️ Revisit — 语义正确但隐式,新人容易误删旧记录或绕过 ordering 直接 query建议改写为显式 `current_owner` 字段 | | `UserDevice.Meta.ordering = ['-bound_at']` 隐式驱动控制权解析 | 实现"后绑挤先绑"语义无需显式状态机,依赖 ORM 默认排序 | ⚠️ Revisit — 语义正确但隐式,新人容易误删旧记录或绕过 ordering 直接 query建议改写为显式 `current_owner` 字段 |
| 30 天 token TTLRedis 后端) | 设备 + 手机端长期在线,短 TTL 体验差 | ✓ Good — 与产品形态匹配 | | 30 天 token TTLRedis 后端) | 设备 + 手机端长期在线,短 TTL 体验差 | ✓ Good — 与产品形态匹配 |
@ -144,22 +168,22 @@ QY LTY Backend 是「洛天依Luotianyi智能陪伴产品」生态的统
| 测试 MAC `AA:BB:CC:DD:EE:FF` 硬编码绕过绑定校验 | 早期开发便利 | ⚠️ Revisit — CONCERNS.md 标 HIGH上规模前必须替换为环境变量开关 | | 测试 MAC `AA:BB:CC:DD:EE:FF` 硬编码绕过绑定校验 | 早期开发便利 | ⚠️ Revisit — CONCERNS.md 标 HIGH上规模前必须替换为环境变量开关 |
| `.planning/` 锚定在 `qy_lty\`(不是 `Lila-Server\` | `qy_lty``qy-lty-admin` 是独立项目CLAUDE.md 规定各自维护 | ✓ Good — 2026-05-07 通过预创建空目录强制锚定生效 | | `.planning/` 锚定在 `qy_lty\`(不是 `Lila-Server\` | `qy_lty``qy-lty-admin` 是独立项目CLAUDE.md 规定各自维护 | ✓ Good — 2026-05-07 通过预创建空目录强制锚定生效 |
## Evolution ## 演进规则
This document evolves at phase transitions and milestone boundaries. 本文档在 phase 切换与 milestone 边界处更新。
**After each phase transition** (via `/gsd-transition`): **每次 phase 切换后**(通过 `/gsd-transition`
1. Requirements invalidated? → Move to Out of Scope with reason 1. 需求被推翻?→ 移到「范围外」并说明理由
2. Requirements validated? → Move to Validated with phase reference 2. 需求已交付?→ 移到「已交付」并标注 phase 引用
3. New requirements emerged? → Add to Active 3. 出现新需求?→ 加到「进行中」
4. Decisions to log? → Add to Key Decisions 4. 有决策需要记录?→ 加到「关键决策」
5. "What This Is" still accurate? → Update if drifted 5. 「项目简介」是否仍然准确?→ 如有偏移则更新
**After each milestone** (via `/gsd-complete-milestone`): **每个 milestone 完成后**(通过 `/gsd-complete-milestone`
1. Full review of all sections 1. 全面回顾所有章节
2. Core Value check — still the right priority? 2. 复核「核心价值」—— 是否仍是当前最高优先级?
3. Audit Out of Scope — reasons still valid? 3. 审视「范围外」—— 排除理由是否仍然成立?
4. Update Context with current state 4. 用当前状态更新「背景上下文」
--- ---
*Last updated: 2026-05-07 after brownfield documentation initialization (existing system mapped, no Active milestone yet — use /gsd-new-milestone to start the next cycle)* *最后更新2026-05-07启动 Milestone v1.0「通用凭据槽位APP ID + Access Token*

View File

@ -1,27 +1,36 @@
# Project State — QY LTY Backend # Project State — QY LTY Backend
**最后更新**: 2026-05-07brownfield 文档化初始化 **最后更新**: 2026-05-07启动 Milestone v1.0 通用凭据槽位
## Project Reference ## 项目引用
See: `.planning/PROJECT.md` (updated 2026-05-07) 参见:`.planning/PROJECT.md`(更新于 2026-05-07
**Core value**: 设备端与手机端通过同一个 user_id 实时互通——`device_{user_id}` 分组语义必须始终成立。 **核心价值**设备端与手机端通过同一个 user_id 实时互通——`device_{user_id}` 分组语义必须始终成立。
**Current focus**: 暂无 Active milestone — 待 `/gsd-new-milestone` 启动下一周期 **当前重点**Milestone v1.0 通用凭据槽位APP ID + Access Token— 后端存储 + 管理端读写 + 客户端读取 + 脱敏
## Status ## 当前位置
```
Phase: 未启动(定义需求中)
Plan: —
Status: 需求定义中roadmap 待生成)
Last activity: 2026-05-07 — 启动 Milestone v1.0
```
## 状态
| 项目 | 状态 | | 项目 | 状态 |
|------|------| |------|------|
| Codebase mapped | ✅ `.planning/codebase/` 7 文档commit `64a8cb8` | | 代码库映射 | ✅ `.planning/codebase/` 7 文档commit `64a8cb8` |
| PROJECT.md | ✅ Validated 已从 codebase 推断填充Active 段空 | | PROJECT.md | ✅ 已加入 Milestone v1.0 段 + Active 6 项 |
| REQUIREMENTS.md | ✅ Validated 已拆 REQ-IDActive 段空Traceability 待 phase 回填 | | REQUIREMENTS.md | 🟡 Active 段待回填CRED-01~06可追溯性待 phase 回填 |
| Roadmap | ⏸️ 暂未生成(无 Active 需求 → 无 phase 可分) | | 路线图 | ⏸️ 待 gsd-roadmapper 生成 |
| Active phase | — | | 当前 phase | — |
| Active milestone | — | | 当前 milestone | v1.0 通用凭据槽位 |
## Next Action ## 下一步
**当你准备开始下一个开发周期** **当你准备开始下一个开发周期**
@ -36,24 +45,24 @@ GSD 会:
**候选优先级排序见 `REQUIREMENTS.md → Active → 候选优先级` 段**。 **候选优先级排序见 `REQUIREMENTS.md → Active → 候选优先级` 段**。
## Workflow Config ## 工作流配置
详见 `.planning/config.json` 详见 `.planning/config.json`
- Mode: **YOLO**(自动通过审批,直接执行) - 模式:**YOLO**(自动通过审批,直接执行)
- Granularity: **Coarse**(每个 milestone 拆 3-5 phase - 粒度:**Coarse**(每个 milestone 拆 3-5 phase
- Parallelization: **enabled** - 并行化:**已启用**
- Workflow agents: research / plan_check / verifier 全部启用 - 工作流 agentresearch / plan_check / verifier 全部启用
- Model profile: **balanced**Sonnet 主力) - 模型档位:**balanced**Sonnet 主力)
- `.planning/` commits to git: **yes** - `.planning/` 提交到 git**是**
随时可用 `/gsd-settings` 调整。 随时可用 `/gsd-settings` 调整。
## Important Anchoring Note ## 锚定路径重要说明
`.planning/` 必须保持在 `c:\Users\admin\Desktop\Lila-Server\qy_lty\` 这一层(**不是父级 `Lila-Server\`**)。父级 `.git` 容易让 GSD CLI 误把 `Lila-Server` 当作 project_root本目录的存在就是锚定信号不要删。 `.planning/` 必须保持在 `c:\Users\admin\Desktop\Lila-Server\qy_lty\` 这一层(**不是父级 `Lila-Server\`**)。父级 `.git` 容易让 GSD CLI 误把 `Lila-Server` 当作 project_root本目录的存在就是锚定信号不要删。
## Project Rules Reminder ## 项目规则提醒
CLAUDE.md 中两条强制规则,做任何 phase 时必须遵守: CLAUDE.md 中两条强制规则,做任何 phase 时必须遵守:
@ -64,4 +73,4 @@ CLAUDE.md 中两条强制规则,做任何 phase 时必须遵守:
--- ---
*Generated by /gsd-new-project (brownfield doc pass) on 2026-05-07* *由 /gsd-new-projectbrownfield 文档化)生成于 2026-05-07*