Skip to content

TRI-NET chat and calling: signed nicknames, CallKit, LiveKit, and Fullmoon UI - #90

Open
dmitrii-f-t27 wants to merge 32 commits into
mainfrom
feat/regen-final
Open

TRI-NET chat and calling: signed nicknames, CallKit, LiveKit, and Fullmoon UI#90
dmitrii-f-t27 wants to merge 32 commits into
mainfrom
feat/regen-final

Conversation

@dmitrii-f-t27

@dmitrii-f-t27 dmitrii-f-t27 commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

Refs #82

Follow-up to #89.

Summary

  • add signed per-device identity, exact nickname claim/lookup, multi-device linking, and encrypted direct/group chat
  • implement CallKit/PushKit call lifecycle, audible incoming-call presentation, separate audio/video intent, and terminal cleanup
  • route automatically over signed local mesh when available, with LiveKit/WebRTC fallback and macOS client parity
  • add the Fullmoon-inspired chat-first UI, presence, fingerprints, and server-authoritative unread state
  • integrate current main and preserve the previously published PR TRI-NET chat and calling: signed nicknames, CallKit, LiveKit, and Fullmoon UI #90 history without force-pushing
  • complete the macOS calling target and keep T27-generated Rust byte-identical while excluding it from hand-written formatting/lint rewrites

Validation

  • cargo fmt --all --check: passed
  • cargo clippy --all-targets -- -D warnings: passed
  • cargo build --verbose: passed
  • cargo test --verbose: passed
  • cargo test --manifest-path services/call-api/Cargo.toml: 24 passed
  • internet_call.t27: parse and typecheck passed with 0 errors / 0 warnings; 29 tests, 27 invariants, 1 benchmark; generated Rust matches byte-for-byte
  • iOS physical-device build-for-testing: passed
  • iPhone 17 physical unit run: 44/44 passed
  • macOS app build: passed

Current verification boundary

  • iPhone 13 was unavailable during the final run, so the final merged commit was not rerun on that device
  • the checked-in runtime endpoints are local (http://SSDs-MacBook-Pro.local:8080 and ws://SSDs-MacBook-Pro.local:7880)
  • public Internet/background calling is not verified or deployed: no confirmed public HTTPS/WSS/TURN route and no APNs provider credentials were available for this validation

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>
@dmitrii-f-t27
dmitrii-f-t27 marked this pull request as ready for review July 22, 2026 17:05
SSD DDD and others added 21 commits July 24, 2026 13:50
trios_radiod on 3 boards, no Ethernet: ETX convergence, DATA delivery,
and M4 internet-over-radio (Ethernet-less node 13 fetched public IP
182.232.227.12 via gateway node 11, entirely over 2.4 GHz). Six radiod
bring-up defects documented (one-shot writer, O(n) prebuffer, AGC blind,
own-TX DC leak, fused bursts, fixed jitter).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Boards 2+3 fully off Ethernet. Frequency sweep 915/1575/2400/2450/5800
MHz: links strongly frequency-dependent, 2450 MHz best (backbone solid +
board 12 joins). Stable reliable config = default 2.4 GHz, no retune:
board 13 (wire-free) fetched internet over radio (182.232.227.12),
gateway confirmed reply. Board 12 marginal (needs CSMA). Operating
recipe + reboot-restore documented.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…#9)

At 2425 MHz with CSMA/CA + hop-by-hop relay session fix, all three links
converge and board 12 (the previously-marginal node) fetched public IP
182.232.227.12 over the radio mesh. Documents the 4 changes (CSMA,
TRIOS_FREQ+channel scan, fetch retry, relay crypto fix), the 2.4 GHz
interferer hopping, and per-node tuning.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…er radio @2455 (refs #9)

Boards 2+3 physically off Ethernet; live channel scan picked 2455 MHz
(2425 had since jammed). Gateway fetched 182.232.227.12 and board 12
logged INTERNET-VIA-RADIO-MESH over the air, no cable but power+console.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- 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).
Implements exact nickname directory lookup, Internet and signed local call lifecycle, CallKit/PushKit handling, E2EE direct messages, Dala-style UI, and production deployment contracts.

Refs #82
# Conflicts:
#	phone/TriNetVideo/ViewModel.swift
#	phone/TriNetVideo/Views.swift
#	phone/desktop/VideoCallTab.swift
#	phone/shared/InternetCall.swift
# Conflicts:
#	src/bin/tri_rti.rs
#	src/lib.rs
@dmitrii-f-t27 dmitrii-f-t27 changed the title Follow-up: signed nickname calling, group chat, and mesh lab configs TRI-NET chat and calling: signed nicknames, CallKit, LiveKit, and Fullmoon UI Aug 24, 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.

1 participant