Skip to content

feat(transport): Phase 3 — auto-detection + get-dm v2 + docs#178

Merged
grunch merged 4 commits into
mainfrom
feat/transport-v2-autodetect
Jun 17, 2026
Merged

feat(transport): Phase 3 — auto-detection + get-dm v2 + docs#178
grunch merged 4 commits into
mainfrom
feat/transport-v2-autodetect

Conversation

@grunch

@grunch grunch commented Jun 17, 2026

Copy link
Copy Markdown
Member

Phase 3 of docs/TRANSPORT_V2_SPEC.md — capability auto-detection + UX/docs

Completes the CLI's transport-v2 support: the operator no longer needs --transport, the get-dm historical listing works on v2, and the transport is surfaced/documented.

Stacked on #177 (Phase 2). Review this diff on top of it; retargets to main once #177 merges.

What changed

  • Auto-detection. New events::fetch_protocol_version_with reads the node's protocol_versions tag from its kind-38385 info event (short INFO_PROBE_TIMEOUT = 5s so a node without one degrades fast). init_contextresolve_transport runs it once at startup when --transport/TRANSPORT is unset:
    • "2" → set TRANSPORT=nip44;
    • "1" / absent / unreachable → leave unset, so the messaging layer keeps the gift-wrap default.
    • An explicit --transport is authoritative and skips the probe entirely.
  • Backward-compat guard. A pre-v2 daemon advertises no protocol_versions tag, so auto-detect leaves the CLI on gift-wrap (v1) rather than silently mis-pairing — this is the version-skew guard Phase 1 flagged. --transport still forces either side.
  • get-dm listing is transport-aware. create_filter for the DirectMessages* kinds now uses transport.event_kind() and, on v2, pins author = mostro_pubkey (new mostro_pubkey param threaded through its 6 call sites). Closes the Phase 2 known gap — listing past Mostro DMs works on a v2 node.
  • Verbose surface. resolve_transport logs the active transport and how it was chosen (explicit / auto-detected protocol vN / default fallback) at info (shown with -v).
  • Docs. docs/commands.md gains a Global options section documenting --transport (and the other global flags); the spec is marked complete.

Tests

  • New deterministic, offline test: protocol_versions tag read + parse (mirrors the existing pow probe test). Auto-detect wiring + the v2 create_filter author-pin are integration-level (live relay/node) and covered by the manual checks below.
  • Full suite green; cargo clippy --all-targets --all-features -D warnings + cargo fmt --check clean.

🧪 Manual testing — step by step

Needs a Mostro daemon on mostro-core 0.13 reachable on a relay.

1. Auto-detect a v2 node (no --transport)

  1. Set transport = "nip44" in the daemon's settings.toml; restart.
  2. Run without --transport, verbose:
    mostro-cli -v -m <node pubkey> -r ws://localhost:7000 listorders
  3. Expected: an info log Transport: nip44 (auto-detected protocol v2), and the command works (kind-14 traffic). A full newordr → takesell/takebuy → addinvoice → fiatsent → release round-trips without ever passing --transport. ✔️

2. Auto-detect a v1 node

  1. Set the daemon back to transport = "gift-wrap" (or use a default node); restart.
  2. Run mostro-cli -v … listorders without --transport.
  3. Expected: Transport: gift-wrap (auto-detected protocol v1) (or the "could not detect … defaulting to gift-wrap" line if the node publishes no info event), and behaviour is identical to today. ✔️

3. Explicit override wins (skips the probe)

  1. Against the v2 node, run mostro-cli -v --transport gift-wrap … listorders.
  2. Expected: Transport: gift-wrap (explicit) — no probe — and (since the node only listens on kind 14) the command times out. Re-run with --transport nip44 or no flag → works. Confirms the flag is authoritative. ✔️

4. get-dm listing on v2

  1. After completing a trade against the v2 node, run mostro-cli --transport nip44 … getdm (or omit --transport to auto-detect).
  2. Expected: past Mostro→user DMs are listed (kind-14, author = Mostro). Before this PR the same listing returned nothing on a v2 node. ✔️

5. Pre-v2 daemon / unreachable node

  1. Point the CLI (no --transport) at a node that publishes no kind-38385 info event (or an unreachable relay).
  2. Expected: after a brief (~5s) probe, Could not detect node transport … defaulting to gift-wrap, and the CLI proceeds on v1 — no hang for the full 15s fetch timeout, no mis-pairing. ✔️

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Implemented automatic transport detection at startup. The CLI now queries the daemon's capabilities and auto-selects between nip44 (v2) and gift-wrap (v1), eliminating the need to explicitly specify --transport in most cases.
  • Documentation

    • Added Global Options section documenting command-wide flags, environment variables, and the new --transport auto-detection behavior.

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@grunch, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 45 minutes and 14 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cb2ce6f0-e388-46bb-9f54-ca81280852e5

📥 Commits

Reviewing files that changed from the base of the PR and between bcdc10c and a66f54d.

📒 Files selected for processing (4)
  • docs/TRANSPORT_V2_SPEC.md
  • docs/commands.md
  • src/cli.rs
  • src/util/events.rs

Walkthrough

Phase 3 of Transport V2 is implemented: connect_nostr now waits for relay handshakes before returning; a new fetch_protocol_version_with helper probes the daemon's kind-38385 info event for its protocol_versions tag; and init_context calls a new resolve_transport function to set TRANSPORT=nip44 for v2 nodes or fall back to gift-wrap. Spec and command docs are updated to match.

Changes

Transport V2 Phase 3: capability auto-detection

Layer / File(s) Summary
Relay connection readiness guard
src/util/net.rs
Adds CONNECT_TIMEOUT (10 s) and calls client.wait_for_connection(CONNECT_TIMEOUT).await in connect_nostr after client.connect(), ensuring relay handshakes finish before probe and DM steps run.
Protocol version probe helper
src/util/events.rs
Adds INFO_PROBE_TIMEOUT and fetch_protocol_version_with, which fetches the newest kind-38385 event within the timeout, extracts and parses the protocol_versions tag as u8, and returns None when the tag is absent or unparseable. Includes unit tests for both presence and absence cases.
Transport auto-resolution in CLI startup
src/cli.rs
init_context invokes a new resolve_transport helper right after the Nostr client is ready. resolve_transport honours an explicit TRANSPORT env var, otherwise calls fetch_protocol_version_with and sets TRANSPORT=nip44 for v2, leaving gift-wrap as the default for v1, unknown, or missing protocol data.
Spec and command docs updates
docs/TRANSPORT_V2_SPEC.md, docs/commands.md
Phase 3 section rewritten from PENDING to IMPLEMENTED with startup probe rules, backward-compat fallback, verbose logging notes, and updated test guidance. commands.md gains a Global options section documenting --transport auto-detection/override and other CLI flags.

Sequence Diagram(s)

sequenceDiagram
    participant CLI as mostro-cli
    participant Net as connect_nostr
    participant Events as fetch_protocol_version_with
    participant Relay as Nostr Relay

    CLI->>Net: connect_nostr(relays)
    Net->>Relay: add_relays + connect()
    Net->>Relay: wait_for_connection(CONNECT_TIMEOUT)
    Relay-->>Net: handshake complete
    Net-->>CLI: client (ready)

    CLI->>CLI: resolve_transport(client, mostro_pubkey)
    alt TRANSPORT env var set
        CLI-->>CLI: use explicit transport, return
    else no explicit transport
        CLI->>Events: fetch_protocol_version_with(client, pubkey)
        Events->>Relay: fetch kind-38385 event (INFO_PROBE_TIMEOUT)
        Relay-->>Events: info event or timeout
        Events-->>CLI: Some(version) or None
        alt version == 2
            CLI-->>CLI: set TRANSPORT=nip44
        else version == 1 / unknown / None
            CLI-->>CLI: default to gift-wrap
        end
    end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • MostroP2P/mostro-cli#177: Directly code-connected — introduces the --transport flag and transport-aware DM wrapping that this PR's auto-detection logic builds on and resolves into.

Poem

🐇 Hop hop, no flag to type today,
The rabbit sniffs the relay's way,
Kind 38385 whispers "v2 is here!"
nip44 is set, the path is clear,
Gift-wrap falls back without a fear~
Auto-detect has saved the day! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(transport): Phase 3 — auto-detection + get-dm v2 + docs' accurately summarizes the main changes: Phase 3 implementation with automatic transport detection, get-dm v2 support, and documentation updates.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/transport-v2-autodetect

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5e4f4f13a6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/cli.rs Outdated
Phase 3 of docs/TRANSPORT_V2_SPEC.md — completes the CLI's transport-v2
support.

- Auto-detection: `events::fetch_protocol_version_with` reads the node's
  `protocol_versions` tag (kind-38385 info event) with a short
  INFO_PROBE_TIMEOUT. `init_context` → `resolve_transport` runs it once at
  startup when `--transport`/`TRANSPORT` is unset: "2" → TRANSPORT=nip44;
  "1"/absent/unreachable → leave unset (messaging defaults to gift-wrap). An
  explicit `--transport` is authoritative and skips the probe. A pre-v2 daemon
  publishes no tag, so the CLI stays on v1 instead of mis-pairing
  (backward-compat guard for the version-skew risk Phase 1 flagged).
- get-dm listing is transport-aware: `create_filter` for the DirectMessages*
  kinds now uses `transport.event_kind()` and pins `author = mostro_pubkey` on
  v2 (new `mostro_pubkey` param threaded through call sites), closing the
  Phase 2 gap.
- Verbose: `resolve_transport` logs the active transport and how it was chosen.
- Docs: docs/commands.md gains a Global options section documenting
  `--transport` + auto-detection; spec marked complete.

Tests: deterministic `protocol_versions` tag read/parse. Full suite green;
clippy --all-targets --all-features -D warnings and fmt clean.

Based on Phase 2 (#177).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@grunch grunch force-pushed the feat/transport-v2-autodetect branch from 5e4f4f1 to 9906f2c Compare June 17, 2026 12:54
Base automatically changed from feat/transport-v2-selection to main June 17, 2026 13:55
connect() only spawns background connection tasks; firing subscribe/
send_dm immediately raced the handshake and dropped Mostro's reply,
surfacing as "Timeout waiting for DM". Block on wait_for_connection so
auto-detection and the DM round-trip run against a live relay.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/cli.rs`:
- Around line 508-511: The early return condition for the TRANSPORT environment
variable in the if let Ok(explicit) block treats any present value, including
empty strings or whitespace, as explicit and short-circuits auto-detection. This
is inconsistent with how parse_transport_env handles empty values. Modify the
logic to check if the explicit value is empty or contains only whitespace after
retrieving it from std::env::var("TRANSPORT"), and only return early if the
value is non-empty and meaningful. If the value is empty or whitespace-only,
allow the code to continue to auto-detection instead of returning early.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 66d5314b-da6f-4247-8817-08c474833203

📥 Commits

Reviewing files that changed from the base of the PR and between e89109c and bcdc10c.

📒 Files selected for processing (5)
  • docs/TRANSPORT_V2_SPEC.md
  • docs/commands.md
  • src/cli.rs
  • src/util/events.rs
  • src/util/net.rs

Comment thread src/cli.rs
grunch and others added 2 commits June 17, 2026 16:35
…rsion

Client and node are compatible only when they run the same protocol
version, so the kind-38385 info tag carries a single value ("1" or "2"),
not a list. Rename the tag everywhere the CLI reads/documents it to match
the daemon and protocol spec.

NOTE: must land together with the matching mostrod + protocol changes;
the daemon still emits the old tag name until then.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
resolve_transport short-circuited on any present TRANSPORT value, but
parse_transport_env only honors a non-empty, trimmed value. So
`TRANSPORT=""` (e.g. `--transport ""`) skipped auto-detection and left
the var empty, silently pairing a v2 node to the gift-wrap default. Only
short-circuit on a meaningful value; fall through to auto-detect otherwise.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@grunch grunch merged commit 09855f6 into main Jun 17, 2026
6 checks passed
@grunch grunch deleted the feat/transport-v2-autodetect branch June 17, 2026 19:40
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