From 2ff6d91057505a9392045cf0683eb27fb6f8191d Mon Sep 17 00:00:00 2001 From: Deluan Date: Sun, 24 May 2026 22:21:53 -0300 Subject: [PATCH] fix(participants): add separator to dedup key to avoid prefix collisions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per Gemini review on PR #5527: the dedup key was 'ID+SubRole' with no separator, so (ID='12', SubRole='3') and (ID='1', SubRole='23') would collide. Real-world risk is negligible (artist IDs are fixed-length MD5 hashes), but the fix is trivial — use a NUL byte that cannot appear in either field. --- model/participants.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/model/participants.go b/model/participants.go index e4dcc8c76..8554afbb7 100644 --- a/model/participants.go +++ b/model/participants.go @@ -156,12 +156,15 @@ func (p Participants) Merge(other Participants) { } func (p Participants) add(role Role, participants ...Participant) { + // Use a separator that can't appear in either field so e.g. + // (ID="12", SubRole="3") doesn't collide with (ID="1", SubRole="23"). + const sep = "\x00" seen := make(map[string]int, len(p[role])) for i, artist := range p[role] { - seen[artist.ID+artist.SubRole] = i + seen[artist.ID+sep+artist.SubRole] = i } for _, participant := range participants { - key := participant.ID + participant.SubRole + key := participant.ID + sep + participant.SubRole if idx, ok := seen[key]; ok { // Same artist/sub-role seen before. The merge (e.g. building // album.Participants from per-track participants) is inherently