Major changes: - Add internal/logging package with field constants, context propagation, sensitive data auto-redaction, and per-component log levels - Add worker timeout constants (TimeoutQuickOp, TimeoutHealthCheck, etc.) - Extend SDLC with callback handlers, generate endpoints, and executor - Add new cookbook trees for aeries and slackpath progression - Add skeleton templates for queue, realtime, and microservices - Add worker component template with async job processing - Refactor services and handlers to use new logging infrastructure - Split component.go into component_infra.go and component_listing.go Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
83 lines
2.3 KiB
Go
83 lines
2.3 KiB
Go
package handlers
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/orchard9/rdev/internal/domain"
|
|
"github.com/orchard9/rdev/internal/logging"
|
|
"github.com/orchard9/rdev/internal/service"
|
|
"github.com/orchard9/rdev/pkg/api"
|
|
)
|
|
|
|
// SDLCCallbackHandler handles internal SDLC callback endpoints.
|
|
type SDLCCallbackHandler struct {
|
|
callbackSvc *service.SDLCCallbackService
|
|
internalToken string
|
|
}
|
|
|
|
// NewSDLCCallbackHandler creates a new SDLC callback handler.
|
|
func NewSDLCCallbackHandler(callbackSvc *service.SDLCCallbackService, internalToken string) *SDLCCallbackHandler {
|
|
return &SDLCCallbackHandler{
|
|
callbackSvc: callbackSvc,
|
|
internalToken: internalToken,
|
|
}
|
|
}
|
|
|
|
// Mount registers the internal callback endpoint on the router.
|
|
func (h *SDLCCallbackHandler) Mount(r api.Router) {
|
|
r.Route("/internal/sdlc", func(r chi.Router) {
|
|
r.Post("/callback", h.Callback)
|
|
})
|
|
}
|
|
|
|
// Callback handles POST /internal/sdlc/callback.
|
|
// This is called by the work queue when a build task completes.
|
|
// The endpoint is protected by an internal token to prevent external access.
|
|
func (h *SDLCCallbackHandler) Callback(w http.ResponseWriter, r *http.Request) {
|
|
// Verify internal token
|
|
token := r.Header.Get("X-Internal-Token")
|
|
if h.internalToken != "" && token != h.internalToken {
|
|
api.WriteUnauthorized(w, r, "invalid internal token")
|
|
return
|
|
}
|
|
|
|
var payload domain.SDLCCallbackPayload
|
|
if err := api.DecodeJSON(r, &payload); err != nil {
|
|
api.WriteBadRequest(w, r, "invalid request body")
|
|
return
|
|
}
|
|
|
|
// Validate required fields
|
|
if payload.ProjectID == "" {
|
|
api.WriteBadRequest(w, r, "project_id is required")
|
|
return
|
|
}
|
|
if payload.Feature == "" {
|
|
api.WriteBadRequest(w, r, "feature is required")
|
|
return
|
|
}
|
|
if payload.ArtifactType == "" {
|
|
api.WriteBadRequest(w, r, "artifact_type is required")
|
|
return
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(r.Context(), TimeoutStandard)
|
|
defer cancel()
|
|
|
|
if err := h.callbackSvc.HandleCallback(ctx, &payload); err != nil {
|
|
log := logging.FromContext(ctx).WithHandler("Callback")
|
|
log.Error("SDLC callback handling failed",
|
|
logging.FieldError, err.Error(),
|
|
"task_id", payload.TaskID,
|
|
logging.FieldProjectID, payload.ProjectID,
|
|
"feature", payload.Feature,
|
|
)
|
|
api.WriteInternalError(w, r, "callback handling failed")
|
|
return
|
|
}
|
|
|
|
api.WriteJSON(w, r, http.StatusOK, map[string]bool{"ok": true})
|
|
}
|