init
This commit is contained in:
34
specs/001-config-bootstrap/checklists/requirements.md
Normal file
34
specs/001-config-bootstrap/checklists/requirements.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Specification Quality Checklist: 配置与骨架
|
||||
|
||||
**Purpose**: Validate specification completeness and quality before proceeding to planning
|
||||
**Created**: 2025-11-13
|
||||
**Feature**: [/home/rogee/Projects/any-hub/specs/001-config-bootstrap/spec.md](../spec.md)
|
||||
|
||||
## Content Quality
|
||||
|
||||
- [x] No implementation details (languages, frameworks, APIs)
|
||||
- [x] Focused on user value and business needs
|
||||
- [x] Written for non-technical stakeholders
|
||||
- [x] All mandatory sections completed
|
||||
|
||||
## Requirement Completeness
|
||||
|
||||
- [x] No [NEEDS CLARIFICATION] markers remain
|
||||
- [x] Requirements are testable and unambiguous
|
||||
- [x] Success criteria are measurable
|
||||
- [x] Success criteria are technology-agnostic (no implementation details)
|
||||
- [x] All acceptance scenarios are defined
|
||||
- [x] Edge cases are identified
|
||||
- [x] Scope is clearly bounded
|
||||
- [x] Dependencies and assumptions identified
|
||||
|
||||
## Feature Readiness
|
||||
|
||||
- [x] All functional requirements have clear acceptance criteria
|
||||
- [x] User scenarios cover primary flows
|
||||
- [x] Feature meets measurable outcomes defined in Success Criteria
|
||||
- [x] No implementation details leak into specification
|
||||
|
||||
## Notes
|
||||
|
||||
- Items marked incomplete require spec updates before `/speckit.clarify` or `/speckit.plan`
|
||||
32
specs/001-config-bootstrap/contracts/cli-flags.md
Normal file
32
specs/001-config-bootstrap/contracts/cli-flags.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# CLI Contract: 配置与骨架
|
||||
|
||||
## Command Overview
|
||||
```
|
||||
any-hub [--config <path>] [--check-config] [--version]
|
||||
```
|
||||
|
||||
## Flags
|
||||
| Flag | Type | Default | Description | Behavior |
|
||||
|------|------|---------|-------------|----------|
|
||||
| `--config, -c` | string | `./config.toml` | 指定配置文件路径;优先级高于 `ANY_HUB_CONFIG` | 解析后记录在日志字段 `configPath`,路径不存在则退出并提示 |
|
||||
| `--check-config` | bool | false | 启用只校验模式,不启动 HTTP 服务 | 运行完整加载+校验链路;成功退出码 0,失败非 0 |
|
||||
| `--version` | bool | false | 输出版本信息并退出 | 打印语义化版本(含 commit/hash),忽略其他标志 |
|
||||
|
||||
## Exit Codes
|
||||
| Code | Meaning |
|
||||
|------|---------|
|
||||
| 0 | 操作成功(验证通过或正常退出) |
|
||||
| 1 | 配置解析/校验失败 |
|
||||
| 2 | CLI 参数错误(未知标志、冲突) |
|
||||
|
||||
## Logging Guarantees
|
||||
- 每条日志包含:`timestamp`, `level`, `action` (`check_config`, `startup`, `version`), `configPath`, `result`, `hub`(若适用), `domain`(若适用).
|
||||
- 当写文件失败时会降级到 stdout,并再记录一条 `action=logger_fallback` 的警告。
|
||||
|
||||
## Sample Interactions
|
||||
1. `any-hub --check-config --config /etc/any-hub.toml`
|
||||
- 校验文件,通过则输出 `configuration_valid`,否则列出字段错误。
|
||||
2. `any-hub --version`
|
||||
- 输出 `any-hub version 0.1.0 (commit abc1234)` 并退出。
|
||||
3. `ANY_HUB_CONFIG=/etc/any-hub.toml any-hub`
|
||||
- 若未显式传 `--config`,程序读取环境变量路径并记录来源。
|
||||
62
specs/001-config-bootstrap/data-model.md
Normal file
62
specs/001-config-bootstrap/data-model.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# Data Model: 配置与骨架
|
||||
|
||||
## Entities
|
||||
|
||||
### GlobalConfig
|
||||
- **Description**: 控制 any-hub 全局行为的配置段,位于 `config.toml` 根部。
|
||||
- **Fields**:
|
||||
- `LogLevel` (string, required, enum: trace/debug/info/warn/error)
|
||||
- `LogFilePath` (string, optional, default "")
|
||||
- `LogMaxSize` (int, optional, default 100, MB)
|
||||
- `LogMaxBackups` (int, optional, default 10)
|
||||
- `LogCompress` (bool, optional, default true)
|
||||
- `StoragePath` (string, required, must be writable directory)
|
||||
- `CacheTTL` (duration seconds, optional, default 86400)
|
||||
- `MaxMemoryCacheSize` (bytes, optional, default 268435456)
|
||||
- `MaxRetries` (int >=0, default 3)
|
||||
- `InitialBackoff` (duration, default 1s)
|
||||
- `UpstreamTimeout` (duration, default 30s)
|
||||
- **Validation Rules**: 路径必须存在或可创建;数值必须 >0;LogLevel 必须匹配允许枚举。
|
||||
- **Relationships**: 被 `Config` 聚合并为 `HubConfig` 提供默认值。
|
||||
|
||||
### HubConfig
|
||||
- **Description**: 描述单个代理仓库实例。
|
||||
- **Fields**:
|
||||
- `Name` (string, required, unique)
|
||||
- `Domain` (string, required, FQDN)
|
||||
- `Port` (int, required, 1-65535)
|
||||
- `Upstream` (string, required, http/https URL)
|
||||
- `Proxy` (string, optional, URL)
|
||||
- `CacheTTL` (duration, optional, overrides global)
|
||||
- `EnableHeadCheck` (bool, optional, default true)
|
||||
- **Validation Rules**: `Name` 必须唯一;`Domain` + `Port` 组合不得冲突;URL 必须可解析。
|
||||
- **Relationships**: 属于 `Config`,在运行时用于初始化路由、缓存目录 `StoragePath/<Name>`。
|
||||
|
||||
### Config (Root)
|
||||
- **Description**: 聚合 `GlobalConfig` 与一个或多个 `HubConfig` 条目。
|
||||
- **Fields**:
|
||||
- `Global` (`GlobalConfig`, required)
|
||||
- `Hubs` (`[]HubConfig`, min length 1)
|
||||
- **Validation Rules**: 至少一个 Hub;Hub 列表中所有必填字段存在;引用 `StoragePath` 时需组合 `Hub.Name` 生成可写路径。
|
||||
- **State Transitions**:
|
||||
1. **Loaded**: 从 TOML 解析到结构体。
|
||||
2. **Validated**: 完成默认值填充 + 规则校验。
|
||||
3. **Active**: 提供给 CLI/服务器初始化。
|
||||
|
||||
### CLIFlagSet
|
||||
- **Description**: 运行入口解析到的参数集合。
|
||||
- **Fields**:
|
||||
- `ConfigPath` (string, default `./config.toml`)
|
||||
- `CheckOnly` (bool, set by `--check-config`)
|
||||
- `ShowVersion` (bool, set by `--version`)
|
||||
- **Validation Rules**: 当 `ConfigPath` 指向不存在文件时须立即报错;`CheckOnly` 与正常启动互斥(若为 true 则不进入 server)。
|
||||
- **Relationships**: 在主函数中决定执行路径(验证 / 启动 / 版本输出)。
|
||||
|
||||
### LogSinkConfig
|
||||
- **Description**: 运行期日志输出策略,来源于 `GlobalConfig`。
|
||||
- **Fields**:
|
||||
- `Level` (string, required)
|
||||
- `Output` (enum: stdout|file)
|
||||
- `FilePath`, `MaxSize`, `MaxBackups`, `Compress`(当 Output=file 时必填)
|
||||
- **Validation Rules**: 当选择 file 时需验证写权限;level 必须映射到 Logrus 支持的等级。
|
||||
- **Relationships**: `initLogger(cfg)` 根据该实体创建 logger,并将字段注入所有日志条目。
|
||||
69
specs/001-config-bootstrap/plan.md
Normal file
69
specs/001-config-bootstrap/plan.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# Implementation Plan: 配置与骨架
|
||||
|
||||
**Branch**: `001-config-bootstrap` | **Date**: 2025-11-13 | **Spec**: [spec.md](./spec.md)
|
||||
**Input**: Feature specification from `/specs/001-config-bootstrap/spec.md`
|
||||
|
||||
**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/templates/commands/plan.md` for the execution workflow.
|
||||
|
||||
## Summary
|
||||
|
||||
Phase 0 delivers a reliable bootstrap for any-hub: a validated `internal/config` loader with defaults/tests, a CLI entry (`cmd/any-hub`) that accepts `--config`, `--check-config`, `--version`, and a Logrus + Lumberjack logging stack that honors config-provided level/output. The approach is to codify the configuration schema (global + `[[Hub]]`), implement strict validation with helpful errors, ensure CLI paths separate validation vs. runtime, and guarantee consistent structured logging for both success and failure flows.
|
||||
|
||||
## Technical Context
|
||||
|
||||
**Language/Version**: Go 1.25+ (静态链接,单二进制交付)
|
||||
**Primary Dependencies**: Fiber v3(HTTP 服务)、Viper(配置)、Logrus + Lumberjack(结构化日志 & 滚动)、标准库 `net/http`/`io`
|
||||
**Storage**: 本地文件系统缓存目录 `StoragePath/<Hub>/<path>` + `.meta` 元数据
|
||||
**Testing**: `go test ./...`,使用 `httptest`、临时目录和自建上游伪服务验证配置/缓存/代理路径
|
||||
**Target Platform**: Linux/Unix CLI 进程,由 systemd/supervisor 管理,匿名下游客户端
|
||||
**Project Type**: 单 Go 项目(`cmd/` 入口 + `internal/*` 包)
|
||||
**Performance Goals**: 缓存命中直接返回;回源路径需流式转发,单请求常驻内存 <256MB;命中/回源日志可追踪
|
||||
**Constraints**: 禁止 Web UI 或账号体系;所有行为受单一 TOML 配置控制;每个 Hub 需独立 Domain/Port 绑定;仅匿名访问
|
||||
**Scale/Scope**: 支撑 Docker/NPM/Go/PyPI 等多仓代理,面向弱网及离线缓存复用场景
|
||||
|
||||
## Constitution Check
|
||||
|
||||
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
||||
|
||||
- Feature 聚焦“轻量、匿名、CLI 多仓代理”,未引入 Web UI、账号体系或与代理无关的能力。
|
||||
- 仅使用 Go + 宪法指定依赖(Fiber/Viper/Logrus/Lumberjack + 标准库);无新增第三方库需求。
|
||||
- 行为完全由 `config.toml` 控制,计划中定义所有默认值、优先级(标志 > 环境变量 > 默认)、以及迁移策略。
|
||||
- CLI 与配置实现维持缓存优先 + 流式回源的大前提,并输出命中/回源/失败日志字段,满足可观测原则。
|
||||
- 计划明确覆盖配置解析、必填字段校验、Host Header 约束、中文注释与 `go test` 需求,满足测试 Gate。
|
||||
|
||||
**Post-design re-check (Phase 1)**: 设计阶段确认各文档与合同未偏离宪法约束,仍无新增依赖、UI 或多配置源,GATE 维持通过。
|
||||
|
||||
## Project Structure
|
||||
|
||||
### Documentation (this feature)
|
||||
|
||||
```text
|
||||
specs/[###-feature]/
|
||||
├── plan.md # This file (/speckit.plan command output)
|
||||
├── research.md # Phase 0 output (/speckit.plan command)
|
||||
├── data-model.md # Phase 1 output (/speckit.plan command)
|
||||
├── quickstart.md # Phase 1 output (/speckit.plan command)
|
||||
├── contracts/ # Phase 1 output (/speckit.plan command)
|
||||
└── tasks.md # Phase 2 output (/speckit.tasks command - NOT created by /speckit.plan)
|
||||
```
|
||||
|
||||
### Source Code (repository root)
|
||||
```text
|
||||
cmd/any-hub/main.go # CLI 入口、参数解析
|
||||
internal/config/ # TOML 加载、默认值、校验
|
||||
internal/server/ # Fiber 服务、路由、中间件
|
||||
internal/cache/ # 磁盘/内存缓存与 .meta 管理
|
||||
internal/proxy/ # 上游访问、缓存策略、流式复制
|
||||
configs/ # 示例 config.toml(如需)
|
||||
tests/ # `go test` 下的单元/集成测试,用临时目录
|
||||
```
|
||||
|
||||
**Structure Decision**: 采用单 Go 项目结构,特性代码应放入上述现有目录;如需新增包或目录,必须解释其与 `internal/*` 的关系并给出后续维护策略。
|
||||
|
||||
## Complexity Tracking
|
||||
|
||||
> **Fill ONLY if Constitution Check has violations that must be justified**
|
||||
|
||||
| Violation | Why Needed | Simpler Alternative Rejected Because |
|
||||
|-----------|------------|-------------------------------------|
|
||||
| _None_ | — | — |
|
||||
40
specs/001-config-bootstrap/quickstart.md
Normal file
40
specs/001-config-bootstrap/quickstart.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Quickstart: 配置与骨架
|
||||
|
||||
## 前置条件
|
||||
- 已安装 Go 1.25+,并能运行 `go test ./...`。
|
||||
- 提供一份最小 `config.toml`,包含全局设置与至少一个 `[[Hub]]`。
|
||||
- 当前分支:`001-config-bootstrap`。
|
||||
|
||||
## 步骤
|
||||
1. **编写配置文件**
|
||||
- 复制 `config.example.toml`(若无则创建)到项目根目录 `config.toml`。
|
||||
- 填写必填字段:`StoragePath`、`[[Hub]]` 的 `Name/Domain/Port/Upstream`。
|
||||
2. **运行配置校验**
|
||||
- 执行 `go run ./cmd/any-hub --check-config --config ./config.toml`。
|
||||
- 观察输出:成功时显示“配置验证通过”;失败时按日志提示修复字段。
|
||||
3. **启动 CLI**
|
||||
- `go run ./cmd/any-hub --config ./config.toml`。
|
||||
- 启动日志会打印版本、配置路径、监听端口。
|
||||
4. **查看版本**
|
||||
- `go run ./cmd/any-hub --version`。
|
||||
- 确认输出如 `any-hub version 0.1.0 (commit abc1234)`。
|
||||
5. **检查日志**
|
||||
- 若配置写入文件:查看 `LogFilePath` 位置的滚动日志。
|
||||
- 默认 stdout:在终端确认日志字段(level, action, hub, domain, result)。
|
||||
|
||||
## 验证清单
|
||||
- [ ] `--check-config` 能阻断非法配置并返回非零退出码。
|
||||
- [ ] CLI 成功读取默认或自定义配置路径。
|
||||
- [ ] `--version` 立即输出版本信息。
|
||||
- [ ] 日志初始化遵循配置的级别与输出。
|
||||
|
||||
## 常见错误排查
|
||||
- 出现 `Hub[docker].Domain: Domain 不允许包含协议头`:检查 Hub 配置中是否误写 `http://` 前缀。
|
||||
- 出现 `Global.StoragePath: 不能为空`:确保 `config.toml` 中填写路径或使用默认值。
|
||||
- 若日志提示 `logger_fallback`,说明文件不可写,删除 `LogFilePath` 或放宽目录权限。
|
||||
|
||||
## 日志字段说明
|
||||
- `action`: 表示当前操作(`check_config`、`startup` 等)。
|
||||
- `configPath`: 实际使用的配置文件路径,方便验证 flag/环境变量生效。
|
||||
- `result`: 操作结果(`ok`、`error`)。
|
||||
- `hub` / `domain` / `cacheHit`: 由 `internal/logging.RequestFields` 提供,后续代理请求会自动填充。
|
||||
26
specs/001-config-bootstrap/research.md
Normal file
26
specs/001-config-bootstrap/research.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Research: 配置与骨架
|
||||
|
||||
## 配置加载与校验
|
||||
- **Decision**: 使用 Viper 读取单一 `config.toml`,解析到 `GlobalConfig` + `[]HubConfig` 结构,先合并默认值再执行字段级校验(必填、范围、路径可写),校验失败即返回结构化错误并阻断启动。
|
||||
- **Rationale**: 单一入口与结构化错误能满足宪法“单一控制平面 + 阻断非法配置”的要求,也方便 `--check-config` 模式直接复用相同逻辑。
|
||||
- **Alternatives considered**: 直接手写 `encoding/toml` 解析(缺乏灵活默认/环境覆盖),多文件拆分(违反宪法单一配置要求)。
|
||||
|
||||
## CLI 标志与执行模式
|
||||
- **Decision**: 使用 `pflag`/`flag` 解析 `--config`, `--check-config`, `--version`,解析顺序:标志 > `ANY_HUB_CONFIG` 环境变量 > 默认路径;`--check-config` 触发只读模式,`--version` 输出后立即退出。
|
||||
- **Rationale**: 可预测的优先级防止多来源冲突;独立模式让 CI 可执行校验并快速确认版本,贴合用户故事 1/2。
|
||||
- **Alternatives considered**: 将 `--check-config` 拆成单独子命令(增加学习成本)、允许多配置文件(违背宪法)。
|
||||
|
||||
## 日志初始化策略
|
||||
- **Decision**: 统一在 CLI 启动与校验路径调用 `initLogger(cfg)`,基于 Logrus + Lumberjack:默认 stdout,若配置文件路径可写则启用滚动文件,同时注入字段(hub、domain、action、configPath、result)。
|
||||
- **Rationale**: 结构化日志 + 滚动文件满足宪法可观测性;单初始化路径减少重复配置并确保 `--check-config` 也有可追踪日志。
|
||||
- **Alternatives considered**: log/slog(失去与现有宪法保持一致的依赖);多 logger 实例(复杂度高且容易导致字段缺失)。
|
||||
|
||||
## 测试与验证覆盖
|
||||
- **Decision**: 编写 `internal/config` 单元测试覆盖:必填字段缺失、类型错误、默认值填充、`[[Hub]]` 唯一约束;CLI 集成测试使用 `httptest`/临时目录模拟不同标志组合;日志初始化通过接口注入 writer 以断言字段。
|
||||
- **Rationale**: 完成宪法要求的配置/缓存/路由主路径测试,确保 Phase 0 可在 `go test ./...` 下复现;临时目录避免污染本地环境。
|
||||
- **Alternatives considered**: 仅手动测试(无法满足 Gate)、依赖真实文件系统路径(降低可靠性)。
|
||||
|
||||
## 依赖与最佳实践
|
||||
- **Decision**: 保持依赖集为 Go 标准库 + Viper + Logrus + Lumberjack + pflag(随 Viper 引入),不新增网络/数据库库;使用 `fsnotify` 仅作为 Viper 间接依赖,不启用热加载。
|
||||
- **Rationale**: 满足宪法“受控依赖”原则并保持二进制小巧;禁用热加载可降低错配风险并符合单一配置理念。
|
||||
- **Alternatives considered**: 引入 Cobra CLI(依赖过重且 Phase 0 命令简单)、使用 zap 日志(与既定依赖不符)。
|
||||
96
specs/001-config-bootstrap/spec.md
Normal file
96
specs/001-config-bootstrap/spec.md
Normal file
@@ -0,0 +1,96 @@
|
||||
# Feature Specification: 配置与骨架
|
||||
|
||||
**Feature Branch**: `001-config-bootstrap`
|
||||
**Created**: 2025-11-13
|
||||
**Status**: Draft
|
||||
**Input**: User description: ":配置与骨架 - 实现 internal/config,覆盖 TOML 加载、默认值、校验及测试。 - 初始化 cmd/any-hub,解析 --config、--check-config、--version。 - 建立 logrus 初始化流程,完成基础日志输出。"
|
||||
|
||||
> 宪法对齐(v1.0.0):
|
||||
> - 保持“轻量、匿名、CLI 多仓代理”定位:不得引入 Web UI、账号体系或与代理无关的范围。
|
||||
> - 方案必须基于 Go 1.25+ 单二进制,依赖仅限 Fiber、Viper、Logrus/Lumberjack 及必要标准库。
|
||||
> - 所有行为由单一 `config.toml` 控制;若需新配置项,需在规范中说明字段、默认值与迁移策略。
|
||||
> - 设计需维护缓存优先 + 流式传输路径,并描述命中/回源/失败时的日志与观测需求。
|
||||
> - 验收必须包含配置解析、缓存读写、Host Header 绑定等测试与中文注释交付约束。
|
||||
|
||||
## User Scenarios & Testing *(mandatory)*
|
||||
|
||||
### User Story 1 - 运维人员校验配置 (Priority: P1)
|
||||
|
||||
运维人员需要在启动 any-hub 之前验证 `config.toml` 是否完整、字段合法,以便在 CI/CD 和本地快速发现错误配置,避免生产中断。
|
||||
|
||||
**Why this priority**: 若配置错误无法在启动前阻断,将直接导致多仓代理不可用,是 Phase 0 的最小可行能力。
|
||||
|
||||
**Independent Test**: 提供一份带有缺失字段或非法取值的配置,通过 `--check-config` 运行,命令应返回错误并指出问题;提供一份合格配置则应返回成功状态。
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** 配置文件缺少必填字段,**When** 运维运行 `any-hub --check-config --config broken.toml`,**Then** 命令立即失败并展示缺失字段及修复指引。
|
||||
2. **Given** 配置文件全部合法,**When** 运维运行 `any-hub --check-config --config valid.toml`,**Then** 命令成功退出并记录“配置有效”的日志。
|
||||
|
||||
---
|
||||
|
||||
### User Story 2 - CLI 操作者加载配置并启动 (Priority: P1)
|
||||
|
||||
CLI 操作者需要使用 `--config` 标志加载默认或指定路径的 `config.toml`,在无额外 UI 的环境中完成 any-hub 启动,并通过 `--version` 确认二进制身份。
|
||||
|
||||
**Why this priority**: Phase 0 要求可运行的入口;若 CLI 无法正确加载配置或识别版本,后续阶段均无法进行。
|
||||
|
||||
**Independent Test**: 准备默认路径 `config.toml` 与自定义路径 `custom.toml`,分别运行 `any-hub` 并确认应用读取正确文件、输出版本信息、在缺失文件时提供明确错误。
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** 默认路径存在配置文件,**When** 操作者直接运行 `any-hub`,**Then** 程序打印版本信息、载入默认配置并开始初始化。
|
||||
2. **Given** 自定义配置路径,**When** 操作者运行 `any-hub --config /tmp/custom.toml`,**Then** 程序使用该路径并在日志中记录“正在读取 /tmp/custom.toml”。
|
||||
3. **Given** 用户想快速确认版本,**When** 运行 `any-hub --version`,**Then** 输出语义化版本并立即退出。
|
||||
|
||||
---
|
||||
|
||||
### User Story 3 - 观察日志确保运行健康 (Priority: P2)
|
||||
|
||||
SRE 希望 any-hub 在启动和运行阶段输出结构化、可预测的日志,用以判断配置来源、监听端口和缓存策略,支持文件或 stdout 并尊重配置中的日志级别。
|
||||
|
||||
**Why this priority**: Phase 0 需具备排障手段;若无一致日志,无法判断配置成效或升级问题。
|
||||
|
||||
**Independent Test**: 通过配置项将日志写入文件与 stdout,触发一次成功的配置校验和一次失败案例,验证日志包含时间、级别、Hub 名称/域名、动作结果等字段。
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** 配置中启用文件日志,**When** 程序启动,**Then** 在文件中生成带时间戳、级别、消息字段的日志并滚动管理。
|
||||
2. **Given** 配置校验失败,**When** 运维重试 `--check-config`,**Then** 日志包含校验错误详情和“阻止启动”提示,帮助快速定位问题。
|
||||
|
||||
### Edge Cases
|
||||
|
||||
- 配置文件缺失或路径不可读时,需要输出可操作指引(例如“请提供 --config 或在当前目录创建 config.toml”)。
|
||||
- TOML 语法错误或类型不匹配时,必须指出具体行列与字段,避免笼统报错。
|
||||
- 日志路径无写权限或磁盘填满时,应用需自动退回 stdout 并提示权限/容量问题。
|
||||
|
||||
## Requirements *(mandatory)*
|
||||
|
||||
### Functional Requirements
|
||||
|
||||
- **FR-001**: 系统必须提供 `--config` 标志,默认读取工作目录下的 `config.toml`,并在日志中记录最终使用的路径。
|
||||
- **FR-002**: 系统必须提供 `--check-config` 模式,在不启动服务器的情况下完成配置加载、默认值合并与字段校验,并以退出码区分成功/失败。
|
||||
- **FR-003**: 系统必须提供 `--version` 标志,输出语义化版本号(含 Git 提交或构建信息)后立即退出且不执行其他逻辑。
|
||||
- **FR-004**: 配置加载器必须支持全局与 `[[Hub]]` 段的必填字段校验,自动补齐默认值并返回结构化错误,且覆盖单元测试。
|
||||
- **FR-005**: 日志初始化流程必须尊重配置中的级别/输出位置,支持 stdout 及文件滚动策略,且在任何模式(校验/启动)中启用结构化日志字段。
|
||||
- **FR-006**: 当配置合法时,系统必须输出一条“配置验证通过”或“启动完成”的信息;当配置非法时,必须输出明确的字段及原因,方便用户修复。
|
||||
|
||||
### Key Entities *(include if feature involves data)*
|
||||
|
||||
- **Configuration Profile**: 由全局段(日志、缓存、重试、内存限制)及一个或多个 Hub 条目组成,需保证 `Name/Domain/Port/Upstream` 等必填项存在,并允许可选字段继承或覆盖默认值。
|
||||
- **CLI Flag Set**: 运行入口可解析 `--config`、`--check-config`、`--version` 等标志;不同组合需决定流程(例如校验模式不启动服务器、版本模式直接退出)。
|
||||
|
||||
## Success Criteria *(mandatory)*
|
||||
|
||||
### Measurable Outcomes
|
||||
|
||||
- **SC-001**: 100% 的非法 `config.toml` 在 `--check-config` 阶段被阻断,并输出至少一条包含字段名与错误原因的日志。
|
||||
- **SC-002**: 在默认与自定义路径情况下,`any-hub` 启动时间不超过 2 秒即可完成配置加载并打印版本信息。
|
||||
- **SC-003**: 至少 95% 的启动/校验日志包含时间、级别、动作、配置路径等标准字段,可直接用于排障。
|
||||
- **SC-004**: CLI 操作者能够在 1 次运行内确认版本号与配置状态,相关指令的使用步骤在 README/DEVELOPMENT 中有据可查。
|
||||
|
||||
## Assumptions
|
||||
|
||||
- 默认配置文件路径为仓库根目录或部署目录下的 `config.toml`;若环境变量 `ANY_HUB_CONFIG` 已存在,则 CLI 标志优先级高于环境变量。
|
||||
- 日志默认输出到 stdout,且仅在配置显式开启时写入文件,避免初期部署的磁盘依赖。
|
||||
- 版本号信息可通过构建流程注入,若缺失则回退为“unknown”。
|
||||
152
specs/001-config-bootstrap/tasks.md
Normal file
152
specs/001-config-bootstrap/tasks.md
Normal file
@@ -0,0 +1,152 @@
|
||||
---
|
||||
|
||||
description: "Task list for feature 001-config-bootstrap"
|
||||
---
|
||||
|
||||
# Tasks: 配置与骨架
|
||||
|
||||
**Input**: Design documents from `/specs/001-config-bootstrap/`
|
||||
**Prerequisites**: plan.md (required), spec.md (required for user stories), research.md, data-model.md, contracts/
|
||||
|
||||
**Tests**: 宪法 v1.0.0 要求覆盖配置解析、CLI 流程与日志可观测性,本任务列表默认包含相应单元/集成测试。
|
||||
|
||||
**Organization**: Tasks are grouped by user story to enable independent implementation and testing of each story.
|
||||
|
||||
## Format: `[ID] [P?] [Story] Description`
|
||||
|
||||
- **[P]**: Can run in parallel (different files, no dependencies)
|
||||
- **[Story]**: Which user story this task belongs to (e.g., US1, US2, US3)
|
||||
- Include exact file paths in descriptions
|
||||
|
||||
## Phase 1: Setup (Shared Infrastructure)
|
||||
|
||||
**Purpose**: Ensure repository has the baseline artifacts and documentation required for Phase 0 delivery.
|
||||
|
||||
- [X] T001 Create canonical sample config包含全局段与单个 Hub 的默认值在 `configs/config.example.toml`
|
||||
- [X] T002 Document Phase 0 bootstrap prerequisites(Go 版本、依赖、命令)于 `DEVELOPMENT.md`
|
||||
- [X] T003 [P] Link quickstart入口与 CLI 使用章节到 `README.md`,方便新成员找到 `--check-config`/`--version`
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Foundational (Blocking Prerequisites)
|
||||
|
||||
**Purpose**: Provide shared config/CLI scaffolding and fixtures required by all user stories.
|
||||
|
||||
- [X] T004 定义 `Config`/`GlobalConfig`/`HubConfig` 结构与默认常量于 `internal/config/types.go`
|
||||
- [X] T005 实现基础加载器(读取 TOML、合并默认值)骨架于 `internal/config/loader.go`
|
||||
- [X] T006 [P] 抽象校验错误类型与帮助函数(含字段路径)于 `internal/config/errors.go`
|
||||
- [X] T007 建立 `internal/config/testdata/{valid,missing}.toml` 及通用测试 helper 于 `internal/config/test_helpers_test.go`
|
||||
- [X] T008 为 CLI 提供统一 flag 解析入口(占位逻辑)于 `cmd/any-hub/main.go`
|
||||
|
||||
**Checkpoint**: Config 模型、加载骨架与 CLI flag 入口完成后,用户故事可并行推进。
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: User Story 1 - 运维人员校验配置 (Priority: P1) 🎯 MVP
|
||||
|
||||
**Goal**: 任何非法 `config.toml` 都能在 `--check-config` 阶段被阻断,同时输出明确字段与修复建议。
|
||||
|
||||
**Independent Test**: 使用 `go test ./cmd/any-hub -run TestCheckConfig*` 和 `go test ./internal/config`,验证缺失字段/类型错误会失败且成功配置通过。
|
||||
|
||||
### Tests for User Story 1
|
||||
|
||||
- [X] T009 [P] [US1] 编写缺失字段/类型错误用例,确保 `LoadConfig` 返回结构化错误(`internal/config/loader_test.go`)
|
||||
- [X] T010 [P] [US1] 编写 CLI 集成测试:执行 `--check-config` 并断言退出码/日志(`cmd/any-hub/main_test.go`)
|
||||
|
||||
### Implementation for User Story 1
|
||||
|
||||
- [X] T011 [US1] 完成默认值合并与字段级校验逻辑(路径/数值/唯一性)于 `internal/config/validation.go`
|
||||
- [X] T012 [US1] 将 `--check-config` flag 与新校验逻辑接线,并返回对应退出码于 `cmd/any-hub/main.go`
|
||||
- [X] T013 [US1] 定义用户可读的错误消息与中文注释,更新 `internal/config/errors.go`
|
||||
- [X] T014 [US1] 更新 `quickstart.md` 与 `README.md`,列出 `--check-config` 使用示例与常见错误修复
|
||||
|
||||
**Checkpoint**: `any-hub --check-config` 可以独立验证配置且输出标准日志。
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: User Story 2 - CLI 操作者加载配置并启动 (Priority: P1)
|
||||
|
||||
**Goal**: CLI 能根据 flag/环境/默认顺序加载配置,启动流程打印版本与配置来源,并提供 `--version` 快速查询。
|
||||
|
||||
**Independent Test**: 通过 `cmd/any-hub/main_test.go` 的 flag 优先级测试以及 `cmd/any-hub/version_test.go` 的版本输出测试验证。
|
||||
|
||||
### Tests for User Story 2
|
||||
|
||||
- [X] T015 [P] [US2] 编写 flag vs. 环境变量 vs. 默认路径的优先级测试(`cmd/any-hub/main_test.go`)
|
||||
- [X] T016 [P] [US2] 为 `--version` 输出添加测试,断言语义化字符串与退出行为(`cmd/any-hub/version_test.go`)
|
||||
|
||||
### Implementation for User Story 2
|
||||
|
||||
- [X] T017 [US2] 实现配置路径解析顺序(flag > `ANY_HUB_CONFIG` > 默认),并在日志中记录来源(`cmd/any-hub/main.go`)
|
||||
- [X] T018 [US2] 实装 `--version` 逻辑(含构建信息注入)于 `cmd/any-hub/version.go`
|
||||
- [X] T019 [US2] 在正常启动路径中输出版本号、监听端口与配置路径(结构化日志)于 `cmd/any-hub/main.go`
|
||||
- [X] T020 [US2] 更新 `DEVELOPMENT.md` 与 `README.md` 的 CLI 章节,描述 flag 组合与退出码
|
||||
|
||||
**Checkpoint**: `any-hub` 可直接启动/加载配置,`--version` 即时返回信息。
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: User Story 3 - 观察日志确保运行健康 (Priority: P2)
|
||||
|
||||
**Goal**: 启动与校验流程都能输出结构化日志,支持 stdout/文件滚动,并在写文件失败时自动回退。
|
||||
|
||||
**Independent Test**: 通过 `internal/logging/logger_test.go`(模拟文件权限/滚动策略)与 `cmd/any-hub/logging_integration_test.go`(验证 stdout 回退)。
|
||||
|
||||
### Tests for User Story 3
|
||||
|
||||
- [X] T021 [P] [US3] 创建 logger 单元测试:验证级别/输出配置与字段注入(`internal/logging/logger_test.go`)
|
||||
- [X] T022 [P] [US3] 编写集成测试覆盖文件不可写时的 stdout 回退(`cmd/any-hub/logging_integration_test.go`)
|
||||
|
||||
### Implementation for User Story 3
|
||||
|
||||
- [X] T023 [US3] 新增 `internal/logging/logger.go`,根据配置初始化 Logrus + Lumberjack,并暴露 `InitLogger`
|
||||
- [X] T024 [US3] 在 `cmd/any-hub/main.go` 的校验与启动路径调用 `InitLogger`,并注入 `action/configPath/result` 字段
|
||||
|
||||
- [X] T025 [US3] 添加日志字段构建与公共 helper(`internal/logging/fields.go`),确保包含 hub/domain/命中状态
|
||||
- [X] T026 [US3] 更新 `quickstart.md`/`DEVELOPMENT.md`,记录日志配置字段与排障步骤
|
||||
|
||||
**Checkpoint**: 日志可根据配置切换输出,并提供足够字段支持排障。
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Polish & Cross-Cutting Concerns
|
||||
|
||||
**Purpose**: Finishing touches that ensure maintainability and documentation alignment.
|
||||
|
||||
- [X] T027 运行 `gofmt`/`go test ./...` 并将结果记录到 `DEVELOPMENT.md` 的验证段
|
||||
- [X] T028 为关键结构与算法补充中文注释,覆盖 `internal/config`、`cmd/any-hub`、`internal/logging`
|
||||
- [X] T029 [P] 更新 `CHANGELOG.md`(若存在)与 `README.md`,概述 Phase 0 能力及后续路线
|
||||
|
||||
---
|
||||
|
||||
## Dependencies & Execution Order
|
||||
|
||||
### Phase Dependencies
|
||||
- Phase 1 → Phase 2 → User Stories (US1/US2/US3) → Phase 6
|
||||
|
||||
### User Story Dependencies
|
||||
- US1 和 US2 都依赖 Phase 2;US3 依赖 US1/US2 的 CLI/logging 接口完成后再启
|
||||
- US1 是 MVP(配置校验),需先完成以解锁后续部署
|
||||
|
||||
### Parallel Execution Examples
|
||||
- **US1**: T009 与 T010 可并行编写测试;实现任务 T011/T012 需等测试框架 ready
|
||||
- **US2**: T015 与 T016 可同测;T017/T018 可并行后共同驱动 T019
|
||||
- **US3**: T021 与 T022 可并行;T023/T025 可并行后统一在 T024 接线
|
||||
|
||||
---
|
||||
|
||||
## Implementation Strategy
|
||||
|
||||
### MVP First (User Story 1 Only)
|
||||
1. 完成 Phase 1-2
|
||||
2. 交付 US1(配置校验 + CLI check),并通过 quickstart 测试
|
||||
3. 可在此阶段发布 CLI 校验版本,供 CI 使用
|
||||
|
||||
### Incremental Delivery
|
||||
1. MVP(US1)完成后,向 CLI 启动/版本(US2)演进
|
||||
2. 最后实现日志观测(US3),再进入 Polish
|
||||
|
||||
### Parallel Team Strategy
|
||||
- 团队 A:聚焦 `internal/config`(US1)
|
||||
- 团队 B:并行处理 CLI flag/版本(US2)
|
||||
- 团队 C:在 CLI 接口稳定后实现日志(US3)
|
||||
Reference in New Issue
Block a user