fix(cli): display system push messages without decryption
Some checks failed
CI / Lint (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Broker tests (Postgres) (push) Has been cancelled
CI / Docker build (linux/amd64) (push) Has been cancelled

System messages (watch_triggered, mcp_deployed, peer_joined, etc.)
have senderPubkey='system' with empty ciphertext. The push handler
now formats them as readable plaintext instead of failing to decrypt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alejandro Gutiérrez
2026-04-08 18:51:12 +01:00
parent f8c6f9ae74
commit bfc62b9a72
2 changed files with 31 additions and 5 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "claudemesh-cli", "name": "claudemesh-cli",
"version": "0.8.7", "version": "0.8.8",
"description": "Claude Code MCP client for claudemesh — peer mesh messaging between Claude sessions.", "description": "Claude Code MCP client for claudemesh — peer mesh messaging between Claude sessions.",
"keywords": [ "keywords": [
"claude-code", "claude-code",

View File

@@ -1612,11 +1612,37 @@ export class BrokerClient {
// Decrypt asynchronously, then enqueue. Ordering within the // Decrypt asynchronously, then enqueue. Ordering within the
// buffer is preserved by awaiting before push. // buffer is preserved by awaiting before push.
void (async (): Promise<void> => { void (async (): Promise<void> => {
const kind: InboundPush["kind"] = senderPubkey // System messages (peer_joined, watch_triggered, mcp_deployed, etc.)
// have senderPubkey="system" with empty nonce/ciphertext — skip decryption.
const isSystem = msg.subtype === "system" || senderPubkey === "system";
const kind: InboundPush["kind"] = isSystem
? "broadcast"
: senderPubkey
? "direct" ? "direct"
: "unknown"; : "unknown";
let plaintext: string | null = null; let plaintext: string | null = null;
if (senderPubkey && nonce && ciphertext) { if (isSystem) {
// Format system event as readable plaintext
const event = msg.event ? String(msg.event) : "system";
const data = msg.eventData as Record<string, unknown> | undefined;
if (event === "watch_triggered" && data) {
plaintext = `[WATCH] ${data.label ?? data.url}: ${data.oldValue}${data.newValue}`;
} else if (event === "mcp_deployed" && data) {
plaintext = `[SERVICE] "${data.name}" deployed (${data.tool_count} tools) by ${data.deployed_by}`;
} else if (event === "mcp_undeployed" && data) {
plaintext = `[SERVICE] "${data.name}" undeployed by ${data.by}`;
} else if (event === "mcp_scope_changed" && data) {
plaintext = `[SERVICE] "${data.name}" scope changed to ${JSON.stringify(data.scope)} by ${data.by}`;
} else if (event === "peer_joined" && data) {
plaintext = `[MESH] ${data.displayName ?? "peer"} joined`;
} else if (event === "peer_left" && data) {
plaintext = `[MESH] ${data.displayName ?? "peer"} left`;
} else if (data) {
plaintext = `[${event}] ${JSON.stringify(data)}`;
} else {
plaintext = `[${event}]`;
}
} else if (senderPubkey && nonce && ciphertext) {
plaintext = await decryptDirect( plaintext = await decryptDirect(
{ nonce, ciphertext }, { nonce, ciphertext },
senderPubkey, senderPubkey,