diff --git a/src/api/blackboard_routes.py b/src/api/blackboard_routes.py index 2c512f9..0974dc0 100644 --- a/src/api/blackboard_routes.py +++ b/src/api/blackboard_routes.py @@ -12,17 +12,41 @@ from src.blackboard.operations import Blackboard from src.blackboard.models import Task, Review from src.blackboard.queries import Queries from src.blackboard.db import VALID_STATUSES, VALID_TRANSITIONS, COMMENT_TYPES, OUTPUT_TYPES +from src.blackboard.registry import ProjectRegistry from src.utils import get_data_root router = APIRouter(prefix="/api/projects/{project_id}", tags=["blackboard"]) +# 虚拟项目白名单(不需要在 registry 注册) +_VIRTUAL_PROJECTS = frozenset({"_general", "_mail"}) + + +def _validate_project(project_id: str) -> str: + """校验 project_id,已知项目/虚拟项目放行,未知项目返回 400""" + if project_id in _VIRTUAL_PROJECTS: + return project_id + reg = ProjectRegistry(get_data_root()) + if reg.get_project(project_id): + return project_id + raise HTTPException(400, { + "ok": False, + "error": "project_not_found", + "detail": f"Project '{project_id}' is not registered.", + "suggestions": [ + f"Register first: POST /api/projects with id='{project_id}'", + "Or use '_general' for tasks without a specific project", + ], + }) + def _bb(project_id: str) -> Blackboard: + _validate_project(project_id) return Blackboard(get_data_root() / project_id / "blackboard.db") def _q(project_id: str) -> Queries: + _validate_project(project_id) return Queries(get_data_root() / project_id / "blackboard.db")