Token-less automated sessions are rejected under OAuth2, so visibility,
follower and audience checks never worked there. With the host's alerts
principal declared they run on the recipient's behalf through it.
Recording/routing bookkeeping stays system so alerting never depends on
the IdP. Undeclared: unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
QRun-IO/.github#2 adds a tag-and-release job that signs vX with the
QRUN_TAG_SIGNING_KEY secret after Maven Central confirms the artifact.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Regenerated against UI API 1.6.0: every operation has an operationId and
the standard error responses (BasicErrorResponseV1: error, code, message,
fieldErrors, traceId); the extension's own error schema is kept but
deprecated; hand-written error bodies go through QJavalinUtils so they carry
code/message/traceId. Extension MINOR bumped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Monitor lease claims and run results, and alert reminder/notification
timers, changed on every scheduler pass and each wrote a FIELD audit row
(~7k alerts_monitor and ~1.8k alerts_alert audits per 6h in production).
AlertsDb.update now omits the DML audit when an update touches only the
RuntimeFields of its table; any update with a configuration or state field
is audited in full.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The alerts-sink drain thread (and schedulers) run engine work through
AlertsRuntime.asSystem with no QContext, so new QSystemUserSession()
read a null instance and warned "QInstance was not supplied" on every
call. AlertsSecurity.systemSession(QInstance) takes the instance; the
no-arg form delegates with the context instance.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The producer read a literal version, so released artifacts reported a stale
or -SNAPSHOT version. qbit-alerts.properties (version=${project.version}) is
Maven-filtered and the producer loads it; tests assert producer == bundle ==
artifact version.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The bundle version is now Maven-filtered, so a literal SNAPSHOT in the test
fails every release build. Surefire passes the artifact version in
qbit.artifactVersion.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On release branches the bundle's version and the producer's differed, so the
bundle test that asserts they match failed, and released bundles recorded
SNAPSHOT as their provenance. help/*.yaml is now filtered:
version: ${project.version}.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Host-neutral text (kof22-specific facts removed), registered with
HelpBundles in the producer, gated by HelpBundleAssertions. Replaces the
temporary AlertsHelp loader.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merges feature/notify-email-requested (#22) onto current develop and
reconciles it with the paginated emailer, user pause, quiet hours and the
notification preferences. REQUESTED email honours the category email
minimum severity, pause (SECURITY bypasses) and quiet hours. No schema
change, so no new changeset.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
develop owns qbit-alerts:29 and the join indexes are now :30, so the
foreign-key changesets move from 30-53 to 31-54. Constraint and index
names are unchanged. Changesets 32-54 use PostgreSQL-only SQL
(row_to_json), so they carry dbms:postgresql and the H2 tests skip them.
The H2 digest test and AlertsForeignKeysTest's pre-FK cut now stop
before :31.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
develop now owns qbit-alerts:29 (in_app_min_severity), so the join-index
changeset becomes qbit-alerts:30. Index names are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- coverage is decided by scope and severity, so a subscription with fewer events
still counts; follow-ups go to the owner team only after it was told of the raise
- the first-visit type sync is best effort and never breaks the bell
- default channels keep the bell and replace only the built-in email choice
- KIND_SETUP in AlertsHome.kinds(); help marker reworded
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds alerts-defaults.changelog.sql (in-app and email channels, alerts and other
groups; insert-only, guarded, tested through real Liquibase), a help bundle for
the app and every table, a Setup card on the home, guardrail tests, and docs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ownerTeamId on a group and defaultChannelIds on a user were stored but never
read. An alert that no subscription matches (WARNING and above) now goes to the
owner team of its group (or the nearest parent with one); default channels
decide where a user is reached when a subscription names none. Types, groups and
default monitors also sync on the first bell request.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
AlertsForeignKeysTest applies the shipped changelog with Liquibase to
PostgreSQL 17 (Testcontainers) and asserts every one-to-many join and table
possible-value field has a foreign key with the decided ON DELETE rule (or
an exemption with a reason), every FK column leads an index, orphans are
quarantined then nulled or deleted, re-runs are no-ops, and a constraint a
host already added is skipped. The H2 digest-migration test stops before
the PostgreSQL-only FK changesets.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Changeset 30 indexes the FK columns no earlier index leads with. Changesets
31-53 add one constraint each, fk_<child_table>_<child_column>, guarded by a
precondition on the name so a host that already added it marks it ran. Each
first records orphans in qqq_fk_quarantine, then nulls a nullable column or
deletes a row whose column is NOT NULL (full row kept in row_data).
ON DELETE: CASCADE for owned detail rows (timeline, record refs, delivery
log of an alert, team members, notification recipients, escalation steps);
SET NULL for optional pointers (group, parent group, owner/assigned team,
monitor, subscription, alert event, escalation policy); RESTRICT for config
that must not vanish under live data (alert type, a channel or team that a
subscription, delivery or escalation step uses).
The H2 test schema carries the same constraints and indexes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Record-view child lists, such as a notification's Recipients, failed with
"Error in JSON Serialization". ChildRecordListData carries the child
QTableMetaData, whose SourceQBitAware getSourceQBitConfig() hands Jackson
the AlertsQBitConfig; its getRuntime() returns an AlertsRuntime that points
back at the config, so serialization recursed to Jackson's 1000-level
nesting limit.
getRuntime() and getAudienceResolver() are now @JsonIgnore, as in the cms,
quick-search and sql-workbench configs. ChildListWidgetsJsonTest renders
the Recipients list with rows and every child-list widget, and serializes
each one; all three tests fail without the fix.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AlertsPreferences.ensure was an unlocked check-then-insert, and a page
load fires the home widgets and the bell together. On kof22 this left
two identical "alerts (bootstrap rule)" subscriptions for the owner, so
every alert notified them twice. First calls are now serialized in the
JVM. Across replicas, each first call keeps the oldest bootstrap
subscription and deletes the rest. Subscriptions a person made are never
touched.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Changeset 29 adds alerts_alert (monitor_id, status), alerts_monitor
(alert_type_id) and alerts_type (group_id). MonitorEvaluator looks up a
per-record monitor's open alerts by monitor_id + status on every
evaluation, and the type and group record pages list children by these
columns. A new test checks that every one-to-many join's child column
leads an index in the shipped changelog.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>