From ca67cf6313c505272cc6f85ef62b818fb23e59c1 Mon Sep 17 00:00:00 2001 From: CarterPerez-dev Date: Thu, 14 May 2026 01:12:07 -0400 Subject: [PATCH] fix(canary-phase11): use repo-supplied HasMore/NextCursor before rollup Both audits flagged buildPage as a non-blocking but worth-cleaning nit: it re-derived next_cursor from len(events) and the last event's ID rather than using the HasMore + NextCursor flags that event.Repository.ListByToken already computes via the LIMIT+1 peek trick. Both calculations agreed today, but the duplication would mask a divergence if the repo's pagination logic ever evolved (e.g. switched to opaque token cursors). Inline buildPage into gatherManageData and use list.HasMore + list.NextCursor as the authoritative signals. Drops the buildPage helper. Behavior identical; tests still pass. --- .../backend/internal/token/handler.go | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/PROJECTS/beginner/canary-token-generator/backend/internal/token/handler.go b/PROJECTS/beginner/canary-token-generator/backend/internal/token/handler.go index ce6a3f2d..c5e44cf9 100644 --- a/PROJECTS/beginner/canary-token-generator/backend/internal/token/handler.go +++ b/PROJECTS/beginner/canary-token-generator/backend/internal/token/handler.go @@ -239,14 +239,19 @@ func (h *Handler) GetManage(w http.ResponseWriter, r *http.Request) { return } - events, total, silenced := h.gatherManageData(r, tok.ID, cursor, limit) + events, page, total, silenced := h.gatherManageData( + r, + tok.ID, + cursor, + limit, + ) resp := ManageResponse{ Token: tok.ToManageView(h.svc.TriggerURL(tok.ID)), Events: events, EventsTotal: total, EventsSilencedActive: silenced, - Page: buildPage(events, limit), + Page: page, } h.writeJSON(w, http.StatusOK, envelopeData(resp)) } @@ -282,9 +287,9 @@ func (h *Handler) gatherManageData( tokenID string, cursor int64, limit int, -) (events []event.Response, total, silenced int64) { +) (events []event.Response, page ManagePage, total, silenced int64) { if h.eventQuery == nil { - return nil, 0, 0 + return nil, ManagePage{}, 0, 0 } list, err := h.eventQuery.ListByToken( r.Context(), tokenID, event.ListOptions{Cursor: cursor, Limit: limit}, @@ -296,6 +301,12 @@ func (h *Handler) gatherManageData( for i := range list.Events { events = append(events, list.Events[i].ToResponse()) } + if list.HasMore { + page = ManagePage{ + NextCursor: strconv.FormatInt(list.NextCursor, 10), + HasMore: true, + } + } if total, err = h.eventQuery.CountByToken( r.Context(), @@ -316,18 +327,7 @@ func (h *Handler) gatherManageData( silenced = 0 } } - return events, total, silenced -} - -func buildPage(events []event.Response, limit int) ManagePage { - if len(events) < limit || len(events) == 0 { - return ManagePage{} - } - last := events[len(events)-1] - return ManagePage{ - NextCursor: strconv.FormatInt(last.ID, 10), - HasMore: true, - } + return events, page, total, silenced } func parseCursor(raw string) (int64, error) {