The broker node has no way to tell anyone anything. Filed from CannObserv/broker#1, which needs a destination for its health findings; the endpoint and the credential are notifier's.
The problem on the broker side
co-broker runs a bus-health probe every ten minutes. It checks memory against the noeviction cap, every stream's length against its retention cap, last-entry age on the groupless streams, XPENDING on all five consumer groups, DLQ depth, and disk headroom.
Its entire output is a WARN line in journald on a node nobody is logged into. That is not an alert; it is a log entry with an audience of zero. It is also the cluster's only always-on broker-side signal - every in-process alternative stops reporting exactly when the process it rides is the thing that is down.
What is being asked for
An endpoint that accepts a small JSON health report from a tagged node, authenticated with an X-API-Key, and dispatches it. The shape, roughly:
{
"source": "co-broker",
"finding_count": 0,
"findings": [{"check": "dlq", "subject": "content.fetch.dlq", "message": "..."}],
"timestamp": "2026-09-08T21:58:44Z"
}
Same shape as notifier#44's Observo arrangement - ACL rule, tenant, API key - so if that lands first this should mostly be a second tenant rather than new machinery.
The requirement that is easy to miss
Alert on the absence of reports, not only on their contents.
A findings-only push is silent in exactly the cases that matter most: a dead probe, a stopped timer, a wedged uv run, or a dead node all produce zero findings and zero traffic, which is indistinguishable from a healthy broker. CannObserv/observo#473 is what that costs - a tailnet-bound Redis crash-looped and the cluster ran starved for two weeks because nothing was watching for silence.
So the broker will send a report every tick regardless of finding_count, and what notifier needs to provide is a dead-man's timer on top: if no report arrives from co-broker for some multiple of the ten-minute cadence, that is itself the alert. If that capability does not exist here, say so and it becomes the interesting half of this issue rather than an afterthought.
Tailscale ACL
This needs a rule admitting tag:broker as a src toward tag:notifier, which is a change to a deliberate constraint rather than an oversight. broker#1's D8 says the broker initiates nothing and its success criteria say tag:broker appears in no rule as a src - the reasoning being anti-centrality, that nothing should make the broker a client of a bus participant. Notifier is not a bus participant, so the rule as written is stricter than the reason requires, and broker#1 is amending D8 to say "the broker is a client of no bus participant" instead.
Worth knowing rather than discovering: peer visibility follows the acls rules, not the ssh rules. A node absent from the peer's netmap will not resolve over MagicDNS at all, so the rule has to exist before any of this can be tested.
Related
Tracked by CannObserv/broker#3 (alerting), a sub-issue of the CannObserv/broker#1 epic. That issue holds the D8 amendment this rule needs.
The broker node has no way to tell anyone anything. Filed from CannObserv/broker#1, which needs a destination for its health findings; the endpoint and the credential are notifier's.
The problem on the broker side
co-brokerruns a bus-health probe every ten minutes. It checks memory against thenoevictioncap, every stream's length against its retention cap, last-entry age on the groupless streams,XPENDINGon all five consumer groups, DLQ depth, and disk headroom.Its entire output is a WARN line in journald on a node nobody is logged into. That is not an alert; it is a log entry with an audience of zero. It is also the cluster's only always-on broker-side signal - every in-process alternative stops reporting exactly when the process it rides is the thing that is down.
What is being asked for
An endpoint that accepts a small JSON health report from a tagged node, authenticated with an
X-API-Key, and dispatches it. The shape, roughly:{ "source": "co-broker", "finding_count": 0, "findings": [{"check": "dlq", "subject": "content.fetch.dlq", "message": "..."}], "timestamp": "2026-09-08T21:58:44Z" }Same shape as notifier#44's Observo arrangement - ACL rule, tenant, API key - so if that lands first this should mostly be a second tenant rather than new machinery.
The requirement that is easy to miss
Alert on the absence of reports, not only on their contents.
A findings-only push is silent in exactly the cases that matter most: a dead probe, a stopped timer, a wedged
uv run, or a dead node all produce zero findings and zero traffic, which is indistinguishable from a healthy broker. CannObserv/observo#473 is what that costs - a tailnet-bound Redis crash-looped and the cluster ran starved for two weeks because nothing was watching for silence.So the broker will send a report every tick regardless of
finding_count, and what notifier needs to provide is a dead-man's timer on top: if no report arrives fromco-brokerfor some multiple of the ten-minute cadence, that is itself the alert. If that capability does not exist here, say so and it becomes the interesting half of this issue rather than an afterthought.Tailscale ACL
This needs a rule admitting
tag:brokeras asrctowardtag:notifier, which is a change to a deliberate constraint rather than an oversight. broker#1's D8 says the broker initiates nothing and its success criteria saytag:brokerappears in no rule as asrc- the reasoning being anti-centrality, that nothing should make the broker a client of a bus participant. Notifier is not a bus participant, so the rule as written is stricter than the reason requires, and broker#1 is amending D8 to say "the broker is a client of no bus participant" instead.Worth knowing rather than discovering: peer visibility follows the
aclsrules, not thesshrules. A node absent from the peer's netmap will not resolve over MagicDNS at all, so the rule has to exist before any of this can be tested.Related
Tracked by CannObserv/broker#3 (alerting), a sub-issue of the CannObserv/broker#1 epic. That issue holds the D8 amendment this rule needs.