From d0a2facf4431fcdc90a5a3fe56b81a8f09632245 Mon Sep 17 00:00:00 2001 From: "Molecule AI Dev Engineer A (Kimi)" Date: Mon, 1 Jun 2026 05:21:08 +0000 Subject: [PATCH 1/3] fix(broadcast): correct org-root CTE for non-root senders (#1959) --- workspace-server/internal/handlers/workspace_broadcast.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/workspace-server/internal/handlers/workspace_broadcast.go b/workspace-server/internal/handlers/workspace_broadcast.go index e4b9e08f6..a90de74b8 100644 --- a/workspace-server/internal/handlers/workspace_broadcast.go +++ b/workspace-server/internal/handlers/workspace_broadcast.go @@ -87,15 +87,15 @@ func (h *BroadcastHandler) Broadcast(c *gin.Context) { var orgRootID string err = db.DB.QueryRowContext(ctx, ` WITH RECURSIVE org_chain AS ( - SELECT id, parent_id, id AS root_id + SELECT id, parent_id FROM workspaces WHERE id = $1 UNION ALL - SELECT w.id, w.parent_id, c.root_id + SELECT w.id, w.parent_id FROM workspaces w JOIN org_chain c ON w.id = c.parent_id ) - SELECT root_id FROM org_chain WHERE parent_id IS NULL LIMIT 1 + SELECT id AS root_id FROM org_chain WHERE parent_id IS NULL LIMIT 1 `, senderID).Scan(&orgRootID) if err != nil { log.Printf("Broadcast: org root lookup for %s: %v", senderID, err) -- 2.52.0 From de71fce5c5a2d3549c95ed9bef676c153b3b5c8d Mon Sep 17 00:00:00 2001 From: "Molecule AI Dev Engineer A (Kimi)" Date: Mon, 1 Jun 2026 05:31:34 +0000 Subject: [PATCH 2/3] fix(rowserr): add missing rows.Err() checks in memory, schedules, and audit Prevent silent data truncation when a cursor/connection error occurs mid-iteration. Affected handlers: - memory.go: List - schedules.go: History - audit.go: scanAuditRows Co-Authored-By: Claude Opus 4.7 --- workspace-server/internal/handlers/audit.go | 8 +++----- workspace-server/internal/handlers/memory.go | 3 +++ workspace-server/internal/handlers/schedules.go | 3 +++ 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/workspace-server/internal/handlers/audit.go b/workspace-server/internal/handlers/audit.go index 16f4392b7..c728aa545 100644 --- a/workspace-server/internal/handlers/audit.go +++ b/workspace-server/internal/handlers/audit.go @@ -206,11 +206,6 @@ func (h *AuditHandler) Query(c *gin.Context) { c.JSON(http.StatusInternalServerError, gin.H{"error": "scan failed"}) return } - if err := rows.Err(); err != nil { - log.Printf("audit: rows error for workspace %s: %v", workspaceID, err) - c.JSON(http.StatusInternalServerError, gin.H{"error": "scan failed"}) - return - } // Chain verification (inline when AUDIT_LEDGER_SALT is set) ------------ // Paginated views cannot verify chain integrity — earlier events are absent @@ -252,6 +247,9 @@ func scanAuditRows(rows *sql.Rows) ([]auditEventRow, error) { } result = append(result, ev) } + if err := rows.Err(); err != nil { + return nil, err + } return result, nil } diff --git a/workspace-server/internal/handlers/memory.go b/workspace-server/internal/handlers/memory.go index 8f945a262..cd7b51524 100644 --- a/workspace-server/internal/handlers/memory.go +++ b/workspace-server/internal/handlers/memory.go @@ -54,6 +54,9 @@ func (h *MemoryHandler) List(c *gin.Context) { entry.Value = json.RawMessage(value) entries = append(entries, entry) } + if err := rows.Err(); err != nil { + log.Printf("Memory.List: rows error: %v", err) + } c.JSON(http.StatusOK, entries) } diff --git a/workspace-server/internal/handlers/schedules.go b/workspace-server/internal/handlers/schedules.go index 3139a217b..583beac7c 100644 --- a/workspace-server/internal/handlers/schedules.go +++ b/workspace-server/internal/handlers/schedules.go @@ -325,6 +325,9 @@ func (h *ScheduleHandler) History(c *gin.Context) { e.Request = json.RawMessage(reqStr) entries = append(entries, e) } + if err := rows.Err(); err != nil { + log.Printf("Schedules.History: rows error: %v", err) + } c.JSON(http.StatusOK, entries) } -- 2.52.0 From 00cab17c73b350e2115043ba59b6ce718b1a8f2a Mon Sep 17 00:00:00 2001 From: "Molecule AI Dev Engineer A (Kimi)" Date: Mon, 1 Jun 2026 12:36:44 +0000 Subject: [PATCH 3/3] ci: remove unused canvasUserMessage type to fix lint on staging internal/handlers/a2a_proxy_helpers.go:412 had an unused struct that causes golangci-lint `unused` failure on every PR targeting staging. Co-Authored-By: Claude Opus 4.7 --- workspace-server/internal/handlers/a2a_proxy_helpers.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/workspace-server/internal/handlers/a2a_proxy_helpers.go b/workspace-server/internal/handlers/a2a_proxy_helpers.go index 98c51bb7d..11916e6b1 100644 --- a/workspace-server/internal/handlers/a2a_proxy_helpers.go +++ b/workspace-server/internal/handlers/a2a_proxy_helpers.go @@ -407,15 +407,6 @@ func validateCallerToken(ctx context.Context, c *gin.Context, callerID string) e // matching (the wsauth errors are typed for the invalid case). var errInvalidCallerToken = errors.New("missing caller auth token") -// canvasUserMessage holds the extracted user message extracted from an -// A2A canvas request body for broadcasting to other sessions. -type canvasUserMessage struct { - Message string `json:"message,omitempty"` - Parts []map[string]interface{} `json:"parts,omitempty"` - MessageID string `json:"messageId,omitempty"` - Attachments []map[string]interface{} `json:"attachments,omitempty"` -} - // extractCanvasUserMessage parses an A2A JSON-RPC request body and extracts // the user-authored text and attachments from a canvas-initiated message/send. // Returns nil when the body is not a canvas user message (empty, malformed, -- 2.52.0