- Shipped
- August 27, 2026 at 8:26 PM UTC
- Author
- Kamo
- Commit
- d51af23
THE BADGE WAS ABOUT THE QUEUE, NOT ABOUT YOU. /new-count counted every NEW report platform-wide, so it could only fall when somebody moved a status — reading the queue did nothing to it and there was no way to work through it. It now counts what is still untriaged AND unread by the caller. One predicate, three surfaces: a report is new to you when its status is NEW and you have no system_bug_view row for it. countByStatusUnviewedBy answers the badge, SystemBugDTO.viewed dresses the card, and the console's isNewToViewer draws the glow from the same two facts. A badge saying 3 above five glowing cards is a bug report, not a queue. Reading is deliberately NOT triage. Opening a report marks it read for you and leaves it NEW for everybody else — a shared flag would let the first reader clear it off the whole team's list. LIVE, over a CONTENTLESS BROADCAST. The legal and training badges each own a per-member NATS subject carrying their number; that shape does not fit here, because filing a report changes the count for every MANAGE_SYSTEM_BUGS holder at once and PlatformRightsResolver answers "does this member hold it", never "who holds it". So system.bugs.changed says only that the queue moved and each console re-reads its own count over the authenticated seed. Because the payload holds no number, no title and no id, it needed no new guarded prefix in StompDestinationAuthz — every entry there exists to stop one member reading another's per-member topic, and there is no such thing on this one. Every announce is AFTER the @Transactional method returned, never inside it: announcing from within would tell every console to re-read a row a rollback then took away, and the re-read would land on the old number with nothing to correct it. POST /{id}/viewed is idempotent — the console fires it on every open, from every tab — and the unique index on (bug_id, member_id) is what enforces that, not the pre-check, which two tabs race straight past. GET /status-counts feeds the numbers beside each entry of the status filter. Every predicate of the listing is applied except the status one, because the number next to an entry is a promise about what picking it will show. Needs KamoInitializerService's system_bug_view migration to have run first.