9 Commits
Author SHA1 Message Date
james.maesandClaude Opus 5.5 411a8ff604 Merge origin/develop into feature/notification-preferences-section; pin QQQ 4.1.0-RC.7
Keeps develop's per-user Slack delivery, escalation and mute work; the
in_app_min_severity changeset moves to qbit-alerts:29; the Notifications
preferences section gains Slack per category; pause also skips non-security
Slack; the summary schema carries preferencesSection (alerts extension 1.1.0).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 16:36:00 -05:00
james.maesandClaude Opus 5.5 718e13c236 feat(notifications): deliver notifications to Slack per user preference
NotificationSlackSender runs after the emailer: core SendMessageAction to the
configured provider (default "slack") with user:<id>, no qbit-slack import.
Pause and quiet hours apply (CRITICAL bypasses quiet hours), SECURITY sends
title and link only, daily digest DMs, SKIPPED without a provider or on a
user-facing refusal. Supersedes the 2026-10-13 "Slack never per user"
decision (owner, 2026-10-14; QRun-IO/qbit-slack DESIGN section 10).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 11:27:35 -05:00
james.maesandClaude Opus 5.5 3d56ccc403 feat(routing): fan record alerts out to followers via core RecordFollowers
An alert about a record now also reaches the record's followers, from
core RecordFollowers.get(instance, ref, FollowEvent.ALERT) (QRun-IO/qqq#1164,
QQQ 4.1.0-RC.6). Followers are deduplicated with existing recipients by
user and channel. They must pass the source-record permission and lock
checks, and they get the same preferences and suppression as any other
recipient. With no provider registered, routing is unchanged. There is no
dependency on qbit-collaboration, and the #1164 stand-in marker is gone.

Also adopt qbit-build-parent 2.1.0 with the guardrails enforced and strict
raw-route mode. Comments that only used the word "stand-in" are reworded.

Refs #16 (architecture review QRun-IO/qqq#1150, finding F12).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 07:43:46 -05:00
james.maesandClaude Opus 5.5 60b68cf722 refactor(notifications): deliver core QAlerts.notify; delete the spi stand-in
Core 4.1.0-RC.6 ships user notifications (QAlerts.notify,
NotificationSignal and friends; QRun-IO/qqq#1125). The qbit's sink now
implements core's notify path, so a QAlerts.notify from any qbit reaches
the notification queue, inbox, channels, quiet hours and preferences.
The rest of the stand-in package com.kingsrook.qbits.alerts.spi goes
(NotificationSignal, NotificationAudience, NotificationCategory,
NotificationSeverity, AlertLink, package-info), and so does
AlertsRuntime.sink().

Breaking for anything that used com.kingsrook.qbits.alerts.spi; its only
consumer, qbit-easypost-tracking, moved to core in #16 there.

Closes #15 (architecture review QRun-IO/qqq#1150, F3 and F12).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:34:22 -05:00
james.maesandClaude Opus 5.5 2692f8b1dc feat(api): alerts UI routes as spec'd extension endpoints; webhook to /qqq/hooks; follow via collaboration
#13: the six inbox and record-panel routes move from the raw
AlertsRouteProvider onto a MiddlewareSpecExtension "alerts" (prefix
/alerts). Paths are unchanged. The committed fragment
openapi/qqq-v1/alerts.yaml is checked by a contract test, and the server
tests run in strict mode. Additive fields let Next stop hard-coding
alerts names: the summary has inboxHref, and inbox items and panel
alerts have actions with process names and hrefs.

#14: the Alertmanager webhook moves to POST /qqq/hooks/alerts/alertmanager.
The old /qqq/v1 path is an opt-in deprecated alias (legacyAlertmanagerPath,
default off; it needs non-strict mode). The alias sends Deprecation and
Sunset headers and logs a warning per call.

#16: POST /alerts/record-panel/watch is removed; collaboration owns
following a record. The record panel reports follow.available when the
collaboration extension is registered. Existing record-scoped watch
subscriptions stay readable and are deprecated. Follower fan-out waits for
core RecordFollowersProviderInterface (STAND-IN(core=QRun-IO/qqq#1164,
removeBy=4.1.0-RC.7)).

The checkstyle header template now matches the short Apache header that
the sources already use. The core baseline becomes 4.1.0-RC.6.

Closes #13, closes #14, closes #16 (architecture review QRun-IO/qqq#1150,
F2, F7, F12, F20).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:18:36 -05:00
james.maesandClaude Opus 5.5 63bdc9313d feat(preferences): Notifications section in user Preferences
Registers a core Preferences section 'notifications' backed by
alerts_user_preference, alerts_notification_preference and the user's own
alerts_subscription rows: pause, digest time and time zone, alert email and
in-app switches, per-category in-app/email settings (security can't be
muted) and per-subscription overrides. Adds in_app_min_severity
(changeset qbit-alerts:21), honours it for in-app delivery, and skips
non-security emails while paused. The inbox summary returns
preferencesSection.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:35:29 -05:00
james.maesandClaude Opus 5.5 cb3d206e0f refactor(alerts): use core QAlerts and WebhookSigner from QQQ 4.1.0-RC.5
Bump the core baseline to 4.1.0-RC.5 and delete the alert-side copies in
the spi package. The qbit now registers its sink in core's
AlertsInstanceMetaData, so core QAlerts.raise/resolve/heartbeat from any
host qbit reaches it. The alertsQBitStandIn name is gone.

The notification types (NotificationSignal and friends) and
AlertsRuntime.sink().notify stay, binary compatible, for the released
qbit-easypost-tracking. They are tagged
STAND-IN(core=QRun-IO/qqq#1125, removeBy=4.1.0-RC.6).

StandardWebhookSigner delegates to core WebhookSigner. The wire format is
unchanged. Legacy secrets shorter than core's 16-byte minimum are
zero-padded, which gives an identical HMAC-SHA256.

Refs #15 (architecture review QRun-IO/qqq#1150, F3 and F11).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:31:16 -05:00
james.maesandClaude Opus 5.5 020d38e810 fix(api): notificationsHref is the Next UI route /app/notifications
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 10:15:52 -05:00
james.maesandClaude Opus 5.5 1a6bb6096e docs: user notifications design (owner decisions 2026-10-13)
Extends the alerts model with admin-authored and producer-emitted user
notifications, per-user recipient rows, dynamic audiences, the Next UI
notification center, and QAlerts.notify in the core SPI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 09:45:34 -05:00