@calebcall/camera-ui-notify 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/README.md +41 -11
- package/bundle.zip +0 -0
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,52 @@ All notable changes to **Notify** are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.7.1] - 2026-08-02
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **Alertmanager mode: documented the required path prefix.** Mimir and Grafana Cloud serve the
|
|
13
|
+
Alertmanager API under a prefix (`/alertmanager` by default); a standalone Alertmanager serves it
|
|
14
|
+
at the root. 0.7.0's field placeholder and README both showed a bare host, so configuring it the
|
|
15
|
+
documented way produced `404 page not found` on every send. The README now gives both forms side
|
|
16
|
+
by side, and the field description and placeholder show the Grafana Cloud shape. No code was
|
|
17
|
+
wrong here — the documentation was.
|
|
18
|
+
- **A 404 from Alertmanager now explains itself.** Go's default mux answers with a bare
|
|
19
|
+
`404 page not found`, which says nothing about the missing prefix that caused it. The error now
|
|
20
|
+
adds that hint. Other statuses are untouched.
|
|
21
|
+
- **A pasted full endpoint is accepted.** Alertmanager's own docs show the complete
|
|
22
|
+
`.../api/v2/alerts` URL, so copying it into the base-URL field is the obvious mistake; a trailing
|
|
23
|
+
`/api/v2/alerts` is now trimmed rather than producing `/api/v2/alerts/api/v2/alerts`.
|
|
24
|
+
- **Documented where Grafana Cloud Alertmanager credentials come from.** The username is the
|
|
25
|
+
numeric Alertmanager instance ID from the Cloud portal; the password is an Access Policy token
|
|
26
|
+
(`glc_...`) with the `alerts:write` scope — *not* a Grafana service-account token (`glsa_...`),
|
|
27
|
+
which authenticates to Grafana rather than to the Alertmanager.
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
|
|
31
|
+
- **Alertmanager mode no longer sends `startsAt`**, letting Alertmanager stamp it from its own
|
|
32
|
+
clock. The alert's start time is now correct even on a host whose clock has drifted.
|
|
33
|
+
- **`grafana_ttl` default raised from 300 to 900 seconds.** `endsAt` must be absolute — the
|
|
34
|
+
Alertmanager API has no relative form — so it is still derived from the camera.ui host's clock. A
|
|
35
|
+
host running more than `grafana_ttl` behind the Alertmanager sends an `endsAt` already in the
|
|
36
|
+
past, and the alert is accepted with a `200`, resolved on arrival, and never appears as active —
|
|
37
|
+
a silent no-op that reads as success. 15 minutes gives that failure real margin where 5 did not,
|
|
38
|
+
and the README now names the symptom and the fix (keep the host in NTP sync).
|
|
39
|
+
|
|
40
|
+
### Removed
|
|
41
|
+
|
|
42
|
+
- **`grafana_irm_ttl` and the IRM `endsAt` experiment, both added in 0.7.0.** They did nothing. IRM
|
|
43
|
+
decides whether a group is resolved from a template on the payload's status — its default is
|
|
44
|
+
`{{ payload.status == "resolved" }}` — and ignores `endsAt` entirely, so no value in a single
|
|
45
|
+
firing request can close a group; only a second request can. IRM alerts once again carry the
|
|
46
|
+
documented never-resolves sentinel `0001-01-01T00:00:00Z`, which states the actual behaviour
|
|
47
|
+
instead of implying an auto-close that never happens, and the README says plainly that groups are
|
|
48
|
+
closed by hand.
|
|
49
|
+
|
|
50
|
+
A delayed resolve was considered and rejected: it would require a background timer and per-event
|
|
51
|
+
state in a plugin that is otherwise one stateless POST per event, and a restart would strand the
|
|
52
|
+
group open regardless.
|
|
53
|
+
|
|
8
54
|
## [0.7.0] - 2026-08-02
|
|
9
55
|
|
|
10
56
|
### Changed
|
package/README.md
CHANGED
|
@@ -115,11 +115,11 @@ different services, so each has its own connection fields.
|
|
|
115
115
|
| `grafana_server` | yes | annotations | Base URL of the Grafana instance. Trailing `/` trimmed. |
|
|
116
116
|
| `grafana_token` | yes | annotations | Service-account token, sent as `Authorization: Bearer <token>`. |
|
|
117
117
|
| `grafana_tags` | no | annotations | Comma-separated extra tags. |
|
|
118
|
-
| `grafana_am_url` | yes | alertmanager | Base URL of the **Alertmanager**, not of Grafana.
|
|
119
|
-
| `grafana_am_user` | no | alertmanager | Basic-auth username. For Grafana Cloud, the Alertmanager instance ID. |
|
|
120
|
-
| `grafana_am_password` | no | alertmanager | Basic-auth password. For Grafana Cloud, an
|
|
118
|
+
| `grafana_am_url` | yes | alertmanager | Base URL of the **Alertmanager**, not of Grafana — **including any path prefix** (see below). A pasted `.../api/v2/alerts` endpoint is accepted and trimmed. |
|
|
119
|
+
| `grafana_am_user` | no | alertmanager | Basic-auth username. For Grafana Cloud, the numeric Alertmanager instance ID. |
|
|
120
|
+
| `grafana_am_password` | no | alertmanager | Basic-auth password. For Grafana Cloud, an Access Policy token with the `alerts:write` scope. Required if a username is set, and vice versa. |
|
|
121
121
|
| `grafana_alertname` | no | alertmanager | `alertname` label. Defaults to `CameraUINotification`. |
|
|
122
|
-
| `grafana_ttl` | no | alertmanager | Seconds before Alertmanager auto-resolves the alert. Default `
|
|
122
|
+
| `grafana_ttl` | no | alertmanager | Seconds before Alertmanager auto-resolves the alert. Default `900`, minimum `30`. |
|
|
123
123
|
| `grafana_irm_url` | yes | irm | Inbound webhook URL of an IRM / OnCall integration. The token is in the URL, so it is masked and kept out of every error message. |
|
|
124
124
|
| `grafana_irm_ttl` | no | irm | Seconds before the alert is eligible to auto-resolve. Default `300`, minimum `30`. Whether IRM acts on it depends on the integration's templates. |
|
|
125
125
|
|
|
@@ -140,8 +140,35 @@ Cloud's hosted Alertmanager (username = instance ID, password = API token).
|
|
|
140
140
|
> rule evaluation. Point this at a real Alertmanager. (Versions 0.6.0–0.6.1 targeted Grafana here
|
|
141
141
|
> and always failed with `400 bad request data`.)
|
|
142
142
|
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
> **Get the URL right — this is the most common way to misconfigure this mode.** Mimir and Grafana
|
|
144
|
+
> Cloud serve the Alertmanager API under a path prefix, `/alertmanager` by default; a standalone
|
|
145
|
+
> Alertmanager serves it at the root. Omit the prefix and every send fails with a bare
|
|
146
|
+
> `404 page not found`.
|
|
147
|
+
>
|
|
148
|
+
> | Target | Enter | Resulting POST |
|
|
149
|
+
> | --- | --- | --- |
|
|
150
|
+
> | Grafana Cloud / Mimir | `https://alertmanager-prod-xx.grafana.net/alertmanager` | `…/alertmanager/api/v2/alerts` |
|
|
151
|
+
> | Standalone Alertmanager | `http://alertmanager:9093` | `…/api/v2/alerts` |
|
|
152
|
+
>
|
|
153
|
+
> **Grafana Cloud credentials** come from two different places. The **username** is the numeric
|
|
154
|
+
> Alertmanager instance ID, shown with the URL on the Alertmanager details page in the Cloud
|
|
155
|
+
> portal. The **password** is an **Access Policy token** (`glc_…`) carrying the `alerts:write`
|
|
156
|
+
> scope, created under Access Policies — *not* a Grafana service-account token (`glsa_…`), which
|
|
157
|
+
> authenticates to Grafana rather than to the Alertmanager.
|
|
158
|
+
|
|
159
|
+
`endsAt` is `now + grafana_ttl`, which lets Alertmanager auto-resolve the alert without a
|
|
160
|
+
second request. `startsAt` is deliberately not sent — Alertmanager stamps it from its own clock.
|
|
161
|
+
|
|
162
|
+
> **If sends succeed but no alert appears, check the clock.** `endsAt` has to be absolute
|
|
163
|
+
> (Alertmanager's API has no relative form), so it is computed from the camera.ui host's clock. A
|
|
164
|
+
> host running more than `grafana_ttl` *behind* the Alertmanager sends an `endsAt` already in the
|
|
165
|
+
> past: the alert is accepted with a `200`, resolved on arrival, and never shows as active. The
|
|
166
|
+
> symptom is a clean `notify: delivered` in the log and an empty
|
|
167
|
+
> `GET {alertmanager}/api/v2/alerts`. Keep the host in NTP sync. The 900-second default exists to
|
|
168
|
+
> give that failure some margin.
|
|
169
|
+
>
|
|
170
|
+
> Second, gentler trap: alerts self-resolve after `grafana_ttl` and drop off the active list, so
|
|
171
|
+
> when testing, look within the window rather than an hour later. Labels are `alertname`, `source=camera.ui`, `severity` (camera.ui's own four
|
|
145
172
|
levels, verbatim), `camera`, `camera_id`, and a unique `event_id` — the last of these matters, because
|
|
146
173
|
Alertmanager deduplicates on the label set and without it two detections on one camera inside the
|
|
147
174
|
TTL window would collapse into a single alert. The absolute deep link becomes `generatorURL`,
|
|
@@ -157,11 +184,14 @@ labels/annotations/`generatorURL`/`imageURL`, `groupKey`, `commonLabels`, `exter
|
|
|
157
184
|
|
|
158
185
|
Alert groups are keyed **per camera** — `camera.ui:<camera>`, falling back to `camera.ui` for a
|
|
159
186
|
notification that names no camera — so one busy camera can't bury a quiet one. Within a group each
|
|
160
|
-
event keeps its own `fingerprint`, so detections stay individually visible.
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
187
|
+
event keeps its own `fingerprint`, so detections stay individually visible.
|
|
188
|
+
|
|
189
|
+
**IRM groups do not auto-resolve.** IRM decides that from a template on the payload's status — its
|
|
190
|
+
default is `{{ payload.status == "resolved" }}` — so a group closes only when a *second* request
|
|
191
|
+
arrives saying so. `endsAt` is ignored, which is why alerts carry the documented never-resolves
|
|
192
|
+
sentinel rather than a future time that would imply a close that never comes. This plugin sends one
|
|
193
|
+
stateless POST per event and no follow-up, by design: a delayed resolve would mean a background
|
|
194
|
+
timer and per-event state, and a restart would strand the group open anyway. Close them in IRM.
|
|
165
195
|
|
|
166
196
|
> **Camera names:** `camera` carries the camera's display name, taken from `Data["cameraName"]`
|
|
167
197
|
> when a publisher supplies one and otherwise from the deep link, which camera.ui routes by name.
|
package/bundle.zip
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"displayName": "Notify",
|
|
3
3
|
"name": "@calebcall/camera-ui-notify",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.1",
|
|
5
5
|
"description": "A fully-local, multi-backend camera.ui notifier plugin: delivers notifications to ntfy, Gotify, or a generic webhook, entirely on your own hardware with no cloud dependency.",
|
|
6
6
|
"author": "calebcall (https://github.com/calebcall/camera-ui-notify)",
|
|
7
7
|
"main": "./main.go",
|
|
@@ -48,14 +48,14 @@
|
|
|
48
48
|
"protocolLevel": 1
|
|
49
49
|
},
|
|
50
50
|
"optionalDependencies": {
|
|
51
|
-
"@calebcall/camera-ui-notify-darwin-arm64": "0.7.
|
|
52
|
-
"@calebcall/camera-ui-notify-darwin-amd64": "0.7.
|
|
53
|
-
"@calebcall/camera-ui-notify-linux-amd64": "0.7.
|
|
54
|
-
"@calebcall/camera-ui-notify-linux-arm64": "0.7.
|
|
55
|
-
"@calebcall/camera-ui-notify-windows-amd64": "0.7.
|
|
56
|
-
"@calebcall/camera-ui-notify-windows-arm64": "0.7.
|
|
57
|
-
"@calebcall/camera-ui-notify-linux-amd64-musl": "0.7.
|
|
58
|
-
"@calebcall/camera-ui-notify-linux-arm64-musl": "0.7.
|
|
51
|
+
"@calebcall/camera-ui-notify-darwin-arm64": "0.7.1",
|
|
52
|
+
"@calebcall/camera-ui-notify-darwin-amd64": "0.7.1",
|
|
53
|
+
"@calebcall/camera-ui-notify-linux-amd64": "0.7.1",
|
|
54
|
+
"@calebcall/camera-ui-notify-linux-arm64": "0.7.1",
|
|
55
|
+
"@calebcall/camera-ui-notify-windows-amd64": "0.7.1",
|
|
56
|
+
"@calebcall/camera-ui-notify-windows-arm64": "0.7.1",
|
|
57
|
+
"@calebcall/camera-ui-notify-linux-amd64-musl": "0.7.1",
|
|
58
|
+
"@calebcall/camera-ui-notify-linux-arm64-musl": "0.7.1"
|
|
59
59
|
},
|
|
60
60
|
"files": [
|
|
61
61
|
"bundle.zip",
|