diff --git a/qy_lty/docs/修改记录.md b/qy_lty/docs/修改记录.md index 790a713..c848a8c 100644 --- a/qy_lty/docs/修改记录.md +++ b/qy_lty/docs/修改记录.md @@ -23,6 +23,41 @@ +### [2026-05-07] Phase 1 — Django Admin 注册凭据槽位(脱敏 + 单例约束 + 禁删) + +配套 Phase:[.planning/phases/01-credential-data-layer/](.planning/phases/01-credential-data-layer/) +覆盖需求:CRED-02 + +- **文件路径**: `aiapp/admin.py`(修改 — 顶部 import 追加 `CredentialSlot` 与 `mask_token`,文件末尾追加 `CredentialSlotAdmin` 注册) +- **修改类型**: 新增 +- **修改内容**: + - 注册 `CredentialSlotAdmin`:`list_display = ('id', 'app_id', 'access_token_masked', 'updated_at')`,其中 `access_token_masked` 是计算字段(调 `common.utils.mask_token` 仅显示末 4 位掩码) + - `fieldsets` 分「凭据信息」(`app_id` / `access_token` 明文可写)+「元数据」(`updated_at` 只读、可折叠) + - 重写 `has_add_permission`:已存在记录时返回 `False`(Admin 列表页隐藏「增加」按钮,强制单例语义) + - 重写 `has_delete_permission`:永远返回 `False`(含批量动作;防运营误删丢失单例) + - 不修改既有 `BotAdmin` / `ChatMessageAdmin` 注册块 +- **修改原因**: CRED-02 — 在 SimpleUI 后台为运营提供受控的凭据录入入口;列表 / 查看态脱敏防截图 / 录屏泄露;编辑态保留明文供录入;新增 / 删除按钮隐藏强制单例语义不被运营误操作破坏 +- **跨项目联动**: 无 — qy-lty-admin 同期 v1.0 前端集成 milestone 已规划但未启动;待前端启动 phase 后由对方仓库写一条互引条目。本改动仅触及服务端 Django Admin(运营访问 `/admin/aiapp/credentialslot/` 直接录入),与 `qy-lty-admin/`(Web 管理后台前端)无 API 联动;CLAUDE.md 跨项目规则下纯服务端改动不需要在 `qy-lty-admin/docs/修改记录.md` 写互引条目。Phase 2 暴露 `/api/v1/admin/credential-slot/` 接口时再做前后端联动。 + +### [2026-05-07] Phase 1 — 凭据槽位数据层(CredentialSlot 单例模型 + 迁移 + mask_token 工具) + +配套 Phase:[.planning/phases/01-credential-data-layer/](.planning/phases/01-credential-data-layer/) +覆盖需求:CRED-01 +设计参考:1:1 复刻 `userapp.models.AffinitySetting`(`userapp/models.py:247-314`)的 pk=1 + `save()` 钩子 + `get_solo()` 单例三件套 + +- **文件路径**: + - `common/utils.py`(新增 — `mask_token(token, visible_tail=4)` 工具函数,供本 Phase Admin 与 Phase 3 阿里云日志 formatter 共用) + - `aiapp/models.py`(修改 — 文件末尾追加 `CredentialSlot` 模型,3 字段 + save 钩子 + `get_solo` 类方法) + - `aiapp/migrations/0004_credentialslot.py`(新增 — `python manage.py makemigrations aiapp` 自动生成) +- **修改类型**: 新增 +- **修改内容**: + - 新增 `CredentialSlot` 模型(aiapp app):`app_id` CharField(128, blank=True, default='')、`access_token` CharField(512, blank=True, default='')、`updated_at` DateTimeField(auto_now=True);`save()` 钩子在已有记录时把新对象 pk 改为现有那条;`get_solo()` 类方法走 `get_or_create(pk=1)` + - 新增 `common.utils.mask_token(token, visible_tail=4, mask_char='*')`:空输入返回 `''`;短于 visible_tail 时全脱敏不暴露长度;其余保留末 N 位明文 + - 自动生成迁移 `aiapp/migrations/0004_credentialslot.py`,`python manage.py migrate` 通过;首次访问 `CredentialSlot.objects.get_or_create(pk=1)` 拿到一条空记录 +- **修改原因**: Milestone v1.0「通用凭据槽位(APP ID + Access Token)」Phase 1 — 在 DB 层落地全局单例的凭据存储槽位,为 Phase 2 管理端 REST、Phase 3 客户端 REST + 日志脱敏奠基;mask_token 抽到 `common/` 让 Phase 3 阿里云日志 formatter 直接复用,避免重复实现 +- **后续动作**: Phase 2 暴露 `/api/v1/admin/credential-slot/` GET(脱敏) / PUT(覆写);Phase 3 暴露 `/api/credential-slot/` GET 明文 + 阿里云日志 formatter 用 `mask_token` 过滤 `access_token` 字段 +- **跨项目联动**: 无 — qy-lty-admin 同期 v1.0 前端集成 milestone 已规划但未启动;待前端启动 phase 后由对方仓库写一条互引条目。本改动是纯数据层 + 工具函数,无任何 HTTP / WebSocket 接口暴露,`qy-lty-admin` 与 Unity 客户端均无感知;不需要在前端写互引条目。 + ### [2026-05-07] 引入 GSD 工作流并完成 brownfield 文档化初始化 - **文件路径**: