From 508a5976e860f78169fb54772c75c09584da9134 Mon Sep 17 00:00:00 2001 From: Molecule AI Fullstack Engineer Date: Fri, 15 May 2026 03:16:07 +0000 Subject: [PATCH 1/2] fix(handlers): log DB Scan errors previously silently ignored (3 files) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tokens.go Create: COUNT query Scan error ignored — if DB fails, count=0, bypassing the per-workspace token rate limit. Now logs the error and fails open (DB errors should not block token creation). memories.go Commit: GLOBAL scope parent lookup Scan error ignored — if DB fails, workspace is incorrectly treated as root, allowing a forbidden GLOBAL write. Now returns 500 (fail closed, security-sensitive path). memories.go Search: parent lookup Scan error ignored — DB failure causes wrong TEAM-scope search results (self-only filter instead of team filter). Now logs and falls back to self-only (functional degradation, not security). container_files.go List: workspace name lookup Scan error ignored — now logs and continues (non-critical; container name candidates still tried). Co-Authored-By: Claude Opus 4.7 --- .../internal/handlers/container_files.go | 4 +++- workspace-server/internal/handlers/memories.go | 12 ++++++++++-- workspace-server/internal/handlers/tokens.go | 7 +++++-- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/workspace-server/internal/handlers/container_files.go b/workspace-server/internal/handlers/container_files.go index 290bd5f74..0e76f6fd3 100644 --- a/workspace-server/internal/handlers/container_files.go +++ b/workspace-server/internal/handlers/container_files.go @@ -31,7 +31,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 -- 2.52.0 From 2f9c35f7d0641edb7be132b3afdd0fdae26d21a1 Mon Sep 17 00:00:00 2001 From: Molecule AI Fullstack Engineer Date: Fri, 15 May 2026 07:35:38 +0000 Subject: [PATCH 2/2] fix(handlers): add missing log import to container_files.go log.Printf was called at line 35 but "log" was not imported, causing a build failure. Closes QA review comment on PR #1117. Co-Authored-By: Claude Opus 4.7 --- workspace-server/internal/handlers/container_files.go | 1 + 1 file changed, 1 insertion(+) diff --git a/workspace-server/internal/handlers/container_files.go b/workspace-server/internal/handlers/container_files.go index 0e76f6fd3..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" -- 2.52.0