Addendum 5 follow-up. sweepStalePresences() flipped presence.disconnected_at purely on last_ping_at age, with no knowledge of the in-memory lease, and a flip never closed anything — so a session could be hidden from list_peers (DB-backed) while pushes still reached it (memory-backed) and its daemon was never told to reconnect: the half-visible ghost seen in prod at 2026-09-08 22:05Z. - lease.ts: liveLeasePresenceIds() (online + OPEN + pong within 75 s) and reconcileFlippedPresences() (flipped ids that still hold an ONLINE lease); STALE_PONG_THRESHOLD_MS becomes the single shared constant. - broker.ts: sweepStalePresences(keep) skips the live set and returns the ids it flipped; setStaleSweepReconciler() lets index.ts (owner of `connections`) feed the keep-set and react to flips without a circular import. - index.ts: registers the reconciler before startSweepers(); every flipped presence that still has an online lease is evicted via evictPresenceFully(), which closes the socket (4004) so the daemon reconnects and re-hellos. Offline (in-grace) leases are left to their grace timer on purpose — the 90 s cutoff can land inside the window. Tests: 4 pure cases in tests/lease.test.ts (keep-set selection incl. the 75 s edge, the ghost case, in-grace exemption, empty). Broker tsc clean; suite 79 passed, 6 files fail only for missing DATABASE_URL / bun broker (pre-existing, environment). Cambio: barrido DB de presencias reconciliado con las leases en memoria HARD RULES touched: ninguna (broker only, no schema) Blast radius: broker prod (all meshes) · revert: trivial (1 commit) Smoke: 🟡 tests puros + tsc; verificación en vivo post-deploy: last_ping_at avanza ≥10 min tras un reattach y ningún 'stale sweep flipped' en logs Veredicto: safe — deploy junto al resto de fix/daemon-restart-mesh-blackout-1.37.1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
10 KiB
10 KiB