diff --git a/workspace-server/internal/handlers/activity.go b/workspace-server/internal/handlers/activity.go index 6eabf44a..8ff6e984 100644 --- a/workspace-server/internal/handlers/activity.go +++ b/workspace-server/internal/handlers/activity.go @@ -303,7 +303,7 @@ func (h *ActivityHandler) Report(c *gin.Context) { Metadata interface{} `json:"metadata"` } if err := c.ShouldBindJSON(&body); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } diff --git a/workspace-server/internal/handlers/agent.go b/workspace-server/internal/handlers/agent.go index 7af21866..9daa0927 100644 --- a/workspace-server/internal/handlers/agent.go +++ b/workspace-server/internal/handlers/agent.go @@ -27,7 +27,7 @@ func (h *AgentHandler) Assign(c *gin.Context) { Model string `json:"model" binding:"required"` } if err := c.ShouldBindJSON(&body); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } @@ -86,7 +86,7 @@ func (h *AgentHandler) Replace(c *gin.Context) { Model string `json:"model" binding:"required"` } if err := c.ShouldBindJSON(&body); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } @@ -165,7 +165,7 @@ func (h *AgentHandler) Move(c *gin.Context) { TargetWorkspaceID string `json:"target_workspace_id" binding:"required"` } if err := c.ShouldBindJSON(&body); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } diff --git a/workspace-server/internal/handlers/approvals.go b/workspace-server/internal/handlers/approvals.go index a343b8a1..4b394c7e 100644 --- a/workspace-server/internal/handlers/approvals.go +++ b/workspace-server/internal/handlers/approvals.go @@ -30,7 +30,7 @@ func (h *ApprovalsHandler) Create(c *gin.Context) { Context map[string]interface{} `json:"context"` } if err := c.ShouldBindJSON(&body); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } @@ -170,7 +170,7 @@ func (h *ApprovalsHandler) Decide(c *gin.Context) { DecidedBy string `json:"decided_by"` } if err := c.ShouldBindJSON(&body); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } diff --git a/workspace-server/internal/handlers/artifacts.go b/workspace-server/internal/handlers/artifacts.go index 2dec903f..12463c7a 100644 --- a/workspace-server/internal/handlers/artifacts.go +++ b/workspace-server/internal/handlers/artifacts.go @@ -141,7 +141,7 @@ func (h *ArtifactsHandler) Create(c *gin.Context) { var req createArtifactsRepoRequest if err := c.ShouldBindJSON(&req); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } @@ -302,7 +302,7 @@ func (h *ArtifactsHandler) Fork(c *gin.Context) { var req forkArtifactsRepoRequest if err := c.ShouldBindJSON(&req); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } @@ -367,7 +367,7 @@ func (h *ArtifactsHandler) Token(c *gin.Context) { var req artifactsTokenRequest if err := c.ShouldBindJSON(&req); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } diff --git a/workspace-server/internal/handlers/budget.go b/workspace-server/internal/handlers/budget.go index 0af2ee8e..1430ace0 100644 --- a/workspace-server/internal/handlers/budget.go +++ b/workspace-server/internal/handlers/budget.go @@ -90,7 +90,7 @@ func (h *BudgetHandler) PatchBudget(c *gin.Context) { // so we unmarshal into a raw map first. var raw map[string]interface{} if err := c.ShouldBindJSON(&raw); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } diff --git a/workspace-server/internal/handlers/bundle.go b/workspace-server/internal/handlers/bundle.go index 079dbb79..0c080398 100644 --- a/workspace-server/internal/handlers/bundle.go +++ b/workspace-server/internal/handlers/bundle.go @@ -35,7 +35,7 @@ func (h *BundleHandler) Export(c *gin.Context) { b, err := bundle.Export(ctx, workspaceID, h.configsDir, h.docker) if err != nil { - c.JSON(http.StatusNotFound, gin.H{"error": err.Error()}) + c.JSON(http.StatusNotFound, gin.H{"error": "bundle not found"}) return } @@ -46,7 +46,7 @@ func (h *BundleHandler) Export(c *gin.Context) { func (h *BundleHandler) Import(c *gin.Context) { var b bundle.Bundle if err := c.ShouldBindJSON(&b); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid bundle"}) return } diff --git a/workspace-server/internal/handlers/channels.go b/workspace-server/internal/handlers/channels.go index df9a3815..e27a93be 100644 --- a/workspace-server/internal/handlers/channels.go +++ b/workspace-server/internal/handlers/channels.go @@ -136,7 +136,7 @@ func (h *ChannelHandler) Create(c *gin.Context) { } if err := adapter.ValidateConfig(body.Config); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": "invalid config: " + err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid channel config"}) return } @@ -294,7 +294,8 @@ func (h *ChannelHandler) Send(c *gin.Context) { } if err := h.manager.SendOutbound(ctx, channelID, body.Text); err != nil { - c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + log.Printf("Channels: send outbound failed for channel %s: %v", channelID, err) + c.JSON(http.StatusInternalServerError, gin.H{"error": "send failed"}) return } @@ -307,7 +308,8 @@ func (h *ChannelHandler) Test(c *gin.Context) { ctx := c.Request.Context() if err := h.manager.SendOutbound(ctx, channelID, "🔔 Molecule AI channel test — connection successful!"); err != nil { - c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + log.Printf("Channels: test message failed for channel %s: %v", channelID, err) + c.JSON(http.StatusInternalServerError, gin.H{"error": "test message failed"}) return } @@ -436,7 +438,7 @@ func (h *ChannelHandler) Webhook(c *gin.Context) { // Parse the webhook first to get the chat_id msg, err := adapter.ParseWebhook(c, nil) if err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": "parse error: " + err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "webhook parse failed"}) return } if msg == nil { diff --git a/workspace-server/internal/handlers/checkpoints.go b/workspace-server/internal/handlers/checkpoints.go index 96fdb1b9..0c07b7d8 100644 --- a/workspace-server/internal/handlers/checkpoints.go +++ b/workspace-server/internal/handlers/checkpoints.go @@ -71,7 +71,7 @@ func (h *CheckpointsHandler) Upsert(c *gin.Context) { Payload json.RawMessage `json:"payload"` } if err := c.ShouldBindJSON(&body); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } diff --git a/workspace-server/internal/handlers/delegation.go b/workspace-server/internal/handlers/delegation.go index 9ca07107..8c0d681f 100644 --- a/workspace-server/internal/handlers/delegation.go +++ b/workspace-server/internal/handlers/delegation.go @@ -114,7 +114,7 @@ func (h *DelegationHandler) Delegate(c *gin.Context) { // the 400 response and returns the error so the caller can return. func bindDelegateRequest(c *gin.Context, body *delegateRequest) error { if err := c.ShouldBindJSON(body); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid delegation request"}) return err } if _, err := uuid.Parse(body.TargetID); err != nil { @@ -344,7 +344,7 @@ func (h *DelegationHandler) Record(c *gin.Context) { DelegationID string `json:"delegation_id" binding:"required"` } if err := c.ShouldBindJSON(&body); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } if _, err := uuid.Parse(body.TargetID); err != nil { @@ -392,7 +392,7 @@ func (h *DelegationHandler) UpdateStatus(c *gin.Context) { ResponsePreview string `json:"response_preview,omitempty"` } if err := c.ShouldBindJSON(&body); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } if body.Status != "completed" && body.Status != "failed" { diff --git a/workspace-server/internal/handlers/discovery.go b/workspace-server/internal/handlers/discovery.go index fb90f6a5..6d8c82aa 100644 --- a/workspace-server/internal/handlers/discovery.go +++ b/workspace-server/internal/handlers/discovery.go @@ -302,7 +302,7 @@ func (h *DiscoveryHandler) CheckAccess(c *gin.Context) { TargetID string `json:"target_id" binding:"required"` } if err := c.ShouldBindJSON(&payload); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } diff --git a/workspace-server/internal/handlers/memories.go b/workspace-server/internal/handlers/memories.go index 824e40e5..3efff1dc 100644 --- a/workspace-server/internal/handlers/memories.go +++ b/workspace-server/internal/handlers/memories.go @@ -145,7 +145,7 @@ func (h *MemoriesHandler) Commit(c *gin.Context) { Namespace string `json:"namespace,omitempty"` // optional; defaults to "general" } if err := c.ShouldBindJSON(&body); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } diff --git a/workspace-server/internal/handlers/memory.go b/workspace-server/internal/handlers/memory.go index 3b5b2227..8f945a26 100644 --- a/workspace-server/internal/handlers/memory.go +++ b/workspace-server/internal/handlers/memory.go @@ -116,7 +116,7 @@ func (h *MemoryHandler) Set(c *gin.Context) { IfMatchVersion *int64 `json:"if_match_version"` } if err := c.ShouldBindJSON(&body); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } diff --git a/workspace-server/internal/handlers/org.go b/workspace-server/internal/handlers/org.go index 45fccfad..cd59a142 100644 --- a/workspace-server/internal/handlers/org.go +++ b/workspace-server/internal/handlers/org.go @@ -250,7 +250,7 @@ func (h *OrgHandler) Import(c *gin.Context) { Template OrgTemplate `json:"template"` // or inline template } if err := c.ShouldBindJSON(&body); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } @@ -264,7 +264,7 @@ func (h *OrgHandler) Import(c *gin.Context) { // letting an unauthenticated caller probe arbitrary filesystem paths. resolved, err := resolveInsideRoot(h.orgDir, body.Dir) if err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("invalid dir: %v", err)}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid org directory"}) return } orgBaseDir = resolved @@ -279,11 +279,11 @@ func (h *OrgHandler) Import(c *gin.Context) { // refactor. Fails loudly on missing / cyclic / escaping includes. expanded, err := resolveYAMLIncludes(data, orgBaseDir) if err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("!include expansion failed: %v", err)}) + c.JSON(http.StatusBadRequest, gin.H{"error": "org template expansion failed"}) return } if err := yaml.Unmarshal(expanded, &tmpl); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("invalid YAML: %v", err)}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid org template"}) return } } else if body.Template.Name != "" { diff --git a/workspace-server/internal/handlers/org_plugin_allowlist.go b/workspace-server/internal/handlers/org_plugin_allowlist.go index ff58d6ac..5309c837 100644 --- a/workspace-server/internal/handlers/org_plugin_allowlist.go +++ b/workspace-server/internal/handlers/org_plugin_allowlist.go @@ -237,7 +237,7 @@ func (h *OrgPluginAllowlistHandler) PutAllowlist(c *gin.Context) { var req putAllowlistRequest if err := c.ShouldBindJSON(&req); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } if req.EnabledBy == "" { diff --git a/workspace-server/internal/handlers/plugins_install.go b/workspace-server/internal/handlers/plugins_install.go index b75d6ef6..23ee1913 100644 --- a/workspace-server/internal/handlers/plugins_install.go +++ b/workspace-server/internal/handlers/plugins_install.go @@ -45,7 +45,7 @@ func (h *PluginsHandler) Install(c *gin.Context) { var req installRequest if err := c.ShouldBindJSON(&req); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } @@ -56,11 +56,9 @@ func (h *PluginsHandler) Install(c *gin.Context) { c.JSON(he.Status, he.Body) return } - c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + c.JSON(http.StatusInternalServerError, gin.H{"error": "plugin install failed"}) return } - // On success, we own stagedDir cleanup. On error, resolveAndStage - // has already cleaned it up (and its returned result is nil). defer os.RemoveAll(result.StagedDir) // Org plugin allowlist gate (#591). @@ -77,7 +75,7 @@ func (h *PluginsHandler) Install(c *gin.Context) { c.JSON(he.Status, he.Body) return } - c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + c.JSON(http.StatusInternalServerError, gin.H{"error": "plugin deliver failed"}) return } @@ -96,7 +94,7 @@ func (h *PluginsHandler) Uninstall(c *gin.Context) { ctx := c.Request.Context() if err := validatePluginName(pluginName); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid plugin name"}) return } @@ -179,7 +177,7 @@ func (h *PluginsHandler) Download(c *gin.Context) { ctx := c.Request.Context() if err := validatePluginName(pluginName); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid plugin name"}) return } @@ -223,7 +221,7 @@ func (h *PluginsHandler) Download(c *gin.Context) { c.JSON(he.Status, he.Body) return } - c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + c.JSON(http.StatusInternalServerError, gin.H{"error": "plugin download failed"}) return } defer os.RemoveAll(result.StagedDir) diff --git a/workspace-server/internal/handlers/registry.go b/workspace-server/internal/handlers/registry.go index 6289ea42..38772529 100644 --- a/workspace-server/internal/handlers/registry.go +++ b/workspace-server/internal/handlers/registry.go @@ -126,13 +126,13 @@ func validateAgentURL(rawURL string) error { func (h *RegistryHandler) Register(c *gin.Context) { var payload models.RegisterPayload if err := c.ShouldBindJSON(&payload); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } // C6: reject SSRF-capable URLs before persisting or caching them. if err := validateAgentURL(payload.URL); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } @@ -251,7 +251,7 @@ func (h *RegistryHandler) Register(c *gin.Context) { func (h *RegistryHandler) Heartbeat(c *gin.Context) { var payload models.HeartbeatPayload if err := c.ShouldBindJSON(&payload); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } @@ -390,7 +390,7 @@ func (h *RegistryHandler) evaluateStatus(c *gin.Context, payload models.Heartbea func (h *RegistryHandler) UpdateCard(c *gin.Context) { var payload models.UpdateCardPayload if err := c.ShouldBindJSON(&payload); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } diff --git a/workspace-server/internal/handlers/schedules.go b/workspace-server/internal/handlers/schedules.go index 555a5898..3139a217 100644 --- a/workspace-server/internal/handlers/schedules.go +++ b/workspace-server/internal/handlers/schedules.go @@ -114,7 +114,7 @@ func (h *ScheduleHandler) Create(c *gin.Context) { // Validate and compute next run nextRun, err := scheduler.ComputeNextRun(body.CronExpr, body.Timezone, time.Now()) if err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } @@ -198,7 +198,7 @@ func (h *ScheduleHandler) Update(c *gin.Context) { } nextRun, err := scheduler.ComputeNextRun(cronExpr, tz, time.Now()) if err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } nextRunAt = &nextRun diff --git a/workspace-server/internal/handlers/secrets.go b/workspace-server/internal/handlers/secrets.go index dd7abe05..261222d9 100644 --- a/workspace-server/internal/handlers/secrets.go +++ b/workspace-server/internal/handlers/secrets.go @@ -222,7 +222,7 @@ func (h *SecretsHandler) Set(c *gin.Context) { Value string `json:"value" binding:"required"` } if err := c.ShouldBindJSON(&body); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } @@ -335,7 +335,7 @@ func (h *SecretsHandler) SetGlobal(c *gin.Context) { Value string `json:"value" binding:"required"` } if err := c.ShouldBindJSON(&body); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } diff --git a/workspace-server/internal/handlers/template_import.go b/workspace-server/internal/handlers/template_import.go index f942900d..d3a8557a 100644 --- a/workspace-server/internal/handlers/template_import.go +++ b/workspace-server/internal/handlers/template_import.go @@ -122,7 +122,7 @@ func (h *TemplatesHandler) Import(c *gin.Context) { Files map[string]string `json:"files" binding:"required"` } if err := c.ShouldBindJSON(&body); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } @@ -140,7 +140,7 @@ func (h *TemplatesHandler) Import(c *gin.Context) { } if err := writeFiles(destDir, body.Files); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } @@ -164,7 +164,7 @@ func (h *TemplatesHandler) ReplaceFiles(c *gin.Context) { Files map[string]string `json:"files" binding:"required"` } if err := c.ShouldBindJSON(&body); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } @@ -183,7 +183,7 @@ func (h *TemplatesHandler) ReplaceFiles(c *gin.Context) { // Validate all paths first for relPath := range body.Files { if err := validateRelPath(relPath); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } } @@ -227,7 +227,7 @@ func (h *TemplatesHandler) ReplaceFiles(c *gin.Context) { } os.MkdirAll(destDir, 0o755) if err := writeFiles(destDir, body.Files); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } c.JSON(http.StatusOK, gin.H{"status": "replaced", "workspace": workspaceID, "files": len(body.Files), "source": "template"}) diff --git a/workspace-server/internal/handlers/templates.go b/workspace-server/internal/handlers/templates.go index ce353aab..f0fd69d7 100644 --- a/workspace-server/internal/handlers/templates.go +++ b/workspace-server/internal/handlers/templates.go @@ -134,7 +134,7 @@ func (h *TemplatesHandler) ListFiles(c *gin.Context) { subPath := c.DefaultQuery("path", "") if subPath != "" { if err := validateRelPath(subPath); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid path"}) return } } @@ -258,7 +258,7 @@ func (h *TemplatesHandler) ReadFile(c *gin.Context) { } if err := validateRelPath(filePath); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid path"}) return } @@ -318,7 +318,7 @@ func (h *TemplatesHandler) WriteFile(c *gin.Context) { } if err := validateRelPath(filePath); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid path"}) return } @@ -326,7 +326,7 @@ func (h *TemplatesHandler) WriteFile(c *gin.Context) { Content string `json:"content"` } if err := c.ShouldBindJSON(&body); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } @@ -367,7 +367,7 @@ func (h *TemplatesHandler) DeleteFile(c *gin.Context) { } if err := validateRelPath(filePath); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid path"}) return } diff --git a/workspace-server/internal/handlers/viewport.go b/workspace-server/internal/handlers/viewport.go index 549ea058..6bbba394 100644 --- a/workspace-server/internal/handlers/viewport.go +++ b/workspace-server/internal/handlers/viewport.go @@ -39,7 +39,7 @@ func (h *ViewportHandler) Save(c *gin.Context) { Zoom float64 `json:"zoom"` } if err := c.ShouldBindJSON(&body); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid viewport data"}) return } diff --git a/workspace-server/internal/handlers/workspace.go b/workspace-server/internal/handlers/workspace.go index 2265f2ff..2a2005cd 100644 --- a/workspace-server/internal/handlers/workspace.go +++ b/workspace-server/internal/handlers/workspace.go @@ -76,14 +76,14 @@ func (h *WorkspaceHandler) TokenRegistry() *provisionhook.Registry { func (h *WorkspaceHandler) Create(c *gin.Context) { var payload models.CreateWorkspacePayload if err := c.ShouldBindJSON(&payload); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid workspace payload"}) return } // #685/#688: validate field lengths and reject injection characters before // any DB or provisioner interaction. if err := validateWorkspaceFields(payload.Name, payload.Role, payload.Model, payload.Runtime); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid workspace fields"}) return } @@ -133,7 +133,7 @@ func (h *WorkspaceHandler) Create(c *gin.Context) { var workspaceDir interface{} if payload.WorkspaceDir != "" { if err := validateWorkspaceDir(payload.WorkspaceDir); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid workspace directory"}) return } workspaceDir = payload.WorkspaceDir @@ -145,7 +145,7 @@ func (h *WorkspaceHandler) Create(c *gin.Context) { workspaceAccess = provisioner.WorkspaceAccessNone } if err := provisioner.ValidateWorkspaceAccess(workspaceAccess, payload.WorkspaceDir); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid workspace access"}) return } @@ -411,7 +411,7 @@ func (h *WorkspaceHandler) Get(c *gin.Context) { // #687: reject non-UUID IDs before hitting the DB. if err := validateWorkspaceID(id); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid workspace ID"}) return } @@ -569,13 +569,13 @@ func (h *WorkspaceHandler) Update(c *gin.Context) { // #687: reject non-UUID IDs before hitting the DB. if err := validateWorkspaceID(id); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid workspace ID"}) return } var body map[string]interface{} if err := c.ShouldBindJSON(&body); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) return } @@ -591,7 +591,7 @@ func (h *WorkspaceHandler) Update(c *gin.Context) { if err := validateWorkspaceFields( strField("name"), strField("role"), "" /*model not patchable*/, strField("runtime"), ); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid workspace fields"}) return } @@ -644,7 +644,7 @@ func (h *WorkspaceHandler) Update(c *gin.Context) { if wsDir != nil { if dirStr, isStr := wsDir.(string); isStr && dirStr != "" { if err := validateWorkspaceDir(dirStr); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid workspace directory"}) return } } @@ -707,7 +707,7 @@ func (h *WorkspaceHandler) Delete(c *gin.Context) { // #687: reject non-UUID IDs before hitting the DB. if err := validateWorkspaceID(id); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid workspace ID"}) return } @@ -864,7 +864,7 @@ func (h *WorkspaceHandler) Delete(c *gin.Context) { // Hard delete the workspace row if _, err := db.DB.ExecContext(ctx, "DELETE FROM workspaces WHERE id = ANY($1::uuid[])", purgeIDs); err != nil { log.Printf("Purge workspace row error for %v: %v", allIDs, err) - c.JSON(http.StatusInternalServerError, gin.H{"error": "purge failed: " + err.Error()}) + c.JSON(http.StatusInternalServerError, gin.H{"error": "purge failed"}) return } c.JSON(http.StatusOK, gin.H{"status": "purged", "cascade_deleted": len(descendantIDs)})