mirror of
https://github.com/jamiepine/voicebox.git
synced 2026-09-19 23:00:45 -07:00
Mobile companion app + paired-device backend
New iOS-first companion (Expo SDK 54 + NativeWind v4) with three tabs: Captures (the hero — floating gold mic, live mic-meter waveform, expand-row playback), Generate (profile picker + speak + autoplay + recent), and Voices (searchable profile list). Pairing (V0): backend mints a one-time token, mobile scans/pastes the voicebox:// URL, server returns a long-lived bearer it stores only as a SHA-256 hash. Bearer-or-loopback auth applied to every user-data router so binding 0.0.0.0 doesn't leak existing endpoints. Loopback callers (the desktop app) keep their friction-free access. Desktop Settings → Mobile pane: live host picker (LAN / Tailscale auto- detected via the App-bundle binary path on macOS), QR rendering, 5-minute expiry countdown, copyable URL fallback, paired-device list with revoke. Auto-closes when a new device pairs. just dev now binds the backend to 0.0.0.0 so paired phones can reach it — and just setup-python pins mlx-audio==0.4.1 + mlx-lm so fresh Apple Silicon worktrees get a working STT path on first install.
This commit is contained in:
+42
-19
@@ -1,6 +1,23 @@
|
||||
"""Route registration for the voicebox API."""
|
||||
"""Route registration for the voicebox API.
|
||||
|
||||
from fastapi import FastAPI
|
||||
Authentication model
|
||||
--------------------
|
||||
Two router groups:
|
||||
|
||||
* **Open** — ``health`` (status checks anyone on the LAN may probe) and
|
||||
``pairing`` (pre-pair endpoints + admin endpoints with their own
|
||||
loopback-only or token-only gates).
|
||||
|
||||
* **Protected** — everything else, gated by ``require_bearer_or_loopback``:
|
||||
loopback callers (the desktop app over 127.0.0.1) pass without auth as
|
||||
before; LAN/Tailscale callers must present a valid paired-device bearer.
|
||||
This is what lets ``just dev`` bind to 0.0.0.0 without exposing user
|
||||
data to anyone on the same network.
|
||||
"""
|
||||
|
||||
from fastapi import Depends, FastAPI
|
||||
|
||||
from ..utils.auth import require_bearer_or_loopback
|
||||
|
||||
|
||||
def register_routers(app: FastAPI) -> None:
|
||||
@@ -23,22 +40,28 @@ def register_routers(app: FastAPI) -> None:
|
||||
from .speak import router as speak_router
|
||||
from .mcp_bindings import router as mcp_bindings_router
|
||||
from .events import router as events_router
|
||||
from .pairing import router as pairing_router
|
||||
|
||||
# Open — health probes and the pre-pair / admin pairing endpoints.
|
||||
app.include_router(health_router)
|
||||
app.include_router(profiles_router)
|
||||
app.include_router(channels_router)
|
||||
app.include_router(generations_router)
|
||||
app.include_router(history_router)
|
||||
app.include_router(transcription_router)
|
||||
app.include_router(llm_router)
|
||||
app.include_router(captures_router)
|
||||
app.include_router(stories_router)
|
||||
app.include_router(effects_router)
|
||||
app.include_router(audio_router)
|
||||
app.include_router(models_router)
|
||||
app.include_router(settings_router)
|
||||
app.include_router(tasks_router)
|
||||
app.include_router(cuda_router)
|
||||
app.include_router(speak_router)
|
||||
app.include_router(mcp_bindings_router)
|
||||
app.include_router(events_router)
|
||||
app.include_router(pairing_router)
|
||||
|
||||
# Protected — loopback callers pass through; LAN callers need a paired bearer.
|
||||
protected = [Depends(require_bearer_or_loopback)]
|
||||
app.include_router(profiles_router, dependencies=protected)
|
||||
app.include_router(channels_router, dependencies=protected)
|
||||
app.include_router(generations_router, dependencies=protected)
|
||||
app.include_router(history_router, dependencies=protected)
|
||||
app.include_router(transcription_router, dependencies=protected)
|
||||
app.include_router(llm_router, dependencies=protected)
|
||||
app.include_router(captures_router, dependencies=protected)
|
||||
app.include_router(stories_router, dependencies=protected)
|
||||
app.include_router(effects_router, dependencies=protected)
|
||||
app.include_router(audio_router, dependencies=protected)
|
||||
app.include_router(models_router, dependencies=protected)
|
||||
app.include_router(settings_router, dependencies=protected)
|
||||
app.include_router(tasks_router, dependencies=protected)
|
||||
app.include_router(cuda_router, dependencies=protected)
|
||||
app.include_router(speak_router, dependencies=protected)
|
||||
app.include_router(mcp_bindings_router, dependencies=protected)
|
||||
app.include_router(events_router, dependencies=protected)
|
||||
|
||||
Reference in New Issue
Block a user