Skip to content

feat: pubkey alias system for display name resolution#3

Open
tjdownes wants to merge 3 commits intodevfrom
feat/pubkey-aliases
Open

feat: pubkey alias system for display name resolution#3
tjdownes wants to merge 3 commits intodevfrom
feat/pubkey-aliases

Conversation

@tjdownes
Copy link
Copy Markdown
Owner

@tjdownes tjdownes commented May 1, 2026

Summary

  • Adds a pubkey_aliases table so admins can assign human-readable display names to client public keys that never appear in the adverts table (e.g. MeshCore phone-app users whose device does not broadcast LoRa adverts)
  • sqlite_handler.py: pubkey_aliases table + migration 12; CRUD helpers set/get/delete/list
  • storage_collector.py: get_node_name_by_pubkey() checks aliases first (highest priority), falls back to adverts table
  • api_endpoints.py: GET /api/pubkey_aliases, POST|DELETE /api/pubkey_alias, GET /api/resolve_pubkey_names batch lookup; acl_clients response includes node_name

Test plan

  • pytest tests/test_sqlite_pubkey_aliases.py: 17 tests
  • pytest tests/test_storage_collector_name_resolution.py: 16 tests
  • pytest tests/test_resolve_pubkey_names_endpoint.py: 11 tests
  • Device test: set alias via POST /api/pubkey_alias, verify name appears in UI

tjdownes and others added 2 commits May 1, 2026 05:50
Adds a new `pubkey_aliases` table so admins can assign human-readable
display names to client public keys that never appear in the adverts
table (e.g. MeshCore phone-app users whose device does not broadcast
LoRa adverts).

- sqlite_handler.py: `pubkey_aliases` table created on DB init plus
  migration 12 for existing databases; CRUD helpers set/get/delete/list
- storage_collector.py: `get_node_name_by_pubkey()` now checks aliases
  first (highest priority), then falls back to the adverts table as
  before; new wrapper methods set/delete/list aliases forwarded to the
  DB handler
- api_endpoints.py: new GET /api/pubkey_aliases and
  POST|DELETE /api/pubkey_alias endpoints; GET /api/resolve_pubkey_names
  batch lookup for the UI poll cycle; `acl_clients` response now
  includes `node_name` resolved via the same lookup chain

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The batch name-resolution endpoint was wired up in api_endpoints.py but
the resolve_pubkey_names method and its _get_companion_name_by_pubkey
helper were not yet present.  Add both.

resolve_pubkey_names(pubkeys=<comma-separated hex>) returns a JSON map
of {pubkey: name|null} using the same priority chain as the rest of the
alias system: admin alias → adverts table → companion derivation.

44 tests across three files:
- test_sqlite_pubkey_aliases: CRUD against real in-memory SQLite
- test_storage_collector_name_resolution: alias-first priority chain
- test_resolve_pubkey_names_endpoint: batch resolution, companion
  fallback, whitespace handling, empty input, and error path

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@tjdownes tjdownes closed this May 1, 2026
@tjdownes tjdownes reopened this May 1, 2026
Migration 11 used MAX(id) to pick the canonical row per (room_hash,
client_pubkey) when rebuilding room_client_sync with the UNIQUE
constraint.  This was wrong: eviction writes a new row with
last_activity=0, and when that row has the highest id the migration
silently preserved the evicted state, discarding real activity data.

Fix migration 11's INSERT SELECT to JOIN against a subquery that
computes both MAX(id) (for operational columns) and MAX(last_activity)
(so the best-ever activity timestamp survives, regardless of which row
had the highest id).

Add migration 13 ("fix_room_client_sync_last_activity") to repair
devices that already ran the flawed migration 11.  For every client
where last_activity=0 but sync_since>0 (actively synced before the
bad migration), last_activity is restored to sync_since as the best
available estimate of when the client was last seen.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

1 participant