- Shipped
- August 14, 2026 at 11:43 PM UTC
- Author
- Kamo
- Commit
- 6dadd99
The NavTop obligation badge sums two counts — packages to sign and courses to take — and only one of them was live. The legal half has pushed since its NATS block landed; the training half was a 60-second poll, so a member assigned a course, or excused from one by HR, kept the old number on their chrome until the next tick happened to fire. That was the right call when it was made: DocsService had no `nats:` block, so a subscription would have been three moving parts maintaining a channel with no traffic. The block is there now, and pinned by an arch test, so the channel carries traffic. DocsService publishes **************** on core NATS, in the shape the legal publisher already uses, from the three services that can cross the OPEN boundary: assign, finish, and HR's cancel/waive/retake. The count is read inside the caller's transaction — where a count query flushes the rows they just wrote — and sent after the commit, because an exception in afterCommit propagates and would turn a Finish that has already written an append-only attestation into a 500 telling the member they failed. TrainingPlayerService is deliberately left out and asserted negatively: its only status write is ASSIGNED -> IN_PROGRESS on every open of the player, which is open to open. Publishing there would put a frame on the wire, logged at INFO with its full payload, every time somebody clicked into a course, for a number that did not change. FAILED_RETAKE_ALLOWED and AWAITING_GRADING are the two that look like completions and are not — both still owe the member work, so neither moves the badge.