Simplify system implementation

This commit is contained in:
yuxuanhui
2026-08-04 18:59:21 +08:00
parent bf8da90433
commit ee0064135c
19 changed files with 418 additions and 1169 deletions
@@ -0,0 +1,24 @@
# 配置与运行时
## 配置入口
进程配置集中在 `zhixing-server/src/zhixing_server/bootstrap/config.py:Settings`:
- 继承 `pydantic_settings.BaseSettings`,字段声明默认值和可接受类型。
- 通过 `SettingsConfigDict(env_file=".env", env_prefix="ZHIXING_", extra="ignore")` 读取环境变量;新增变量应遵循 `ZHIXING_<FIELD>` 命名。
- `app_env` 使用 `Literal["development", "test", "production"]`,不要在业务代码里重复字符串校验。
- `get_settings()` 使用 `@lru_cache`,在一个进程内复用同一配置对象。
端点通过 FastAPI 依赖注入拿配置,例如 `interfaces/http/system.py:system_status` 的 `Annotated[Settings, Depends(get_settings)]`。不要在路由或领域代码中直接读取 `os.environ`、`.env` 或 Docker 变量。
## 应用生命周期与部署
- `bootstrap/app.py:create_app` 创建 `FastAPI(title=settings.app_name)`,然后挂载 `operational_router` 和 `api_v1_router`。
- `main.py` 只导出 ASGI `app`,容器入口可以安全导入它。
- 健康检查固定为 `/healthz`;业务 API 固定挂在 `/api/v1` 下。
- 开发环境由 Vite 将 `/api` 和 `/healthz` 代理到 `VITE_DEV_API_TARGET`(默认 `http://localhost:8000`);生产环境由 `zhixing-web/nginx/default.conf.template` 以 `API_UPSTREAM` 代理。浏览器代码不要拼接后端绝对地址。
- Docker Compose 的环境变量和端口默认值见根目录 `.env.example`、`docker-compose.dev.yml` 和 `docker-compose.prod.yml`。
## 目前没有的能力
当前仓库没有数据库连接、迁移、任务队列或日志配置实现。不要只因为 `Settings.log_level` 字段存在就引入一套日志框架;如果新增持久化或结构化日志,应先形成可验证的实现和对应规格。
@@ -1,51 +0,0 @@
# Database Guidelines
> Database patterns and conventions for this project.
---
## Overview
<!--
Document your project's database conventions here.
Questions to answer:
- What ORM/query library do you use?
- How are migrations managed?
- What are the naming conventions for tables/columns?
- How do you handle transactions?
-->
(To be filled by the team)
---
## Query Patterns
<!-- How should queries be written? Batch operations? -->
(To be filled by the team)
---
## Migrations
<!-- How to create and run migrations -->
(To be filled by the team)
---
## Naming Conventions
<!-- Table names, column names, index names -->
(To be filled by the team)
---
## Common Mistakes
<!-- Database-related mistakes your team has made -->
(To be filled by the team)
+38 -42
View File
@@ -1,54 +1,50 @@
# Directory Structure
# 后端目录与模块边界
> How backend code is organized in this project.
## 当前布局
---
## Overview
<!--
Document your project's backend directory structure here.
Questions to answer:
- How are modules/packages organized?
- Where does business logic live?
- Where are API endpoints defined?
- How are utilities and helpers organized?
-->
(To be filled by the team)
---
## Directory Layout
```
<!-- Replace with your actual structure -->
src/
├── ...
└── ...
```text
zhixing-server/
├── src/zhixing_server/
│ ├── bootstrap/ # 应用工厂和进程配置
│ │ ├── app.py
│ │ └── config.py
│ ├── interfaces/http/ # 跨上下文 HTTP 路由目录
│ │ ├── router.py # /api/v1 路由目录
│ │ └── system.py # /healthz、/api/v1/system/status
│ ├── modules/ # 业务 bounded context(目前为空)
│ │ └── README.md
│ ├── shared/ # 没有特定业务所有权的小型基础能力
│ ├── main.py # ASGI 入口,只导出 app
│ └── __init__.py
└── tests/ # 按行为/入口组织的 pytest 测试
```
---
`zhixing-server/src/zhixing_server/bootstrap/app.py:create_app` 负责组合 FastAPI 应用,`main.py` 只执行 `app = create_app()`。不要把应用组合、环境读取或业务逻辑塞进 `main.py`。
## Module Organization
## 新增业务上下文
<!-- How should new features/modules be organized? -->
只有在领域语言和所有权边界明确后,才在 `modules/` 下创建上下文。推荐形状来自 `zhixing-server/src/zhixing_server/modules/README.md`:
(To be filled by the team)
```text
modules/<bounded_context>/
├── domain/ # 实体、值对象、领域服务、端口
├── application/ # 用例和编排
├── infrastructure/ # 存储及外部系统适配器
└── presentation/ # HTTP 或消息驱动的交付适配器
```
---
domain 层不能导入 FastAPI、持久化客户端或 infrastructure 适配器。上下文内的 presentation 负责把输入转换成用例需要的类型;顶层 `interfaces/http` 只承载跨上下文的运维入口和路由目录。
## Naming Conventions
## 命名与导入
<!-- File and folder naming rules -->
- Python 包、模块和函数使用 `snake_case`;测试文件使用 `test_*.py`,例如 `tests/test_system_http.py`。
- 对外公开的类、响应模型和函数应有类型标注与文档字符串,参照 `bootstrap/config.py` 和 `interfaces/http/system.py`。
- `shared/` 只能放跨上下文且无业务归属的原语;不要把某个上下文的领域规则放进去。
- 避免新建全局 `services/`、`repositories/` 或 `utils/` 目录来绕过上下文边界。
(To be filled by the team)
## 参考实现
---
## Examples
<!-- Link to well-organized modules as examples -->
(To be filled by the team)
- 应用组合:`zhixing-server/src/zhixing_server/bootstrap/app.py`
- 路由目录:`zhixing-server/src/zhixing_server/interfaces/http/router.py`
- 运维/系统端点:`zhixing-server/src/zhixing_server/interfaces/http/system.py`
- 当前 HTTP 契约测试:`zhixing-server/tests/test_system_http.py`
+15 -42
View File
@@ -1,51 +1,24 @@
# Error Handling
# 错误处理
> How errors are handled in this project.
## 当前行为
---
服务目前没有自定义异常层、全局异常处理器或统一错误 envelope。FastAPI/Pydantic 负责请求验证和标准 HTTP 错误响应;现有成功端点只返回声明过的响应模型。新增错误契约前,应先确认前端是否需要稳定的错误字段,并用 HTTP 契约测试锁定它。
## Overview
## 分层规则
<!--
Document your project's error handling conventions here.
- 在 HTTP 边界完成输入解析和验证,不要把 `Request`、`HTTPException` 或 FastAPI 依赖对象带入 domain。
- 领域或应用层的业务失败应使用可识别的领域异常(当该层实际出现时),由 presentation 层映射为 HTTP 响应;不要在 domain 层导入 FastAPI。
- 不能恢复的配置错误应在启动时暴露,而不是在每个端点里静默使用空值。`Settings` 的类型和默认值应让错误尽早发生。
- 不要捕获 `Exception` 后返回成功、空对象或吞掉 traceback。只有在能补充上下文、转换边界错误或保证资源清理时才捕获具体异常。
Questions to answer:
- What error types do you define?
- How are errors propagated?
- How are errors logged?
- How are errors returned to clients?
-->
## 前端边界
(To be filled by the team)
`zhixing-web/src/shared/api/request-json.ts:requestJson` 对非 2xx 响应抛出 `ApiError`,并保留 HTTP 状态码;React Query 通过 `isError` 将其传给 feature 页面。页面应显式渲染加载、错误和成功状态,参照 `features/system/pages/system-status-page.tsx`,不要把错误静默成“无数据”。
---
当前 `requestJson` 只对响应体做泛型断言,不做运行时 schema 校验。因此来自外部或不稳定来源的数据在进入页面前必须增加明确的运行时校验,不能把 TypeScript 类型当成网络验证。
## Error Types
## 测试要求
<!-- Custom error classes/types -->
(To be filled by the team)
---
## Error Handling Patterns
<!-- Try-catch patterns, error propagation -->
(To be filled by the team)
---
## API Error Responses
<!-- Standard error response format -->
(To be filled by the team)
---
## Common Mistakes
<!-- Error handling mistakes your team has made -->
(To be filled by the team)
- 对新增 HTTP 错误状态,优先在 `zhixing-server/tests/` 验证状态码和 JSON 契约。
- 对前端错误展示,在页面测试中 mock query hook 的 `isError`/`error` 状态并断言用户可见文本。
- 不要只测试异常类被抛出而不测试边界响应或用户行为。
@@ -0,0 +1,30 @@
# HTTP API 契约
## 路由组合
`zhixing-server/src/zhixing_server/interfaces/http/router.py` 是 `/api/v1` 的唯一目录入口:
```python
api_v1_router = APIRouter(prefix="/api/v1")
api_v1_router.include_router(system_router, prefix="/system", tags=["system"])
```
跨上下文的运维端点放在 `operational_router`;业务端点应由对应上下文的 presentation 适配器提供,再由路由目录挂载。不要在 `bootstrap/app.py` 里堆积路径字符串。
## 响应模型
每个稳定的 JSON 响应都应有 Pydantic `BaseModel`,并在装饰器中声明 `response_model`。现有 `HealthResponse` 和 `SystemStatusResponse` 位于 `interfaces/http/system.py`:
- `/healthz` 返回严格的 `{"status": "ok"}`,设置 `include_in_schema=False` 以供容器探针使用。
- `/api/v1/system/status` 返回 `status`、`service`、`environment`;只暴露安全的运行时元数据,不返回环境变量原文或秘密。
- 字段名是前后端契约的一部分。变更时同步更新 `zhixing-server/tests/test_system_http.py`、`zhixing-web/src/features/system/api/system.types.ts` 和页面测试。
## 输入、依赖和错误
- 通过 FastAPI 参数、`Annotated` 依赖和 Pydantic 模型完成边界转换;不要把原始请求对象传入 domain。
- 简单、无阻塞的当前端点使用同步 `def`,保持与 `system.py` 一致;只有实际需要异步 I/O 时才使用 `async def`。
- 当前服务没有自定义错误 envelope。验证错误和显式 HTTP 错误沿用 FastAPI 默认契约,除非先增加全局约定并补充测试。
## 验证
后端契约用 `TestClient(create_app())` 测试,参照 `tests/test_system_http.py`。前端使用同源 `/api/v1/...` 路径,经 `shared/api/request-json.ts` 调用;不要在 feature 页面内直接调用 `fetch`。
+24 -29
View File
@@ -1,38 +1,33 @@
# Backend Development Guidelines
# 后端开发规格
> Best practices for backend development in this project.
后端是 Python 3.12 + FastAPI 的单体服务。当前代码只包含启动组合、环境配置、运维端点和 `system` HTTP 切片;业务 bounded context 尚未创建。新增后端代码应先确认它属于启动边界、共享基础设施、HTTP 入口还是某个明确的 bounded context。
---
## 规格导航
## Overview
| 规格 | 用途 |
| --- | --- |
| [目录与模块边界](./directory-structure.md) | 包结构、bounded context 和导入边界 |
| [配置与运行时](./configuration-and-runtime.md) | `Settings`、应用工厂和部署环境 |
| [HTTP 契约](./http-api-contracts.md) | 路由组合、响应模型和同源 API 路径 |
| [错误处理](./error-handling.md) | 当前 FastAPI 错误行为及跨层错误传递 |
| [质量与测试](./quality-guidelines.md) | Ruff、Pyright、pytest 及禁止模式 |
This directory contains guidelines for backend development. Fill in each file with your project's specific conventions.
## 开发前检查
---
- 先阅读 `docs/adr/0001-bounded-context-first-modular-monolith.md`,确认新业务是否有清晰的语言和所有权边界。
- 先阅读目标上下文的 `modules/<bounded_context>/README.md`(如已存在),再决定 domain、application、infrastructure、presentation 的位置。
- 变更 HTTP 字段时同时检查 `zhixing-server/tests/`、前端 feature API 类型以及 `docs/adr/0002-use-a-same-origin-browser-api.md`。
- 不要为了“未来可能需要”创建空的数据库、服务或日志层;当前仓库没有这些实现。
## Guidelines Index
## 质量检查
| Guide | Description | Status |
|-------|-------------|--------|
| [Directory Structure](./directory-structure.md) | Module organization and file layout | To fill |
| [Database Guidelines](./database-guidelines.md) | ORM patterns, queries, migrations | To fill |
| [Error Handling](./error-handling.md) | Error types, handling strategies | To fill |
| [Quality Guidelines](./quality-guidelines.md) | Code standards, forbidden patterns | To fill |
| [Logging Guidelines](./logging-guidelines.md) | Structured logging, log levels | To fill |
在 `zhixing-server/` 下运行:
---
```bash
uv run ruff format --check .
uv run ruff check .
uv run pyright
uv run pytest
```
## How to Fill These Guidelines
For each guideline file:
1. Document your project's **actual conventions** (not ideals)
2. Include **code examples** from your codebase
3. List **forbidden patterns** and why
4. Add **common mistakes** your team has made
The goal is to help AI assistants and new team members understand how YOUR project works.
---
**Language**: All documentation should be written in **English**.
根目录 `./dev.sh check` 和 `./dev.sh test` 会执行完整前后端检查。
@@ -1,51 +0,0 @@
# Logging Guidelines
> How logging is done in this project.
---
## Overview
<!--
Document your project's logging conventions here.
Questions to answer:
- What logging library do you use?
- What are the log levels and when to use each?
- What should be logged?
- What should NOT be logged (PII, secrets)?
-->
(To be filled by the team)
---
## Log Levels
<!-- When to use each level: debug, info, warn, error -->
(To be filled by the team)
---
## Structured Logging
<!-- Log format, required fields -->
(To be filled by the team)
---
## What to Log
<!-- Important events to log -->
(To be filled by the team)
---
## What NOT to Log
<!-- Sensitive data, PII, secrets -->
(To be filled by the team)
+27 -40
View File
@@ -1,51 +1,38 @@
# Quality Guidelines
# 后端质量与测试
> Code quality standards for backend development.
## 工具链
---
`zhixing-server/pyproject.toml` 固定 Python 3.12,使用 `uv` 管理环境和锁文件。质量门禁由以下配置定义:
## Overview
- Ruff 格式化:100 列、双引号。
- Ruff lint:`B`, `E`, `F`, `I`, `SIM`, `UP`。
- Pyright:`strict`,检查 `src` 和 `tests`。
- Pytest:严格配置和严格 markers,测试目录为 `tests/`。
<!--
Document your project's quality standards here.
不要只在编辑器里运行局部检查;提交前至少执行:
Questions to answer:
- What patterns are forbidden?
- What linting rules do you enforce?
- What are your testing requirements?
- What code review standards apply?
-->
```bash
uv run ruff format --check .
uv run ruff check .
uv run pyright
uv run pytest
```
(To be filled by the team)
## 代码规则
---
- 函数、方法和公开类使用完整类型标注;公共入口写清楚参数、返回值和边界原因,参照 `bootstrap/config.py`、`bootstrap/app.py`。
- HTTP 响应显式使用 Pydantic 模型和 `response_model`,不要返回随意拼接的 dict。
- 配置通过 `Settings` 注入,不直接读取进程环境;应用组合集中在 `create_app`。
- 领域代码不得依赖 FastAPI、持久化客户端或 infrastructure,符合 `modules/README.md` 的边界。
- 变更端点时同时更新行为测试和与之对应的前端契约。
## Forbidden Patterns
## 测试形状
<!-- Patterns that should never be used and why -->
`tests/test_system_http.py` 使用 `TestClient(create_app())` 从真实应用组合出发,断言状态码和完整 JSON。新增路由优先采用相同的黑盒 HTTP 测试;只有纯领域逻辑才单独测试函数或对象。
(To be filled by the team)
## 禁止模式
---
## Required Patterns
<!-- Patterns that must always be used -->
(To be filled by the team)
---
## Testing Requirements
<!-- What level of testing is expected -->
(To be filled by the team)
---
## Code Review Checklist
<!-- What reviewers should check -->
(To be filled by the team)
- 不要提交未使用的 import、宽泛 `except Exception`、无类型的公共参数或绕过 Pyright 的 `Any`。
- 不要把秘密、完整环境变量、请求凭据写进响应或日志;系统状态端点只返回安全元数据。
- 不要引入没有真实使用场景的空数据库/日志抽象,或在尚未理解 bounded context 前创建业务模块。
- 不要为了让测试通过复制 `create_app` 的路由逻辑;测试应调用实际应用工厂。