feat: broadcast system notifications on peer join/leave

When a peer connects or disconnects, the broker now broadcasts a
system push (subtype: "system") to all other peers in the same mesh.
The CLI formats these as [system] channel notifications so AI sessions
can react to topology changes without polling.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Alejandro Gutiérrez
2026-04-07 23:28:49 +01:00
parent 5cb4cc4fe7
commit 453705a4e1
4 changed files with 148 additions and 17 deletions

View File

@@ -51,8 +51,13 @@ export interface InboundPush {
/** Hint for UI: "direct" (crypto_box), "channel"/"broadcast"
* (plaintext for now). */
kind: "direct" | "broadcast" | "channel" | "unknown";
/** Optional semantic tag — "reminder" when fired by the scheduler. */
subtype?: "reminder";
/** Optional semantic tag — "reminder" when fired by the scheduler,
* "system" for broker-originated topology events. */
subtype?: "reminder" | "system";
/** Machine-readable event name (e.g. "peer_joined", "peer_left"). */
event?: string;
/** Structured payload for the event. */
eventData?: Record<string, unknown>;
}
type PushHandler = (msg: InboundPush) => void;
@@ -937,7 +942,9 @@ export class BrokerClient {
receivedAt: new Date().toISOString(),
plaintext,
kind,
...(msg.subtype ? { subtype: msg.subtype as "reminder" } : {}),
...(msg.subtype ? { subtype: msg.subtype as "reminder" | "system" } : {}),
...(msg.event ? { event: String(msg.event) } : {}),
...(msg.eventData ? { eventData: msg.eventData as Record<string, unknown> } : {}),
};
this.pushBuffer.push(push);
if (this.pushBuffer.length > 500) this.pushBuffer.shift();