v2.0.0: claims model - signed MMUR2 votes in a truth DB, merged view in a rebuildable cache DB; POST /api/claims, claims and merge routes, unsigned writes answer 410
Build and Push Docker Image / build (push) Successful in 5m1s

This commit is contained in:
Worph
2026-10-25 17:36:00 +00:00
parent b0adefb97b
commit 84af298792
78 changed files with 7203 additions and 5617 deletions
+36 -1
View File
@@ -201,6 +201,14 @@ type SearchHit struct {
// match is the authoritative test, run on each hydrated record. Pass the same
// query/filters match evaluates, or results will be missing.
func (c *Client) Search(query string, filters []SearchFilter, limit int, match func(hashID string, fields map[string]string) bool) ([]SearchHit, error) {
return c.SearchAs(query, filters, limit, "", match)
}
// SearchAs is Search seen by viewer (a uid, "" for the shared view): every
// candidate is matched with the viewer's own claims overlaid, and the records
// the viewer holds claims on are candidates too, so their own corrections are
// searchable for them.
func (c *Client) SearchAs(query string, filters []SearchFilter, limit int, viewer string, match func(hashID string, fields map[string]string) bool) ([]SearchHit, error) {
s, err := c.kv()
if err != nil {
return nil, err
@@ -245,7 +253,7 @@ func (c *Client) Search(query string, filters []SearchFilter, limit int, match f
}
}
for _, id := range survivors {
fields, err := readRecord(ctx, s, id)
fields, err := c.readRecordAs(ctx, s, id, viewer)
if err != nil {
return nil, err
}
@@ -261,6 +269,33 @@ func (c *Client) Search(query string, filters []SearchFilter, limit int, match f
break
}
}
if viewer == "" {
return hits, nil
}
seen := make(map[string]bool, len(hits))
for _, h := range hits {
seen[h.HashID] = true
}
own, err := c.viewerRIDs(ctx, viewer)
if err != nil {
return nil, err
}
for _, id := range own {
if seen[id] {
continue
}
fields, err := c.readRecordAs(ctx, s, id, viewer)
if err != nil {
return nil, err
}
if fields != nil && match(id, fields) {
hits = append(hits, SearchHit{HashID: id, Fields: fields})
}
}
sort.Slice(hits, func(i, j int) bool { return hits[i].HashID < hits[j].HashID })
if len(hits) > limit {
hits = hits[:limit]
}
return hits, nil
}