Skip to content

feat: add ConfigRequest.Capabilities for client capability negotiation#28

Open
myleshorton wants to merge 2 commits into
mainfrom
fisk/config-capabilities
Open

feat: add ConfigRequest.Capabilities for client capability negotiation#28
myleshorton wants to merge 2 commits into
mainfrom
fisk/config-capabilities

Conversation

@myleshorton

@myleshorton myleshorton commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

What

Add a Capabilities []string field to ConfigRequest and the first capability constant:

CapabilityNonSelectableOutbounds = "non_selectable_outbounds"

The client advertises capabilities it supports; the server enables optional behavior only for clients that report the matching capability — capability negotiation instead of version sniffing.

Why

lantern-cloud gates its new proxyless rule-set detour (an infrastructure outbound sent via ConfigResponse.NonSelectableOutbounds) on whether the client will treat that outbound as non-selectable. A client that doesn't (pre–getlantern/radiance#549) would let its URLTest auto-select the low-latency direct+frag dialer and route traffic through it — exposing the real IP.

The current gate is a hardcoded client-version floor (9.1.14-beta). A capability is strictly better:

  • Correct signal. "Client honors NonSelectableOutbounds" is exactly the property that matters — not a version number that has to be kept in sync with whichever release happened to carry #549 (and breaks across forks/prereleases).
  • Generalizes. #549 honors any tag in NonSelectableOutbounds. Gating on this one capability covers every future infra outbound with no new token and no client release — the whole point of NonSelectableOutbounds. Gating on "proxyless" specifically would need a new token per outbound.
  • Symmetric. The client says "I understand non_selectable_outbounds" ↔ the server sends non_selectable_outbounds.

Note: the client already advertises the outline outbound type ("outline") via its auto-derived supported-protocols list, but that predates #549 — so it can't be used as the gate (old clients report it too). This new, explicitly-added capability is the safe signal.

Consumers

  • radiance — advertises CapabilityNonSelectableOutbounds in config/fetcher.go (added in the same code that honors NonSelectableOutbounds, so advertising it ⟺ handling it safely).
  • lantern-cloud#2936 — gates the proxyless detour on slices.Contains(req.Capabilities, common.CapabilityNonSelectableOutbounds), replacing the version floor.

Testing

go test ./...TestCapabilitiesRoundTrip (key present, value round-trips, nil + empty-slice both omitted). Build + gofmt clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WGpKfgkbfdJwwsTaouMDoR

Summary by CodeRabbit

  • New Features

    • Added client capability support for configuration negotiation.
    • Introduced a capability flag for handling non-selectable outbounds, helping clients and servers agree on outbound behavior.
    • Added a new request field to send capability information during configuration requests.
  • Tests

    • Added coverage to verify capability data is preserved through JSON serialization and omitted when empty.

Adds a Capabilities []string field to ConfigRequest and the first capability
constant, CapabilityNonSelectableOutbounds ("non_selectable_outbounds"): the
client advertises that it honors ConfigResponse.NonSelectableOutbounds so the
server can gate infrastructure outbounds (e.g. a proxyless download_detour) on
the capability instead of sniffing the client version. Future optional outbounds
reuse the same signal — no new token per feature.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WGpKfgkbfdJwwsTaouMDoR
Copilot AI review requested due to automatic review settings July 6, 2026 19:59
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@myleshorton, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 41 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

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 reviews.

How do review limits work?

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

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, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8f594136-a9a4-4594-bb89-3832fe3949bd

📥 Commits

Reviewing files that changed from the base of the PR and between 57aaafd and de5009f.

📒 Files selected for processing (2)
  • types.go
  • types_test.go
📝 Walkthrough

Walkthrough

This PR adds a new CapabilityNonSelectableOutbounds constant and a Capabilities []string field to the ConfigRequest struct in types.go to support capability-based negotiation, along with a new test verifying JSON round-trip serialization behavior including omitempty handling.

Changes

Capabilities support

Layer / File(s) Summary
Capability constant and struct field
types.go
Adds CapabilityNonSelectableOutbounds constant and a Capabilities []string field (JSON tag capabilities,omitempty) to ConfigRequest, reordering fields and adding clarifying comments.
Round-trip serialization test
types_test.go
Adds TestCapabilitiesRoundTrip verifying Capabilities serializes correctly and is omitted from JSON when nil or empty.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Related PRs: None found.

Suggested labels: enhancement

Suggested reviewers: None specified.

🐰 A whisker-twitch, a new field appears,
Capabilities hop in, dispelling version fears,
Non-selectable paths stay tucked away,
JSON round-trips tested — omitempty saves 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 clearly matches the main change: adding ConfigRequest.Capabilities for client capability negotiation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fisk/config-capabilities

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.

Copilot AI 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.

Pull request overview

Adds explicit client capability negotiation to the shared common types so servers can safely enable optional behaviors based on what the client reports (instead of relying on version floors), starting with support for ConfigResponse.NonSelectableOutbounds.

Changes:

  • Add ConfigRequest.Capabilities []string for client-advertised capabilities.
  • Introduce CapabilityNonSelectableOutbounds = "non_selectable_outbounds" constant with documentation.
  • Add a JSON round-trip test covering presence and omitempty behavior for Capabilities.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
types.go Adds ConfigRequest.Capabilities plus the first capability constant used for negotiation.
types_test.go Adds TestCapabilitiesRoundTrip to verify serialization/deserialization and omitempty omission behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread types_test.go Outdated
@myleshorton

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.


Your plan includes PR reviews subject to rate limits. More reviews will be available in 50 minutes.

Copilot AI 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.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Use `"capabilities"` (with quotes) so the omit check can't false-positive on a
bare substring in a value, consistent with the positive assertion.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WGpKfgkbfdJwwsTaouMDoR
@myleshorton myleshorton requested a review from Copilot July 6, 2026 20:18
@myleshorton

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.


Your plan includes PR reviews subject to rate limits. More reviews will be available in 41 minutes.

Copilot AI 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.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

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.

2 participants