From 660cd0adf8a3e2838db271f0a1617a476a892790 Mon Sep 17 00:00:00 2001 From: david <58231312+davseby@users.noreply.github.com> Date: Tue, 25 Aug 2026 19:06:34 +0300 Subject: [PATCH] fix document search blocks computation --- .../hook/processor/container_image_watcher.go | 10 ++++++++++ .../processor/container_image_watcher_test.go | 4 +++- server/core/internal/document/node.go | 8 ++++---- server/core/internal/document/node_test.go | 18 ++++++++++++++++++ 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/server/core/internal/document/hook/processor/container_image_watcher.go b/server/core/internal/document/hook/processor/container_image_watcher.go index db12ce4b..f5af95d2 100644 --- a/server/core/internal/document/hook/processor/container_image_watcher.go +++ b/server/core/internal/document/hook/processor/container_image_watcher.go @@ -50,7 +50,17 @@ func (ciw *ContainerImageWatcher) Process(ctx context.Context, inp Input) (decim case err == nil: ciws.Status = ContainerImageWatcherStatusActive case errors.Is(err, registry.ErrUnauthorized): + // an unauthorized fetch yields no digest to compare against, so the + // score drops regardless of the stored baseline — which may itself be + // empty when the hook was created while unauthorized. ciws.Status = ContainerImageWatcherStatusUnauthorized + + state, merr := json.Marshal(ciws) + if merr != nil { + return decimal.Zero, nil, fmt.Errorf("marshaling container image watcher state: %w", merr) + } + + return decimal.Zero, state, nil default: return decimal.Zero, nil, fmt.Errorf("fetching container image digest: %w", err) } diff --git a/server/core/internal/document/hook/processor/container_image_watcher_test.go b/server/core/internal/document/hook/processor/container_image_watcher_test.go index f5c7fa2a..256db0b5 100644 --- a/server/core/internal/document/hook/processor/container_image_watcher_test.go +++ b/server/core/internal/document/hook/processor/container_image_watcher_test.go @@ -119,8 +119,10 @@ func Test_ContainerImageWatcher_Process(t *testing.T) { ciw := ContainerImageWatcher{Image: image} + // an empty baseline digest — a hook created or reset while + // unauthorized — must not match the empty digest of a failed fetch. score, state, err := ciw.Process(context.Background(), stubInput{ - state: imageWatcherState(t, "sha256:old"), + state: imageWatcherState(t, ""), }) require.NoError(t, err) diff --git a/server/core/internal/document/node.go b/server/core/internal/document/node.go index 86a63e0d..878e3342 100644 --- a/server/core/internal/document/node.go +++ b/server/core/internal/document/node.go @@ -173,14 +173,14 @@ func (b Block) HasBlock(blockID string) bool { func (b Block) Search(organizationID string, documentID xid.ID) map[string]search.Block { res := make(map[string]search.Block) - var text string + var text strings.Builder for _, cb := range b.Content { // All parent nodes that contain text have a content element // with the text type. This includes Headings, Paragraphs, // CodeBlock, CodeBlockTitle, ListItem and so on. if cb.Type == BlockNodeText { - text = cb.Text + text.WriteString(cb.Text) continue } @@ -189,14 +189,14 @@ func (b Block) Search(organizationID string, documentID xid.ID) map[string]searc maps.Insert(res, maps.All(content)) } - if text != "" { + if text.Len() != 0 { if id, ok := b.UID(); ok && id != "" { res[id] = search.Block{ ID: id, OrganizationID: organizationID, DocumentID: documentID, Type: string(b.Type), - Text: text, + Text: text.String(), } } } diff --git a/server/core/internal/document/node_test.go b/server/core/internal/document/node_test.go index 786d4aa5..79cc8a06 100644 --- a/server/core/internal/document/node_test.go +++ b/server/core/internal/document/node_test.go @@ -223,6 +223,17 @@ func Test_RootBlock_Search(t *testing.T) { }, }, }, + // marks split the text into multiple fragments; all of + // them must be indexed, not just the last one. + { + Type: BlockNodeParagraph, + Attrs: Attributes{"uid": "p2"}, + Content: []Block{ + {Type: BlockNodeText, Text: "plain "}, + {Type: BlockNodeText, Text: "bold", Marks: []Mark{{Type: "bold"}}}, + {Type: BlockNodeText, Text: " tail"}, + }, + }, // no uid: the text is not indexable. { Type: BlockNodeParagraph, @@ -252,6 +263,13 @@ func Test_RootBlock_Search(t *testing.T) { Type: "listItem", Text: "nested", }, + "p2": { + ID: "p2", + OrganizationID: "org-1", + DocumentID: documentID, + Type: "paragraph", + Text: "plain bold tail", + }, }, res) }