c5264deb46
mavwaked and mavenclient have been written, tested and deployed nowhere since V-463 parked them. homesrv has a microphone because it is a laptop, but it is in the wrong room. workpc is where he sits, and it has a fifine on card 0. V-515 said this was a config line: "ipc.Dial already speaks tcp://host:port?token=... so this is config, not protocol work". That premise is wrong and it is worth writing down. Both mavwaked and mavenclient speak internal/voice through voice.Dial, not internal/ipc. The netaddr token guards the daemon-to-daemon IPC seam and never touches the voice wire. That wire is plaintext with no auth at all, and voice/server.go says so: production binds inside the wg tunnel, because "the wg layer IS the L0 floor". workpc is not a wg peer. It sits on wlan0. So the floor here is ssh: mavend publishes the voice port to homesrv loopback only (127.0.0.1:9110, since host 9100 is Vikunja's MCP), and a user unit on workpc forwards it over his key. Nothing new is on the LAN. That mattered more than it looks: SurfaceVoice caps acts at L0, so an unauthorized speaker could not run a destructive tool, but L0 does not cap reading. A LAN bind would let anyone on the wifi hear his facts, his notes and his calendar read back. Two things the deployment found that no test could: The vendored onnxruntime under deps/ has two copies and the stale one is 1.17.1. The Go binding asks for API 26, so silero refused to load until 1.26.0 was shipped instead. mavwaked logged it and kept running on the energy threshold, which is the designed fallback working. The fifine offers 2 channels at 44100 or 48000 and nothing else. mavwaked asks arecord for 16kHz mono, so hw:0,0 dies on "Channels count non available" before a frame is read. The unit uses plughw:0,0 so ALSA downmixes and resamples. Verified end to end through mavwaked's own -test mode, so no human had to speak: a 2.43s Russian fixture reached mavend over the tunnel, was transcribed on the workstation by CW2, routed intent=query, claimed by the calendar source, and came back as 3.68s of piper audio. There is still no wake word (V-487 stage two), so the loop runs open. Silero is passed on purpose, since it declines white noise the energy floor accepts. Barge-in is not, because its threshold is room-specific and this room has no number yet.
41 lines
1.5 KiB
Desktop File
41 lines
1.5 KiB
Desktop File
# maven-voice-tunnel — the ssh leg that carries the voice wire to homesrv.
|
|
#
|
|
# Runs on workpc, as a user unit (`systemctl --user`), beside mavgpud.service.
|
|
#
|
|
# WHY THIS EXISTS AT ALL. internal/voice is plaintext and unauthenticated.
|
|
# Its own server doc says production binds inside the wg tunnel, because "the
|
|
# wg layer IS the L0 floor". workpc is not a wg peer, it sits on wlan0. So ssh
|
|
# is the substitute floor: it authenticates with his key and encrypts the leg,
|
|
# and mavend's published port stays on homesrv loopback (127.0.0.1:9110).
|
|
# Nothing about this puts a Maven port on the LAN.
|
|
#
|
|
# Do not replace this with a LAN bind. SurfaceVoice caps acts at L0, so an
|
|
# unauthorized speaker could not run a destructive tool. It would still hear
|
|
# his facts, his notes and his calendar read back, and L0 does not cap reading.
|
|
#
|
|
# install: cp to ~/.config/systemd/user/ on workpc
|
|
# systemctl --user enable --now maven-voice-tunnel.service
|
|
|
|
[Unit]
|
|
Description=SSH tunnel to mavend's voice wire on homesrv
|
|
After=network-online.target
|
|
Wants=network-online.target
|
|
|
|
[Service]
|
|
# -N: no remote command, forwarding only.
|
|
# ExitOnForwardFailure: fail loudly rather than sit up with a dead forward,
|
|
# which is what makes Restart meaningful.
|
|
# ServerAlive*: a laptop that suspends drops the tunnel silently otherwise.
|
|
ExecStart=/usr/bin/ssh -N \
|
|
-o ExitOnForwardFailure=yes \
|
|
-o ServerAliveInterval=30 \
|
|
-o ServerAliveCountMax=3 \
|
|
-o BatchMode=yes \
|
|
-L 127.0.0.1:9100:127.0.0.1:9110 \
|
|
kami@192.168.1.104
|
|
Restart=always
|
|
RestartSec=5
|
|
|
|
[Install]
|
|
WantedBy=default.target
|