2 Commits
v0.1.5 ... main

Author SHA1 Message Date
Fredrik Johansson
697a7e614d fix: challenge nonce must be 32 bytes per YAW/2 §5.1
All checks were successful
Build / Build & release (push) Successful in 13m46s
The anchor was sending a 16-byte nonce. The spec (yaw2.0-protocol.md §5.1
and yaw2-implementation.md §7.1) requires 32 bytes. Any spec-conformant
peer would fail join signature verification against this anchor, breaking
interop. Signature verification was already using the raw nonce bytes
(not hex), so only the allocation size needed changing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02 18:35:57 +02:00
Fredrik Johansson
d07342e97e docs: fix placeholder URLs in QUICKSTART; add committed example scripts
QUICKSTART.md had the author's personal domain as the example anchor URL
(wss://waste.dev.xplwd.com/ws) which would confuse anyone reading it.
Replaced with wss://YOUR_ANCHOR_DOMAIN/ws and added a new Option 3
section explaining the example scripts.

Added committed *.example versions of the four local-workflow scripts
(launch-tui, launch-web, deploy-web, serve-web). The real filenames are
gitignored so local edits (HOST, ANCHOR, etc.) are never accidentally
committed; the .example files serve as templates users copy once.
Each script fails fast if the placeholder URL/host is still set.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02 11:51:02 +02:00
6 changed files with 266 additions and 6 deletions

View File

@@ -41,13 +41,33 @@ On Linux and Windows a tray icon appears — closing the window hides to tray ra
---
## Option 3 — Run the daemon manually (headless / power users)
## Option 3 — Run the daemon + TUI or web UI locally (power users / dev)
Example scripts are provided for the common local workflows. Copy them and fill in your anchor URL:
```bash
# TUI (terminal UI):
cp launch-tui.sh.example launch-tui.sh
$EDITOR launch-tui.sh # set ANCHOR=wss://your-anchor/ws
./launch-tui.sh
# Web UI in daemon mode (Vite dev server + daemon):
cp launch-web.sh.example launch-web.sh
$EDITOR launch-web.sh # set ANCHOR=wss://your-anchor/ws
./launch-web.sh
```
The real script files are gitignored so your local edits (anchor URL, alias, network) are never accidentally committed.
---
## Option 4 — Run the daemon manually (headless)
If you want the daemon running in the background without the desktop UI — on a server, over SSH, or with the web UI in a browser pointed at your local machine:
```bash
# Download waste-daemon from the releases page, then:
./waste-daemon -alias yourname -anchor wss://your-anchor-server/ws
./waste-daemon -alias yourname -anchor wss://YOUR_ANCHOR_DOMAIN/ws
```
Then open the web UI in a browser at the anchor URL, or point the web UI's daemon mode at `ws://127.0.0.1:17338`.
@@ -83,7 +103,7 @@ The anchor is a tiny signaling server that helps peers find each other — it ne
```bash
# On your VPS:
./waste-anchor -bind 127.0.0.1:8080
./waste-anchor -bind 127.0.0.1:8080 -turn-secret YOUR_COTURN_SECRET
```
Put it behind nginx with a `/ws` WebSocket proxy and serve the web UI static files at `/`. See [README.md](README.md#hosting-on-a-vps) for the full nginx setup.
Put it behind nginx with `/ws` and `/turn-credentials` proxied to the anchor, and the web UI static files at `/`. See [README.md](README.md#hosting-on-a-vps) for the full nginx setup.

View File

@@ -155,8 +155,8 @@ func (a *anchor) handleWS(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithCancel(r.Context())
defer cancel()
// Send a challenge nonce immediately.
nonce := make([]byte, 16)
// Send a challenge nonce immediately. §5.1 requires 32 bytes.
nonce := make([]byte, 32)
rand.Read(nonce)
nonceHex := hex.EncodeToString(nonce)
if err := wsjson.Write(ctx, conn, proto.AnchorMessage{

32
deploy-web.sh.example Normal file
View File

@@ -0,0 +1,32 @@
#!/usr/bin/env bash
# deploy-web.sh — build and push the web UI to the VPS.
# Assumes SSH agent forwarding is set up.
#
# SETUP: copy this file to deploy-web.sh (gitignored) and set HOST below.
#
# Usage:
# ./deploy-web.sh
#
# Optional env vars:
# HOST SSH target (user@host) (required — edit below)
# REMOTE_DIR path on VPS (default: ~/waste-www)
set -euo pipefail
HOST="${HOST:-user@YOUR_VPS_IP}" # ← edit this
REMOTE_DIR="${REMOTE_DIR:-~/waste-www}"
if [[ "$HOST" == *YOUR_VPS_IP* ]]; then
echo "error: edit HOST in this script (or export HOST=user@your-vps before running)" >&2
exit 1
fi
echo "→ building web UI…"
"$(dirname "$0")/build-web.sh"
echo "→ syncing to $HOST:$REMOTE_DIR"
rsync -azv --delete \
--exclude='config.js' \
web/dist/ "$HOST:$REMOTE_DIR/"
echo "✓ done"

96
launch-tui.sh.example Normal file
View File

@@ -0,0 +1,96 @@
#!/usr/bin/env bash
# launch-tui.sh — build and launch the TUI against a remote anchor.
# Starts a local daemon then opens the Bubble Tea terminal UI.
#
# SETUP: copy this file to launch-tui.sh (gitignored) and set ANCHOR below.
#
# Usage:
# ./launch-tui.sh
# ALIAS=alice NETWORK=friends ./launch-tui.sh
#
# Optional env vars (all have defaults):
# ANCHOR anchor WebSocket URL (required — edit below)
# NETWORK network name to join (default: "friends")
# ALIAS display name (default: $USER)
# DATA_DIR identity + message store dir (default: ~/.waste-$ALIAS)
# IPC_PORT local daemon IPC port (default: 17337)
# SHARE_DIR directory to share with peers (optional)
set -euo pipefail
ANCHOR="${ANCHOR:-wss://YOUR_ANCHOR_DOMAIN/ws}" # ← edit this
NETWORK="${NETWORK:-friends}"
ALIAS="${ALIAS:-${USER:-anon}}"
DATA_DIR="${DATA_DIR:-${HOME}/.waste-${ALIAS}}"
_DEFAULT_ALIAS="${USER:-anon}"
if [ "${ALIAS}" = "${_DEFAULT_ALIAS}" ]; then
IPC_PORT="${IPC_PORT:-17337}"
else
_HASH=$(printf '%d' "0x$(printf '%s' "$ALIAS" | md5sum | cut -c1-4)")
IPC_PORT="${IPC_PORT:-$(( 17400 + _HASH % 1000 ))}"
fi
SHARE_DIR="${SHARE_DIR:-}"
RED='\033[0;31m'; GREEN='\033[0;32m'; DIM='\033[2m'; BOLD='\033[1m'; RESET='\033[0m'
if [[ "$ANCHOR" == *YOUR_ANCHOR_DOMAIN* ]]; then
echo -e "${RED}error: edit ANCHOR in this script (or export ANCHOR=wss://... before running)${RESET}" >&2
exit 1
fi
mkdir -p "$DATA_DIR"
echo ""
echo -e "${BOLD}waste TUI${RESET}"
echo -e "${DIM}anchor : ${BOLD}${ANCHOR}${RESET}"
echo -e "${DIM}network : ${BOLD}${NETWORK}${RESET}"
echo -e "${DIM}alias : ${BOLD}${ALIAS}${RESET}"
echo -e "${DIM}data : ${DATA_DIR}${RESET}"
[ -n "$SHARE_DIR" ] && echo -e "${DIM}share : ${SHARE_DIR}${RESET}"
echo ""
echo -e "${DIM}building binaries…${RESET}"
go build -o /tmp/waste-daemon-run ./cmd/daemon
go build -o /tmp/waste-tui-run ./cmd/tui
echo -e "${GREEN}✓ built${RESET}"
echo ""
existing=$(lsof -ti tcp:"$IPC_PORT" 2>/dev/null || true)
[ -n "$existing" ] && kill "$existing" 2>/dev/null && sleep 0.3 || true
echo -e "${DIM}starting daemon on :${IPC_PORT}…${RESET}"
WS_PORT=$(( IPC_PORT + 1 ))
/tmp/waste-daemon-run \
-alias "$ALIAS" -data-dir "$DATA_DIR" \
-ipc-port "$IPC_PORT" -ws-port "$WS_PORT" \
-anchor "$ANCHOR" \
2>/tmp/waste-daemon.log &
DAEMON_PID=$!
n=0
while ! nc -z 127.0.0.1 "$IPC_PORT" 2>/dev/null; do
sleep 0.1; n=$(( n + 1 ))
[ "$n" -gt 80 ] && echo -e "${RED}daemon failed — check /tmp/waste-daemon.log${RESET}" >&2 && exit 1
done
echo -e "${GREEN}✓ daemon started (pid ${DAEMON_PID})${RESET}"
sleep 0.3
if [ -n "$SHARE_DIR" ]; then
JOIN=$(jq -cn --arg net "$NETWORK" --arg dir "$SHARE_DIR" \
'{"type":"join_network","network_name":$net,"share_dir":$dir}')
else
JOIN=$(jq -cn --arg net "$NETWORK" '{"type":"join_network","network_name":$net}')
fi
echo "$JOIN" | nc -q 0 127.0.0.1 "$IPC_PORT" >/dev/null 2>&1 || true
echo -e "${DIM}joined network: ${BOLD}${NETWORK}${RESET}"
cleanup() { kill "$DAEMON_PID" 2>/dev/null || true; }
trap cleanup EXIT INT TERM
echo ""
echo -e "${BOLD}launching TUI${RESET} — ${DIM}ctrl+c to quit${RESET}"
echo ""
exec /tmp/waste-tui-run -ipc "$IPC_PORT" -network "$NETWORK"

74
launch-web.sh.example Normal file
View File

@@ -0,0 +1,74 @@
#!/usr/bin/env bash
# launch-web.sh — start the daemon and open the web UI Vite dev server.
# For local development / daemon-mode browsing.
#
# SETUP: copy this file to launch-web.sh (gitignored) and set ANCHOR below.
#
# Usage:
# ./launch-web.sh
# ALIAS=alice NETWORK=friends ./launch-web.sh
set -euo pipefail
ANCHOR="${ANCHOR:-wss://YOUR_ANCHOR_DOMAIN/ws}" # ← edit this
NETWORK="${NETWORK:-friends}"
ALIAS="${ALIAS:-${USER:-anon}}"
DATA_DIR="${DATA_DIR:-${HOME}/.waste-${ALIAS}}"
IPC_PORT="${IPC_PORT:-17337}"
WS_PORT=$(( IPC_PORT + 1 ))
if [[ "$ANCHOR" == *YOUR_ANCHOR_DOMAIN* ]]; then
echo "error: edit ANCHOR in this script (or export ANCHOR=wss://... before running)" >&2
exit 1
fi
PIDS=()
cleanup() {
for pid in "${PIDS[@]:-}"; do kill "$pid" 2>/dev/null || true; done
wait 2>/dev/null || true
}
trap cleanup EXIT INT TERM
for port in "$IPC_PORT" "$WS_PORT"; do
existing=$(lsof -ti tcp:"$port" 2>/dev/null || true)
[ -n "$existing" ] && kill "$existing" 2>/dev/null || true
done
for port in "$IPC_PORT" "$WS_PORT"; do
n=0
while lsof -ti tcp:"$port" >/dev/null 2>&1; do
sleep 0.1; n=$(( n + 1 )); [ "$n" -gt 30 ] && break
done
done
mkdir -p "$DATA_DIR"
echo "alias : $ALIAS"
echo "network : $NETWORK"
echo "anchor : $ANCHOR"
echo "ws-port : $WS_PORT"
echo ""
echo "building daemon…"
go build -o /tmp/waste-daemon-web ./cmd/daemon
/tmp/waste-daemon-web \
-alias "$ALIAS" -data-dir "$DATA_DIR" \
-ipc-port "$IPC_PORT" -ws-port "$WS_PORT" \
-anchor "$ANCHOR" \
2>/tmp/waste-daemon-web.log &
PIDS+=($!)
n=0
while ! nc -z 127.0.0.1 "$IPC_PORT" 2>/dev/null; do
sleep 0.1; n=$(( n + 1 ))
[ "$n" -gt 80 ] && echo "daemon failed to start — check /tmp/waste-daemon-web.log" >&2 && exit 1
done
sleep 0.2
jq -cn --arg net "$NETWORK" '{"type":"join_network","network_name":$net}' \
| nc -q0 127.0.0.1 "$IPC_PORT" >/dev/null 2>&1 || true
echo "daemon ready — joined $NETWORK"
echo ""
npm run dev --prefix "$(dirname "$0")/web"

38
serve-web.sh.example Normal file
View File

@@ -0,0 +1,38 @@
#!/usr/bin/env bash
# serve-web.sh — start (or restart) the static file server on the VPS.
# Runs `npx serve` in the background, logs to ~/waste-www.log.
#
# SETUP: copy this file to serve-web.sh (gitignored) and set HOST below.
#
# Usage:
# ./serve-web.sh
#
# Optional env vars:
# HOST SSH target (user@host) (required — edit below)
# REMOTE_DIR path on VPS (default: ~/waste-www)
# PORT local port on VPS (default: 1337)
set -euo pipefail
HOST="${HOST:-user@YOUR_VPS_IP}" # ← edit this
REMOTE_DIR="${REMOTE_DIR:-~/waste-www}"
REMOTE_LOG="~/waste-www.log"
REMOTE_PID="~/waste-www.pid"
PORT="${PORT:-1337}"
if [[ "$HOST" == *YOUR_VPS_IP* ]]; then
echo "error: edit HOST in this script (or export HOST=user@your-vps before running)" >&2
exit 1
fi
ssh "$HOST" bash <<EOF
if [ -f $REMOTE_PID ]; then
kill \$(cat $REMOTE_PID) 2>/dev/null || true
rm -f $REMOTE_PID
fi
echo "[\$(date)] starting npx serve on port $PORT" >> $REMOTE_LOG
nohup npx serve -s $REMOTE_DIR -l $PORT >> $REMOTE_LOG 2>&1 &
echo \$! > $REMOTE_PID
echo "→ started (pid \$(cat $REMOTE_PID)), logging to $REMOTE_LOG"
EOF