feat(routing): follower fan-out via core RecordFollowers + guardrails (#16) #24

Merged
KofTwentyTwo merged 1 commits from feature/arch-follower-fanout into develop 2026-10-14 12:47:53 +00:00
KofTwentyTwo commented 2026-10-14 12:43:53 +00:00 (Migrated from github.com)

Summary

Completes #16 (architecture review QRun-IO/qqq#1150, finding F12; agreed with the collaboration owner).

  • Follower fan-out.
    • AlertRouter adds the followers from core RecordFollowers.get(instance, ref, FollowEvent.ALERT) (QRun-IO/qqq#1164, in 4.1.0-RC.6) to any alert that concerns a record.
    • Followers are deduplicated with existing recipients by user and channel.
    • A follower must pass the same source-record permission and record-lock checks as other recipients.
    • The recipient's own preferences and suppression apply.
    • No provider registered means no change.
    • No dependency on qbit-collaboration, which implements the provider. Removes the STAND-IN(core=QRun-IO/qqq#1164, …) marker.
  • Guardrails: parent qbit-build-parent 2.1.0 with qbit.guardrails.enforce=true and strict raw-route mode. All checks pass. The opt-in legacy Alertmanager alias is a documented advisory, and strict-mode tests check that it's rejected.
  • Reworded comments that only used the word "stand-in", e.g. the TEST channel's sample alert.

Tests

./mvnw -B verify on released RC.6: 94 tests, 0 failures, 0 checkstyle violations, JaCoCo gates pass. The new FollowerFanoutTest has 8 cases:

  • followers notified;
  • dedup;
  • no read access means not notified;
  • locked record;
  • preferences respected;
  • no provider;
  • empty list;
  • non-record alert.

🤖 Generated with Claude Code

## Summary Completes #16 (architecture review QRun-IO/qqq#1150, finding F12; agreed with the collaboration owner). - **Follower fan-out.** - `AlertRouter` adds the followers from core `RecordFollowers.get(instance, ref, FollowEvent.ALERT)` (QRun-IO/qqq#1164, in **4.1.0-RC.6**) to any alert that concerns a record. - Followers are deduplicated with existing recipients by user and channel. - A follower must pass the same **source-record permission and record-lock checks** as other recipients. - The recipient's own preferences and suppression apply. - No provider registered means no change. - No dependency on qbit-collaboration, which implements the provider. Removes the `STAND-IN(core=QRun-IO/qqq#1164, …)` marker. - **Guardrails:** parent `qbit-build-parent` **2.1.0** with `qbit.guardrails.enforce=true` and strict raw-route mode. All checks pass. The opt-in legacy Alertmanager alias is a documented advisory, and strict-mode tests check that it's rejected. - Reworded comments that only used the word "stand-in", e.g. the TEST channel's sample alert. ## Tests `./mvnw -B verify` on released RC.6: 94 tests, 0 failures, 0 checkstyle violations, JaCoCo gates pass. The new `FollowerFanoutTest` has 8 cases: - followers notified; - dedup; - no read access means not notified; - locked record; - preferences respected; - no provider; - empty list; - non-record alert. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.