# 任务文档：配置管理重构——统一API凭证管理

- **状态**: Active
- **创建日期**: 2025-11-17
- **负责人**: @AI-Assistant
- **审查人**: @lv

---

## 1. 背景与目标

### 1.1. 当前问题

当前系统对外部服务（如 Tushare, Finnhub）API Token 的管理方式存在两个主要问题：

1.  **配置方式分裂**:
    - **敏感凭证 (API Tokens)**: 通过启动时的**环境变量**注入。这种方式虽然安全，但缺乏灵活性，每次修改都需要重新部署或重启服务。
    - **业务逻辑配置 (AI模型选择等)**: 通过**数据库**统一管理，并支持UI动态调整。
    - 这种分裂的管理模式增加了系统的运维复杂性，与我们追求的“单一事实源”架构理念不符。

2.  **服务韧性不足**:
    - 依赖环境变量的服务采取“快速失败” (Fail-Fast) 策略。如果启动时未提供有效的 API Token，服务会立即崩溃退出。
    - 这种模式虽然能尽早暴露问题，但在一个动态的、持续运行的系统中显得过于“僵硬”。我们期望的行为是：服务在缺少非核心配置时，应能进入一个“降级”状态，待配置就绪后再自动恢复工作，而不是直接停止运行。

### 1.2. 改造目标

本次重构旨在将所有外部服务的 API Token 配置，从环境变量迁移到数据库中，实现与业务逻辑配置的统一管理。具体目标如下：

- **统一配置源**: 将 `system_config` 数据库表作为所有可变配置（包括API Tokens）的唯一事实源。
- **提升易用性**: 允许用户通过前端UI界面，集中管理和更新所有数据源的 API Token。
- **增强服务韧性**: 改造数据提供商服务，使其在缺少 API Token 时不会崩溃，而是进入“降级模式”，并能在 Token 被提供后自动恢复正常工作。
- **简化部署**: 移除对多个环境变量的依赖，使服务的部署和运维过程更加简洁。

---

## 2. 实施方案

本次改造将遵循“后端 -> 服务 -> 前端”的顺序分层实施，确保每一步都有坚实的基础。

### 2.1. 数据模型与持久化层

我们将通过复用 `system_config` 表中现有的 `(config_key, config_value)` 存储模式，来扩展配置管理的能力，使其能够安全地存储和检索数据源的配置。

1.  **定义数据结构**: 在 `common-contracts` 共享库中，定义一个清晰的、用于描述数据源配置的 `DataSourceConfig` 结构体。它将包含 `provider_id`, `api_token`, `api_url` 等字段。
2.  **复用现有表结构**: 我们将向 `system_config` 表中插入一条新的记录，其 `config_key` 固定为 `"data_sources"`，并将所有数据源的配置集合（一个 `HashMap<String, DataSourceConfig>`）序列化后存入该记录的 `config_value` 字段中。
3.  **扩展API**: 在 `data-persistence-service` 中增加新的 HTTP API 端点，用于对数据源配置进行增、删、改、查（CRUD）操作。例如：
    - `GET /api/v1/configs/data-sources`: 获取所有数据源的配置列表。
    - `PUT /api/v1/configs/data-sources`: 创建或更新所有数据源的配置。

### 2.2. 微服务改造：引入“降级与恢复”模式

这是本次重构的核心。所有依赖外部 API Token 的数据提供商服务 (`finnhub`, `tushare`, `alphavantage`) 都将进行如下改造：

1.  **移除启动时检查**: 删除 `config.rs` 中检查环境变量并导致程序崩溃的逻辑。
2.  **引入内部状态机**: 每个服务内部将维护一个状态（例如 `State<ServiceOperationalStatus>`)，包含 `Active` 和 `Degraded(reason: String)` 两种状态。
3.  **动态配置加载**: 服务将不再从环境变量读取 Token，而是在内部启动一个**后台任务**（轮询器），该任务会：
    - 在服务启动时，以及之后每隔一段时间（例如 60 秒），调用 `data-persistence-service` 的新 API 来获取自己的配置。
    - 如果成功获取到有效的 Token，则更新服务内部的 API 客户端，并将服务状态设置为 `Active`。此时，服务正常订阅和处理来自 NATS 的消息。
    - 如果未能获取 Token（或 Token 为空），则将服务状态设置为 `Degraded`，并附上原因（如 "API Token not configured"）。在这种状态下，服务**不会**订阅 NATS 消息队列，避免接收无法处理的任务。
4.  **更新健康检查**: 服务的 `/health` 端点将反映其内部状态。当处于 `Degraded` 状态时，健康检查接口应返回相应的状态码和信息，以便监控系统能够清晰地了解服务当前是否可用。

### 2.3. 前端UI实现

为了让用户能够方便地管理这些配置，我们将在前端进行如下调整：

1.  **创建新UI组件**: 在 `/config` 页面，新增一个名为“数据源配置”的管理面板。
2.  **功能实现**: 该面板将提供一个表单或列表，允许用户：
    - 查看当前所有数据源（Tushare, Finnhub 等）的配置状态。
    - 为每个数据源输入或更新其 API Token。
    - 保存更改。点击保存后，前端将调用 `data-persistence-service` 的新 API，将更新后的配置持久化到数据库中。

---

## 3. 详细任务清单

### 第一阶段：后端基础

- [x] ~~**任务 BE-1**: 在 `common-contracts` 中定义 `DataSourceConfig` 和 `DataSourceProvider` 等共享数据结构。~~
- [x] ~~**任务 BE-3**: 在 `data-persistence-service` 中实现对数据源配置的 CRUD 业务逻辑。~~
- [x] ~~**任务 BE-4**: 在 `data-persistence-service` 中暴露 `GET /api/v1/configs/data-sources` 和 `PUT /api/v1/configs/data-sources` 这两个 API 端点。~~

### 第二阶段：微服务改造

- [x] ~~**任务 SVC-1**: **(Finnhub)** 重构 `finnhub-provider-service`：~~
    - [x] ~~移除 `config.rs` 中的 `FINNHUB_API_KEY` 环境变量加载逻辑。~~
    - [x] ~~实现内部状态机 (`Active`/`Degraded`) 和动态配置轮询器。~~
    - [x] ~~修改 `/health` 端点以反映内部状态。~~
    - [x] ~~调整 NATS 消息订阅逻辑，只在 `Active` 状态下进行订阅。~~
- [x] ~~**任务 SVC-2**: **(Tushare)** 以 `finnhub-provider-service` 为模板，对 `tushare-provider-service` 进行相同的重构。~~
- [x] ~~**任务 SVC-3**: **(Alphavantage)** 以 `finnhub-provider-service` 为模板，对 `alphavantage-provider-service` 进行相同的重构。~~
- [x] ~~**任务 SVC-4**: **(审查)** 审查 `report-generator-service` 的 LLM 配置加载逻辑，确保其与新的动态配置模式在设计理念上保持一致。~~

### 第三阶段：前端实现

- [x] **任务 FE-1**: 在 `/config` 页面设计并实现“数据源配置”UI 组件。
- [x] **任务 FE-2**: 实现 `useApi.ts` 中用于获取和更新数据源配置的 hooks。
- [x] **任务 FE-3**: 将 UI 组件与 API hooks 连接，完成前端的完整功能。
- [x] **任务 FE-4**: 调整 `/llm-config` 页面，使其在UI/UX风格上与新的“数据源配置”面板保持一致性。
