pmc 9965d0bcf0 docs(03-02): 完成 Phase 3 Plan 03-02 + Milestone v1.0 收尾
- 03-02-SUMMARY.md 新建: AccessTokenMaskFilter + LOGGING + 修改记录条目落地, 9 truth × 32 项断言全 PASS, 2 处 Rule 1 auto-fix bug 文档化
- STATE.md 更新: 进度 100%, Phase 3 标记 Complete, Milestone v1.0 收尾, 决策日志补 [Plan 03-02] 7 条
- ROADMAP.md 更新: Milestone v1.0 标  完结, Phase 3 / Plan 03-01+03-02 全部 ✓
- REQUIREMENTS.md 更新: CRED-06 标记 Done, traceability 表 Phase 3 行 Done, 覆盖率 6/6 全 Done

Milestone v1.0「通用凭据槽位 (APP ID + Access Token)」CRED-01 至 CRED-06 全部交付完成。
2026-05-08 10:36:17 +08:00

181 lines
13 KiB
Markdown
Raw Permalink 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.

---
gsd_state_version: 1.0
milestone: v1.0
milestone_name: 通用凭据槽位
status: Milestone v1.0 完成 — CRED-01 至 CRED-06 全部交付Phase 1+2+3 全部 Done下一周期 milestone 候选评估
stopped_at: Plan 03-02 完成CRED-06 日志脱敏 filter 落地9 truth × 32 断言全 PASSMilestone v1.0 已收尾
last_updated: "2026-05-08T02:33:19.667Z"
last_activity: 2026-05-08
progress:
total_phases: 3
completed_phases: 3
total_plans: 6
completed_plans: 6
percent: 100
---
# Project State — QY LTY Backend
**最后更新**: 2026-05-08Phase 3 Plan 03-02 完成AccessTokenMaskFilter 落地CRED-06 标记 Done端到端 9 truth × 32 断言全 PASSMilestone v1.0「通用凭据槽位」CRED-01~06 全部交付)
## 项目引用
参见:`.planning/PROJECT.md`(更新于 2026-05-07
**核心价值**:设备端与手机端通过同一个 user_id 实时互通——`device_{user_id}` 分组语义必须始终成立。
**当前重点**Milestone v1.0 通用凭据槽位APP ID + Access Token**全部完成**。下一周期候选 milestone 评估见 `REQUIREMENTS.md` 候选优先级段。
## 当前位置
```
Phase: 3 of 3客户端读取与日志脱敏— Complete ✓
Plan: 2 of 02CRED-06 阿里云日志脱敏)— Complete ✓
Status: Milestone v1.0 完结,等待下一周期 milestone 立项
Last activity: 2026-05-08
```
Progress: [██████████] 100%(已完成 plan6/6 — Phase 1 全部 + Phase 2 全部 + Phase 3 全部)
## 性能指标
**速度:**
- 已完成 plan 数6
- 平均耗时:~414 s顺序执行模式
- 总执行时间2484 sPlan 01-01: 184 s + Plan 01-02: ~600 s + Plan 02-01: 216 s + Plan 02-02: ~720 s + Plan 03-01: 270 s + Plan 03-02: 494 s
**按 Phase**
| Phase | Plans | Total | Avg/Plan |
|-------|-------|--------|----------|
| 1 | 2/2 | 784 s | 392 s |
| 2 | 2/2 | 936 s | 468 s |
| 3 | 2/2 | 764 s | 382 s |
**最近趋势:**
- 最近 6 个 plan01-01184 s3 task/ 01-02~600 s4 task + checkpoint 验收)/ 02-01216 s3 task / 3 commit / 3 文件)/ 02-02~720 s2 task / 2 commit / 1 创建 + 2 修改文件 + 端到端 28 项断言)/ 03-01270 s3 task / 2 commit / 2 修改文件 + 1 临时验收脚本未入 git + 端到端 15 项断言)/ 03-02494 s4 task / 4 commit / 2 创建 + 2 修改文件 + 端到端 32 项断言 + 2 处 Rule 1 auto-fix bug
- 趋势03-02 略慢于 03-01494 vs 270 s原因是 plan 内置 2 处 bugPattern 4 兜底 regex 吃尾 + tuple args 形态破坏 %s 占位符)需要现场调试 + auto-fixnett 端到端覆盖更广32 vs 15 项断言Milestone v1.0 整体节奏稳定 200-720 s/plan
*每完成一个 plan 后更新*
## 累积上下文
### 决策
完整决策日志见 PROJECT.md「关键决策」表。
当前 milestone 相关决策:
- 凭据槽位以 `pk=1 + get_or_create` 模式落地单例语义PROJECT.md「关键约束」段
- 客户端 GET 接口必须返回**明文** Access Token手机端/设备端实际调用第三方需要),仅管理端 GET 与日志做脱敏
- **[Plan 01-01]** `CredentialSlot` 单例 1:1 复刻 `userapp.models.AffinitySetting`pk=1 + save 钩子重定向 + get_solo不发明新模式
- **[Plan 01-01]** `CredentialSlot` 字段集合最小化app_id(128) / access_token(512) / updated_at不加 `created_at`(单例无创建语义)
- **[Plan 01-01]** Admin 与 Phase 3 日志共用同一 `mask_token` 工具(放 `common/utils.py`),不引入第三方加密 / 脱敏库
- **[Plan 01-01]** 探针数据契约DB pk=1 留 `access_token='probe_secret_xxxx'`Plan 01-02 Admin 列表脱敏 checkpoint 期望串 `*************xxxx`
- **[Plan 01-02]** CredentialSlotAdmin access_token 不进 readonly_fields编辑态保持明文 input 供运营录入;脱敏靠 list_display 的 access_token_masked 计算字段)
- **[Plan 01-02]** has_add_permission 条件式CredentialSlot.objects.exists() 取反),不写死 False首次部署运营仍能录入第一条
- **[Plan 01-02]** has_delete_permission 永远 False含 obj=None 的批量动作场景;防运营误删丢失单例
- **[Plan 01-02]** BotAdmin / ChatMessage 注册块的历史 class 名误用问题不修(不在 phase scope
- **[Plan 01-02]** 修改记录两条条目都在 Task 3 一次性写入「跨项目联动: 无」字段INFO #2 调整),不留 Task 4 二次写入
- **[Plan 01-02]** qy-lty-admin/docs/修改记录.md 不写互引条目Phase 1 是纯服务端改动CLAUDE.md 跨项目规则下纯单端不需要互引Phase 2 暴露 REST 接口时再做前后端互引
- **[Plan 02-01]** CredentialSlotAdminView 1:1 复刻 RTCChatHistoryAPIView 自定义 APIView 风格(不走 RetrieveUpdateAPIView仓库零先例
- **[Plan 02-01]** permission_classes=[IsAuthenticated] + view 内 _ensure_admin 二次校验 is_staff不发明 IsAdminTokenAuthenticated permission 类,沿用 AdminEmailLoginView/AdminLogoutView 模式)
- **[Plan 02-01]** 脱敏放 view 层 _build_response_data helperGET 与 PUT 响应都强制走脱敏,避免 PUT 直接 return success_response(data=serializer.data) 明文回显Pitfall 3
- **[Plan 02-01]** drf-yasg request_body 用独立 CredentialSlotPutRequestSchema 类(与 AdminEmailLoginRequestSchema 模式一致),与实际写入校验的 CredentialSlotSerializer 解耦
- **[Plan 02-01]** 不写 docs/修改记录.md用户在 prompt 显式声明);由 Plan 02-02 Task 2 一次性补两端互引条目
- **[Plan 02-02]** 端到端验收走 Django test clientin-process不启 daphne / runserver内存调用更快、可重复、零端口占用本仓库鉴权 + 标准壳层 middleware 都是 Django MIDDLEWARE 而非 ASGI 层test client 路径与生产路径功能等价
- **[Plan 02-02]** Swagger 验收路径:`/swagger.json/`(带 trailing slashurl 模式 `swagger<format>/`);本仓库 StandardResponseMiddleware 也会包 OpenAPI schema 进 `{success, code, message, data}`,验证脚本需 unwrap `data` 字段basePath=/api 所以 paths key 是 `/v1/admin/credential-slot/`(去掉 /api 前缀)
- **[Plan 02-02]** 测试 token 明文不入仓库02-VERIFICATION.md 仅记长度length=36+ PASS 判定;脚本结束自动 cache.delete 释放 Redis admin_token / token key
- **[Plan 02-02]** DB 探针态主动还原:脚本最后 slot.app_id='probe_app' / slot.access_token='probe_secret_xxxx' / slot.save() 还原,给 Phase 3 留下稳定起点
- **[Plan 02-02]** qy-lty-admin 改动通过父级 Lila-Server/.git 提交qy-lty-admin/ 没有自己的 .gitcommit 46d72b8 在父仓库同时入两端 docs/修改记录.md
- **[Plan 02-02]** 临时验收脚本验完即删:`_phase2_verify.py` / `_phase2_swagger_verify.py` 是一次性证据生成器,证据落地 02-VERIFICATION.md 后无需保留
- **[Plan 03-01]** CredentialSlotClientView 完全独立 APIView 类,不继承 admin view不调 _ensure_admin / _build_response_data / mask_token明文返回与 admin view 形成对称命名 + 反向行为
- **[Plan 03-01]** 路由放顶层 qy_lty/urls.py:api_urlpatterns参考 common/upload/ 风格),最终 URL = /api/credential-slot/,不挂任何 sub-include 命名空间
- **[Plan 03-01]** 客户端响应 schema 独立命名 _credential_slot_client_data_schemaaccess_token description 显式标注「明文」,与 admin 端 _credential_slot_data_schema 对照避免混用脱敏掩码语义
- **[Plan 03-01]** 不调用 logger.info / logger.debug 输出 access_token未引入新泄露源Plan 03-02 的 AccessTokenMaskFilter 是兜底防御
- **[Plan 03-01]** 验收脚本 `_phase3_01_verify.py` 不入 git留在仓库根Plan 03-02 Task 4 末尾统一删除 + 一并写两端 docs/修改记录.md 互引条目
- **[Plan 03-02]** AccessTokenMaskFilter 挂在 LOGGING.handlersaliyun + console而非 loggers 段:挂 logger 仅过滤直接通过该 logger 的 record挂 handler 才统一覆盖所有 logger → handler 路径
- **[Plan 03-02]** dictConfig filter 注册用 `()` 工厂语法不用 `class`dictConfig 标准对 filter 与 handler 语法不互通
- **[Plan 03-02]** 4 个 regex 不合并成 1 个大 regex可读性 + group 数差异JSON/Pyrepr 是 3 group / Query/Fallback 是 2 group合并会让 _sub 变脆
- **[Plan 03-02]** filter 仅识别 access_token 字段名前缀锚点,不脱敏裸 token / Authorization / Bearer那是另一类敏感数据留 v2.x 候选优先级处理
- **[Plan 03-02]** Pattern 4 兜底 regex 终止符增加 `&` / `=` 排除:避免 Pattern 3 的输出 `access_token=********1234&u=1` 被 Pattern 4 把 `********1234&u=1` 整段二次 mask 把末 4 位 `1234` 吃成 `&u=1`auto-fix Rule 1 Bug
- **[Plan 03-02]** tuple args 形态走 `record.getMessage()` 预拼接后 `args=None` 再脱敏:避免 Formatter `%` 拼接时占位符被 mask 吃掉触发 TypeErrorauto-fix Rule 1 Bug
- **[Plan 03-02]** 不写 qy-lty-admin/docs/修改记录.md 互引CONTEXT 锁定 + RESEARCH 实证;客户端给 Unity 用qy-lty-admin 不消费 /api/credential-slot/
### Pending Todos
无(`.planning/todos/pending/` 暂无条目)
### Blockers/Concerns
## Deferred Items
从 brownfield 文档化阶段沉淀的候选优先级(详见 REQUIREMENTS.md → Active → 候选优先级),本期 v1.0 不消化:
| 类别 | 条目 | 状态 | 沉淀于 |
|------|------|------|--------|
| HIGH | ACH-02 成就解锁条件校验缺失 | 候选 | 2026-05-07 brownfield |
| HIGH | SMS 验证码无频率限制 | 候选 | 2026-05-07 brownfield |
| HIGH | 收紧 DEBUG / CORS_ALLOW_ALL_ORIGINS 默认值 | 候选 | 2026-05-07 brownfield |
| HIGH | 移除测试 MAC `AA:BB:CC:DD:EE:FF` 硬编码 | 候选 | 2026-05-07 brownfield |
| HIGH | 测试基础设施搭建pytest 体系) | 候选 | 2026-05-07 brownfield |
| MEDIUM | 好感度 P2/P3/P4Service / 接口 / 客户端集成) | 候选 | 2026-05-07 brownfield |
| MEDIUM | Python 3.8 → 3.11/3.12 升级 | 候选 | 2026-05-07 brownfield |
| MEDIUM | 拆分 device_interaction/views.py1867 行) | 候选 | 2026-05-07 brownfield |
## 下一步
```
Milestone v1.0 已完结。下一步:评估下一周期 milestone 候选(见 REQUIREMENTS.md 候选优先级段);运行 /gsd-complete-milestone 收口(如启用)
```
Phase 3 Plan 03-02 已完成commits 891a5ea / 35eb110 / 7a9e511 / db4d5cf
- Task 1`common/logging/__init__.py`(空 package marker+ `common/logging/filters.py`106 行 AccessTokenMaskFilter4 正则 + tuple args 处理 + filter() 方法commit 891a5ea
- Task 2`qy_lty/settings.py:LOGGING` 注册 `filters`dictConfig `()` 工厂语法)+ `handlers.aliyun` / `handlers.console` 各挂 `filters: ['access_token_mask']`loggers 段 5 条 logger 完全未动commit 35eb110
- Task 3端到端 9 条 truth × 32 项独立断言全 PASS — 覆盖 03-01 的 5 条 client view + filter 4 形态 + 不误伤 Authorization + admin/client roundtrip + 端到端 logger.info 真打印 console 脱敏 + DB 探针态还原commit 7a9e51103-VERIFICATION.md 落地)
- Task 4`docs/修改记录.md` 顶部追加 [2026-05-08] Phase 3 条目(覆盖 5 处文件 + CRED-05/06 + 跨项目联动「无」明示commit db4d5cf
CRED-06 已在 REQUIREMENTS.md 标记 DoneDB 探针态保持 `pk=1 / app_id='probe_app' / access_token='probe_secret_xxxx'`临时验收脚本5 个)全部删除。
**Milestone v1.0「通用凭据槽位APP ID + Access Token」CRED-01 至 CRED-06 全部交付完成**。下一周期候选见上方「Deferred Items」段。
## 工作流配置
详见 `.planning/config.json`
- 模式:**YOLO**(自动通过审批)
- 粒度:**Coarse**3-5 phase / milestone
- 并行化:**已启用**
- workflow agentresearch / plan_check / verifier 全部启用
- 模型档位:**balanced**
- `.planning/` 提交到 git**是**
`/gsd-settings` 可调整。
## 锚定路径重要说明
`.planning/` 必须保持在 `c:\Users\admin\Desktop\Lila-Server\qy_lty\` 这一层(**不是**父级 `Lila-Server\`)。父级 `.git` 容易让 GSD 误把 `Lila-Server` 当作 project_root本目录的存在就是锚定信号。
## 项目规则提醒
CLAUDE.md 两条强制规则(任何 phase 都必须遵守):
1. **沟通语言**:所有面向用户的回复使用中文
2. **修改记录**:每次代码 / 配置 / 迁移 / CI / Docker / 文档结构性改动**必须**追加到 `docs/修改记录.md` 顶部
`qy_lty``qy-lty-admin` 是独立项目,修改记录互不混合。
## Session Continuity
Last session: 2026-05-08T02:30:22Z
Stopped at: Plan 03-02 完成CRED-06 日志脱敏 filter 落地9 truth × 32 断言全 PASSMilestone v1.0 已收尾,等待下一周期 milestone 立项
Resume file: None
---
*由 /gsd-execute-phase 顺序执行器于 2026-05-08 更新Plan 03-02 完成时点Milestone v1.0 完结)*