feat(api): alerts UI API extension, /qqq/hooks webhook, follow via collaboration (#13 #14 #16) #19

Merged
KofTwentyTwo merged 2 commits from feature/arch-ui-api-extension into develop 2026-10-14 12:20:06 +00:00
KofTwentyTwo commented 2026-10-14 01:18:45 +00:00 (Migrated from github.com)

Summary

Closes #13, #14 and #16. Architecture review QRun-IO/qqq#1150, findings F2, F7, F12 and F20.

Method Path operationId
GET /qqq/v1/alerts/inbox/summary alertsInboxSummary
GET /qqq/v1/alerts/inbox alertsInbox
POST /qqq/v1/alerts/inbox/read alertsInboxRead
POST /qqq/v1/alerts/inbox/unread alertsInboxUnread
POST /qqq/v1/alerts/inbox/dismiss alertsInboxDismiss
GET /qqq/v1/alerts/record-panel alertsRecordPanel
POST /qqq/hooks/alerts/alertmanager (machine webhook, outside the UI API)
  • #13 (F2, F20)
    • The UI routes move onto a MiddlewareSpecExtension named alerts (prefix /alerts, extension version 1.0.0). Paths and existing fields are unchanged.
    • The committed fragment src/main/resources/openapi/qqq-v1/alerts.yaml is checked by a contract test. Server tests run with withStrictUiApiRoutes(true).
    • Additive: the summary carries inboxHref, and inbox items and record-panel alerts carry actions (process name, label, href). Next can then drop its hard-coded alerts, alertsAcknowledge/alertsSnooze, alerts_alert and /app/notifications (F20).
  • #14 (F7)
    • The Alertmanager webhook moves to POST /qqq/hooks/alerts/alertmanager, with the same auth and payload.
    • The old /qqq/v1/alerts/ingest/alertmanager is an opt-in deprecated alias, legacyAlertmanagerPath, default off. It can't coexist with strict mode. It returns Deprecation: true and Sunset: Tue, 13 Apr 2027, and logs a warning per call.
    • Ops: point Alertmanager receivers at the new path.
  • #16 (F12), agreed with the collaboration owner: collaboration owns following a record.
    • POST /alerts/record-panel/watch is removed.
    • The record panel returns follow: {available}, true when the collaboration UI API extension is registered. Next builds the follow URL from its collaboration module (qbit-collaboration#8), and alerts has no dependency on collaboration.
    • Existing record-scoped watch subscriptions stay readable and are deprecated, with no migration.
    • Follower fan-out waits for core QRun-IO/qqq#1164 (RecordFollowersProviderInterface) and is marked STAND-IN(core=QRun-IO/qqq#1164, removeBy=4.1.0-RC.7).
  • The checkstyle header template now matches the short Apache header that every source file already uses.
  • Docs: docs/UI-API.md (Next handoff), README, DESIGN, NOTIFICATIONS, CHANGELOG.

Wire changes for Next

  • Additive: inboxHref, actions, follow.available.
  • Removed: the watch call. Next must hide its watch button unless follow.available is true, and use collaboration's follow endpoint.

Merge order: this PR, then the vendored alerts.yaml in Next, then the Next UI change.

Draft until QQQ 4.1.0-RC.6 is released

Verified locally against core develop as 4.1.0-ARCHRC6-SNAPSHOT: mvn verify runs 79 tests with 0 failures and 0 checkstyle violations, with 93.40% instruction and 100% class coverage.

🤖 Generated with Claude Code

## Summary Closes #13, #14 and #16. Architecture review QRun-IO/qqq#1150, findings F2, F7, F12 and F20. | Method | Path | operationId | |---|---|---| | GET | `/qqq/v1/alerts/inbox/summary` | `alertsInboxSummary` | | GET | `/qqq/v1/alerts/inbox` | `alertsInbox` | | POST | `/qqq/v1/alerts/inbox/read` | `alertsInboxRead` | | POST | `/qqq/v1/alerts/inbox/unread` | `alertsInboxUnread` | | POST | `/qqq/v1/alerts/inbox/dismiss` | `alertsInboxDismiss` | | GET | `/qqq/v1/alerts/record-panel` | `alertsRecordPanel` | | POST | `/qqq/hooks/alerts/alertmanager` | (machine webhook, outside the UI API) | - **#13 (F2, F20)** - The UI routes move onto a `MiddlewareSpecExtension` named `alerts` (prefix `/alerts`, extension version 1.0.0). Paths and existing fields are unchanged. - The committed fragment `src/main/resources/openapi/qqq-v1/alerts.yaml` is checked by a contract test. Server tests run with `withStrictUiApiRoutes(true)`. - **Additive:** the summary carries `inboxHref`, and inbox items and record-panel alerts carry `actions` (process name, label, href). Next can then drop its hard-coded `alerts`, `alertsAcknowledge`/`alertsSnooze`, `alerts_alert` and `/app/notifications` (F20). - **#14 (F7)** - The Alertmanager webhook moves to `POST /qqq/hooks/alerts/alertmanager`, with the same auth and payload. - The old `/qqq/v1/alerts/ingest/alertmanager` is an **opt-in** deprecated alias, `legacyAlertmanagerPath`, default off. It can't coexist with strict mode. It returns `Deprecation: true` and `Sunset: Tue, 13 Apr 2027`, and logs a warning per call. - **Ops:** point Alertmanager receivers at the new path. - **#16 (F12)**, agreed with the collaboration owner: collaboration owns following a record. - `POST /alerts/record-panel/watch` is **removed**. - The record panel returns `follow: {available}`, true when the `collaboration` UI API extension is registered. Next builds the follow URL from its collaboration module (qbit-collaboration#8), and alerts has no dependency on collaboration. - Existing record-scoped watch subscriptions stay readable and are deprecated, with no migration. - Follower fan-out waits for core QRun-IO/qqq#1164 (`RecordFollowersProviderInterface`) and is marked `STAND-IN(core=QRun-IO/qqq#1164, removeBy=4.1.0-RC.7)`. - The checkstyle header template now matches the short Apache header that every source file already uses. - Docs: `docs/UI-API.md` (Next handoff), README, DESIGN, NOTIFICATIONS, CHANGELOG. ## Wire changes for Next - Additive: `inboxHref`, `actions`, `follow.available`. - Removed: the `watch` call. Next must hide its watch button unless `follow.available` is true, and use collaboration's follow endpoint. **Merge order:** this PR, then the vendored `alerts.yaml` in Next, then the Next UI change. ## Draft until QQQ 4.1.0-RC.6 is released Verified locally against core develop as `4.1.0-ARCHRC6-SNAPSHOT`: `mvn verify` runs 79 tests with 0 failures and 0 checkstyle violations, with 93.40% instruction and 100% class coverage. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.