Skip to content

Follow-up: signed nickname calling, group chat, and mesh lab configs - #90

Open
deborahnelson8788726 wants to merge 12 commits into
mainfrom
feat/regen-final
Open

Follow-up: signed nickname calling, group chat, and mesh lab configs#90
deborahnelson8788726 wants to merge 12 commits into
mainfrom
feat/regen-final

Conversation

@deborahnelson8788726

Copy link
Copy Markdown
Collaborator

Follow-up to #89.

Summary

  • add per-device signed identity, unique nickname lookup, multi-device linking, and group chat
  • route calls over LiveKit/WebRTC or encrypted local/mesh UDP while preserving the latest ringing, group, BWE, and HMAC INVITE protections
  • add reproducible three-node mesh lab configs
  • reconcile iOS/macOS Xcode project and signing settings

Validation

  • iOS Simulator build: passed
  • iOS unit tests: passed
  • macOS build: passed
  • plist validation and git diff check: passed
  • cargo test --workspace: blocked by pre-existing t27-generated Rust errors (Vec without a generic type and multipath_routing bool/u32 output); no generated files were hand-edited

SSD DDD and others added 6 commits July 22, 2026 17:02
Add per-device P-256 identity, unique nickname discovery, account linking, presence-aware LiveKit call fan-out, and signed mesh invitations. Persist account-level group chats with membership checks and idempotent messages, expose the same UI on iOS and macOS, and add service and client tests.
Clear stale CallKit transactions before new calls, use LiveKit state for the call UI, and recover remote video subscriptions that arrive before the delegate callback. Add focused connection diagnostics. Verified on ssd26 and t27_dev with bidirectional audio/video for 53 seconds and zero RTP packet loss.
WAVE #15 authenticated the INVITE but left it replayable: a valid HMAC only
proves the sender knew the PSK once, so a sniffed INVITE could be replayed to
force a ring/auto-join later. Add a TS_MS field to the (HMAC-covered) payload and
reject any INVITE whose timestamp is missing or outside a +/-15s window. Verified
live: a replayed INVITE (valid MAC, 60s-old TS) -> 0 auto-joins; a fresh one ->
auto-joins. Both platforms; smoke updated and still PASSes. Residual: a 15s window
allows an immediate replay (a seen-MAC cache would close it fully) - left as an option.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@deborahnelson8788726
deborahnelson8788726 marked this pull request as ready for review July 22, 2026 17:05
TRI-NET dev and others added 6 commits July 24, 2026 20:16
- IncomingCallOverlay: gradient backdrop + breathing glow, 3 rippling rings,
  gradient avatar disc, ENCRYPTED . FORWARD-SECRET badge, glowing Accept button
  (ring/haptics/accept-decline wiring preserved). answerButton gains a glow param.
- HANDOFF.md: full continuation guide (running servers, folders, build/run,
  4-feature status + file:line, APNs .p8 requirement, next steps).
Feature C: the server already returns unread_count per chat and
total_unread_count; the client now consumes them.

- InternetCall.swift: GroupChatSummary decodes unread_count (optional for old
  servers); GroupChatsResponse decodes total_unread_count; groupChats() returns
  both. GroupChatController tracks unreadByChat + totalUnread, fires
  onNewMessage for messages from others, clears a chat's badge when opened, and
  reconciles local counts with the server's on each 3s refresh.
- iOS ViewModel + macOS CallManager: groupChat.onNewMessage plays the existing
  ChatChime (same blip as in-call 1:1 chat).
- iOS Views + macOS VideoCallTab: numeric unread badge on the group-chats icon
  and on each chat-list row, with accessibility labels.
- macOS BUILD SUCCEEDED; iOS Simulator BUILD SUCCEEDED.
The call screen looked like a network-engineer tool: raw IP entry, IP/port in
the self line, an IP quick-dial list, and a Route picker as the first thing you
see. Calls were hard to start for a normal user.

Now the flow is: search by @Nickname -> tap a result to call them. Route (Auto
by default) is collapsed behind a disclosure. IPs are gone from the UI.

- Search field placeholder is now 'Search by @Nickname' (was 'nickname or IP').
- Results show each contact as a card with an avatar, nickname, and a Call
  button (macOS) / tap-to-call (iOS) — select + start the call in one action.
- Self line shows 'You are @nick' instead of '@nick | IP:port | fingerprint'.
- Removed the raw-IP quick-dial chips on both platforms (mesh-era affordance).
- Route picker moved under a 'Connection' disclosure (Auto is right for nearly
  everyone; LAN peers still appear by name via the roster).
- macOS + iOS both BUILD SUCCEEDED.

Server call-signaling is verified end-to-end by examples/live_call_check.
User-driven fixes after the previous UI pass was confusing.

Call flow — 'enter a nick, add it, tap to call' (iOS + macOS):
- Saved contacts list (@published, persisted). Add a contact by typing a
  nickname; tap the phone button to call them on the selected route.
- callNickname(_:) helper sets callee/searchQuery and starts the call.
- Directory search (online users) now adds + calls in one tap too.

Ringtone on incoming INTERNET calls (was mesh-only):
- internet.onIncomingCall now sets vm.incomingCall with an internetCallID, so
  the IncomingCallOverlay + RingSynth tri-tone fires for LiveKit calls too,
  not just mesh UDP. Previously internet calls were silent in-app (CallKit only).
- acceptIncoming branches: internetCallID -> answerInternetCall; else mesh.
- Shared beginIncomingTimeout() for the 40s auto-miss on both routes.

UI clarity — settings/icon tap targets:
- Top-bar buttons (group chats, settings) enlarged to 48pt with contentShape +
  solid backgrounds + accessibility labels, so icons are not crowded and the
  whole circle is tappable.
- 'Connection' disclosure shows the route (Internet default, Local Mesh) instead
  of a bare segmented picker as the first thing on screen.
- Removed raw-IP quick-dial chips on both platforms (nickname is the path).

Chat chime on incoming messages: already wired (groupChat.onNewMessage ->
chatChime.play()).

macOS + iOS both BUILD SUCCEEDED; server call-signaling verified end-to-end by
examples/live_call_check (create -> incoming -> join, all green).
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