Skip to content

feat(enhancement): centralize HTTP transport policies - #2021

Open
evandance wants to merge 1 commit into
mainfrom
refactor/http-transport-policy
Open

feat(enhancement): centralize HTTP transport policies#2021
evandance wants to merge 1 commit into
mainfrom
refactor/http-transport-policy

Conversation

@evandance

@evandance evandance commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

Centralize outbound HTTP transport construction and routing so platform-owned endpoints and external destinations use explicit, consistent policies. The change preserves existing provider and factory behavior while making proxy, redirect, security-header, and download handling easier to reason about and test.

Changes

  • Add endpoint-catalog-backed platform/external request classification and a central HTTP policy router.
  • Add optional provider scoping while preserving the all-request behavior of existing transport providers.
  • Route direct HTTP, SDK HTTP, and SDK bootstrap requests through the shared policy construction path.
  • Preserve proxy, custom TLS, retry, and extension layers when cloning transports for untrusted downloads; fail closed when safe cloning is impossible.
  • Harden redirect handling across origin and scheme changes, and add contract coverage for routing, compatibility, and downloader behavior.

Compatibility Notes

  • HTTPS downloads through a proxy pin the CONNECT authority to a validated public IP while preserving the original Host and TLS server name. Proxies that allow CONNECT only by domain may need an ACL update.
  • Plain HTTP hostname downloads through a proxy are rejected because the target IP cannot be pinned independently; use HTTPS or a literal public IP.
  • Apps pre-signed uploads now honor the configured external proxy and transport hooks, so large uploads may traverse the configured proxy.
  • Redirect targets are classified independently on each HTTP hop from the logical URL visible to net/http; interceptor host rewrites do not extend the endpoint catalog.
  • The provider contract applies to HTTP requests. SDK WebSocket bootstrap is covered because it uses HTTP; the subsequent WebSocket connection remains owned by the SDK dialer.

Test Plan

  • make build
  • GOFLAGS=-p=4 make unit-test
  • go vet ./...
  • gofmt -l . produces no output
  • go mod tidy leaves go.mod and go.sum unchanged
  • go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.1.6 run --new-from-rev=origin/main
  • make sidecar-test
  • Manual local verification: lark-cli --version

Related Issues

  • None

Summary by CodeRabbit

  • New Features
    • Added request-class-aware networking to separate platform vs external traffic, including scoped extension interception.
    • Introduced an external-request HTTP client and routed downloads/media/docs/attachments/signature images through it.
    • Added an SDK WebSocket bootstrap transport bridge with platform-only handling and stricter redirect protection.
  • Bug Fixes
    • Hardened redirect safety and credential/header stripping; tightened download/proxy host and IP validation with fail-closed behavior.
    • Streaming requests now preserve typed security-policy errors.
  • Documentation
    • Clarified provider-aware transport requirements for connectivity checks.
  • Tests
    • Expanded coverage for routing, redirects, download validation, proxy/IP safety, and transport bridging.

@evandance
evandance requested a review from liangshuo-1 as a code owner July 23, 2026 03:46
@github-actions github-actions Bot added domain/ccm PR touches the ccm domain domain/im PR touches the im domain domain/mail PR touches the mail domain size/XL Architecture-level or global-impact change labels Jul 23, 2026
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR adds platform/external HTTP request classification, policy-routed clients, extension-aware SDK transport composition, stricter redirect and download protections, external-client adoption, and typed transport-error preservation.

Changes

Provider-aware transport routing and classification

Layer / File(s) Summary
Request classification and policy routing
extension/transport/types.go, internal/core/*, internal/transport/policy_router.go, internal/transport/shared.go
Adds request classes, platform endpoint validation, policy routing, transport graph rebuilding, and external HTTP client construction.
Extension middleware and transport decorators
internal/transport/extension.go, internal/cmdutil/transport.go, internal/auth/transport.go, internal/riskcontrol/transport.go
Adds scoped extension hooks, abort handling, and decorator base accessors for rebuilding transport chains.
SDK bootstrap bridge and factory wiring
internal/transport/default_client.go, internal/cmdutil/factory*.go
Builds separate platform and external chains, installs the SDK bootstrap bridge, and applies same-origin redirect protection.
Redirect and typed error handling
internal/cmdutil/factory_default.go, internal/client/*
Hardens redirect policy and preserves typed transport errors in streaming requests.

Download transport hardening

Layer / File(s) Summary
Download validation and proxy transport
internal/validate/url.go
Adds restricted-IP checks, per-request resolution, proxy IP pinning, TLS proxy handling, retry rules, and safe transport cloning.
Download validation tests
internal/validate/*_test.go
Covers proxy routing, TLS/SNI behavior, restricted targets, legacy dialers, HTTP/2 preservation, and opaque transport failures.
Document cover downloads
shortcuts/doc/doc_resource_cover*.go
Uses external classification and the shared validated download client, expands unsafe IPv4 handling, and removes legacy transport guards.

External client adoption

Layer / File(s) Summary
External download call sites
shortcuts/apps/*, shortcuts/im/*, shortcuts/mail/*, shortcuts/minutes/*, internal/update/*
Uses external-class HTTP clients for object storage, URL, attachment, signature, media, and update downloads.
Supporting transport tests and comments
extension/transport/sidecar/*, shortcuts/mail/signature_compose_test.go, cmd/*, internal/registry/*, internal/transport/config.go
Verifies forced-external sidecar routing and signature image classification, and updates transport-related documentation and test comments.

Estimated code review effort: 5 (Critical) | ~100 minutes

Possibly related PRs

  • larksuite/cli#292: Provides the extension provider and interceptor APIs used by the new transport middleware.
  • larksuite/cli#532: Covers sidecar provider behavior exercised by forced external classification.
  • larksuite/cli#2031: Shares the risk-control transport boundary used in the SDK transport refactor.

Suggested labels: enhancement

Suggested reviewers: liangshuo-1

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.39% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title is concise and accurately summarizes the main change: centralizing HTTP transport policies.
Description check ✅ Passed The description follows the template with Summary, Changes, Test Plan, and Related Issues sections completed.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/http-transport-policy

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.

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown

🚀 PR Preview Install Guide

🧰 CLI update

npm i -g https://pkg.pr.new/larksuite/cli/@larksuite/cli@fde566386f35e26e2a7508574d7c80ee43819c58

🧩 Skill update

npx skills add larksuite/cli#refactor/http-transport-policy -y -g

@codecov

codecov Bot commented Jul 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 78.01724% with 153 lines in your changes missing coverage. Please review.
✅ Project coverage is 75.28%. Comparing base (29a97db) to head (fde5663).

Files with missing lines Patch % Lines
internal/validate/url.go 71.86% 45 Missing and 20 partials ⚠️
internal/transport/policy_router.go 75.65% 18 Missing and 10 partials ⚠️
internal/transport/default_client.go 85.60% 12 Missing and 7 partials ⚠️
internal/riskcontrol/transport.go 0.00% 12 Missing ⚠️
internal/transport/extension.go 79.59% 8 Missing and 2 partials ⚠️
internal/cmdutil/factory_default.go 90.12% 6 Missing and 2 partials ⚠️
internal/auth/transport.go 0.00% 6 Missing ⚠️
internal/cmdutil/factory.go 60.00% 1 Missing and 1 partial ⚠️
internal/cmdutil/transport.go 92.85% 2 Missing ⚠️
shortcuts/doc/doc_resource_cover.go 85.71% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2021      +/-   ##
==========================================
+ Coverage   75.19%   75.28%   +0.08%     
==========================================
  Files         914      917       +3     
  Lines       96783    97345     +562     
==========================================
+ Hits        72778    73288     +510     
+ Misses      18407    18389      -18     
- Partials     5598     5668      +70     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai 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.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
internal/validate/url.go (2)

1-1: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Extract a shared "hardened transport leaf" helper. Both sites independently implement the same clone-and-guard pattern (wrap DialContext/DialTLSContext/DialTLS with remote-IP validation, fail closed when safe cloning isn't possible), which has already caused the two implementations to diverge on error typing.

  • internal/validate/url.go#L195-271: extract newDownloadTransportLeaf/configureDirectDownloadTransport's dial-wrapping/guard logic into a shared helper (e.g., in internal/transport or internal/validate) parameterized by the remote-IP predicate and proxy-handling policy (freeze-selected-proxy vs. disable-proxy).
  • shortcuts/doc/doc_resource_cover.go#L727-801: adopt the same shared helper for cloneDocCoverTransport/newDocCoverTransportLeaf instead of re-implementing the dial/guard wiring, keeping its existing "always disable proxy" policy.
🤖 Prompt for 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.

In `@internal/validate/url.go` at line 1, Extract the duplicated transport
clone-and-guard wiring from
newDownloadTransportLeaf/configureDirectDownloadTransport and
cloneDocCoverTransport/newDocCoverTransportLeaf into one shared helper.
Parameterize it with the remote-IP validation predicate and proxy policy,
preserving frozen selected-proxy behavior for downloads and always-disabled
proxy behavior for document covers; ensure cloning failures fail closed and all
DialContext/DialTLSContext/DialTLS wrappers use consistent error handling.

195-271: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Duplicated fail-closed transport-cloning/IP-guard logic vs. shortcuts/doc/doc_resource_cover.go.

newDownloadTransportLeaf/configureDirectDownloadTransport are structurally near-identical to newDocCoverTransportLeaf in shortcuts/doc/doc_resource_cover.go (dial wrapping, DialTLSContext/DialTLS guards, remote-IP validation). See consolidated comment below.

🤖 Prompt for 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.

In `@internal/validate/url.go` around lines 195 - 271, The direct transport
cloning and dial/IP-validation logic in newDownloadTransportLeaf and
configureDirectDownloadTransport duplicates newDocCoverTransportLeaf;
consolidate these paths through the existing shared transport-wrapper helper or
extract their common implementation into one reusable symbol. Preserve
fail-closed handling, DialContext/DialTLSContext/DialTLS coverage, connection
closing on validation failure, and the distinct proxy behavior.
shortcuts/doc/doc_resource_cover.go (1)

727-801: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Duplicated fail-closed transport-cloning/IP-guard logic vs. internal/validate/url.go.

blockedDocCoverTransport/cloneDocCoverTransport/newDocCoverTransportLeaf closely mirror blockedDownloadTransport/cloneDownloadTransport/newDownloadTransportLeaf in internal/validate/url.go, including the new DialTLS-guard wrapping. See consolidated comment below.

🤖 Prompt for 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.

In `@shortcuts/doc/doc_resource_cover.go` around lines 727 - 801, Replace the
duplicated blocked transport, clone logic, and leaf IP-guard implementation in
blockedDocCoverTransport, cloneDocCoverTransport, and newDocCoverTransportLeaf
with the shared transport-cloning/validation utilities from
internal/validate/url.go. Reuse the existing blockedDownloadTransport,
cloneDownloadTransport, and newDownloadTransportLeaf behavior, including DialTLS
and DialTLSContext guarding, while preserving the document-cover fail-closed
behavior.
🤖 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 `@internal/cmdutil/factory_default.go`:
- Around line 97-126: The four rejection paths in safeRedirectPolicy must return
appropriately classified errs errors instead of fmt.Errorf: use validation for
redirect-count or invalid-request cases, network for transport redirect
failures, and security-policy errors for HTTPS downgrade or credential-stripping
policy violations. Preserve the existing messages and behavior, and update the
redirect assertions in factory_http_test.go to verify both the typed error and
message.

In `@internal/transport/policy_router.go`:
- Around line 56-68: Replace the bare fmt.Errorf calls with appropriate errs.*
constructors for all affected transport guards: the nil-request and
invalid-class handling in internal/transport/policy_router.go at lines 56-68 and
81-94, and the redirect-location and blocked-redirect handling in
internal/transport/default_client.go at lines 55-80. Update the relevant
RoundTrip and redirect-checking logic while preserving their existing control
flow and messages.

In `@internal/validate/url.go`:
- Around line 185-193: Replace the bare fmt.Errorf used to initialize
blockedDownloadTransport.err in the transport-cloning fallback with
errs.NewInternalError(errs.SubtypeUnknown, ...), matching the typed error
construction used by blockedDocCoverTransport. Preserve the existing "cannot
safely clone download transport %T" message and formatting arguments.

---

Outside diff comments:
In `@internal/validate/url.go`:
- Line 1: Extract the duplicated transport clone-and-guard wiring from
newDownloadTransportLeaf/configureDirectDownloadTransport and
cloneDocCoverTransport/newDocCoverTransportLeaf into one shared helper.
Parameterize it with the remote-IP validation predicate and proxy policy,
preserving frozen selected-proxy behavior for downloads and always-disabled
proxy behavior for document covers; ensure cloning failures fail closed and all
DialContext/DialTLSContext/DialTLS wrappers use consistent error handling.
- Around line 195-271: The direct transport cloning and dial/IP-validation logic
in newDownloadTransportLeaf and configureDirectDownloadTransport duplicates
newDocCoverTransportLeaf; consolidate these paths through the existing shared
transport-wrapper helper or extract their common implementation into one
reusable symbol. Preserve fail-closed handling,
DialContext/DialTLSContext/DialTLS coverage, connection closing on validation
failure, and the distinct proxy behavior.

In `@shortcuts/doc/doc_resource_cover.go`:
- Around line 727-801: Replace the duplicated blocked transport, clone logic,
and leaf IP-guard implementation in blockedDocCoverTransport,
cloneDocCoverTransport, and newDocCoverTransportLeaf with the shared
transport-cloning/validation utilities from internal/validate/url.go. Reuse the
existing blockedDownloadTransport, cloneDownloadTransport, and
newDownloadTransportLeaf behavior, including DialTLS and DialTLSContext
guarding, while preserving the document-cover fail-closed behavior.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b8af4ea3-abfb-4bed-b614-408a8887f761

📥 Commits

Reviewing files that changed from the base of the PR and between 67015ee and e052549.

📒 Files selected for processing (34)
  • cmd/config/init_interactive.go
  • cmd/doctor/doctor.go
  • extension/transport/sidecar/interceptor_test.go
  • extension/transport/types.go
  • internal/auth/transport.go
  • internal/cmdutil/factory.go
  • internal/cmdutil/factory_default.go
  • internal/cmdutil/factory_http_test.go
  • internal/cmdutil/factory_proxy_warn_test.go
  • internal/cmdutil/testing_test.go
  • internal/cmdutil/transport.go
  • internal/cmdutil/transport_test.go
  • internal/core/types.go
  • internal/core/types_test.go
  • internal/registry/remote.go
  • internal/transport/config.go
  • internal/transport/default_client.go
  • internal/transport/extension.go
  • internal/transport/extension_test.go
  • internal/transport/policy_router.go
  • internal/transport/policy_router_test.go
  • internal/transport/shared.go
  • internal/transport/shared_test.go
  • internal/update/update.go
  • internal/validate/url.go
  • internal/validate/url_test.go
  • shortcuts/apps/file_common.go
  • shortcuts/doc/doc_resource_cover.go
  • shortcuts/doc/doc_resource_cover_test.go
  • shortcuts/im/helpers.go
  • shortcuts/mail/helpers.go
  • shortcuts/mail/signature_compose.go
  • shortcuts/minutes/minutes_download.go
  • shortcuts/minutes/minutes_download_test.go

Comment thread internal/cmdutil/factory_default.go
Comment thread internal/transport/policy_router.go
Comment thread internal/validate/url.go
@evandance
evandance force-pushed the refactor/http-transport-policy branch from e052549 to daf7052 Compare July 24, 2026 09:12

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (1)
internal/validate/url_test.go (1)

150-152: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Use trusted TLS settings for the legacy DialTLS tests.

Both tests can reuse the tls.Config from server.Client().Transport.(*http.Transport).TLSClientConfig instead of setting InsecureSkipVerify; this preserves the same trusted connection behavior without the static-analysis finding.

🤖 Prompt for 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.

In `@internal/validate/url_test.go` around lines 150 - 152, The legacy DialTLS
tests use InsecureSkipVerify instead of the trusted TLS configuration. In
internal/validate/url_test.go lines 150-152 and
shortcuts/doc/doc_resource_cover_test.go lines 745-747, reuse the
TLSClientConfig from server.Client().Transport.(*http.Transport) in the tls.Dial
configuration, preserving the existing trusted connection behavior without
disabling certificate verification.

Source: Linters/SAST tools

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

Nitpick comments:
In `@internal/validate/url_test.go`:
- Around line 150-152: The legacy DialTLS tests use InsecureSkipVerify instead
of the trusted TLS configuration. In internal/validate/url_test.go lines 150-152
and shortcuts/doc/doc_resource_cover_test.go lines 745-747, reuse the
TLSClientConfig from server.Client().Transport.(*http.Transport) in the tls.Dial
configuration, preserving the existing trusted connection behavior without
disabling certificate verification.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8b155bfd-3bd6-4d32-9fa4-a443e1f38bcf

📥 Commits

Reviewing files that changed from the base of the PR and between e052549 and daf7052.

📒 Files selected for processing (34)
  • cmd/config/init_interactive.go
  • cmd/doctor/doctor.go
  • extension/transport/sidecar/interceptor_test.go
  • extension/transport/types.go
  • internal/auth/transport.go
  • internal/cmdutil/factory.go
  • internal/cmdutil/factory_default.go
  • internal/cmdutil/factory_http_test.go
  • internal/cmdutil/factory_proxy_warn_test.go
  • internal/cmdutil/testing_test.go
  • internal/cmdutil/transport.go
  • internal/cmdutil/transport_test.go
  • internal/core/types.go
  • internal/core/types_test.go
  • internal/registry/remote.go
  • internal/transport/config.go
  • internal/transport/default_client.go
  • internal/transport/extension.go
  • internal/transport/extension_test.go
  • internal/transport/policy_router.go
  • internal/transport/policy_router_test.go
  • internal/transport/shared.go
  • internal/transport/shared_test.go
  • internal/update/update.go
  • internal/validate/url.go
  • internal/validate/url_test.go
  • shortcuts/apps/file_common.go
  • shortcuts/doc/doc_resource_cover.go
  • shortcuts/doc/doc_resource_cover_test.go
  • shortcuts/im/helpers.go
  • shortcuts/mail/helpers.go
  • shortcuts/mail/signature_compose.go
  • shortcuts/minutes/minutes_download.go
  • shortcuts/minutes/minutes_download_test.go
🚧 Files skipped from review as they are similar to previous changes (29)
  • internal/cmdutil/testing_test.go
  • shortcuts/im/helpers.go
  • internal/core/types.go
  • internal/transport/config.go
  • shortcuts/mail/signature_compose.go
  • cmd/doctor/doctor.go
  • internal/auth/transport.go
  • internal/update/update.go
  • internal/transport/shared.go
  • shortcuts/mail/helpers.go
  • internal/cmdutil/factory.go
  • shortcuts/minutes/minutes_download.go
  • shortcuts/minutes/minutes_download_test.go
  • internal/transport/default_client.go
  • extension/transport/sidecar/interceptor_test.go
  • shortcuts/apps/file_common.go
  • internal/core/types_test.go
  • internal/cmdutil/factory_default.go
  • internal/transport/extension.go
  • internal/validate/url.go
  • cmd/config/init_interactive.go
  • internal/transport/shared_test.go
  • shortcuts/doc/doc_resource_cover.go
  • internal/transport/extension_test.go
  • internal/cmdutil/transport.go
  • internal/transport/policy_router_test.go
  • internal/transport/policy_router.go
  • internal/cmdutil/transport_test.go
  • internal/cmdutil/factory_http_test.go

@evandance
evandance force-pushed the refactor/http-transport-policy branch from daf7052 to 8d4c615 Compare July 24, 2026 09:22

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 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 `@internal/cmdutil/transport_test.go`:
- Around line 97-131: Update
TestBuildSDKTransportAppliesSecurityHeadersToEveryRequestClass and the
additionally referenced HTTP tests to use the required isolated setup: assign
LARKSUITE_CLI_CONFIG_DIR to t.TempDir(), create the test configuration, and
construct the factory via cmdutil.TestFactory(t, config) before creating clients
or mocking requests. Preserve each test’s existing assertions and request
behavior.
- Around line 97-99: Update
TestBuildSDKTransportAppliesSecurityHeadersToEveryRequestClass to capture the
current exttransport provider before calling exttransport.Register(nil), then
register a t.Cleanup callback that restores the captured provider after the
test.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fb05899e-8033-4164-b39e-b1cceb000b47

📥 Commits

Reviewing files that changed from the base of the PR and between daf7052 and 8d4c615.

📒 Files selected for processing (35)
  • cmd/config/init_interactive.go
  • cmd/doctor/doctor.go
  • extension/transport/sidecar/interceptor_test.go
  • extension/transport/types.go
  • internal/auth/transport.go
  • internal/cmdutil/factory.go
  • internal/cmdutil/factory_default.go
  • internal/cmdutil/factory_http_test.go
  • internal/cmdutil/factory_proxy_warn_test.go
  • internal/cmdutil/testing_test.go
  • internal/cmdutil/transport.go
  • internal/cmdutil/transport_test.go
  • internal/core/types.go
  • internal/core/types_test.go
  • internal/registry/remote.go
  • internal/riskcontrol/transport.go
  • internal/transport/config.go
  • internal/transport/default_client.go
  • internal/transport/extension.go
  • internal/transport/extension_test.go
  • internal/transport/policy_router.go
  • internal/transport/policy_router_test.go
  • internal/transport/shared.go
  • internal/transport/shared_test.go
  • internal/update/update.go
  • internal/validate/url.go
  • internal/validate/url_test.go
  • shortcuts/apps/file_common.go
  • shortcuts/doc/doc_resource_cover.go
  • shortcuts/doc/doc_resource_cover_test.go
  • shortcuts/im/helpers.go
  • shortcuts/mail/helpers.go
  • shortcuts/mail/signature_compose.go
  • shortcuts/minutes/minutes_download.go
  • shortcuts/minutes/minutes_download_test.go
🚧 Files skipped from review as they are similar to previous changes (28)
  • shortcuts/apps/file_common.go
  • internal/registry/remote.go
  • internal/cmdutil/factory_proxy_warn_test.go
  • shortcuts/minutes/minutes_download.go
  • internal/cmdutil/testing_test.go
  • shortcuts/mail/signature_compose.go
  • extension/transport/types.go
  • internal/transport/config.go
  • extension/transport/sidecar/interceptor_test.go
  • internal/auth/transport.go
  • cmd/doctor/doctor.go
  • shortcuts/mail/helpers.go
  • internal/core/types.go
  • internal/update/update.go
  • internal/transport/shared.go
  • shortcuts/im/helpers.go
  • internal/core/types_test.go
  • internal/transport/default_client.go
  • internal/transport/extension.go
  • shortcuts/doc/doc_resource_cover.go
  • internal/cmdutil/transport.go
  • internal/transport/shared_test.go
  • internal/transport/policy_router_test.go
  • internal/transport/extension_test.go
  • internal/cmdutil/factory_default.go
  • internal/validate/url.go
  • internal/transport/policy_router.go
  • internal/cmdutil/factory_http_test.go

Comment thread internal/cmdutil/transport_test.go
Comment thread internal/cmdutil/transport_test.go

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/validate/url.go (1)

73-117: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

New error paths use bare fmt.Errorf instead of typed errs.* constructors.

resolveDownloadHost, ValidateDownloadSourceURL, NewDownloadHTTPClient's CheckRedirect, proxyAwareDownloadTransport.RoundTrip, pinDownloadRequestTargetToIP, canRetryDownloadTarget's callers, and validateConnRemoteIP all construct errors with bare fmt.Errorf (e.g. "local/internal host is not allowed", "failed to resolve host", "blocked download target: %w"). A prior review already flagged this exact pattern for blockedDownloadTransport.err in this file, recommending errs.NewInternalError(...) instead of a bare error. The same fix applies broadly here: validation failures (bad host/URL) should use the validation-error constructor, and resolver/network failures should use the network-error constructor, so callers that classify errors via errs.ProblemOf don't see these as unclassified internal errors.

🔧 Example fix for resolveDownloadHost
 func resolveDownloadHost(ctx context.Context, rawHost string, lookupIP downloadLookupIPFunc) ([]net.IP, error) {
 	host := strings.TrimSpace(strings.ToLower(rawHost))
 	if host == "" {
-		return nil, fmt.Errorf("URL host is required")
+		return nil, errs.NewValidationError(errs.SubtypeInvalidArgument, "host", "URL host is required")
 	}
 	if host == "localhost" || strings.HasSuffix(host, ".localhost") {
-		return nil, fmt.Errorf("local/internal host is not allowed")
+		return nil, errs.NewValidationError(errs.SubtypeInvalidArgument, "host", "local/internal host is not allowed")
 	}

Based on learnings, error-path tests must assert typed metadata via errs.ProblemOf rather than message substrings — but that's only possible once these call sites actually return typed errors.

Also applies to: 121-148, 165-221, 263-265, 289-358, 486-506

🤖 Prompt for 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.

In `@internal/validate/url.go` around lines 73 - 117, Replace bare fmt.Errorf
calls across ValidateDownloadSourceURL, resolveDownloadHost,
NewDownloadHTTPClient.CheckRedirect, proxyAwareDownloadTransport.RoundTrip,
pinDownloadRequestTargetToIP, canRetryDownloadTarget callers, and
validateConnRemoteIP with the appropriate errs constructors. Use validation
errors for malformed or blocked URL/host targets and network errors for DNS,
connection, or transport failures; preserve wrapped causes where applicable.
Update related error-path tests to assert typed metadata through errs.ProblemOf
rather than matching messages.

Source: Coding guidelines

🧹 Nitpick comments (1)
internal/validate/url.go (1)

414-457: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Triplicated dial-wrap-and-validate logic across DialContext/DialTLSContext/DialTLS.

The three blocks wrapping cloned.DialContext, cloned.DialTLSContext, and cloned.DialTLS each repeat the same dial → check err → validateConnRemoteIP → close-on-fail sequence. Extracting a small generic helper would reduce duplication; functionally this is correct, including the new DialTLS branch that closes the gap left when only DialTLSContext was covered.

♻️ Suggested consolidation
+func wrapDialWithIPValidation[F ~func(string, string) (net.Conn, error)](orig F) F {
+	return func(network, addr string) (net.Conn, error) {
+		conn, err := orig(network, addr)
+		if err != nil {
+			return nil, err
+		}
+		if err := validateConnRemoteIP(conn); err != nil {
+			conn.Close()
+			return nil, err
+		}
+		return conn, nil
+	}
+}
🤖 Prompt for 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.

In `@internal/validate/url.go` around lines 414 - 457, Refactor
configureDirectDownloadTransport to extract the repeated dial, error-check,
validateConnRemoteIP, and close-on-failure sequence into a small reusable
helper. Update the DialContext, DialTLSContext, and DialTLS wrappers to delegate
through that helper while preserving their existing callback signatures and
behavior.
🤖 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 `@internal/validate/url_internal_test.go`:
- Around line 96-106: Update TestProxiedDownloadRejectsRestrictedResolvedTarget
and TestProxiedPlainHTTPHostnameRejectsLocalProxy to inspect errors through
errs.ProblemOf, asserting the expected category, subtype, and parameter instead
of matching err.Error() substrings. Ensure resolveDownloadHost and RoundTrip
expose the corresponding typed errs errors so these assertions validate
structured metadata while preserving existing cause checks.

In `@internal/validate/url.go`:
- Around line 236-257: Update proxiedTransportForTLSServer so cloned transports
do not assign the downstream serverName to transport.TLSClientConfig.ServerName.
Preserve the proxy TLS configuration separately, allowing Go’s HTTPS-proxy
handshake to use the proxy hostname while retaining serverName only for
downstream transport selection and caching.

---

Outside diff comments:
In `@internal/validate/url.go`:
- Around line 73-117: Replace bare fmt.Errorf calls across
ValidateDownloadSourceURL, resolveDownloadHost,
NewDownloadHTTPClient.CheckRedirect, proxyAwareDownloadTransport.RoundTrip,
pinDownloadRequestTargetToIP, canRetryDownloadTarget callers, and
validateConnRemoteIP with the appropriate errs constructors. Use validation
errors for malformed or blocked URL/host targets and network errors for DNS,
connection, or transport failures; preserve wrapped causes where applicable.
Update related error-path tests to assert typed metadata through errs.ProblemOf
rather than matching messages.

---

Nitpick comments:
In `@internal/validate/url.go`:
- Around line 414-457: Refactor configureDirectDownloadTransport to extract the
repeated dial, error-check, validateConnRemoteIP, and close-on-failure sequence
into a small reusable helper. Update the DialContext, DialTLSContext, and
DialTLS wrappers to delegate through that helper while preserving their existing
callback signatures and behavior.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c9e87b1e-f0f6-4be1-8f86-7b04cef4f661

📥 Commits

Reviewing files that changed from the base of the PR and between 8d4c615 and 5337516.

📒 Files selected for processing (7)
  • internal/cmdutil/factory_default.go
  • internal/cmdutil/transport_test.go
  • internal/transport/default_client.go
  • internal/transport/extension_test.go
  • internal/validate/url.go
  • internal/validate/url_internal_test.go
  • internal/validate/url_test.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • internal/transport/default_client.go
  • internal/validate/url_test.go
  • internal/cmdutil/factory_default.go
  • internal/cmdutil/transport_test.go

Comment thread internal/validate/url_internal_test.go
Comment thread internal/validate/url.go
@evandance
evandance force-pushed the refactor/http-transport-policy branch from b787454 to 06d5b18 Compare July 25, 2026 10:13
@evandance

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai 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.

Actionable comments posted: 9

♻️ Duplicate comments (1)
internal/cmdutil/transport_test.go (1)

97-99: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Missing provider capture/restore reintroduces a previously flagged issue.

exttransport.Register(nil) overwrites the global extension provider with no capture/restore, unlike every other test in this file (133-196, 303-368, etc.) which all use previous := exttransport.GetProvider() + t.Cleanup. This exact line range was flagged before and reported addressed, but the fix isn't present here.

🩺 Proposed fix
 func TestBuildSDKTransportAppliesSecurityHeadersToEveryRequestClass(t *testing.T) {
-	exttransport.Register(nil)
+	previous := exttransport.GetProvider()
+	exttransport.Register(nil)
+	t.Cleanup(func() { exttransport.Register(previous) })
 	received := make(chan http.Header, 2)
🤖 Prompt for 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.

In `@internal/cmdutil/transport_test.go` around lines 97 - 99, Update
TestBuildSDKTransportAppliesSecurityHeadersToEveryRequestClass to capture the
current extension provider before calling exttransport.Register(nil), then
register a t.Cleanup callback that restores the captured provider, matching the
established pattern used by the other tests in this file.
🧹 Nitpick comments (4)
internal/validate/url_internal_test.go (1)

130-135: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid falling back to the real resolver in a unit test.

net.DefaultResolver.LookupIP makes this test depend on ambient DNS for any host other than public.example. Returning a fixed IP (or an error) for unexpected hosts keeps the test hermetic and fails fast instead of hanging in offline CI sandboxes.

🤖 Prompt for 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.

In `@internal/validate/url_internal_test.go` around lines 130 - 135, Update the
lookupIP test helper to avoid calling net.DefaultResolver.LookupIP for
unexpected hosts; return a fixed deterministic IP or an explicit error instead,
while preserving the public.example mapping so the test remains hermetic and
fails fast.
internal/auth/transport.go (1)

36-44: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a decorator contract test for SecurityPolicyTransport.

Both new methods are uncovered. A small test asserting that transport.CloneHTTPTransportForRequestClass (or a direct WithBaseRoundTripper/BaseRoundTripper round-trip) preserves the security policy layer would make a regression here fail loudly, since policy_router.go relies on this contract to keep the platform error-parsing layer while swapping the leaf *http.Transport.

Note that BaseRoundTripper() never returns nil (it falls back to transport.Fallback()), so the nil-guard in transformHTTPTransportForRequestClass will never trip for this type — worth asserting the fallback path explicitly too.

🤖 Prompt for 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.

In `@internal/auth/transport.go` around lines 36 - 44, The SecurityPolicyTransport
decorator methods lack coverage for preserving the security-policy layer while
replacing the leaf transport. Add a focused contract test using
WithBaseRoundTripper/BaseRoundTripper or CloneHTTPTransportForRequestClass that
verifies the wrapped policy remains intact, and explicitly assert
BaseRoundTripper falls back to transport.Fallback() when no base transport is
configured.

Sources: Coding guidelines, Linters/SAST tools

internal/transport/extension_test.go (1)

62-64: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Restore the previously registered provider instead of nil.

Other tests in this file capture exttransport.GetProvider() and restore it in cleanup; these two reset the global registry to nil, which silently drops any provider installed by a package-level or earlier setup. Making all cleanups symmetric removes an ordering-dependent failure mode.

♻️ Suggested change
+	previousProvider := exttransport.GetProvider()
 	interceptor := &testHeaderInterceptor{}
 	exttransport.Register(testProvider{interceptor: interceptor})
-	t.Cleanup(func() { exttransport.Register(nil) })
+	t.Cleanup(func() { exttransport.Register(previousProvider) })

Also applies to: 138-144

🤖 Prompt for 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.

In `@internal/transport/extension_test.go` around lines 62 - 64, The test cleanup
around the provider registration must restore the previously registered provider
rather than resetting it to nil. In each affected test, capture
exttransport.GetProvider() before calling exttransport.Register, then have
t.Cleanup restore that captured provider, matching the existing cleanup pattern
elsewhere in the file.
internal/transport/extension.go (1)

100-101: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Use BaseRoundTripper() in RoundTrip so a nil Base cannot panic.

BaseRoundTripper() already treats a nil Base as Shared(), and WithBaseRoundTripper accepts a nil argument without substitution — so a rebuilt middleware with nil base would nil-deref here instead of falling back.

♻️ Proposed change
 	req = req.WithContext(origCtx)
-	resp, err := m.Base.RoundTrip(req)
+	resp, err := m.BaseRoundTripper().RoundTrip(req)
🤖 Prompt for 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.

In `@internal/transport/extension.go` around lines 100 - 101, Update RoundTrip to
invoke BaseRoundTripper() instead of dereferencing m.Base directly when
forwarding the request. Preserve the existing context restoration and error
handling while ensuring a nil base falls back to the shared round tripper.
🤖 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 `@internal/cmdutil/factory_http_test.go`:
- Around line 321-325: Update the error assertions in the safeRedirectPolicy
test to obtain the typed problem via errs.ProblemOf(err) and assert its
redirect-error metadata, while retaining the existing HTTPS downgrade condition
as appropriate. Do not rely solely on err.Error() string matching; ensure the
test fails if safeRedirectPolicy returns an untyped error.

In `@internal/cmdutil/transport_test.go`:
- Around line 303-368: Update TestNewDefaultInstallsSDKBootstrapSecurityPolicy
to preserve and restore http.DefaultClient’s Transport and CheckRedirect while
exercising NewDefault’s global rewiring. Arrange the test transport so the final
http.DefaultClient.Do request is delivered to the roundTripFunc network, and
ensure non-SDK bootstrap traffic remains unmodified while SDK bootstrap policy
behavior is still asserted.

In `@internal/transport/default_client.go`:
- Around line 55-61: Update the bootstrap policy failure paths in the transport
initialization flow to return typed errors via
errs.NewInternalError(errs.SubtypeUnknown, ...), replacing the plain fmt.Errorf
results. Preserve the existing messages and wrap or otherwise retain the
upstream cause for the nil transport result when available.

In `@internal/transport/extension_test.go`:
- Around line 444-449: Update
TestSDKBootstrapRedirectGuardChecksLocationAfterExtensionPostHook and
TestSDKBootstrapTransportFailsClosedWithoutPlatformPolicy to inspect typed
metadata via errs.ProblemOf instead of only matching err.Error(). Assert the
expected category, subtype, and param for the cross-origin policy/access_denied
and missing-policy failures, following the existing assertions in the sibling
tests near lines 204-208 and 229-232, while preserving the external-call count
checks.

In `@internal/validate/url_internal_test.go`:
- Around line 78-82: Replace the unsynchronized proxyCalled flag in both
affected tests with a concurrency-safe atomic.Bool (or the existing
buffered-channel pattern), storing the value in the httptest handler and loading
it after RoundTrip before asserting that the proxy was not contacted.

In `@shortcuts/doc/doc_resource_cover_test.go`:
- Around line 731-734: Update the RoundTrip error assertion in the relevant
document-cover test to inspect errs.ProblemOf(err) and verify the expected
category, subtype errs.SubtypeUnknown, and parameter metadata for the
fail-closed clone error. Also assert that the original error is preserved as the
cause, while retaining the existing message check only if needed for context.

In `@shortcuts/doc/doc_resource_cover.go`:
- Around line 787-801: Extend the tests for the cloning logic that wraps
cloned.DialTLS to directly cover both outcomes: when
validateDocCoverConnRemoteIP rejects the connection, assert the connection is
closed and the returned error is the expected typed policy error; when
origDialTLS returns an error, assert the wrapper preserves that exact underlying
error.
- Around line 739-750: Update both reconstruction paths in the transport
transformation logic around newDocCoverTransportLeaf so they preserve the
configured proxy while still applying target-pinning safeguards. Remove the
behavior that clears cloned.Proxy, and ensure transports rebuilt from the
structural TransformHTTPTransport capability and *http.Transport.Clone retain
external proxy routing.

In `@shortcuts/mail/signature_compose.go`:
- Line 231: Add a test covering the signature image download flow around
ExternalHTTPClient, using a server response with a platform-shaped error payload
and asserting the download succeeds without platform protocol parsing. Ensure
the test exercises the external-client routing contract and would fail if the
implementation reverted to HttpClient().

---

Duplicate comments:
In `@internal/cmdutil/transport_test.go`:
- Around line 97-99: Update
TestBuildSDKTransportAppliesSecurityHeadersToEveryRequestClass to capture the
current extension provider before calling exttransport.Register(nil), then
register a t.Cleanup callback that restores the captured provider, matching the
established pattern used by the other tests in this file.

---

Nitpick comments:
In `@internal/auth/transport.go`:
- Around line 36-44: The SecurityPolicyTransport decorator methods lack coverage
for preserving the security-policy layer while replacing the leaf transport. Add
a focused contract test using WithBaseRoundTripper/BaseRoundTripper or
CloneHTTPTransportForRequestClass that verifies the wrapped policy remains
intact, and explicitly assert BaseRoundTripper falls back to
transport.Fallback() when no base transport is configured.

In `@internal/transport/extension_test.go`:
- Around line 62-64: The test cleanup around the provider registration must
restore the previously registered provider rather than resetting it to nil. In
each affected test, capture exttransport.GetProvider() before calling
exttransport.Register, then have t.Cleanup restore that captured provider,
matching the existing cleanup pattern elsewhere in the file.

In `@internal/transport/extension.go`:
- Around line 100-101: Update RoundTrip to invoke BaseRoundTripper() instead of
dereferencing m.Base directly when forwarding the request. Preserve the existing
context restoration and error handling while ensuring a nil base falls back to
the shared round tripper.

In `@internal/validate/url_internal_test.go`:
- Around line 130-135: Update the lookupIP test helper to avoid calling
net.DefaultResolver.LookupIP for unexpected hosts; return a fixed deterministic
IP or an explicit error instead, while preserving the public.example mapping so
the test remains hermetic and fails fast.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5061fa93-5da8-4179-9568-99ccd2bbc898

📥 Commits

Reviewing files that changed from the base of the PR and between 5337516 and 06d5b18.

📒 Files selected for processing (38)
  • cmd/config/init_interactive.go
  • cmd/doctor/doctor.go
  • extension/transport/sidecar/interceptor_test.go
  • extension/transport/types.go
  • internal/auth/transport.go
  • internal/client/client.go
  • internal/client/client_test.go
  • internal/cmdutil/factory.go
  • internal/cmdutil/factory_default.go
  • internal/cmdutil/factory_http_test.go
  • internal/cmdutil/factory_proxy_warn_test.go
  • internal/cmdutil/testing_test.go
  • internal/cmdutil/transport.go
  • internal/cmdutil/transport_test.go
  • internal/core/types.go
  • internal/core/types_test.go
  • internal/registry/remote.go
  • internal/riskcontrol/transport.go
  • internal/transport/config.go
  • internal/transport/default_client.go
  • internal/transport/extension.go
  • internal/transport/extension_test.go
  • internal/transport/policy_router.go
  • internal/transport/policy_router_test.go
  • internal/transport/shared.go
  • internal/transport/shared_test.go
  • internal/update/update.go
  • internal/validate/url.go
  • internal/validate/url_internal_test.go
  • internal/validate/url_test.go
  • shortcuts/apps/file_common.go
  • shortcuts/doc/doc_resource_cover.go
  • shortcuts/doc/doc_resource_cover_test.go
  • shortcuts/im/helpers.go
  • shortcuts/mail/helpers.go
  • shortcuts/mail/signature_compose.go
  • shortcuts/minutes/minutes_download.go
  • shortcuts/minutes/minutes_download_test.go
🚧 Files skipped from review as they are similar to previous changes (17)
  • internal/transport/config.go
  • internal/cmdutil/testing_test.go
  • shortcuts/mail/helpers.go
  • cmd/doctor/doctor.go
  • shortcuts/minutes/minutes_download.go
  • internal/cmdutil/factory_proxy_warn_test.go
  • shortcuts/minutes/minutes_download_test.go
  • internal/registry/remote.go
  • shortcuts/apps/file_common.go
  • internal/transport/shared_test.go
  • cmd/config/init_interactive.go
  • internal/client/client_test.go
  • extension/transport/sidecar/interceptor_test.go
  • extension/transport/types.go
  • internal/transport/shared.go
  • internal/client/client.go
  • internal/transport/policy_router_test.go

Comment thread internal/cmdutil/factory_http_test.go
Comment thread internal/cmdutil/transport_test.go
Comment thread internal/transport/default_client.go
Comment thread internal/transport/extension_test.go
Comment thread internal/validate/url_internal_test.go Outdated
Comment thread shortcuts/doc/doc_resource_cover_test.go
Comment thread shortcuts/doc/doc_resource_cover.go Outdated
Comment thread shortcuts/doc/doc_resource_cover.go Outdated
Comment thread shortcuts/mail/signature_compose.go
@evandance
evandance force-pushed the refactor/http-transport-policy branch from 06d5b18 to cb1d379 Compare July 27, 2026 03:29
@evandance

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@evandance
evandance force-pushed the refactor/http-transport-policy branch from cb1d379 to 7a3485a Compare July 27, 2026 03:32
@evandance

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai 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.

Actionable comments posted: 3

🧹 Nitpick comments (2)
internal/validate/url.go (1)

248-269: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

proxiedByTLSServer grows unbounded, one *http.Transport (and idle conn pool) per distinct TLS host.

Each unique download hostname permanently adds a cloned transport with its own connection pool for the process lifetime. For a CLI this is usually a handful of hosts, but a long-running batch download (or a redirect chain across many origins) accumulates pools that are only released by CloseIdleConnections. A small bound (or eviction) would cap the footprint.

🤖 Prompt for 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.

In `@internal/validate/url.go` around lines 248 - 269, Bound the cache managed by
proxiedTransportForTLSServer so proxiedByTLSServer cannot grow indefinitely
across distinct server names. Add a small fixed capacity with eviction of older
entries, closing each evicted transport’s idle connections, while preserving
reuse of cached transports and TLS/proxy configuration for retained entries.
shortcuts/doc/doc_resource_cover.go (1)

696-719: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Dead MaxRedirects: 3 option shadows the real hardcoded limit.

validate.NewDownloadHTTPClient(base, validate.DownloadHTTPClientOptions{MaxRedirects: 3}) returns a client whose CheckRedirect (governed by MaxRedirects) is discarded — only .Transport is used. The actual enforced limit is the separately hardcoded len(via) >= 3 in the local CheckRedirect at Line 708. If either constant is changed without the other, the redirect limit silently diverges from what a reader would expect from the DownloadHTTPClientOptions value.

Consider dropping the unused MaxRedirects field here (since it has no effect), or extracting a single named constant shared by both.

♻️ Suggested tweak
-	cloned.Transport = validate.NewDownloadHTTPClient(base, validate.DownloadHTTPClientOptions{ //nolint:forbidigo // guarded external download
-		MaxRedirects: 3,
-	}).Transport
+	cloned.Transport = validate.NewDownloadHTTPClient(base, validate.DownloadHTTPClientOptions{}).Transport //nolint:forbidigo // guarded external download; redirect limit enforced below
 	cloned.CheckRedirect = func(req *http.Request, via []*http.Request) error { //nolint:forbidigo // redirects must be validated for external --url downloads.
-		if len(via) >= 3 {
+		if len(via) >= docCoverURLMaxRedirects {
🤖 Prompt for 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.

In `@shortcuts/doc/doc_resource_cover.go` around lines 696 - 719, In
newDocCoverHTTPClient, eliminate the unused DownloadHTTPClientOptions
MaxRedirects value or replace both redirect-limit literals with one shared named
constant. Ensure the local CheckRedirect logic remains the sole enforced
redirect policy while preventing the configured limit from diverging from
len(via) >= 3.
🤖 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 `@internal/validate/url_test.go`:
- Around line 160-163: Update the legacy DialTLS guard test around
download.Transport.RoundTrip to inspect the returned error with errs.ProblemOf,
asserting category, subtype, and param values for downloadTargetPolicyError and
verifying the underlying cause is preserved; retain the existing message check
only if needed alongside these typed assertions.

In `@shortcuts/doc/doc_resource_cover_test.go`:
- Around line 728-746: The test TestNewDocCoverHTTPClientGuardsLegacyDialTLS
should assert structured error metadata with errs.ProblemOf instead of only
matching the error string. Validate the expected category, subtype, and param,
and verify the underlying cause is preserved, following
TestNewDocCoverHTTPClientFailsClosedForOpaqueTransport and
TestDirectDownloadLegacyDialTLSClosesRestrictedConnection.

In `@shortcuts/mail/signature_compose_test.go`:
- Around line 122-154: Update TestDownloadSignatureImageUsesExternalRequestClass
to construct its command factory with the repository’s Cmdutil.TestFactory
pattern, and isolate LARKSUITE_CLI_CONFIG_DIR with t.Setenv and t.TempDir.
Preserve the custom factory.HttpClient override so the test continues injecting
the policy-router client.

---

Nitpick comments:
In `@internal/validate/url.go`:
- Around line 248-269: Bound the cache managed by proxiedTransportForTLSServer
so proxiedByTLSServer cannot grow indefinitely across distinct server names. Add
a small fixed capacity with eviction of older entries, closing each evicted
transport’s idle connections, while preserving reuse of cached transports and
TLS/proxy configuration for retained entries.

In `@shortcuts/doc/doc_resource_cover.go`:
- Around line 696-719: In newDocCoverHTTPClient, eliminate the unused
DownloadHTTPClientOptions MaxRedirects value or replace both redirect-limit
literals with one shared named constant. Ensure the local CheckRedirect logic
remains the sole enforced redirect policy while preventing the configured limit
from diverging from len(via) >= 3.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c9cc313e-4944-446c-9d01-6bdf9f7905e1

📥 Commits

Reviewing files that changed from the base of the PR and between 06d5b18 and cb1d379.

📒 Files selected for processing (39)
  • cmd/config/init_interactive.go
  • cmd/doctor/doctor.go
  • extension/transport/sidecar/interceptor_test.go
  • extension/transport/types.go
  • internal/auth/transport.go
  • internal/client/client.go
  • internal/client/client_test.go
  • internal/cmdutil/factory.go
  • internal/cmdutil/factory_default.go
  • internal/cmdutil/factory_http_test.go
  • internal/cmdutil/factory_proxy_warn_test.go
  • internal/cmdutil/testing_test.go
  • internal/cmdutil/transport.go
  • internal/cmdutil/transport_test.go
  • internal/core/types.go
  • internal/core/types_test.go
  • internal/registry/remote.go
  • internal/riskcontrol/transport.go
  • internal/transport/config.go
  • internal/transport/default_client.go
  • internal/transport/extension.go
  • internal/transport/extension_test.go
  • internal/transport/policy_router.go
  • internal/transport/policy_router_test.go
  • internal/transport/shared.go
  • internal/transport/shared_test.go
  • internal/update/update.go
  • internal/validate/url.go
  • internal/validate/url_internal_test.go
  • internal/validate/url_test.go
  • shortcuts/apps/file_common.go
  • shortcuts/doc/doc_resource_cover.go
  • shortcuts/doc/doc_resource_cover_test.go
  • shortcuts/im/helpers.go
  • shortcuts/mail/helpers.go
  • shortcuts/mail/signature_compose.go
  • shortcuts/mail/signature_compose_test.go
  • shortcuts/minutes/minutes_download.go
  • shortcuts/minutes/minutes_download_test.go
🚧 Files skipped from review as they are similar to previous changes (29)
  • internal/transport/config.go
  • extension/transport/types.go
  • internal/update/update.go
  • internal/core/types.go
  • internal/registry/remote.go
  • shortcuts/im/helpers.go
  • extension/transport/sidecar/interceptor_test.go
  • internal/client/client_test.go
  • shortcuts/mail/signature_compose.go
  • internal/cmdutil/factory.go
  • shortcuts/apps/file_common.go
  • internal/cmdutil/factory_proxy_warn_test.go
  • internal/transport/shared_test.go
  • internal/riskcontrol/transport.go
  • internal/transport/shared.go
  • internal/client/client.go
  • shortcuts/minutes/minutes_download_test.go
  • shortcuts/mail/helpers.go
  • internal/transport/default_client.go
  • internal/transport/policy_router.go
  • shortcuts/minutes/minutes_download.go
  • internal/cmdutil/factory_default.go
  • internal/cmdutil/transport.go
  • internal/core/types_test.go
  • internal/transport/policy_router_test.go
  • internal/cmdutil/testing_test.go
  • internal/transport/extension.go
  • internal/cmdutil/transport_test.go
  • internal/cmdutil/factory_http_test.go

Comment thread internal/validate/url_test.go
Comment thread shortcuts/doc/doc_resource_cover_test.go
Comment thread shortcuts/mail/signature_compose_test.go

@coderabbitai coderabbitai 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.

Actionable comments posted: 3

♻️ Duplicate comments (1)
internal/validate/url_test.go (1)

160-163: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Legacy DialTLS guard tests assert only message substrings. Both tests exercise the same downloadTargetPolicyError boundary in internal/validate/url.go, which now classifies as policy/access_denied; neither pins that classification, so removing the typed wrap would keep both green.

  • internal/validate/url_test.go#L160-L163: add an errs.ProblemOf assertion for errs.CategoryPolicy / errs.SubtypeAccessDenied after the existing message check.
  • shortcuts/doc/doc_resource_cover_test.go#L742-L745: add the same errs.ProblemOf assertion, matching the pattern already used in TestNewDocCoverHTTPClientFailsClosedForOpaqueTransport.

As per coding guidelines: "Error-path tests must assert typed metadata through errs.ProblemOf (category, subtype, and param) ... rather than relying only on message substrings."

🤖 Prompt for 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.

In `@internal/validate/url_test.go` around lines 160 - 163, Both legacy DialTLS
guard tests only validate error text and must also assert typed metadata. In
internal/validate/url_test.go lines 160-163 and
shortcuts/doc/doc_resource_cover_test.go lines 742-745, add errs.ProblemOf
assertions for errs.CategoryPolicy, errs.SubtypeAccessDenied, and the expected
param, following the existing pattern in
TestNewDocCoverHTTPClientFailsClosedForOpaqueTransport; retain the current
message checks.

Source: Coding guidelines

🤖 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 `@internal/transport/default_client.go`:
- Around line 147-160: Update the fallback redirect-limit branch in
sdkBootstrapRedirectPolicy to return the established typed network error via
errs.NewNetworkError(errs.SubtypeNetworkTransport, "too many redirects") instead
of fmt.Errorf, matching the equivalent factory redirect handling and preserving
the existing redirect limit.
- Around line 234-254: Update installSDKTransportBridge so it does not mutate
shared http.DefaultClient.Transport or CheckRedirect while requests may use
them; route the SDK bridge through a dedicated http.Client, or ensure one-time
initialization completes before any DefaultClient traffic can begin. Preserve
the existing sdkBootstrapTransport reuse and redirect-policy behavior for the
client used by the bridge.

In `@internal/transport/extension.go`:
- Around line 62-106: Update ExtensionMiddleware.RoundTrip to invoke the wrapped
transport through BaseRoundTripper() instead of accessing m.Base directly,
preserving the existing request, hook, and error flow while ensuring nil Base
values use Shared().

---

Duplicate comments:
In `@internal/validate/url_test.go`:
- Around line 160-163: Both legacy DialTLS guard tests only validate error text
and must also assert typed metadata. In internal/validate/url_test.go lines
160-163 and shortcuts/doc/doc_resource_cover_test.go lines 742-745, add
errs.ProblemOf assertions for errs.CategoryPolicy, errs.SubtypeAccessDenied, and
the expected param, following the existing pattern in
TestNewDocCoverHTTPClientFailsClosedForOpaqueTransport; retain the current
message checks.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7dff2721-bde3-4de0-8815-17290566683d

📥 Commits

Reviewing files that changed from the base of the PR and between cb1d379 and 7a3485a.

📒 Files selected for processing (39)
  • cmd/config/init_interactive.go
  • cmd/doctor/doctor.go
  • extension/transport/sidecar/interceptor_test.go
  • extension/transport/types.go
  • internal/auth/transport.go
  • internal/client/client.go
  • internal/client/client_test.go
  • internal/cmdutil/factory.go
  • internal/cmdutil/factory_default.go
  • internal/cmdutil/factory_http_test.go
  • internal/cmdutil/factory_proxy_warn_test.go
  • internal/cmdutil/testing_test.go
  • internal/cmdutil/transport.go
  • internal/cmdutil/transport_test.go
  • internal/core/types.go
  • internal/core/types_test.go
  • internal/registry/remote.go
  • internal/riskcontrol/transport.go
  • internal/transport/config.go
  • internal/transport/default_client.go
  • internal/transport/extension.go
  • internal/transport/extension_test.go
  • internal/transport/policy_router.go
  • internal/transport/policy_router_test.go
  • internal/transport/shared.go
  • internal/transport/shared_test.go
  • internal/update/update.go
  • internal/validate/url.go
  • internal/validate/url_internal_test.go
  • internal/validate/url_test.go
  • shortcuts/apps/file_common.go
  • shortcuts/doc/doc_resource_cover.go
  • shortcuts/doc/doc_resource_cover_test.go
  • shortcuts/im/helpers.go
  • shortcuts/mail/helpers.go
  • shortcuts/mail/signature_compose.go
  • shortcuts/mail/signature_compose_test.go
  • shortcuts/minutes/minutes_download.go
  • shortcuts/minutes/minutes_download_test.go
🚧 Files skipped from review as they are similar to previous changes (19)
  • cmd/doctor/doctor.go
  • shortcuts/mail/helpers.go
  • internal/cmdutil/testing_test.go
  • extension/transport/types.go
  • internal/cmdutil/factory_proxy_warn_test.go
  • internal/client/client_test.go
  • shortcuts/mail/signature_compose.go
  • shortcuts/mail/signature_compose_test.go
  • shortcuts/apps/file_common.go
  • internal/core/types_test.go
  • shortcuts/minutes/minutes_download_test.go
  • extension/transport/sidecar/interceptor_test.go
  • internal/core/types.go
  • internal/transport/policy_router_test.go
  • internal/transport/shared.go
  • internal/transport/shared_test.go
  • shortcuts/minutes/minutes_download.go
  • internal/cmdutil/transport_test.go
  • internal/cmdutil/factory_http_test.go

Comment thread internal/transport/default_client.go
Comment thread internal/transport/default_client.go
Comment thread internal/transport/extension.go
@evandance
evandance force-pushed the refactor/http-transport-policy branch from 7a3485a to 52a39a8 Compare July 27, 2026 03:57
@evandance

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@evandance

Copy link
Copy Markdown
Collaborator Author

Follow-up on CodeRabbit review 4785206785 nitpicks: fixed explicit TLS 1.2 for synthesized configs, preserved source HTTP/2 capability in derived transports, and restored previous test providers. No change for the unreachable lastErr fallback, the per-download-client cache bounded by redirect limits, or context-free URL helpers whose boundary-specific validation/param contract would be broken by forcing policy errors.

@evandance

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
internal/transport/extension_test.go (1)

474-496: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider isolating proxy env/state like the sibling tests.

Unlike TestLegacyProviderKeepsAllRequestBehavior and TestScopedProviderOnlyRunsForSupportedRequestClass, this test doesn't call unsetProxyPluginEnv(t) / resetProxyPluginState(). sdkBootstrapHTTPClient's existing transport is reused via identityTransportPolicy, so an inherited HTTP_PROXY in CI could route the loopback httptest request through a proxy and make it flaky (Go's ProxyFromEnvironment doesn't auto-exempt loopback).

♻️ Suggested isolation
 func TestDefaultClientBridgeCoversWebSocketSDKBootstrap(t *testing.T) {
 	preserveHTTPClientState(t, sdkBootstrapHTTPClient)
+	unsetProxyPluginEnv(t)
+	resetProxyPluginState()
+	t.Setenv(EnvNoProxy, "1")
🤖 Prompt for 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.

In `@internal/transport/extension_test.go` around lines 474 - 496, Update
TestDefaultClientBridgeCoversWebSocketSDKBootstrap to isolate proxy-related
global state like its sibling tests: call unsetProxyPluginEnv(t) and
resetProxyPluginState() before reusing sdkBootstrapHTTPClient with
identityTransportPolicy. Preserve the existing test setup and assertions.
🤖 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 `@internal/validate/url_internal_test.go`:
- Around line 99-125: Add a table case to
TestCloneDownloadHTTPTransportPreservesHTTP2Policy with ForceAttemptHTTP2 left
false and TLSNextProto containing an "h2" entry returning a nil
http.RoundTripper, and set want to true. Keep the existing cases unchanged so
the test directly fails if cloneDownloadHTTPTransport removes its
TLSNextProto-based ForceAttemptHTTP2 branch.

---

Nitpick comments:
In `@internal/transport/extension_test.go`:
- Around line 474-496: Update TestDefaultClientBridgeCoversWebSocketSDKBootstrap
to isolate proxy-related global state like its sibling tests: call
unsetProxyPluginEnv(t) and resetProxyPluginState() before reusing
sdkBootstrapHTTPClient with identityTransportPolicy. Preserve the existing test
setup and assertions.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 69dfa91d-36ca-40ec-9c21-6d1a18fb8254

📥 Commits

Reviewing files that changed from the base of the PR and between 62b5f47 and a60c183.

📒 Files selected for processing (39)
  • cmd/config/init_interactive.go
  • cmd/doctor/doctor.go
  • extension/transport/sidecar/interceptor_test.go
  • extension/transport/types.go
  • internal/auth/transport.go
  • internal/client/client.go
  • internal/client/client_test.go
  • internal/cmdutil/factory.go
  • internal/cmdutil/factory_default.go
  • internal/cmdutil/factory_http_test.go
  • internal/cmdutil/factory_proxy_warn_test.go
  • internal/cmdutil/testing_test.go
  • internal/cmdutil/transport.go
  • internal/cmdutil/transport_test.go
  • internal/core/types.go
  • internal/core/types_test.go
  • internal/registry/remote.go
  • internal/riskcontrol/transport.go
  • internal/transport/config.go
  • internal/transport/default_client.go
  • internal/transport/extension.go
  • internal/transport/extension_test.go
  • internal/transport/policy_router.go
  • internal/transport/policy_router_test.go
  • internal/transport/shared.go
  • internal/transport/shared_test.go
  • internal/update/update.go
  • internal/validate/url.go
  • internal/validate/url_internal_test.go
  • internal/validate/url_test.go
  • shortcuts/apps/file_common.go
  • shortcuts/doc/doc_resource_cover.go
  • shortcuts/doc/doc_resource_cover_test.go
  • shortcuts/im/helpers.go
  • shortcuts/mail/helpers.go
  • shortcuts/mail/signature_compose.go
  • shortcuts/mail/signature_compose_test.go
  • shortcuts/minutes/minutes_download.go
  • shortcuts/minutes/minutes_download_test.go
🚧 Files skipped from review as they are similar to previous changes (32)
  • internal/registry/remote.go
  • internal/cmdutil/testing_test.go
  • internal/transport/config.go
  • extension/transport/types.go
  • internal/core/types.go
  • internal/client/client.go
  • internal/riskcontrol/transport.go
  • cmd/config/init_interactive.go
  • shortcuts/im/helpers.go
  • internal/auth/transport.go
  • shortcuts/minutes/minutes_download_test.go
  • extension/transport/sidecar/interceptor_test.go
  • internal/transport/shared_test.go
  • shortcuts/minutes/minutes_download.go
  • internal/client/client_test.go
  • internal/update/update.go
  • internal/cmdutil/factory.go
  • internal/core/types_test.go
  • shortcuts/mail/signature_compose_test.go
  • shortcuts/apps/file_common.go
  • internal/transport/shared.go
  • internal/transport/default_client.go
  • shortcuts/mail/helpers.go
  • internal/transport/policy_router.go
  • internal/transport/extension.go
  • internal/transport/policy_router_test.go
  • internal/cmdutil/factory_default.go
  • internal/validate/url.go
  • shortcuts/doc/doc_resource_cover.go
  • internal/cmdutil/transport.go
  • internal/cmdutil/transport_test.go
  • internal/cmdutil/factory_http_test.go

Comment thread internal/validate/url_internal_test.go
@evandance
evandance force-pushed the refactor/http-transport-policy branch from a60c183 to b537fbf Compare July 27, 2026 09:28
@evandance

Copy link
Copy Markdown
Collaborator Author

Also addressed the WebSocket bootstrap test-isolation nit from review 4785493846: it now isolates the config directory, proxy-plugin env/cache, and direct-egress setting before exercising Shared().

@evandance

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (1)
internal/validate/url_internal_test.go (1)

136-161: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

want is derived from the source, so this test can't fail.

source never sets TLSNextProto, so line 152 yields want == false and the assertion reduces to false == false. The rebuild path would still pass if it dropped HTTP/2 preservation entirely. Set TLSNextProto["h2"] on the source (as the sibling table case does) so want is true and both rebuilt transports are actually pinned.

♻️ Proposed change
 	source := &http.Transport{
 		Proxy: http.ProxyURL(&url.URL{Scheme: "http", Host: "proxy.example:8080"}),
+		TLSNextProto: map[string]func(string, *tls.Conn) http.RoundTripper{
+			"h2": func(string, *tls.Conn) http.RoundTripper { return nil },
+		},
 	}

As per path instructions: "contract tests must assert the changed field or behavior directly so reverting the implementation causes failure".

🤖 Prompt for 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.

In `@internal/validate/url_internal_test.go` around lines 136 - 161, Make
TestDownloadTransportLeafPreservesAutomaticHTTP2 exercise the enabled HTTP/2
case by initializing source.TLSNextProto with an "h2" entry before rebuilding
it. Keep deriving want from the source if desired, but ensure it evaluates to
true so both direct and proxied transports are verified to preserve
ForceAttemptHTTP2.

Source: Path instructions

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

Nitpick comments:
In `@internal/validate/url_internal_test.go`:
- Around line 136-161: Make TestDownloadTransportLeafPreservesAutomaticHTTP2
exercise the enabled HTTP/2 case by initializing source.TLSNextProto with an
"h2" entry before rebuilding it. Keep deriving want from the source if desired,
but ensure it evaluates to true so both direct and proxied transports are
verified to preserve ForceAttemptHTTP2.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 91f2d1c9-4919-46b5-9e8f-9d4e55e2a41f

📥 Commits

Reviewing files that changed from the base of the PR and between 62b5f47 and b537fbf.

📒 Files selected for processing (39)
  • cmd/config/init_interactive.go
  • cmd/doctor/doctor.go
  • extension/transport/sidecar/interceptor_test.go
  • extension/transport/types.go
  • internal/auth/transport.go
  • internal/client/client.go
  • internal/client/client_test.go
  • internal/cmdutil/factory.go
  • internal/cmdutil/factory_default.go
  • internal/cmdutil/factory_http_test.go
  • internal/cmdutil/factory_proxy_warn_test.go
  • internal/cmdutil/testing_test.go
  • internal/cmdutil/transport.go
  • internal/cmdutil/transport_test.go
  • internal/core/types.go
  • internal/core/types_test.go
  • internal/registry/remote.go
  • internal/riskcontrol/transport.go
  • internal/transport/config.go
  • internal/transport/default_client.go
  • internal/transport/extension.go
  • internal/transport/extension_test.go
  • internal/transport/policy_router.go
  • internal/transport/policy_router_test.go
  • internal/transport/shared.go
  • internal/transport/shared_test.go
  • internal/update/update.go
  • internal/validate/url.go
  • internal/validate/url_internal_test.go
  • internal/validate/url_test.go
  • shortcuts/apps/file_common.go
  • shortcuts/doc/doc_resource_cover.go
  • shortcuts/doc/doc_resource_cover_test.go
  • shortcuts/im/helpers.go
  • shortcuts/mail/helpers.go
  • shortcuts/mail/signature_compose.go
  • shortcuts/mail/signature_compose_test.go
  • shortcuts/minutes/minutes_download.go
  • shortcuts/minutes/minutes_download_test.go
🚧 Files skipped from review as they are similar to previous changes (34)
  • cmd/doctor/doctor.go
  • internal/transport/config.go
  • cmd/config/init_interactive.go
  • shortcuts/im/helpers.go
  • internal/update/update.go
  • internal/auth/transport.go
  • shortcuts/mail/helpers.go
  • internal/cmdutil/testing_test.go
  • internal/registry/remote.go
  • internal/client/client.go
  • shortcuts/minutes/minutes_download_test.go
  • internal/cmdutil/factory.go
  • extension/transport/types.go
  • internal/client/client_test.go
  • internal/core/types.go
  • internal/cmdutil/factory_proxy_warn_test.go
  • shortcuts/mail/signature_compose.go
  • extension/transport/sidecar/interceptor_test.go
  • shortcuts/minutes/minutes_download.go
  • internal/transport/extension.go
  • internal/core/types_test.go
  • internal/transport/shared.go
  • shortcuts/mail/signature_compose_test.go
  • shortcuts/apps/file_common.go
  • internal/transport/shared_test.go
  • internal/transport/default_client.go
  • internal/riskcontrol/transport.go
  • internal/cmdutil/factory_default.go
  • internal/transport/policy_router_test.go
  • internal/cmdutil/transport.go
  • internal/cmdutil/transport_test.go
  • internal/cmdutil/factory_http_test.go
  • internal/validate/url.go
  • internal/transport/policy_router.go

@evandance
evandance force-pushed the refactor/http-transport-policy branch from b537fbf to a0a8ee8 Compare July 27, 2026 10:02
@evandance

Copy link
Copy Markdown
Collaborator Author

Follow-up on CodeRabbit review 4785584884: the suggested explicit TLSNextProto["h2"] setup would test a custom protocol handler, not Go’s automatic HTTP/2 path, so I did not apply it literally. The test now hard-asserts automatic H2 through the real download-clone entry. Tracing that path also exposed and fixed a genuine double-Clone gap: the first policy-router clone now preserves stdlib auto-H2 before the download transport rebuilds direct/proxied branches. The table keeps custom TLS/dial, explicit opt-in, custom handler, and explicit opt-out behavior pinned.

@evandance

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (2)
internal/core/types_test.go (1)

143-170: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider pinning the normalization branches too.

IsPlatformEndpointURL has a nil guard and a case-insensitive scheme comparison, and IsPlatformEndpointHost lowercases the hostname — none of those branches are exercised. Adding nil, HTTPS://..., and OPEN.FEISHU.CN cases would keep the documented contract from silently regressing.

♻️ Suggested additional cases
 	for _, rawURL := range []string{
 		"https://open.feishu.cn/path",
 		"https://open.feishu.cn:443/path",
+		"HTTPS://OPEN.FEISHU.CN/path",
 	} {
@@
 	if !IsPlatformEndpointURL(candidate) {
 			t.Errorf("IsPlatformEndpointURL(%q) = false, want true", rawURL)
 		}
 	}
+
+	if IsPlatformEndpointURL(nil) {
+		t.Error("IsPlatformEndpointURL(nil) = true, want false")
+	}
 }
🤖 Prompt for 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.

In `@internal/core/types_test.go` around lines 143 - 170, Extend
TestIsPlatformEndpointURL_RequiresSecureStandardOrigin to cover normalization
branches: verify a nil URL is rejected, an uppercase HTTPS scheme with the
standard host is accepted, and an uppercase OPEN.FEISHU.CN hostname is accepted.
Keep the existing rejection and acceptance cases unchanged.
internal/transport/extension_test.go (1)

802-832: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add an abort-path test for ExtensionMiddleware.RoundTrip.

ExtensionMiddleware short-circuits on abortErr from PreRoundTripE, returning an *exttransport.AbortError and skipping the base transport, but internal/transport/extension_test.go only exercises normal/fallback behavior. Add a test that uses an AbortableInterceptor returning a non-nil error and asserts the post hook receives (nil, reason) while the base transport is not called.

🤖 Prompt for 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.

In `@internal/transport/extension_test.go` around lines 802 - 832, Add a test
alongside TestExtensionMiddlewareUsesFallbackWhenBaseIsNil that configures an
AbortableInterceptor whose PreRoundTripE returns a non-nil error, then calls
ExtensionMiddleware.RoundTrip and verifies it returns an
*exttransport.AbortError. Assert the post hook receives a nil response and the
same abort reason, and verify the base transport call count remains zero.

Source: Coding guidelines

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

Nitpick comments:
In `@internal/core/types_test.go`:
- Around line 143-170: Extend
TestIsPlatformEndpointURL_RequiresSecureStandardOrigin to cover normalization
branches: verify a nil URL is rejected, an uppercase HTTPS scheme with the
standard host is accepted, and an uppercase OPEN.FEISHU.CN hostname is accepted.
Keep the existing rejection and acceptance cases unchanged.

In `@internal/transport/extension_test.go`:
- Around line 802-832: Add a test alongside
TestExtensionMiddlewareUsesFallbackWhenBaseIsNil that configures an
AbortableInterceptor whose PreRoundTripE returns a non-nil error, then calls
ExtensionMiddleware.RoundTrip and verifies it returns an
*exttransport.AbortError. Assert the post hook receives a nil response and the
same abort reason, and verify the base transport call count remains zero.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 204b95d6-b509-41da-a385-7aeffddd7bee

📥 Commits

Reviewing files that changed from the base of the PR and between b537fbf and a0a8ee8.

📒 Files selected for processing (39)
  • cmd/config/init_interactive.go
  • cmd/doctor/doctor.go
  • extension/transport/sidecar/interceptor_test.go
  • extension/transport/types.go
  • internal/auth/transport.go
  • internal/client/client.go
  • internal/client/client_test.go
  • internal/cmdutil/factory.go
  • internal/cmdutil/factory_default.go
  • internal/cmdutil/factory_http_test.go
  • internal/cmdutil/factory_proxy_warn_test.go
  • internal/cmdutil/testing_test.go
  • internal/cmdutil/transport.go
  • internal/cmdutil/transport_test.go
  • internal/core/types.go
  • internal/core/types_test.go
  • internal/registry/remote.go
  • internal/riskcontrol/transport.go
  • internal/transport/config.go
  • internal/transport/default_client.go
  • internal/transport/extension.go
  • internal/transport/extension_test.go
  • internal/transport/policy_router.go
  • internal/transport/policy_router_test.go
  • internal/transport/shared.go
  • internal/transport/shared_test.go
  • internal/update/update.go
  • internal/validate/url.go
  • internal/validate/url_internal_test.go
  • internal/validate/url_test.go
  • shortcuts/apps/file_common.go
  • shortcuts/doc/doc_resource_cover.go
  • shortcuts/doc/doc_resource_cover_test.go
  • shortcuts/im/helpers.go
  • shortcuts/mail/helpers.go
  • shortcuts/mail/signature_compose.go
  • shortcuts/mail/signature_compose_test.go
  • shortcuts/minutes/minutes_download.go
  • shortcuts/minutes/minutes_download_test.go
🚧 Files skipped from review as they are similar to previous changes (31)
  • internal/registry/remote.go
  • internal/cmdutil/testing_test.go
  • cmd/doctor/doctor.go
  • shortcuts/im/helpers.go
  • internal/client/client_test.go
  • shortcuts/minutes/minutes_download_test.go
  • internal/update/update.go
  • extension/transport/types.go
  • internal/cmdutil/factory_proxy_warn_test.go
  • shortcuts/mail/signature_compose.go
  • internal/auth/transport.go
  • shortcuts/apps/file_common.go
  • internal/transport/shared.go
  • internal/riskcontrol/transport.go
  • internal/core/types.go
  • shortcuts/mail/signature_compose_test.go
  • internal/transport/policy_router.go
  • internal/client/client.go
  • internal/cmdutil/factory.go
  • shortcuts/minutes/minutes_download.go
  • shortcuts/doc/doc_resource_cover.go
  • extension/transport/sidecar/interceptor_test.go
  • internal/transport/policy_router_test.go
  • internal/validate/url.go
  • internal/cmdutil/factory_http_test.go
  • internal/transport/default_client.go
  • internal/transport/shared_test.go
  • internal/transport/extension.go
  • internal/cmdutil/transport_test.go
  • internal/cmdutil/transport.go
  • internal/cmdutil/factory_default.go

@evandance
evandance force-pushed the refactor/http-transport-policy branch from a0a8ee8 to 447e33c Compare July 27, 2026 10:13
@evandance

Copy link
Copy Markdown
Collaborator Author

Addressed both test-coverage suggestions from review 4785864371. Endpoint tests now exercise nil, an explicitly constructed uppercase HTTPS scheme (avoiding url.Parse normalization), and uppercase host normalization. Extension middleware now pins the abort contract: typed AbortError, original reason passed to post, and zero base-transport calls.

@evandance

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai 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.

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 `@shortcuts/mail/signature_compose_test.go`:
- Around line 122-154: Update TestDownloadSignatureImageUsesExternalRequestClass
so the platform and external routes use observably different RoundTrippers: make
the platform route fail or return a distinct response, while retaining the
expected payload only for the external route. Ensure the assertions verify the
external payload and content type, causing the test to fail if
downloadSignatureImage no longer forces the external request class.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fcd87d03-3a2e-4cb1-9b02-562f15668100

📥 Commits

Reviewing files that changed from the base of the PR and between a0a8ee8 and 447e33c.

📒 Files selected for processing (39)
  • cmd/config/init_interactive.go
  • cmd/doctor/doctor.go
  • extension/transport/sidecar/interceptor_test.go
  • extension/transport/types.go
  • internal/auth/transport.go
  • internal/client/client.go
  • internal/client/client_test.go
  • internal/cmdutil/factory.go
  • internal/cmdutil/factory_default.go
  • internal/cmdutil/factory_http_test.go
  • internal/cmdutil/factory_proxy_warn_test.go
  • internal/cmdutil/testing_test.go
  • internal/cmdutil/transport.go
  • internal/cmdutil/transport_test.go
  • internal/core/types.go
  • internal/core/types_test.go
  • internal/registry/remote.go
  • internal/riskcontrol/transport.go
  • internal/transport/config.go
  • internal/transport/default_client.go
  • internal/transport/extension.go
  • internal/transport/extension_test.go
  • internal/transport/policy_router.go
  • internal/transport/policy_router_test.go
  • internal/transport/shared.go
  • internal/transport/shared_test.go
  • internal/update/update.go
  • internal/validate/url.go
  • internal/validate/url_internal_test.go
  • internal/validate/url_test.go
  • shortcuts/apps/file_common.go
  • shortcuts/doc/doc_resource_cover.go
  • shortcuts/doc/doc_resource_cover_test.go
  • shortcuts/im/helpers.go
  • shortcuts/mail/helpers.go
  • shortcuts/mail/signature_compose.go
  • shortcuts/mail/signature_compose_test.go
  • shortcuts/minutes/minutes_download.go
  • shortcuts/minutes/minutes_download_test.go
🚧 Files skipped from review as they are similar to previous changes (34)
  • internal/cmdutil/testing_test.go
  • internal/cmdutil/factory_proxy_warn_test.go
  • internal/auth/transport.go
  • shortcuts/minutes/minutes_download_test.go
  • shortcuts/mail/helpers.go
  • internal/transport/config.go
  • internal/transport/shared.go
  • shortcuts/im/helpers.go
  • internal/cmdutil/factory.go
  • internal/update/update.go
  • internal/transport/default_client.go
  • shortcuts/minutes/minutes_download.go
  • internal/registry/remote.go
  • extension/transport/sidecar/interceptor_test.go
  • internal/client/client.go
  • shortcuts/mail/signature_compose.go
  • shortcuts/apps/file_common.go
  • cmd/config/init_interactive.go
  • internal/client/client_test.go
  • cmd/doctor/doctor.go
  • internal/core/types_test.go
  • internal/core/types.go
  • extension/transport/types.go
  • internal/transport/shared_test.go
  • internal/transport/extension.go
  • internal/transport/policy_router.go
  • shortcuts/doc/doc_resource_cover.go
  • internal/cmdutil/transport_test.go
  • internal/cmdutil/factory_default.go
  • internal/cmdutil/factory_http_test.go
  • internal/transport/policy_router_test.go
  • internal/cmdutil/transport.go
  • internal/validate/url.go
  • internal/riskcontrol/transport.go

Comment thread shortcuts/mail/signature_compose_test.go
@fangshuyu-768 fangshuyu-768 removed the domain/ccm PR touches the ccm domain label Jul 28, 2026
@evandance
evandance force-pushed the refactor/http-transport-policy branch from 447e33c to 2e6bb2c Compare July 28, 2026 10:04
@github-actions github-actions Bot added the domain/ccm PR touches the ccm domain label Jul 28, 2026
@evandance
evandance force-pushed the refactor/http-transport-policy branch from 2e6bb2c to a324d8c Compare July 28, 2026 11:38
@fangshuyu-768 fangshuyu-768 removed the domain/ccm PR touches the ccm domain label Jul 29, 2026
@evandance
evandance force-pushed the refactor/http-transport-policy branch from a324d8c to fde5663 Compare July 30, 2026 03:35
@github-actions github-actions Bot added the domain/ccm PR touches the ccm domain label Jul 30, 2026
@evandance evandance removed domain/im PR touches the im domain domain/mail PR touches the mail domain domain/ccm PR touches the ccm domain labels Jul 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XL Architecture-level or global-impact change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants