package server import ( "encoding/json" "net/http" "path/filepath" "strings" "time" "chat-agent-system/internal/swboot" ) // handleProjectTypesCatalog GET /api/v1/project-types/catalog func (s *Server) handleProjectTypesCatalog(w http.ResponseWriter, r *http.Request) { if _, ok := s.requirePrincipal(w, r); !ok { return } writeJSONResponse(w, http.StatusOK, map[string]any{ "project_types": swboot.ProjectTypesCatalog(), }) } // handleComplianceProfilesCatalog GET /api/v1/compliance-profiles/catalog func (s *Server) handleComplianceProfilesCatalog(w http.ResponseWriter, r *http.Request) { if _, ok := s.requirePrincipal(w, r); !ok { return } writeJSONResponse(w, http.StatusOK, map[string]any{ "compliance_profiles": swboot.ComplianceProfilesCatalog(), }) } // handleProjectCreationPreview POST /api/v1/projects/creation-preview func (s *Server) handleProjectCreationPreview(w http.ResponseWriter, r *http.Request) { user, err := s.authenticateUser(r) if err != nil || user == nil { writeSafeError(w, r, http.StatusUnauthorized, `{"error":"ERR_UNAUTHENTICATED","message":"请先登录"}`) return } if ok, permErr := s.userHasSystemPermission(r.Context(), user, "project:create"); permErr != nil { writeDomainError(w, r, http.StatusInternalServerError, permErr) return } else if !ok { writeJSONResponse(w, http.StatusForbidden, map[string]string{ "error_code": "ERR_FORBIDDEN", "message": "无权创建项目", }) return } var req swboot.CreationPreviewInput if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeSafeError(w, r, http.StatusBadRequest, `{"error":"ERR_INVALID_PARAM","message":"无效的 JSON 请求体"}`) return } // SWBOOT-10: controlled_patch is only preview-valid with an admin-allowlisted // repo binding; fail-closed when the allowlist is not configured. if strings.TrimSpace(req.ExecutionMode) == swboot.ExecutionControlledPatch && strings.TrimSpace(req.RepoPath) != "" { if exec, err := s.swbootExec(); err == nil { if abs, absErr := filepath.Abs(strings.TrimSpace(req.RepoPath)); absErr == nil { req.RepoPath = abs req.RepoAllowlisted = exec.Allowlist.IsAllowlisted(abs) } } } res := swboot.BuildCreationPreview(req, time.Now().UTC()) status := http.StatusOK if !res.Valid { status = http.StatusBadRequest } writeJSONResponse(w, status, res) }