diff --git a/qy-lty-admin/.planning/REQUIREMENTS.md b/qy-lty-admin/.planning/REQUIREMENTS.md index d3a92f9..ed4ae75 100644 --- a/qy-lty-admin/.planning/REQUIREMENTS.md +++ b/qy-lty-admin/.planning/REQUIREMENTS.md @@ -2,7 +2,7 @@ **初始化日期**: 2026-05-07 **类型**: Brownfield 文档化(从 `.planning/codebase/` 推断) -**状态**: 已落地能力归档完成;Active milestone 待 `/gsd-new-milestone` 启动 +**状态**: 已落地能力归档完成;Milestone v1.0「通用凭据槽位前端集成」已生成 ROADMAP.md(3 个 phase,coarse 粒度) --- @@ -14,7 +14,7 @@ - [x] **AUTH-01** 邮箱 + 密码登录页(`app/login/page.tsx`、`lib/api/auth.ts:emailLogin`) - [x] **AUTH-02** 注册 / 找回密码占位页(`app/register/`、`app/forgot-password/`) -- [x] **AUTH-03** Bearer token 拦截器自动注入(`lib/api/client.ts` 请求拦截器) +- [x] **AUTH-03** Bearer token 拦截器自动注入(`lib/api/client.ts` 请求拦截器) - [x] **AUTH-04** 401 响应统一处理(清空 token + 重定向 `/login`) - [x] **AUTH-05** Cookie 镜像 token(`js-cookie`,7 天有效期,供 middleware 读取) - [x] **AUTH-06** 退出登录调后端 logout 接口并清空双存储 @@ -82,7 +82,7 @@ **Milestone v1.0:通用凭据槽位前端集成** 启动日期:2026-05-07 -联动:qy_lty 后端 Milestone v1.0(3 个 phase,API 契约已锁定) +联动:qy_lty 后端 Milestone v1.0(3 个 phase,API 契约已锁定);端到端验收依赖后端 Phase 2「管理端读写接口」落地 目标:在 `/ai-model` 页面集成 APP ID + Access Token 录入/编辑窗口,调用后端管理接口完成读写。 ### 通用凭据槽位前端集成(CRED-FE) @@ -127,10 +127,22 @@ ## Traceability - + -(暂无 phase;待 `/gsd-new-milestone` 后启动) +### Milestone v1.0 通用凭据槽位前端集成(2026-05-07 ROADMAP 落地) + +| Requirement | Phase | UI hint | Status | +|-------------|-------|---------|--------| +| CRED-FE-01 API 客户端 `lib/api/credential-slot.ts`(类型 + 适配器 + GET/PUT) | Phase 1 凭据槽位 API 客户端 | — | Pending | +| CRED-FE-02 RBAC 模块声明(`lib/permissions.ts` 加 `credential-slot` key + 矩阵分配) | Phase 2 RBAC 收敛 + AI 模型页入口 | yes | Pending | +| CRED-FE-03 `/ai-model` 页面入口(受 `hasPermission('credential-slot')` 收敛) | Phase 2 RBAC 收敛 + AI 模型页入口 | yes | Pending | +| CRED-FE-04 编辑对话框 `CredentialSlotDialog.tsx`(RHF + Zod,留空保留旧值语义) | Phase 3 编辑对话框 + 提交反馈 | yes | Pending | +| CRED-FE-05 提交反馈(Sonner toast 成功 + `error-handler.ts` 失败映射) | Phase 3 编辑对话框 + 提交反馈 | yes | Pending | + +**覆盖率**:5/5 Active 需求映射到 phase ✓(无孤儿,无重复) + +**跨项目依赖**:Phase 3 success criteria #5(端到端串联)依赖 qy_lty 后端 Milestone v1.0 Phase 2「管理端读写接口」落地;前端代码层工作(Phase 1-3)本身不阻塞、可与后端并行推进。 --- -*Last updated: 2026-05-07 启动 Milestone v1.0「通用凭据槽位前端集成」* +*Last updated: 2026-05-07 — Milestone v1.0「通用凭据槽位前端集成」ROADMAP 生成,Traceability 回填 5/5* diff --git a/qy-lty-admin/.planning/ROADMAP.md b/qy-lty-admin/.planning/ROADMAP.md new file mode 100644 index 0000000..4eed44f --- /dev/null +++ b/qy-lty-admin/.planning/ROADMAP.md @@ -0,0 +1,76 @@ +# Roadmap:洛天依应用管理后台(qy-lty-admin) + +## 概览 + +本路线图聚焦 **Milestone v1.0「通用凭据槽位前端集成」**:在 Web 管理后台的 `/ai-model` 大模型管理页面接入后端 v1.0 暴露的 `/api/v1/admin/credential-slot/` 端点,让运营者能够录入与编辑 APP ID + Access Token,且 Access Token 仅展示末 4 位脱敏掩码、留空保留旧值。粒度为 **coarse**(目标 2-4 phase),按"API 客户端 → 权限收敛 + 页面入口 → 编辑对话框 + 反馈"自下而上分三个 phase 串行推进。 + +**跨项目依赖(重要)**:本前端 milestone 的代码层工作(Phase 1-3)**不阻塞** qy_lty 后端,可独立开发并以 mock / 联调环境推进;但**端到端集成测试**与上线验收**强依赖** qy_lty 后端 Milestone v1.0 的 **Phase 2「管理端读写接口」**(GET/PUT `/api/v1/admin/credential-slot/`)落地后才能跑通。规划时序上,建议本仓库 Phase 1 与后端 Phase 1-2 并行,本仓库 Phase 3 与后端 Phase 2 收尾对齐,以便 milestone 完成时双方在 `docs/修改记录.md` 互相引用条目。 + +## Milestones + +- 🚧 **v1.0 通用凭据槽位前端集成** — Phase 1-3(启动 2026-05-07,与 qy_lty 后端 v1.0 并行) + +## Phases + +**Phase 编号说明:** +- 整数 phase(1、2、3):当期 milestone 计划工作 +- 小数 phase(2.1、2.2):紧急插入工作(标记 INSERTED) + +小数 phase 在数值序内夹在前后整数之间执行。 + +- [ ] **Phase 1: 凭据槽位 API 客户端** — 落地 `lib/api/credential-slot.ts`:类型定义、`mapBackendCredentialSlot` 适配器、`getCredentialSlot()` / `updateCredentialSlot()` 两个调用,并从 `lib/api/index.ts` 导出 +- [ ] **Phase 2: RBAC 收敛 + AI 模型页入口** — 在 `lib/permissions.ts` 新增 `credential-slot` 模块 key,分配给"超级管理员"与"AI模型管理员";在 `/ai-model` 页面渲染受权限收敛的"凭据槽位"入口(按钮或卡片) +- [ ] **Phase 3: 编辑对话框 + 提交反馈** — 实现 `components/ai-model/CredentialSlotDialog.tsx`(React Hook Form + Zod、脱敏掩码预填、留空保留旧值语义),并通过 Sonner toast + `error-handler.ts` 完成成功/失败反馈 + +## Phase Details + +### Phase 1: 凭据槽位 API 客户端 +**Goal**: 在 `lib/api/` 层提供独立、无 UI 依赖的凭据槽位读写客户端,让后续 phase 可以直接以"调用 + 类型"方式接入,不必再次处理 axios / 适配器细节 +**Depends on**: Nothing(本 milestone 首个 phase) +**Requirements**: CRED-FE-01 +**Success Criteria**(必须为真): + 1. `lib/api/credential-slot.ts` 导出 `getCredentialSlot()` 与 `updateCredentialSlot(payload)` 两个函数,分别走 `apiClient.get` / `apiClient.put` 命中 `/v1/admin/credential-slot/`,与现有 `lib/api/*.ts` 的拦截器、Bearer token 注入、`StandardResponseMiddleware` 解包行为完全一致 + 2. 模块导出共享类型 `CredentialSlot { appId: string; accessTokenMasked: string; updatedAt: string }` 与提交载荷类型,前端类型为 camelCase;后端 snake_case 字段(`app_id` / `access_token` / `updated_at`)通过 `mapBackendCredentialSlot()` 适配器统一转换,沿用 `lib/api/adapters.ts` 的 `mapBackend*` 约定 + 3. `lib/api/index.ts` 导出新模块,`import { getCredentialSlot, updateCredentialSlot, type CredentialSlot } from '@/lib/api'` 在任一组件文件中均能解析通过 `tsc --noEmit` + 4. 在浏览器开发态以 mock 后端或后端 Phase 2 联调环境调用 `getCredentialSlot()`,控制台可以看到一条带 `Authorization: Bearer ...` 的请求,且返回值字段名是前端 camelCase(说明适配器生效,未把后端原始 snake_case 直接透传) +**Plans**: TBD + +### Phase 2: RBAC 收敛 + AI 模型页入口 +**Goal**: 通过 `lib/permissions.ts` 把"凭据槽位"声明为受控模块、仅向"超级管理员"与"AI模型管理员"开放;并在 `/ai-model` 页面渲染受权限校验收敛的入口控件,让授权用户能看到入口、未授权用户看不到入口 +**Depends on**: Phase 1 +**Requirements**: CRED-FE-02, CRED-FE-03 +**Success Criteria**(必须为真): + 1. `lib/permissions.ts` 的 `PermissionModule` 类型新增 `'credential-slot'` 字面量,`PERMISSION_MATRIX` 中"超级管理员"与"AI模型管理员"两个角色的模块列表均包含 `'credential-slot'`,其余角色(内容管理员、卡牌管理员、查看者)不包含;调用 `hasPermission('credential-slot')` 在两类账户下返回 `true`,其他角色返回 `false` + 2. `getModuleFromPath('/ai-model')` 行为不变(凭据槽位是 `/ai-model` 内嵌子能力,不占独立路由),不引入侧边栏新菜单项 + 3. 以"AI模型管理员"角色登录访问 `/ai-model`,页面工具栏 / Header 区域可见明确的"凭据槽位"入口控件(按钮或卡片,文案明确);以"内容管理员"或"查看者"角色登录访问同一页面,入口控件不渲染(DOM 中不存在,而非仅隐藏) + 4. 入口控件的可见性判断走 `hasPermission('credential-slot')`,不直接读 `localStorage.user_role` 字符串比较;点击入口控件触发对话框打开行为(Phase 3 落地后端到端可用,本 phase 至少打开一个空对话框占位以验证联动点存在) +**Plans**: TBD +**UI hint**: yes + +### Phase 3: 编辑对话框 + 提交反馈 +**Goal**: 落地 `CredentialSlotDialog` 组件让授权运营者能够查看脱敏的当前凭据、安全地提交新值,且成功 / 失败两条路径都有清晰的 toast 反馈;表单语义采用"留空保留旧值"避免回写脱敏掩码假值 +**Depends on**: Phase 2 +**Requirements**: CRED-FE-04, CRED-FE-05 +**Success Criteria**(必须为真): + 1. 打开对话框时自动调用 `getCredentialSlot()` 拉取数据:`app_id` 字段以**明文**预填、`access_token` 字段以**末 4 位掩码**显示并附"如需更新请重新输入,留空保留旧值"提示文案、`updated_at` 以只读形式呈现(运营可看到"上次更新"时间) + 2. 表单使用 React Hook Form + Zod 校验:当 `app_id` 输入框被清空且与原值不同则提示"不能为空";`access_token` 字段允许留空(语义=保留旧值),但**一旦用户输入新值**则要求非空白字符;提交时**仅传递用户实际改动过的字段**给 `updateCredentialSlot()`,**绝不**把脱敏掩码当真值回写 + 3. 提交成功路径:`updateCredentialSlot()` 返回成功后,调用 `useToast()` 弹出 Sonner 成功 toast(中文文案,如"凭据槽位已更新"),对话框自动关闭,再次打开时数据被重新拉取并展示新的 `updated_at` + 4. 提交失败路径:后端返回非成功响应或网络异常时,错误经由 `lib/api/error-handler.ts` 统一映射为可读中文消息后通过 toast 提示;对话框保持打开、表单字段保留用户输入、不丢失编辑态 + 5. 端到端串联(依赖 qy_lty 后端 Phase 2 落地):以"超级管理员"账户登录 → 进入 `/ai-model` → 点击凭据槽位入口 → 输入一组真实 APP ID + Access Token → 提交 → 看到成功 toast → 关闭后重新打开对话框,`access_token` 仅显示新值末 4 位、`updated_at` 已刷新 +**Plans**: TBD +**UI hint**: yes + +## Progress + +**执行顺序:** +Phase 按数值顺序执行:1 → 2 → 3(如出现紧急插入,记为 1.1 / 2.1 等) + +| Phase | Plans Complete | Status | Completed | +|-------|----------------|--------|-----------| +| 1. 凭据槽位 API 客户端 | 0/TBD | Not started | - | +| 2. RBAC 收敛 + AI 模型页入口 | 0/TBD | Not started | - | +| 3. 编辑对话框 + 提交反馈 | 0/TBD | Not started | - | + +--- + +*生成时间:2026-05-07,Milestone v1.0「通用凭据槽位前端集成」启动;与 qy_lty 后端 v1.0 并行,端到端验收依赖后端 Phase 2 落地* diff --git a/qy-lty-admin/.planning/STATE.md b/qy-lty-admin/.planning/STATE.md index 4051166..f0c1678 100644 --- a/qy-lty-admin/.planning/STATE.md +++ b/qy-lty-admin/.planning/STATE.md @@ -1,6 +1,6 @@ # Project State — 洛天依应用管理后台(qy-lty-admin) -**最后更新**: 2026-05-07(启动 Milestone v1.0 通用凭据槽位前端集成) +**最后更新**: 2026-05-07(Milestone v1.0 通用凭据槽位前端集成 ROADMAP 落地,Phase 1 待启动) ## 项目引用 @@ -13,50 +13,85 @@ ## 当前位置 ``` -Phase: 未启动(定义需求中) -Plan: — -Status: 需求定义中(roadmap 待生成) -Last activity: 2026-05-07 — 启动 Milestone v1.0 +Milestone: v1.0 通用凭据槽位前端集成 +Phase: Phase 1「凭据槽位 API 客户端」 +Plan: —(待 /gsd-plan-phase 1 生成) +Status: 待启动(Not started) +Progress: [░░░░░░░░░░] 0%(0/3 phase 完成) +Last activity: 2026-05-07 — ROADMAP.md 落地、REQUIREMENTS.md Traceability 回填 ``` +**下一步行动**:运行 `/gsd-plan-phase 1` 把 Phase 1 拆解为可执行的 plan 节点。 + +## Phase 概览 + +| Phase | 标题 | 需求 | UI hint | 状态 | +|-------|------|------|---------|------| +| 1 | 凭据槽位 API 客户端 | CRED-FE-01 | — | 待启动 | +| 2 | RBAC 收敛 + AI 模型页入口 | CRED-FE-02, CRED-FE-03 | yes | 未开始 | +| 3 | 编辑对话框 + 提交反馈 | CRED-FE-04, CRED-FE-05 | yes | 未开始 | + ## 联动 milestone - **qy_lty 后端 v1.0「通用凭据槽位」**:3 个 phase(数据层 → 管理端读写 → 客户端读取+脱敏) - - 前端 PUT 路径依赖后端 Phase 2(管理端读写接口)落地 - - 前端集成测试需等后端至少跑完 Phase 2 + - 本仓库 Phase 1(API 客户端)**不阻塞**,可在后端联调前以 mock 推进 + - 本仓库 Phase 3(端到端串联 success criteria #5)**强依赖** 后端 Phase 2「管理端读写接口」落地 + - 节奏建议:本仓库 Phase 1-2 与后端 Phase 1-2 并行;本仓库 Phase 3 收尾节奏与后端 Phase 2 完工对齐 -## 状态 +## 性能指标 + +| 指标 | 数值 | +|------|------| +| 已完成 phase | 0 / 3 | +| 已完成 plan | 0 / TBD | +| Milestone 进度 | 0% | +| 启动日期 | 2026-05-07 | +| 最近活动 | 2026-05-07 ROADMAP.md 落地 | + +## 累积上下文 + +### 关键决策 + +- **2026-05-07 phase 拆分(Option B / 3 phase)**:API 客户端独立成 Phase 1(无 UI),权限矩阵 + 入口控件合并为 Phase 2(UI),编辑对话框 + 反馈合并为 Phase 3(UI)。理由:Phase 1 是纯逻辑、可在后端联调前独立打磨;Phase 2 一旦完成,未授权角色即彻底看不到入口(安全前置);Phase 3 集中处理"留空保留旧值"语义这条最容易翻车的业务规则。 +- **2026-05-07 跨项目依赖明确**:前端 phase 不阻塞代码编写,但端到端验收依赖 qy_lty 后端 Phase 2(管理端读写接口)落地;本仓库 Phase 3 收尾节奏与后端 Phase 2 完工对齐。 +- **2026-05-07 表单"留空保留旧值"语义**:后端 GET 返回的是末 4 位脱敏掩码,前端**绝不**能把掩码当真值再 PUT 回去;Phase 3 success criteria #2 显式约束。 + +### 待办事项 + +(暂无;待 plan 生成后补齐) + +### 阻塞项 + +(无) + +### 风险项 + +- 后端 Phase 2(管理端读写接口)若延期,本仓库 Phase 3 的 success criteria #5(端到端串联)无法验证;需要并行盯好后端进度,必要时以 mock 服务先验证 Phase 1-2。 +- 前端权限矩阵仅是 UI 礼貌(参见 PROJECT.md 关键决策表),后端必须独立校验 `/api/v1/admin/credential-slot/` 的角色权限;该闭环是 PERM-06 的范畴,本 milestone 不消化但需要在端到端验收时顺带确认后端是否对该接口实施了角色校验。 + +## 状态总览 | 项目 | 状态 | |------|------| | 代码库映射 | ✅ `.planning/codebase/` 7 文档(commit `a85b6a7`) | | PROJECT.md | ✅ 已加入 Milestone v1.0 段 + Active 5 项 | -| REQUIREMENTS.md | 🟡 Active 段待回填(CRED-FE-01~05),可追溯性待 phase 回填 | -| 路线图 | ⏸️ 待 gsd-roadmapper 生成 | -| 当前 phase | — | +| REQUIREMENTS.md | ✅ Active 段已落地,Traceability 已回填 5/5 | +| 路线图 | ✅ ROADMAP.md 落地(3 phase,coarse) | +| 当前 phase | Phase 1 待启动 | | 当前 milestone | v1.0 通用凭据槽位前端集成 | -## 下一步 +## 会话连续性 -**当你准备开始下一个开发周期**: - -``` -/gsd-new-milestone -``` - -GSD 会: -1. 询问 milestone 目标(例如:后端权限校验闭环验证、Token 存储重构、测试基础设施……) -2. 把需求加到 `.planning/REQUIREMENTS.md` 的 Active 段 -3. 路由到 `/gsd-roadmap` 拆 phase - -**候选优先级排序见 `REQUIREMENTS.md → Active → 候选优先级` 段**。 +**最近会话**:2026-05-07 +**最近动作**:roadmapper 生成 ROADMAP.md(3 个 phase,Option B 拆分)+ 回填 REQUIREMENTS.md Traceability(5/5)+ 切换 STATE.md 到 Phase 1 待启动 +**下一会话起点**:`/gsd-plan-phase 1` 启动 Phase 1 规划 ## 工作流配置 详见 `.planning/config.json`: - 模式:**YOLO**(自动通过审批,直接执行) -- 粒度:**Coarse**(每个 milestone 拆 3-5 phase) +- 粒度:**Coarse**(本期 milestone 拆为 3 phase) - 并行化:**已启用** - 工作流 agent:research / plan_check / verifier 全部启用 - 模型档位:**balanced**(Sonnet 主力) @@ -81,4 +116,4 @@ CLAUDE.md 中两条强制规则,做任何 phase 时必须遵守: --- -*由 /gsd-new-project(brownfield 文档化)生成于 2026-05-07* +*2026-05-07 由 gsd-roadmapper 切换到 Phase 1 待启动状态*