7 Commits

Author SHA1 Message Date
Fredrik Johansson
d02e18e212 feat: per-network share directories + isolation test
Each network now carries its own share dir, set at join_network time via
optional share_dir field or updated live with set_share_dir. The global
-share-dir daemon flag becomes a fallback default.

- proto: add ShareDir/DownloadDir to NetworkInfo and IpcMessage
- netmgr: Join accepts shareDir override; SetShareDir updates live
- ipc: wire join_network share_dir and set_share_dir command
- daemon: remove -share-dir from auto-join path (pass "" for default)
- test-network.sh: per-network join with share_dir; isolation verification
  section confirms alice/friends and alice/work share dirs are independent
- test-tui.sh: join_network with share_dir; peer IDs resolved after join

All tests pass: YAW/2.1 FS, share isolation, file transfer, persistence.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 15:13:26 +02:00
Fredrik Johansson
274ff423f6 feat: implement YAW/2.1 forward-secret signaling
Upgrades the signaling layer from static X25519 (2.0) to per-session
ephemeral X25519 (2.1). Recorded signaling traffic cannot be decrypted
even if long-term Ed25519 keys later leak, because esk is zeroed on
session close.

Protocol:
- Each peer generates a fresh X25519 keypair (esk/epk) per session.
- Peers exchange signed `ekey` messages sealed under static keys before
  the offer/answer. Offer/answer/candidate payloads are then sealed with
  ephemeral keys (crypto_box(·, peer_epk, my_esk)).
- ekey sig binds both peer IDs and the epk to prevent replay to third parties.
- Offerer waits up to 2 s for the peer's ekey; if none arrives it falls back
  to YAW/2.0 static-key sealing and logs "2.0 fallback offer".
- 2.0 peers silently ignore the unknown `ekey` kind — full interop preserved.

Implementation:
- crypto.go: add EphemeralKey.PublicRaw/PrivateRaw/Wipe helpers.
- proto.go: add SigEkey kind; EPK/V/EkeySig fields on SignalingPayload.
- anchor/client.go: replace flat pcs map with peerSession struct tracking
  ephemeral keys, peerEPK, and fs flag; openBoxAuto tries ephemeral then
  static; sealAndSend chooses seal based on session state.
- test-network.sh: pipe daemon stderr through tee to daemon.log; add
  YAW/2.1 FS verification section.
- test-tui.sh: same daemon.log capture.
- README.md: document 2.1 forward secrecy, file transfer IPC, updated roadmap.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 14:45:15 +02:00
Fredrik Johansson
0051c8fdbf Remove hardcoded home path from test scripts
Share directories are now created under \$DATA_ROOT/<peer>/share/
with generated dummy files instead of pointing at /home/frejoh/Downloads.
Tests are now fully self-contained and safe to share.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 13:42:28 +02:00
Fredrik Johansson
b87f14a361 Bring wire protocol into full YAW/2 spec compliance
Five interop issues fixed against PROTOCOL.md:

- Join signature now covers nonce_raw || net_ascii (64-char UTF-8 hex
  string) as specified in §5.1, not net_raw_bytes. Both anchor server
  and client updated to match.

- Chat wire fields renamed to spec names: text/ts (Unix ms int64)
  replacing body/sent_at (ISO timestamp). Flat layout on PeerMessage
  matches §8 exactly; store and TUI updated accordingly.

- Direct messages now use the spec "pm" type (flat {type,mid,text,ts})
  instead of chat+to. Receiver reconstructs a ChatMessage with
  dm:<short-id> room for IPC/storage. §8 compliant.

- File transfer message types changed to spec hyphenated names:
  file-offer, file-accept, file-cancel, file-done with spec field
  names (name/size not filename/size_bytes). §9 compliant.

- DataChannel open-race (§14 gotcha #3) fixed with sync.Once: doOpen
  fires on OnOpen callback or immediately if the channel is already
  open when WireDataChannel is called (answerer race).

Also fixes two bugs found during testing:

- mid was missing from outgoing wire messages, causing all received
  messages to arrive with mid="" and collide on the UNIQUE DB
  constraint. mid is now included on all sent chat/pm messages; a
  random mid is generated for any received message that omits it.

- Test scripts hardened: kill -9 + active lsof polling replaces blind
  sleep for port cleanup; join_network sent before peer_field queries
  (local_peer is now network-scoped and nil until joined).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 11:38:01 +02:00
Fredrik Johansson
8d3ca9d331 Add file listing: share-dir flag, file_list_req/resp DataChannel messages
- proto: FileEntry, FileListResp types; MsgFileListReq/Resp msg types;
  CmdGetFileList + EvtFileList IPC types; Files field on IpcMessage
- mesh: ShareDir field + ScanShareDir(); on DataChannel open, auto-send
  MsgFileListReq to new peer; handle MsgFileListReq (scan + reply) and
  MsgFileListResp (emit EvtFileList to IPC subscribers)
- ipc: get_file_list command — own list returned immediately; remote peer
  list requested via DataChannel (response arrives as EvtFileList event)
- daemon: -share-dir flag wired to mesh.ShareDir
- test scripts: pass -share-dir /home/frejoh/Downloads/{alice,bob,charlie};
  test-network.sh verifies each peer's own file list via get_file_list
- FUTURE.md: document per-network share directories and multi-network design

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 19:07:11 +02:00
Fredrik Johansson
5a0bcee8c6 Fix TUI startup and test script bugs
- TUI: replace per-call bufio.Scanner with a goroutine+channel reader
  (lineReader) so a single scanner lives for the connection lifetime;
  previous pattern silently dropped messages due to scanner read-ahead
- test-tui.sh / test-network.sh: add `return 0` to wait_port — when the
  port opens and the while condition becomes false, bash returned the
  condition's exit code (1) to the caller, tripping set -e immediately
- .gitignore: use /tui (root-only) instead of tui to avoid ignoring cmd/tui/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 18:46:40 +02:00
Fredrik Johansson
714ac15816 Add Bubble Tea TUI (cmd/tui) with three-pane layout
- Connects to a running daemon's IPC port on startup
- Sends join_network then get_state; listens for events in real time
- Three-pane layout: room list (left), message history (centre), peers (right)
- Tab/Shift+Tab to switch rooms, Enter to send, PgUp/PgDn to scroll
- DM rooms appear automatically when a DM arrives
- test-tui.sh boots the full stack (anchor + 3 peers) and opens the TUI
  as alice, with bob and charlie sending periodic messages as live noise
- README: layout diagram, key bindings, TUI section; roadmap item marked done

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 18:30:56 +02:00