- 新增 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)
159 lines
8.1 KiB
Markdown
159 lines
8.1 KiB
Markdown
---
|
||
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-export:lib/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 2(RBAC + 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)`(模块级私有 adapter,snake → 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 2:lib/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*
|
||
*执行 Agent:gsd-executor (Opus 4.7)*
|
||
*父仓库 commit hash:a0d0b9c (Task 1) / c072bbe (Task 2)*
|