feat(dev): wire WSS tunnel into mirrorstack dev (--tunnel)#22
Merged
Conversation
This was referenced May 5, 2026
c59ae46 to
03dfe35
Compare
5e55180 to
e6f0846
Compare
Closes the CLI-side gap. \`mirrorstack dev --tunnel\` now:
1. Loads credentials (errors out with login hint if expired)
2. POSTs /v1/tunnel/token to mirrorstack-dispatch → ttok + wss_url
3. Parses Config.ID out of main.go (the canonical module id)
4. Opens WSS, sends register {module_id, local_url, version}, awaits
register_ack with a 10s timeout
5. Holds the tunnel handle for the lifetime of the dev session
6. On Ctrl-C / module exit: shutdown signal → close frame → drop conn
The tunnel comes up BEFORE compose so a registration failure doesn't
waste the user's time bringing containers up first.
Notable wiring choices:
- \`new_multi_thread\` runtime with one worker, not \`new_current_thread\`.
The pinger / inbound-frame reader is a spawned task; current-thread
runtimes only tick during \`block_on\`, which would freeze the spawned
future the moment the connect call returned.
- Module identity comes from parsing \`Config.ID = "..."\` out of main.go.
That's the same value the SDK uses for \`mod_<id>\` schemas, and what
the CLI scaffold substituted from the platform UUID. A future PR can
switch to a \`.mirrorstack/meta.json\` written at scaffold time; for
now, parsing main.go is a one-line regex on a file whose shape we
control.
- New \`--local-url\` flag (default http://localhost:8080) tells dispatch
where to 302 incoming Leaf 1 calls. Most modules will run there, but
the SDK's HTTP listener is configurable, so the flag stays.
- New \`MIRRORSTACK_DISPATCH_URL\` env (default https://api.mirrorstack.ai
per ingress path-routing convention) overrides the dispatch base.
Adds \`tokio.rt-multi-thread\` feature; otherwise no new deps.
Test plan:
- [x] cargo test (43 pass; 5 new module_meta tests)
- [x] cargo clippy --all-targets -- -D warnings clean
- [x] cargo fmt --all -- --check clean
- [ ] After WS API GW IaC ships: \`mirrorstack dev --tunnel\` against a
deployed dispatch service, confirm register_ack arrives + browser
hits to /m/<module_id>/foo 302 to localhost
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
e6f0846 to
f179c8c
Compare
…T_LOCAL_URL Two fixes from the multi-agent review: 1. Promote `session_expired()` from commands/module/mod.rs to commands/ mod.rs as `pub(crate)`, so dev::open_tunnel and module::init route their 401-handling through the same helper. Without this they had the exact same string inline in two places — accidental duplication that would drift the moment one is reworded. 2. Promote the magic `"http://localhost:8080"` literal to a `DEFAULT_LOCAL_URL` const next to `DEFAULT_DB_URL`. Used at one site today (the --local-url flag's fallback in open_tunnel), but the value was duplicated in the arg's doc string, so a future change would have three places to update. One source of truth now. Skipped from the review: - The 200ms post-shutdown sleep — flagged as worth replacing with an awaited shutdown future, but TunnelHandle::shutdown is fire-and- forget by design and reshaping it is part of issue #29's liveness signal work. - module_meta::extract_id leading-comment edge case — covered by the existing test naming and not worth tightening for v1. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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
Final CLI piece for Phase 1. `mirrorstack dev --tunnel` now drives the full handshake against the dispatch service:
```
$ mirrorstack dev --tunnel
✓ fetching tunnel token from http://localhost:8083
✓ tunnel registered (session conn_abc...)
✓ bootstrapped docker-compose.yml
[+] Running 2/2
✓ module running — Ctrl-C to stop
module │ mirrorstack: my-mod module (My Mod) listening on :8080
^C
✓ tunnel closed
✓ docker compose down
```
Wiring
Tunnel comes up before compose so a registration failure doesn't waste the user's time bringing containers up first.
Notable choices
Blocked on
Deps added
Test plan
🤖 Generated with Claude Code