Files
Agent-System/internal/server/software_project_handlers.go
T
weichen 83561682eb feat(swboot): wire SWBOOT-10 controlled patch executor (fail-closed)
DB-backed repo_path_allowlist reader (deny-all until admin seeds), per-prefix
admin test_commands (goose 00075), execution evidence table (goose 00074),
isolated git-worktree patch executor with command allowlist/time/output caps
and failure-stops evidence; controlled_patch creation/preview unlocked only
with an allowlisted repo binding (projectworkflow gate + catalog flag);
creator-only server endpoints for bindings/executions; merge/push/deploy stay
behind a typed separate-authorization boundary. Module boundary: app->swboot
composition import registered.
2026-09-26 00:56:59 +00:00

73 lines
2.4 KiB
Go

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 {
writeSafeError(w, r, http.StatusInternalServerError, `{"error":"ERR_INTERNAL","message":"`+permErr.Error()+`"}`)
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)
}