package handlers import ( "context" "net/http" "github.com/go-chi/chi/v5" "github.com/orchard9/rdev/internal/auth" "github.com/orchard9/rdev/internal/domain" "github.com/orchard9/rdev/internal/service" "github.com/orchard9/rdev/pkg/api" ) // SDLCGenerateHandler handles async SDLC artifact generation endpoints. type SDLCGenerateHandler struct { generateSvc *service.SDLCGenerateService } // NewSDLCGenerateHandler creates a new SDLC generate handler. func NewSDLCGenerateHandler(generateSvc *service.SDLCGenerateService) *SDLCGenerateHandler { return &SDLCGenerateHandler{ generateSvc: generateSvc, } } // Mount registers the generate endpoint on the router. func (h *SDLCGenerateHandler) Mount(r api.Router) { r.Route("/projects/{id}/sdlc/features/{slug}", func(r chi.Router) { r.With(auth.RequireScope(auth.ScopeProjectsExecute, auth.ScopeAdmin)).Post("/generate", h.Generate) }) } // GenerateRequest is the request body for POST /projects/{id}/sdlc/features/{slug}/generate. type GenerateRequest struct { // ArtifactType is the type of artifact to generate: spec, design, tasks, code, qa ArtifactType string `json:"artifact_type"` // TaskID is the specific task to implement (required for artifact_type: "code") TaskID string `json:"task_id,omitempty"` // Provider specifies which code agent to use (optional) Provider string `json:"provider,omitempty"` } // Generate handles POST /projects/{id}/sdlc/features/{slug}/generate. // It enqueues an async task to generate an SDLC artifact. func (h *SDLCGenerateHandler) Generate(w http.ResponseWriter, r *http.Request) { projectID := chi.URLParam(r, "id") featureSlug := chi.URLParam(r, "slug") var req GenerateRequest if err := api.DecodeJSON(r, &req); err != nil { api.WriteBadRequest(w, r, "invalid request body") return } // Validate artifact_type if req.ArtifactType == "" { api.WriteBadRequest(w, r, "artifact_type is required") return } if !domain.IsValidGenerateArtifactType(req.ArtifactType) { api.WriteBadRequest(w, r, "invalid artifact_type: must be one of spec, design, tasks, code, qa") return } // Validate task_id is provided for code generation if req.ArtifactType == "code" && req.TaskID == "" { api.WriteBadRequest(w, r, "task_id is required for artifact_type: code") return } ctx, cancel := context.WithTimeout(r.Context(), TimeoutStandard) defer cancel() result, err := h.generateSvc.GenerateArtifact(ctx, projectID, featureSlug, &domain.SDLCGenerateRequest{ ArtifactType: req.ArtifactType, TaskID: req.TaskID, Provider: req.Provider, }) if err != nil { writeSDLCError(w, r, err) return } api.WriteJSON(w, r, http.StatusAccepted, result) }