Repository navigation
feat(local): LAN/Tailscale access + secure-context UUID polyfill - #113
betoneira26 wants to merge 1 commit into
Conversation
- vite.config: bind 0.0.0.0 and allow LAN/tailnet hosts so the dev server is reachable beyond loopback (the API stays on 127.0.0.1 and is proxied). - src/client/polyfills: fall back to a getRandomValues-derived v4 UUID when crypto.randomUUID is missing. On plain-HTTP access via an IP (not a secure context) the CopilotKit client threw and the Dot hung on "thinking". - docs/LOCAL-SETUP: reproducible runbook (local Intelligence stack, LAN/tailnet gateway forwarding, Slack managed channel, voice). - deployment/local: socat systemd units to expose the realtime gateway port and an .env template. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
4b940c1 to
83864ff
Compare
NathanTarbert
left a comment
There was a problem hiding this comment.
Thanks @betoneira26, this is a really useful writeup. The explanation of why crypto.randomUUID disappears on plain-HTTP LAN addresses is clear. The polyfill does it right: it only installs when randomUUID is missing, uses crypto.getRandomValues with the correct version and variant bits, and loads as a module so the CSP stays intact. The runbook covers the parts people usually get stuck on, like the gateway port the browser needs and local Slack and voice.
The part I'd change before merging is the Vite config. With host: '0.0.0.0' and allowedHosts: true set unconditionally, every npm run dev would listen on the network, not just setups that want LAN access, and Vite's host check that protects against DNS rebinding is turned off. The Vite dev server also serves project files directly, outside OpenDots' own auth, so it isn't a good thing to expose beyond localhost even with a token set.
A safer shape would be:
- Keep
127.0.0.1as the default and make LAN access opt-in, for examplenpm run dev -- --hostor an env flag that sets the host. - Use an explicit
allowedHostslist, like the LAN IP or tailnet name, rather thantrue. - For access from other machines, have the runbook use a production build served by the OpenDots server, with
OWNER_TOKENset and HTTPS in front (tailscale serveworks well for that), rather than the Vite dev server.
Two smaller things in the runbook. deployment/local/opendots-gateway-lan.service has bind=192.168.1.38 hardcoded, which should be a placeholder. The Funnel example exposes the whole local Intelligence dashboard publicly. If Slack only needs the events path, funnelling just that would be safer.
Adds two small code changes plus a runbook for running OpenDots self-hosted (local CopilotKit Intelligence) and reaching it from other machines on a LAN or tailnet.
Changes
vite.config.ts: the dev server binds0.0.0.0withallowedHosts: trueso the app is reachable beyond loopback (the API stays on loopback and is proxied by Vite).src/client/polyfills.ts(+ one import inmain.tsx):crypto.randomUUIDfallback built fromcrypto.getRandomValues. On plain-HTTP access via an IP (not a secure context)crypto.randomUUIDisundefined, the client throws, and the Dot stays stuck on "thinking". The fallback is a plain module (not an inline script) so it also survives a strict CSP.docs/LOCAL-SETUP.md: a reproducible runbook (local Intelligence stack, LAN/Tailscale access, why the realtime gateway port must be forwarded to be browser-reachable, Slack managed channel, voice).deployment/local/:socatsystemd units to expose the realtime gateway port plus a commented.envtemplate.Notes
.env,data/,.copilotkit/remain git-ignored).npm run typecheckandnpm run lintpass.