pmc ce0df098be docs(01-01): 完成 Phase 1 Plan 01-01「凭据槽位 API 客户端」收尾
- 新增 01-01-SUMMARY.md:记录 Task 1/2 commits、关键串命中、字节产物对比、Self-Check PASSED
- STATE.md:当前位置切到 'Plan 01-01 完成 / 01-02 待执行',进度 50%(Phase 1 内部 1/2 plan),新增 Plan 执行记录表 + 2026-05-08 关键决策
- ROADMAP.md:Phase 1 进度 0/2 → 1/2,状态 Not started → In Progress
- REQUIREMENTS.md:CRED-FE-01 Active 段已勾选 [x];Traceability 状态切到  Done(commits a0d0b9c + c072bbe)

Plan 01-01 父仓库 commits:a0d0b9c (lib/api/credential-slot.ts) + c072bbe (lib/api/index.ts)
2026-05-08 11:06:42 +08:00

159 lines
8.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.

---
phase: 01-credential-slot-api
plan: 01
subsystem: api-client
tags: [api-client, credential-slot, milestone-v1.0, brownfield]
requires: []
provides:
- artifact: lib/api/credential-slot.ts
description: 凭据槽位 API 客户端模块(类型 + adapter + GET/PUT 函数)
- export: getCredentialSlot
from: lib/api/credential-slot.ts
via: lib/api/index.ts (具名 re-export)
- export: updateCredentialSlot
from: lib/api/credential-slot.ts
via: lib/api/index.ts (具名 re-export)
- type: CredentialSlot
from: lib/api/credential-slot.ts
via: lib/api/index.ts (具名 re-export)
- type: CredentialSlotUpdatePayload
from: lib/api/credential-slot.ts
via: lib/api/index.ts (具名 re-export)
affects:
- lib/api/index.ts
tech_stack:
added: []
patterns:
- "1:1 复刻 lib/api/ai-models.ts 风格mapBackend* + 双保险解包 + export const fn = async"
- "类型命名屏障accessTokenMasked vs accessToken 在 TS 编译期切断脱敏字符串回写 bug"
- "barrel re-exportlib/api/index.ts 末尾具名 re-export与现有 export * 风格混用合法"
key_files:
created:
- lib/api/credential-slot.ts
modified:
- lib/api/index.ts
decisions:
- 采用「具名 re-export」而非 `export *`:符合 RESEARCH 问题 6 + CONTEXT.md 锁定写法,可读性最高、未来重名冲突可控
- PUT body 不带 `updated_at`:沿用 updateAiModel / updateOutfit 约定,由后端 auto_now 维护
- `BackendCredentialSlot` 不导出:仅 adapter 入参类型,与 `mapBackend*` 模块级私有约定一致
- 路径写 `/v1/admin/credential-slot/`(不带 `/api` 前缀API_BASE_URL 已含 `/api`
metrics:
duration_seconds: 76
completed_date: 2026-05-08
tasks_completed: 2
files_changed: 2
requirements:
- CRED-FE-01
---
# Phase 1 Plan 01-01凭据槽位 API 客户端 Summary
**One-liner**1:1 复刻 ai-models.ts 风格落地 `lib/api/credential-slot.ts`,封装 GET/PUT + camelCase 类型 + adapter并在 `lib/api/index.ts` 末尾具名 re-export 4 个公共符号。
## 背景
Milestone v1.0「通用凭据槽位前端集成」启动 plan纯逻辑层无 UI为 Phase 2RBAC + AI 模型页入口)/ Phase 3编辑对话框 + Sonner 反馈)提供调用层基础。本 plan 同时建立类型层屏障:`CredentialSlot.accessTokenMasked`脱敏vs `CredentialSlotUpdatePayload.accessToken`(明文)字段名故意不同,让 TS 编译期切断「把脱敏掩码当真值回写 PUT」这条 bug 路径。
## Tasks Executed
### Task 1新建 lib/api/credential-slot.ts类型 + adapter + GET/PUT
- **状态**: ✅ 完成
- **Commit**: `a0d0b9c`(父级 Lila-Server 仓库)
- **文件**: `lib/api/credential-slot.ts`新增64 行 / 2620 字节)
- **产物**:
- `interface BackendCredentialSlot`snake_case模块级私有不导出
- `export interface CredentialSlot { appId, accessTokenMasked, updatedAt }`(公共响应类型)
- `export interface CredentialSlotUpdatePayload { appId, accessToken }`(公共提交载荷类型)
- `function mapBackendCredentialSlot(raw)`(模块级私有 adaptersnake → camel
- `export const getCredentialSlot = async (): Promise<CredentialSlot>` — 走 `apiClient.get('/v1/admin/credential-slot/')`
- `export const updateCredentialSlot = async (payload): Promise<CredentialSlot>` — 走 `apiClient.put('/v1/admin/credential-slot/', { app_id, access_token })`
- **关键串命中**:
- `response.data?.data || response.data` 双保险解包:**2 次**GET / PUT 各一)
- `apiClient.get('/v1/admin/credential-slot/')`1 次
- `apiClient.put('/v1/admin/credential-slot/'`1 次
- `/api/v1/admin/credential-slot`(重复 /api 前缀):**0 次** ✓(路径正确)
- PUT body 字面量不含 `updated_at` 键 ✓(仅注释行提及)
- **自动验证**: `node -e ...` 9 个 regex 检查 + 0 路径前缀检查 + 双保险解包计数 = 2 → 退出码 0打印 `OK`
### Task 2lib/api/index.ts 末尾追加具名 re-export
- **状态**: ✅ 完成
- **Commit**: `c072bbe`(父级 Lila-Server 仓库)
- **文件**: `lib/api/index.ts`修改197 → 204 行,+7 行内容diff 显示 8 insertions 含末尾 newline 重排)
- **追加位置**: `handleApiError` 函数定义L191-196之后L197 空行 + L198-204 新增块)
- **追加内容**7 行):
```typescript
// 凭据槽位Milestone v1.0 通用凭据槽位前端集成 — Phase 1 / CRED-FE-01
export {
getCredentialSlot,
updateCredentialSlot,
type CredentialSlot,
type CredentialSlotUpdatePayload,
} from './credential-slot'
```
- **关键串命中**:
- `from './credential-slot'`1 次
- `getCredentialSlot,`1 次
- `updateCredentialSlot,`1 次
- `type CredentialSlot,`1 次
- `type CredentialSlotUpdatePayload,`1 次
- `export * from './credential-slot'`(错误的 barrel 风格):**0 次** ✓
- **现有内容保留**: `import * as client from "./client"``export * from "./card"/"./upload"/"./food"``usersApi``rolesApi``handleApiError` 全部不变
- **自动验证**: `node -e ...` 5 个 regex 计数检查 + barrel 风格反向检查 + card 导出保留检查 + handleApiError 保留检查 → 退出码 0打印 `OK`
## 累计 Commit 列表
| # | Hash | Message | Files |
|---|------|---------|-------|
| 1 | `a0d0b9c` | feat(01-01): 新建 lib/api/credential-slot.ts 凭据槽位 API 客户端 | qy-lty-admin/lib/api/credential-slot.ts |
| 2 | `c072bbe` | feat(01-01): lib/api/index.ts 末尾追加凭据槽位具名 re-export | qy-lty-admin/lib/api/index.ts |
(最终 SUMMARY + STATE 提交另行追加,见底部)
## Success Criteria 自检
- [x] `lib/api/credential-slot.ts` 文件存在
- [x] 文件导出 `CredentialSlot` 类型 + `CredentialSlotUpdatePayload` 类型 + `getCredentialSlot` 函数 + `updateCredentialSlot` 函数共 4 个公共符号
- [x] `mapBackendCredentialSlot` 函数已定义(私有,未导出)
- [x] GET / PUT 路径**精确**为 `/v1/admin/credential-slot/`(不含重复 `/api`
- [x] GET 与 PUT 函数体内各含 1 次 `response.data?.data || response.data` 双保险解包(共 2 次)
- [x] PUT body 字面量**不含** `updated_at`
- [x] `lib/api/index.ts` 末尾通过具名 re-export 暴露 4 个符号,路径 `./credential-slot`
- [x] `lib/api/index.ts` 中现有 `export * from "./card"/"./upload"/"./food"``usersApi` / `rolesApi` / `handleApiError` 完全不变
- [x] 两个文件均为合法 UTF-8无 BOM 干扰、无残缺字符)
## Deviations from Plan
**无** — plan 执行 0 偏差。所有锁定写法路径、解包行、PUT body 不含 updated_at、私有 adapter、具名 re-export 风格、追加位置)均严格按 PLAN action 落地。
## 与后续 plan 的衔接
- **Plan 01-02**(同一 phase将处理`docs/修改记录.md` 顶部追加 Phase 1 条目 + 跑双重验证(`npm run lint` + `npx tsc --noEmit`+ 探针验证 barrel 入口
- **Phase 2** 起可用 `import { getCredentialSlot, updateCredentialSlot, type CredentialSlot, type CredentialSlotUpdatePayload } from '@/lib/api'` 直接消费本 plan 产物
- **本 plan 不写 `docs/修改记录.md`** — 集中由 Plan 01-02 落地,避免 Phase 1 内部多次写入
## Known Stubs
无 — 本 plan 是纯 API 客户端层所有产物类型、adapter、API 函数)都已完整实现并可直接消费。无任何占位或 TODO。
## 字节级关键产物对比
| 文件 | 状态 | 行数(前→后) | 字节 |
|------|------|--------------|------|
| `lib/api/credential-slot.ts` | 新增 | 0 → 64 | 2620 |
| `lib/api/index.ts` | 修改 | 197 → 204 | (追加 7 行) |
## Self-Check: PASSED
- [x] `lib/api/credential-slot.ts` 存在 (FOUND)
- [x] `lib/api/index.ts` 末尾包含具名 re-export 块 (FOUND)
- [x] commit `a0d0b9c` 在 git log 中 (FOUND, 父级 Lila-Server 仓库)
- [x] commit `c072bbe` 在 git log 中 (FOUND, 父级 Lila-Server 仓库)
- [x] Task 1 / Task 2 verify.automated 命令均退出码 0 + 打印 `OK`
---
*生成时间2026-05-08*
*执行 Agentgsd-executor (Opus 4.7)*
*父仓库 commit hasha0d0b9c (Task 1) / c072bbe (Task 2)*