feat(tunnel): add up/down commands + unify login/logout [RD-209] - #28
Merged
Merged
Conversation
Two UX fixes for the tunnel CLI:
1. Tunnel lifecycle commands
- hsh tunnel up bring the netstack online without re-auth
- hsh tunnel down take it offline while staying logged in
Drives the new POST /v1/tunnel/{up,down} daemon endpoints. `up`
maps a 409 not_logged_in to an actionable 'run hsh login' hint via
the new TunnelApiError.isNotLoggedIn() helper; both surface the
already_up/already_down no-op states.
2. Unified login/logout
Previously `hsh login` (CLI keychain auth) and `hsh tunnel login`
(daemon auth) looked redundant. Now `hsh login` logs the CLI in and
then, best-effort, drives the daemon's own login flow if the daemon
is installed/running/configured — otherwise it silently no-ops, so
tunnel-less setups are unaffected. `hsh logout` mirrors this.
The daemon still owns its token: loginDaemon() routes credentials
THROUGH the daemon's IPC login flow (it does its own gateway
round-trip); we never hand it the CLI's keychain token. This
preserves the daemon-as-sole-token-writer trust model.
--no-tunnel opts out of the daemon step on both commands.
`hsh tunnel login`/`logout` remain as the explicit daemon-only entry
points (now thin wrappers over the shared loginDaemon/logoutDaemon).
Tests: tunnel-ipc-client.test.ts covers up/down request shape, the
already-up/down flags, and the 409-vs-401 error distinction.
Requires the daemon-side endpoints (hoophq/hoop). Against an older
daemon the new endpoints return 501 and the CLI renders a clean
'not implemented in this daemon build' message.
🤖 Generated with Mister Maluco
Co-Authored-By: MisterMal <teskeslab@lucasteske.dev>
On-demand counterpart to the daemon's new periodic auto-refresh: hsh tunnel refresh re-fetch the connection list from the gateway Drives POST /v1/connections/refresh. Reports the active connection count on success and a clear 'tunnel is down — bring it up first' hint when the daemon has no live tunnel (running: false). Adds TunnelClient.refreshConnections() + RefreshConnectionsResponse, with IPC client tests covering the request shape and the down no-op. Pairs with the daemon-side endpoint in hoophq/hoop. 🤖 Generated with Mister Maluco Co-Authored-By: MisterMal <teskeslab@lucasteske.dev>
Contributor
Author
Update: added
|
EmanuelJr
approved these changes
Jun 3, 2026
1.86.0 is the hoop release that ships the tunnel up/down lifecycle endpoints and the connection-list refresh that the new `hsh tunnel up|down|refresh` commands depend on. 🤖 Generated with Mister Maluco Co-Authored-By: MisterMal <teskeslab@lucasteske.dev>
racerxdl
added a commit
that referenced
this pull request
Jul 6, 2026
…eychain tests [DEP-37] Review follow-ups: - macOS backend now writes the token through `security -i` with the command on stdin instead of `-w <token>` on argv, closing the brief window where any same-user process could read the secret via ps. The quoting rules (backslash and double-quote escapes) were verified empirically against the security CLI; values with control characters are rejected up front since the -i protocol is line-oriented. The code comments previously claimed stdin was used while the implementation inlined the value — both now match reality. - MacOSKeychain accepts injectable service/account (defaults unchanged) so integration tests can target a scratch keychain item. Six new darwin-only tests exercise the real keychain: round-trip, in-place update, quoting edge cases, absent item, idempotent delete, and control-character rejection. - README documents token storage per platform, the HSH_KEYCHAIN_BACKEND override, the deliberate decision to keep the fallback file plaintext-0600 (an encryption key stored next to the file adds nothing), and the downgrade caveat after migration. Also rebased onto main (0.3.2); logout keeps the --no-tunnel daemon leg from #28 with the now-async CLI logout. 🤖 Generated with Mister Maluco Co-Authored-By: MisterMal <teskeslab@lucasteske.dev>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two UX fixes for the tunnel CLI surface.
1. Tunnel lifecycle commands
hsh tunnel up— bring the netstack online without re-authenticatinghsh tunnel down— take it offline while staying logged inDrives the new
POST /v1/tunnel/{up,down}daemon endpoints.upmaps a 409not_logged_into an actionable 'run hsh login' hint via the newTunnelApiError.isNotLoggedIn(); both surface thealready_up/already_downno-op states.2. Unified login/logout
Previously
hsh login(CLI keychain auth) andhsh tunnel login(daemon auth) looked redundant and confused users. Now:hsh loginlogs the CLI in, then — best-effort — drives the daemon's own login flow if the daemon is installed/running/configured. If not, it silently no-ops, so tunnel-less setups are unaffected.hsh logoutmirrors this.--no-tunnelopts out of the daemon step on both.Trust model preserved:
loginDaemon()routes credentials through the daemon's IPC login flow (the daemon does its own gateway round-trip) — we never hand it the CLI's keychain token. The daemon remains the sole writer of its token.hsh tunnel login/logoutremain as explicit daemon-only entry points, now thin wrappers over the sharedloginDaemon/logoutDaemon.Testing
tests/tunnel-ipc-client.test.ts: up/down request shape,already_up/already_downflags, and the 409-vs-401 error distinction.Dependency
Requires the daemon-side endpoints in hoophq/hoop#1507. Against an older daemon the new endpoints return 501 and the CLI renders a clean 'not implemented in this daemon build' message — no crash.
Automated by MisterMal