feat(cli): self-renewing session attestation + honest send + hide daemons (1.37.0)

Fixes the "peers stop receiving after a while / like expiring" class of bugs.

- Session attestation self-renewal (root cause of the expiry). The daemon
  minted a 12h-TTL parent attestation once at `claudemesh launch` and replayed
  the same stale token on every WS reconnect. Past launch+12h the broker
  rejected session_hello with `expired`, after which the daemon reconnect-
  looped forever with the dead token and the session silently fell off the
  mesh — its ephemeral pubkey lingering in rosters, undeliverable. Trigger was
  any reconnect past 12h: a network blip, a sleep/wake, or (most reliably) a
  broker redeploy that drops every WS at once, killing all sessions >12h old
  together. buildHello now re-mints a fresh attestation per (re)connect from
  the in-memory mesh.secretKey (already used at daemon rehydration), so
  presence is self-healing across reconnects/redeploys. The 12h security bound
  is preserved — live tokens stay short-lived, just refreshed on use. This is
  what lets sessions stay on the mesh for days; the existing keepalive
  (30s ping) + auto-reconnect (exp backoff) + 90s broker grace were already
  sound — the stale attestation was the single point of failure defeating them.

- Honest send status. The daemon outbox path returned `queued` optimistically
  and the drain retried failures (incl. "no connected peer") async forever, so
  a bare `✔ sent` for an offline or stale-session-key target was misleading.
  Direct sends now pre-check the live roster: offline/unknown key → `⚠ queued
  — no connected peer matches this key` + ephemeral-key explanation; online →
  `✔ sent to <name> (online)`. Applies to both daemon and cold paths; JSON
  gains `recipientOnline` + `status`.

- Hide control-plane daemons from peer list + target resolution. The
  control-plane filter was human-output-only; `peer list --json` still leaked
  the daemon's row, making it look like an addressable peer. Now filtered from
  JSON too (--all still shows it). Name/prefix resolution and the --self
  fan-out filter now exclude control-plane rows by peerRole (the reliable
  marker) rather than the channel string.

- --self no-op warning. --self only governs own-member-key fan-out; passed with
  a session pubkey it was silently ignored. It now warns it had no effect and
  sends normally (messaging a specific session pubkey needs no flag).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alejandro Gutiérrez
2026-06-14 12:51:31 +01:00
parent c747040e0d
commit 213a6b37cc
4 changed files with 105 additions and 17 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "claudemesh-cli",
"version": "1.36.0",
"version": "1.37.0",
"description": "Peer mesh for Claude Code sessions — CLI + MCP server.",
"keywords": [
"claude-code",