Skip to content

feat: direct TCP URI with SSL toggle and optional password auth#635

Merged
boudra merged 8 commits intomainfrom
direct-tcp-uri-and-password-auth/phase-1-refactor
Apr 30, 2026
Merged

feat: direct TCP URI with SSL toggle and optional password auth#635
boudra merged 8 commits intomainfrom
direct-tcp-uri-and-password-auth/phase-1-refactor

Conversation

@boudra
Copy link
Copy Markdown
Collaborator

@boudra boudra commented Apr 30, 2026

Summary

  • Direct connection dialog gets structured fields — Host, Port, "Use SSL" checkbox, masked Password — that compose the canonical tcp://host:port?ssl=true&password=xxx URI used as storage. Single-line Advanced URI input is preserved.
  • Daemon gains optional shared-secret auth for direct TCP connections. HTTP uses Authorization: Bearer; WebSocket connections use the paseo.bearer.<token> subprotocol and close with readable auth failures (Password required / Incorrect password). Configured via auth.password in ~/.paseo/config.json, paseo daemon set-password, or PASEO_PASSWORD. Off by default — old clients keep working unchanged.
  • Drops the port === 443 heuristic. ws/wss is now driven by the explicit useTls flag at every call site (app probe, host runtime, downloads, CLI, relay).

Related issues

Test plan

  • Connect from desktop app to a daemon fronted by a TLS terminator (Tailscale Serve / Caddy) using tcp://host:port?ssl=true — should produce wss://.
  • Set auth.password on the daemon. Connect without a password → expect Password required, not a generic transport timeout.
  • Connect with the wrong password → expect Incorrect password.
  • Connect with the matching password → both HTTP API and WS connection succeed.
  • Open an old stored direct connection (no useTls, no password) → still loads with useTls: false, password: undefined, connects.
  • CLI: paseo --host 'tcp://host:6767?ssl=true&password=xxx' ls -a — works against a password-protected daemon.
  • Pino logs do not contain bearer / Sec-WebSocket-Protocol values (redaction list extended).

@boudra boudra force-pushed the direct-tcp-uri-and-password-auth/phase-1-refactor branch 2 times, most recently from f128be0 to 63c1c09 Compare April 30, 2026 11:54
boudra and others added 8 commits April 30, 2026 20:46
Replaces the heuristic-driven direct-connection model with a user-controlled
one. The Add Host dialog now exposes structured Host, Port, "Use SSL", and
masked Password fields that compose the canonical
`tcp://host:port?ssl=true&password=xxx` URI used as the storage form.

The daemon gains optional shared-secret auth: `Authorization: Bearer <pw>` on
HTTP and `Sec-WebSocket-Protocol: paseo.bearer.<pw>` on the WS upgrade
(browser WebSocket can't set custom headers). Configured via config.json
`auth.password` or `PASEO_PASSWORD` env. Off by default — old clients keep
working unchanged.

The `port === 443` heuristic for ws/wss is gone; the explicit `useTls` flag
drives scheme selection at every call site.
@boudra boudra force-pushed the direct-tcp-uri-and-password-auth/phase-1-refactor branch from 63c1c09 to e3e5f73 Compare April 30, 2026 13:48
@boudra boudra merged commit 088a6c1 into main Apr 30, 2026
13 checks passed
@boudra boudra deleted the direct-tcp-uri-and-password-auth/phase-1-refactor branch April 30, 2026 14:05
brackbk added a commit to hubtool/hubcode that referenced this pull request May 1, 2026
…d auth

Adds two new daemon access modes alongside the existing relay path:

1. Direct TCP with optional TLS — connect via `tcp://host:port?ssl=true`,
   useful for self-hosted daemons behind reverse proxies (Caddy, nginx,
   Cloudflare Tunnel) without going through the hosted relay.

2. Bearer-token password auth — daemon stores a bcrypt-hashed password
   in `daemon-config.json`. Clients send it via `Authorization: Bearer
   <pwd>` (native) or the `hubcode.bearer.<pwd>` WebSocket subprotocol
   (web). Failed auth closes with WS code 4401.

New CLI command: `hubcode daemon set-password` writes the hashed value
to the persisted config.

UI: add-host-modal gets host/port fields, an SSL toggle, password
field, and an Advanced URI mode. Existing direct/relay flows unchanged.

All paseo identifiers renamed: `paseo.bearer.*` → `hubcode.bearer.*`,
`PASEO_PASSWORD` → `HUBCODE_PASSWORD`, `relay.paseo.sh:443` →
`relay.hubcode.ai:443`, etc.

Skipped from upstream PR: nix package hash bump, e2e Playwright fixture
(uses paseo.test hostname; needs separate port), tangential session.ts
refactor unrelated to auth.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant