Skip to content

Track endpoint first-seen time across reconnects - #103

Merged
ako merged 1 commit into
mainfrom
claude/mxcli-hub-columns-timestamps-qxghl0
Aug 6, 2026
Merged

Track endpoint first-seen time across reconnects#103
ako merged 1 commit into
mainfrom
claude/mxcli-hub-columns-timestamps-qxghl0

Conversation

@ako

@ako ako commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Summary

Add persistent tracking of when endpoints were first seen, surviving backend reconnects and container reaps. The hub now displays "first seen" alongside "last seen" and "last used" in the admin UI, with the value sourced from the durable session history rather than the live backend's RegisteredAt timestamp (which resets on reconnect).

Changes

Core Logic

  • registry.go: Compute FirstSeenAt for each endpoint by scanning the durable session history for the earliest sighting of each endpoint slot. Live endpoints inherit this value, and offline endpoints in the history also get it populated.
  • sessions.go:
    • Add slot() method to EndpointRecord to extract the endpoint identity (without session), enabling matching across reconnects and sessions.
    • Refactor key() to use slot() for cleaner composition.
    • Add FirstSeenAt field to EndpointView with documentation explaining it survives reconnects.

Admin UI

  • admin.go:
    • Define epColgroup constant with fixed column widths for consistent alignment across session cards.
    • Add tableMinWidth constant applied to both cards and tables for synchronized horizontal scrolling.
    • Update table layout to use table-layout:fixed with the colgroup, ensuring columns line up across all cards.
    • Add at() helper to generate title attributes with absolute timestamps for truncated cells.
    • Add attr() escaper for HTML attribute values (distinct from element content escaping).
    • Update epRow() to include FirstSeenAt column and add tooltips to all truncatable cells.
    • Update sessionCard() to display "first seen" in the session header and update table headers.
    • Add CSS for text overflow with ellipsis and improved layout comments.

Tests

  • sessions_test.go: Add TestRegistry_SessionsFirstSeenSurvivesReconnect to verify that FirstSeenAt persists when a backend is reaped and reconnects with a fresh RegisteredAt.

Documentation

  • docs-site/src/tools/run-local.md: Document the new "first seen" feature and clarify that it differs from uptime by reading from persistent history.

Implementation Details

  • The firstSeen map is keyed by endpoint slot (not session), allowing the same endpoint to be tracked across multiple sessions.
  • Live endpoints take precedence over offline history records for the same slot, but both inherit the earliest FirstSeenAt from the durable log.
  • Column widths are fixed in CSS to ensure alignment; the URL column is flexible and takes the remainder.
  • Tooltips on truncated cells show the full value; timestamp tooltips show the absolute time behind relative displays like "3d ago".

https://claude.ai/code/session_01EKdcQRPJZxTWq87SH34WYy

The per-session endpoint tables were auto-laid-out, so each session card
sized its columns from its own longest cell and no two cards lined up.
Give the tables `table-layout: fixed` and a shared colgroup, with a
min-width on both the card and the table so a narrow viewport scrolls the
whole set together in `.wrap` rather than squashing cards independently.
URL takes the flexible remainder (it is the column worth reading in full);
overlong cells ellipsise and carry the full value as a tooltip.

Add a "First seen" column. A live backend's RegisteredAt restarts every
time a reaped container reconnects, so it cannot answer "how long has this
URL existed?" — EndpointView.FirstSeenAt is resolved from the durable
session log instead, taking the earliest sighting of the endpoint slot.
SessionView.FirstSeen now derives from that too. Timestamp cells show the
absolute time on hover.

Also add an attribute escaper for the values interpolated into HTML
attributes; esc() escapes markup but leaves quotes alone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EKdcQRPJZxTWq87SH34WYy
@ako
ako merged commit 323e1f9 into main Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants