# RESTful API 重构实现计划 > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. **Goal:** 将后端 HTTP API 改造为完全符合 RESTful 规范,同步更新前端适配代码,并添加路由文档。 **Architecture:** - 后端:重命名路由 URL,简化响应模型,profile 模块重命名为 users - 前端:更新 API 调用路径,简化响应模型 - 文档:新增路由文档,更新 AGENTS.md 规则 **Tech Stack:** FastAPI, Pydantic, Flutter, Dart --- ## Phase 1: 后端 Schema 重构 ### Task 1: 重命名和简化 Auth Schema **Files:** - Modify: `backend/src/v1/auth/schemas.py` **Step 1: 更新 schema 文件** 将现有 schema 重命名并简化: ```python from __future__ import annotations from typing import Literal from pydantic import BaseModel, EmailStr, Field class VerificationCreateRequest(BaseModel): username: str = Field(min_length=3, max_length=30) email: EmailStr password: str = Field(min_length=6) redirect_to: str | None = None class VerificationResendRequest(BaseModel): email: EmailStr class VerificationVerifyRequest(BaseModel): email: EmailStr token: str = Field(pattern=r"^\d{6}$") class SessionCreateRequest(BaseModel): email: EmailStr password: str = Field(min_length=6) class SessionRefreshRequest(BaseModel): refresh_token: str = Field(min_length=1) class SessionDeleteRequest(BaseModel): refresh_token: str = Field(min_length=1) class AuthUser(BaseModel): id: str email: EmailStr class SessionResponse(BaseModel): access_token: str refresh_token: str expires_in: int token_type: str user: AuthUser class UserByEmailResponse(BaseModel): id: str email: EmailStr created_at: str email_confirmed_at: str | None = None class VerificationCreateResponse(BaseModel): email: EmailStr class PasswordResetRequest(BaseModel): email: EmailStr redirect_to: str | None = None class PasswordResetResponse(BaseModel): message: str = "Password reset email sent" ``` **Step 2: 验证类型检查** Run: `cd backend && uv run basedpyright src/v1/auth/schemas.py` Expected: No errors **Step 3: Commit** ```bash git add backend/src/v1/auth/schemas.py git commit -m "refactor(auth): rename and simplify auth schemas for RESTful API" ``` --- ### Task 2: 创建 Users Schema **Files:** - Create: `backend/src/v1/users/schemas.py` **Step 1: 创建 users schema 文件** ```python from __future__ import annotations from pydantic import ( AnyHttpUrl, BaseModel, ConfigDict, Field, field_validator, model_validator, ) class UserResponse(BaseModel): id: str username: str avatar_url: str | None = None bio: str | None = None class UserUpdateRequest(BaseModel): model_config = ConfigDict(extra="forbid") username: str | None = Field(default=None, min_length=3, max_length=30) avatar_url: str | None = Field(default=None) bio: str | None = Field(default=None, max_length=200) @field_validator("avatar_url", mode="before") @classmethod def validate_avatar_url(cls, v: str | None) -> str | None: if v is None: return None parsed = AnyHttpUrl(v) if parsed.scheme not in ("http", "https"): raise ValueError("avatar_url must use http or https scheme") return str(parsed) @model_validator(mode="after") def require_one_field(self) -> "UserUpdateRequest": if self.username is None and self.avatar_url is None and self.bio is None: raise ValueError("At least one field must be provided") return self ``` **Step 2: 验证类型检查** Run: `cd backend && uv run basedpyright src/v1/users/schemas.py` Expected: No errors **Step 3: Commit** ```bash git add backend/src/v1/users/schemas.py git commit -m "feat(users): create users schemas" ``` --- ### Task 3: 创建 Users 模块基础文件 **Files:** - Create: `backend/src/v1/users/__init__.py` - Create: `backend/src/v1/users/dependencies.py` - Move: `backend/src/v1/profile/repository.py` → `backend/src/v1/users/repository.py` - Move: `backend/src/v1/profile/service.py` → `backend/src/v1/users/service.py` **Step 1: 创建 __init__.py** ```python from __future__ import annotations ``` **Step 2: 创建 dependencies.py** ```python from __future__ import annotations from typing import Annotated from fastapi import Depends from core.auth.models import CurrentUser from core.db import get_db from v1.auth.dependencies import get_current_user from v1.users.repository import UserRepository from v1.users.service import UserService async def get_user_repository( db=Depends(get_db), ) -> UserRepository: return UserRepository(db) async def get_user_service( repo: Annotated[UserRepository, Depends(get_user_repository)], current_user: Annotated[CurrentUser, Depends(get_current_user)], ) -> UserService: return UserService(repo, current_user) ``` **Step 3: 移动并更新 repository.py** 复制 `v1/profile/repository.py` 到 `v1/users/repository.py`,无需修改内容。 **Step 4: 移动并更新 service.py** 复制 `v1/profile/service.py` 到 `v1/users/service.py`,更新导入: ```python from v1.users.schemas import UserResponse, UserUpdateRequest ``` **Step 5: 验证类型检查** Run: `cd backend && uv run basedpyright src/v1/users/` Expected: No errors **Step 4: Commit** ```bash git add backend/src/v1/users/ git commit -m "feat(users): create users module from profile" ``` --- ## Phase 2: 后端路由重构 ### Task 4: 重构 Auth Router **Files:** - Modify: `backend/src/v1/auth/router.py` **Step 1: 更新路由定义** ```python from __future__ import annotations from typing import Annotated from fastapi import APIRouter, Depends, Response from fastapi import HTTPException from core.auth.models import CurrentUser from v1.auth.rate_limit import enforce_rate_limit from v1.auth.dependencies import get_auth_service from v1.users.dependencies import get_current_user from v1.auth.schemas import ( VerificationCreateRequest, VerificationCreateResponse, VerificationResendRequest, VerificationVerifyRequest, SessionCreateRequest, SessionDeleteRequest, SessionRefreshRequest, SessionResponse, UserByEmailResponse, ) from v1.auth.service import AuthService router = APIRouter(prefix="/auth", tags=["auth"]) @router.post("/verifications", response_model=VerificationCreateResponse, status_code=202) async def create_verification( payload: VerificationCreateRequest, service: AuthService = Depends(get_auth_service), ) -> VerificationCreateResponse: await enforce_rate_limit( scope="signup_start", identifier=payload.email, limit=5, window_seconds=60, ) return await service.create_verification(payload) @router.post("/verifications/resend", status_code=204) async def resend_verification( payload: VerificationResendRequest, service: AuthService = Depends(get_auth_service), ) -> Response: await enforce_rate_limit( scope="signup_resend", identifier=payload.email, limit=5, window_seconds=60, ) await service.resend_verification(payload) return Response(status_code=204) @router.post("/verifications/verify", response_model=SessionResponse) async def verify_verification( payload: VerificationVerifyRequest, service: AuthService = Depends(get_auth_service), ) -> SessionResponse: await enforce_rate_limit( scope="signup_verify", identifier=payload.email, limit=10, window_seconds=600, ) return await service.verify_verification(payload) @router.post("/sessions", response_model=SessionResponse) async def create_session( payload: SessionCreateRequest, service: AuthService = Depends(get_auth_service), ) -> SessionResponse: await enforce_rate_limit( scope="login", identifier=payload.email, limit=10, window_seconds=60, ) return await service.create_session(payload) @router.post("/sessions/refresh", response_model=SessionResponse) async def refresh_session( payload: SessionRefreshRequest, service: AuthService = Depends(get_auth_service), ) -> SessionResponse: await enforce_rate_limit( scope="refresh", identifier=payload.refresh_token, limit=10, window_seconds=60, ) return await service.refresh_session(payload) @router.delete("/sessions", status_code=204) async def delete_session( payload: SessionDeleteRequest, service: AuthService = Depends(get_auth_service), ) -> Response: await enforce_rate_limit( scope="logout", identifier=payload.refresh_token, limit=10, window_seconds=60, ) await service.delete_session(payload.refresh_token) return Response(status_code=204) @router.get("/users", response_model=UserByEmailResponse) async def get_user_by_email( email: str, current_user: Annotated[CurrentUser, Depends(get_current_user)], service: AuthService = Depends(get_auth_service), ) -> UserByEmailResponse: if current_user.role != "service_role" and current_user.email != email: raise HTTPException(status_code=403, detail="Forbidden") return await service.get_user_by_email(email) ``` **Step 2: 验证类型检查** Run: `cd backend && uv run basedpyright src/v1/auth/router.py` Expected: No errors **Step 3: Commit** ```bash git add backend/src/v1/auth/router.py git commit -m "refactor(auth): rename routes to RESTful style" ``` --- ### Task 5: 重构 Auth Service **Files:** - Modify: `backend/src/v1/auth/service.py` **Step 1: 更新 service 方法名和导入** 更新导入和方法名以匹配新的 schema: ```python from v1.auth.schemas import ( VerificationCreateRequest, VerificationCreateResponse, VerificationResendRequest, VerificationVerifyRequest, SessionCreateRequest, SessionDeleteRequest, SessionRefreshRequest, SessionResponse, UserByEmailResponse, ) ``` 将方法重命名: - `signup_start` → `create_verification` - `signup_resend` → `resend_verification` - `signup_verify` → `verify_verification` - `login` → `create_session` - `refresh` → `refresh_session` - `logout` → `delete_session` `create_verification` 返回 `VerificationCreateResponse(email=payload.email)`。 **Step 2: 验证类型检查** Run: `cd backend && uv run basedpyright src/v1/auth/service.py` Expected: No errors **Step 3: Commit** ```bash git add backend/src/v1/auth/service.py git commit -m "refactor(auth): rename service methods for RESTful API" ``` --- ### Task 6: 更新 Auth Gateway **Files:** - Modify: `backend/src/v1/auth/gateway.py` **Step 1: 更新导入和方法调用** 更新导入使用新 schema 名称,方法调用更新为新的 service 方法名。 **Step 2: 验证类型检查** Run: `cd backend && uv run basedpyright src/v1/auth/gateway.py` Expected: No errors **Step 3: Commit** ```bash git add backend/src/v1/auth/gateway.py git commit -m "refactor(auth): update gateway for new service methods" ``` --- ### Task 7: 创建 Users Router **Files:** - Create: `backend/src/v1/users/router.py` **Step 1: 创建 users router** ```python from __future__ import annotations from typing import Annotated from fastapi import APIRouter, Depends, Path from v1.users.dependencies import get_user_service from v1.users.schemas import UserResponse, UserUpdateRequest from v1.users.service import UserService router = APIRouter(prefix="/users", tags=["users"]) @router.get("/me", response_model=UserResponse) async def get_me( service: Annotated[UserService, Depends(get_user_service)], ) -> UserResponse: return await service.get_me() @router.patch("/me", response_model=UserResponse) async def update_me( payload: UserUpdateRequest, service: Annotated[UserService, Depends(get_user_service)], ) -> UserResponse: return await service.update_me(payload) @router.get("/{username}", response_model=UserResponse) async def get_by_username( username: Annotated[ str, Path(min_length=3, max_length=30, pattern="^[a-zA-Z0-9_]+$") ], service: Annotated[UserService, Depends(get_user_service)], ) -> UserResponse: return await service.get_by_username(username) ``` **Step 2: 验证类型检查** Run: `cd backend && uv run basedpyright src/v1/users/router.py` Expected: No errors **Step 3: Commit** ```bash git add backend/src/v1/users/router.py git commit -m "feat(users): create users router" ``` --- ### Task 8: 更新 Agent Chat Router **Files:** - Modify: `backend/src/v1/agent_chat/router.py` **Step 1: 更新 URL 路径** 将 `/run` 改为根路径: ```python @router.post("", response_model=AgentChatRunResponse) async def run_agent_chat( payload: AgentChatRunRequest, service: Annotated[AgentChatService, Depends(get_agent_chat_service)], ) -> AgentChatRunResponse: return await service.run(payload) ``` **Step 2: 验证类型检查** Run: `cd backend && uv run basedpyright src/v1/agent_chat/router.py` Expected: No errors **Step 3: Commit** ```bash git add backend/src/v1/agent_chat/router.py git commit -m "refactor(agent-chat): change route to RESTful style" ``` --- ### Task 9: 更新主路由注册 **Files:** - Modify: `backend/src/v1/router.py` **Step 1: 更新路由注册** ```python from __future__ import annotations from fastapi import APIRouter from core.http.models import HealthResponse from v1.agent_chat.router import router as agent_chat_router from v1.auth.router import router as auth_router from v1.infra.router import router as infra_router from v1.users.router import router as users_router router = APIRouter(prefix="/api/v1") router.include_router(auth_router) router.include_router(infra_router) router.include_router(users_router) router.include_router(agent_chat_router) @router.get("/health", response_model=HealthResponse) async def health() -> HealthResponse: return HealthResponse(status="ok") ``` **Step 2: 验证类型检查** Run: `cd backend && uv run basedpyright src/v1/router.py` Expected: No errors **Step 3: Commit** ```bash git add backend/src/v1/router.py git commit -m "refactor: register users router instead of profile" ``` --- ## Phase 3: 后端测试更新 ### Task 10: 更新 Auth 路由测试 **Files:** - Modify: `backend/tests/integration/test_auth_routes.py` **Step 1: 更新测试用例的 URL 和断言** - `/signup/start` → `/auth/verifications` - `/signup/resend` → `/auth/verifications/resend` - `/signup/verify` → `/auth/verifications/verify` - `/login` → `/auth/sessions` - `/refresh` → `/auth/sessions/refresh` - `/logout` → `/auth/sessions` - `/users/by-email` → `/auth/users?email=xxx` 更新断言: - `signup_start` 响应只包含 `email` 字段 - `signup_resend` 响应为 204,无 body **Step 2: 运行测试验证** Run: `cd backend && uv run pytest tests/integration/test_auth_routes.py -v` Expected: All tests pass **Step 3: Commit** ```bash git add backend/tests/integration/test_auth_routes.py git commit -m "test(auth): update integration tests for RESTful routes" ``` --- ### Task 11: 创建 Users 路由测试 **Files:** - Move: `backend/tests/integration/test_profile_routes.py` → `backend/tests/integration/test_users_routes.py` **Step 1: 移动并更新测试文件** - 更新 URL:`/profile/me` → `/users/me`,`/profile/{username}` → `/users/{username}` - 更新导入和断言 **Step 2: 运行测试验证** Run: `cd backend && uv run pytest tests/integration/test_users_routes.py -v` Expected: All tests pass **Step 3: Commit** ```bash git add backend/tests/integration/test_users_routes.py git rm backend/tests/integration/test_profile_routes.py git commit -m "test(users): rename profile tests to users" ``` --- ### Task 12: 运行完整测试套件 **Step 1: 运行所有后端测试** Run: `cd backend && uv run pytest -v` Expected: All tests pass **Step 2: 运行类型检查** Run: `cd backend && uv run basedpyright src/` Expected: No errors **Step 3: 运行 lint** Run: `cd backend && uv run ruff check src/` Expected: No errors --- ## Phase 4: 前端适配 ### Task 13: 更新 Auth API **Files:** - Modify: `apps/lib/features/auth/data/auth_api.dart` **Step 1: 更新 URL 路径** ```dart import 'package:social_app/core/api/api_client.dart'; import 'models/signup_request.dart'; import 'models/login_request.dart'; import 'models/auth_response.dart'; class AuthApi { final ApiClient _client; static const _prefix = '/api/v1/auth'; AuthApi(this._client); Future createVerification(SignupStartRequest request) async { final response = await _client.post( '$_prefix/verifications', data: request.toJson(), ); return VerificationCreateResponse.fromJson(response.data); } Future resendVerification(SignupResendRequest request) async { await _client.post( '$_prefix/verifications/resend', data: request.toJson(), ); } Future verifyVerification(SignupVerifyRequest request) async { final response = await _client.post( '$_prefix/verifications/verify', data: request.toJson(), ); return AuthResponse.fromJson(response.data); } Future createSession(LoginRequest request) async { final response = await _client.post( '$_prefix/sessions', data: request.toJson(), ); return AuthResponse.fromJson(response.data); } Future refreshSession(RefreshRequest request) async { final response = await _client.post( '$_prefix/sessions/refresh', data: request.toJson(), ); return AuthResponse.fromJson(response.data); } Future deleteSession(LogoutRequest request) async { await _client.delete( '$_prefix/sessions', data: request.toJson(), ); } } ``` **Step 2: Commit** ```bash git add apps/lib/features/auth/data/auth_api.dart git commit -m "refactor(auth): update API routes to RESTful style" ``` --- ### Task 14: 更新 Auth Response Models **Files:** - Modify: `apps/lib/features/auth/data/models/auth_response.dart` **Step 1: 简化响应模型** ```dart class AuthUser { final String id; final String email; const AuthUser({required this.id, required this.email}); factory AuthUser.fromJson(Map json) { return AuthUser(id: json['id'] as String, email: json['email'] as String); } } class AuthResponse { final String accessToken; final String refreshToken; final int expiresIn; final String tokenType; final AuthUser user; const AuthResponse({ required this.accessToken, required this.refreshToken, required this.expiresIn, required this.tokenType, required this.user, }); factory AuthResponse.fromJson(Map json) { return AuthResponse( accessToken: json['access_token'] as String, refreshToken: json['refresh_token'] as String, expiresIn: json['expires_in'] as int, tokenType: json['token_type'] as String, user: AuthUser.fromJson(json['user'] as Map), ); } } class VerificationCreateResponse { final String email; const VerificationCreateResponse({required this.email}); factory VerificationCreateResponse.fromJson(Map json) { return VerificationCreateResponse(email: json['email'] as String); } } ``` 删除 `SignupStartResponse` 和 `SignupResendResponse`。 **Step 2: Commit** ```bash git add apps/lib/features/auth/data/models/auth_response.dart git commit -m "refactor(auth): simplify response models" ``` --- ### Task 15: 更新 Auth Repository **Files:** - Modify: `apps/lib/features/auth/data/auth_repository.dart` - Modify: `apps/lib/features/auth/data/auth_repository_impl.dart` **Step 1: 更新方法名和返回类型** 将方法名和返回类型更新为新的 API 方法。 **Step 2: Commit** ```bash git add apps/lib/features/auth/data/auth_repository.dart git add apps/lib/features/auth/data/auth_repository_impl.dart git commit -m "refactor(auth): update repository for new API" ``` --- ### Task 16: 更新 Register Cubit **Files:** - Modify: `apps/lib/features/auth/presentation/cubits/register_cubit.dart` **Step 1: 更新 API 调用** - `signupStart` → `createVerification` - `signupResend` → `resendVerification`(现在返回 void) - 更新返回类型 **Step 2: Commit** ```bash git add apps/lib/features/auth/presentation/cubits/register_cubit.dart git commit -m "refactor(auth): update register cubit for new API" ``` --- ### Task 17: 更新 Auth Cubit **Files:** - Modify: `apps/lib/features/auth/presentation/cubits/auth_cubit.dart` **Step 1: 更新 API 调用** - `login` → `createSession` - `refresh` → `refreshSession` - `logout` → `deleteSession` **Step 2: Commit** ```bash git add apps/lib/features/auth/presentation/cubits/auth_cubit.dart git commit -m "refactor(auth): update auth cubit for new API" ``` --- ### Task 18: 创建 Users API 和 Repository **Files:** - Create: `apps/lib/features/users/data/users_api.dart` - Create: `apps/lib/features/users/data/users_repository.dart` - Create: `apps/lib/features/users/data/users_repository_impl.dart` - Create: `apps/lib/features/users/data/models/user_response.dart` **Step 1: 创建 users_api.dart** ```dart import 'package:social_app/core/api/api_client.dart'; import 'models/user_response.dart'; class UsersApi { final ApiClient _client; static const _prefix = '/api/v1/users'; UsersApi(this._client); Future getMe() async { final response = await _client.get('$_prefix/me'); return UserResponse.fromJson(response.data); } Future updateMe(UserUpdateRequest request) async { final response = await _client.patch( '$_prefix/me', data: request.toJson(), ); return UserResponse.fromJson(response.data); } Future getByUsername(String username) async { final response = await _client.get('$_prefix/$username'); return UserResponse.fromJson(response.data); } } ``` **Step 2: 创建 user_response.dart** ```dart class UserResponse { final String id; final String username; final String? avatarUrl; final String? bio; const UserResponse({ required this.id, required this.username, this.avatarUrl, this.bio, }); factory UserResponse.fromJson(Map json) { return UserResponse( id: json['id'] as String, username: json['username'] as String, avatarUrl: json['avatar_url'] as String?, bio: json['bio'] as String?, ); } } class UserUpdateRequest { final String? username; final String? avatarUrl; final String? bio; const UserUpdateRequest({this.username, this.avatarUrl, this.bio}); Map toJson() { return { if (username != null) 'username': username, if (avatarUrl != null) 'avatar_url': avatarUrl, if (bio != null) 'bio': bio, }; } } ``` **Step 3: Commit** ```bash git add apps/lib/features/users/ git commit -m "feat(users): create users API and models" ``` --- ### Task 19: 更新使用 Profile 的页面 **Files:** - Modify: 所有引用 profile API 的 cubit 和 screen **Step 1: 全局搜索 profile 引用** Run: `cd apps && grep -r "profile" lib/ --include="*.dart"` **Step 2: 更新为 users API** 更新所有引用 profile 的代码改为使用新的 users API。 **Step 3: Commit** ```bash git add apps/lib/ git commit -m "refactor: migrate profile to users API" ``` --- ### Task 20: 更新 ApiClient 添加 delete 和 patch 方法 **Files:** - Modify: `apps/lib/core/api/api_client.dart` **Step 1: 添加 delete 和 patch 方法** ```dart Future> delete( String path, { dynamic data, Options? options, }) async { try { return await _dio.delete(path, data: data, options: options); } on DioException catch (e) { throw ApiException.fromDioError(e); } } Future> patch( String path, { dynamic data, Options? options, }) async { try { return await _dio.patch(path, data: data, options: options); } on DioException catch (e) { throw ApiException.fromDioError(e); } } ``` **Step 2: Commit** ```bash git add apps/lib/core/api/api_client.dart git commit -m "feat(api): add delete and patch methods" ``` --- ### Task 21: 更新前端测试 **Files:** - Modify: `apps/test/features/auth/presentation/cubits/register_cubit_test.dart` - 其他相关测试文件 **Step 1: 更新测试用例** 更新 mock 和断言以匹配新的 API 方法名和返回类型。 **Step 2: 运行测试** Run: `cd apps && flutter test` Expected: All tests pass **Step 3: Commit** ```bash git add apps/test/ git commit -m "test: update tests for RESTful API" ``` --- ## Phase 5: 文档 ### Task 22: 创建路由文档 **Files:** - Create: `docs/runtime/runtime-route.md` **Step 1: 创建路由文档** ```markdown # Runtime API Routes 本文档记录所有 HTTP API 端点。修改路由时必须同步更新此文档。 ## 格式说明 - Request/Response 使用 JSON 格式 - 错误响应使用 RFC 7807 `application/problem+json` - 所有端点前缀: `/api/v1` ## Auth ### POST /auth/verifications 创建验证码(注册发起)。 **Request:** ```json { "username": "string (3-30 chars)", "email": "string (email)", "password": "string (min 6 chars)", "redirect_to": "string? (optional)" } ``` **Response:** 202 Accepted ```json { "email": "user@example.com" } ``` **Errors:** - 422: 请求参数无效 - 429: 请求过于频繁 --- ### POST /auth/verifications/resend 重发验证码。 **Request:** ```json { "email": "string (email)" } ``` **Response:** 204 No Content **Errors:** - 422: 请求参数无效 - 429: 请求过于频繁 --- ### POST /auth/verifications/verify 验证码校验。 **Request:** ```json { "email": "string (email)", "token": "string (6 digits)" } ``` **Response:** 200 OK ```json { "access_token": "string", "refresh_token": "string", "expires_in": 3600, "token_type": "bearer", "user": { "id": "string", "email": "string" } } ``` **Errors:** - 401: 验证码无效或已过期 - 422: 请求参数无效 - 429: 请求过于频繁 --- ### POST /auth/sessions 登录(创建会话)。 **Request:** ```json { "email": "string (email)", "password": "string (min 6 chars)" } ``` **Response:** 200 OK ```json { "access_token": "string", "refresh_token": "string", "expires_in": 3600, "token_type": "bearer", "user": { "id": "string", "email": "string" } } ``` **Errors:** - 401: 邮箱或密码错误 - 422: 请求参数无效 - 429: 请求过于频繁 --- ### POST /auth/sessions/refresh 刷新 Token。 **Request:** ```json { "refresh_token": "string" } ``` **Response:** 200 OK ```json { "access_token": "string", "refresh_token": "string", "expires_in": 3600, "token_type": "bearer", "user": { "id": "string", "email": "string" } } ``` **Errors:** - 401: 无效的 refresh token - 422: 请求参数无效 --- ### DELETE /auth/sessions 登出(删除会话)。 **Request:** ```json { "refresh_token": "string" } ``` **Response:** 204 No Content **Errors:** - 422: 请求参数无效 --- ### GET /auth/users 按邮箱查询用户(需要认证)。 **Query Parameters:** - `email`: string (required) **Response:** 200 OK ```json { "id": "string", "email": "string", "created_at": "string (ISO 8601)", "email_confirmed_at": "string? (ISO 8601)" } ``` **Errors:** - 403: 无权限访问 - 404: 用户不存在 - 422: 请求参数无效 --- ## Users ### GET /users/me 获取当前用户信息(需要认证)。 **Response:** 200 OK ```json { "id": "string", "username": "string", "avatar_url": "string?", "bio": "string?" } ``` **Errors:** - 401: 未认证 --- ### PATCH /users/me 更新当前用户信息(需要认证)。 **Request:** ```json { "username": "string? (3-30 chars)", "avatar_url": "string? (URL)", "bio": "string? (max 200 chars)" } ``` **Response:** 200 OK ```json { "id": "string", "username": "string", "avatar_url": "string?", "bio": "string?" } ``` **Errors:** - 401: 未认证 - 422: 请求参数无效 --- ### GET /users/{username} 按用户名查询用户(需要认证)。 **Path Parameters:** - `username`: string (3-30 chars, alphanumeric and underscore) **Response:** 200 OK ```json { "id": "string", "username": "string", "avatar_url": "string?", "bio": "string?" } ``` **Errors:** - 401: 未认证 - 404: 用户不存在 - 422: 请求参数无效 --- ## Agent Chat ### POST /agent-chats 运行 Agent 对话(需要认证)。 **Request:** ```json { "message": "string (1-8000 chars)", "session_id": "string? (UUID)" } ``` **Response:** 200 OK ```json { "session_id": "string (UUID)", "output": "string", "events": [ { "type": "string", "run_id": "string?", "message_id": "string?", "delta": "string?", "tool_name": "string?", "result": "string?", "output": "string?", "error": "string?" } ] } ``` **Errors:** - 401: 未认证 - 422: 请求参数无效 --- ## Infra ### GET /infra/health 检查基础设施健康状态。 **Response:** 200 OK ```json { "status": "healthy" | "unhealthy", "services": { "redis": { "status": "healthy" | "unhealthy", "latency_ms": 0 } } } ``` --- ### GET /health 检查服务健康状态。 **Response:** 200 OK ```json { "status": "ok" } ``` --- ## Error Response Format (RFC 7807) 所有错误响应使用 `application/problem+json` 格式: ```json { "type": "about:blank", "title": "Unauthorized", "status": 401, "detail": "验证码无效或已过期", "instance": "/api/v1/auth/verifications/verify" } ``` 前端应优先读取 `detail` 字段显示给用户。 ``` **Step 2: Commit** ```bash git add docs/runtime/runtime-route.md git commit -m "docs: add runtime route documentation" ``` --- ### Task 23: 更新根目录 AGENTS.md **Files:** - Modify: `AGENTS.md` **Step 1: 添加路由同步规则** 在文件末尾添加: ```markdown ## API Route Documentation When modifying HTTP routes (adding, updating, or removing endpoints): - Sync changes to `docs/runtime/runtime-route.md` - Include: HTTP method, path, request/response schema, status codes, error format - Keep documentation in sync with actual implementation ``` **Step 2: Commit** ```bash git add AGENTS.md git commit -m "docs: add route sync rule to AGENTS.md" ``` --- ## Phase 6: 验收 ### Task 24: 端到端验证 **Step 1: 启动后端服务** Run: `docker compose --env-file .env -f infra/docker/docker-compose.yml up -d` **Step 2: 运行后端测试** Run: `cd backend && uv run pytest -v` Expected: All tests pass **Step 3: 运行前端测试** Run: `cd apps && flutter test` Expected: All tests pass **Step 4: 手动验证注册/登录流程** 使用 Flutter app 或 curl 测试: 1. POST /api/v1/auth/verifications - 注册 2. POST /api/v1/auth/verifications/verify - 验证 3. POST /api/v1/auth/sessions - 登录 4. GET /api/v1/users/me - 获取用户信息 5. DELETE /api/v1/auth/sessions - 登出 --- ## Summary | Phase | Tasks | Description | |-------|-------|-------------| | Phase 1 | 1-3 | 后端 Schema 重构 | | Phase 2 | 4-9 | 后端路由重构 | | Phase 3 | 10-12 | 后端测试更新 | | Phase 4 | 13-21 | 前端适配 | | Phase 5 | 22-23 | 文档 | | Phase 6 | 24 | 验收 |