diff --git a/workspace-server/internal/handlers/container_files.go b/workspace-server/internal/handlers/container_files.go index 290bd5f74..91104a9e3 100644 --- a/workspace-server/internal/handlers/container_files.go +++ b/workspace-server/internal/handlers/container_files.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "io" + "log" "path/filepath" "strings" @@ -31,7 +32,9 @@ func (h *TemplatesHandler) findContainer(ctx context.Context, workspaceID string } // Also check by workspace name from DB var wsName string - db.DB.QueryRowContext(ctx, `SELECT LOWER(REPLACE(name, ' ', '-')) FROM workspaces WHERE id = $1`, workspaceID).Scan(&wsName) + if err := db.DB.QueryRowContext(ctx, `SELECT LOWER(REPLACE(name, ' ', '-')) FROM workspaces WHERE id = $1`, workspaceID).Scan(&wsName); err != nil { + log.Printf("List: workspace name lookup for %s: %v", workspaceID, err) + } if wsName != "" { candidates = append(candidates, wsName) } diff --git a/workspace-server/internal/handlers/memories.go b/workspace-server/internal/handlers/memories.go index 137bab907..c58db6777 100644 --- a/workspace-server/internal/handlers/memories.go +++ b/workspace-server/internal/handlers/memories.go @@ -166,7 +166,11 @@ func (h *MemoriesHandler) Commit(c *gin.Context) { // GLOBAL scope: only root workspaces (no parent) can write if body.Scope == "GLOBAL" { var parentID *string - db.DB.QueryRowContext(ctx, `SELECT parent_id FROM workspaces WHERE id = $1`, workspaceID).Scan(&parentID) + if err := db.DB.QueryRowContext(ctx, `SELECT parent_id FROM workspaces WHERE id = $1`, workspaceID).Scan(&parentID); err != nil { + log.Printf("Commit: parent lookup for workspace %s: %v", workspaceID, err) + c.JSON(http.StatusInternalServerError, gin.H{"error": "workspace lookup failed"}) + return + } if parentID != nil { c.JSON(http.StatusForbidden, gin.H{"error": "only root workspaces can write GLOBAL memories"}) return @@ -278,7 +282,11 @@ func (h *MemoriesHandler) Search(c *gin.Context) { // Get workspace info for access control var parentID *string - db.DB.QueryRowContext(ctx, `SELECT parent_id FROM workspaces WHERE id = $1`, workspaceID).Scan(&parentID) + if err := db.DB.QueryRowContext(ctx, `SELECT parent_id FROM workspaces WHERE id = $1`, workspaceID).Scan(&parentID); err != nil { + // Non-critical: fall back to self-only team filter + log.Printf("Search: parent lookup for workspace %s: %v", workspaceID, err) + parentID = nil + } // Try to generate a query embedding for semantic search. // Falls back to the existing FTS/ILIKE path on failure or when no diff --git a/workspace-server/internal/handlers/tokens.go b/workspace-server/internal/handlers/tokens.go index c41f8c518..e5425a97d 100644 --- a/workspace-server/internal/handlers/tokens.go +++ b/workspace-server/internal/handlers/tokens.go @@ -88,9 +88,12 @@ func (h *TokenHandler) Create(c *gin.Context) { // Rate limit: max active tokens per workspace var count int - db.DB.QueryRowContext(c.Request.Context(), + if err := db.DB.QueryRowContext(c.Request.Context(), `SELECT COUNT(*) FROM workspace_auth_tokens WHERE workspace_id = $1 AND revoked_at IS NULL`, - workspaceID).Scan(&count) + workspaceID).Scan(&count); err != nil { + log.Printf("tokens: rate-limit count lookup for %s: %v", workspaceID, err) + count = 0 // fail open — a DB error should not block token creation + } if count >= maxTokensPerWorkspace { c.JSON(http.StatusTooManyRequests, gin.H{"error": fmt.Sprintf("maximum %d active tokens per workspace", maxTokensPerWorkspace)}) return