Skip to content

refactor: move claudear's http client onto abnegate-http - #171

Open
abnegate wants to merge 5 commits into
mainfrom
migrate/http
Open

abnegate wants to merge 5 commits into
mainfrom
migrate/http

Conversation

@abnegate

@abnegate abnegate commented Oct 5, 2026 •

Copy link
Copy Markdown
Member

Depends on #161 (Docker toolchain).

Build and deploy breaks

  • The Docker image cannot build this until chore(docker): build the image on the toolchain the shared crates need #161 lands. abnegate-http 0.1.2 declares rust-version = "1.97", and the Dockerfile pins RUST_VERSION=1.93. CI uses dtolnay/rust-toolchain@stable and is unaffected.
  • claudear::http, claudear_core::http and the claudear_integrations::github::{HttpClient, ReqwestHttpClient} re-export are gone. Nothing in the workspace used them after this change. Anything outside the workspace that imported them should import abnegate_http instead.

No env var or config key changes.

What changed

claudear-core's local HTTP client (crates/claudear-core/src/http.rs, 242 lines) is replaced by abnegate-http 0.1.2. The client is deleted, and its 22 consumers use abnegate_http::{HttpClient, HttpResponse, ReqwestHttpClient}. The migration plan split this into three steps (CLA1: core, CLA2: integrations, CLA3: analysis). They ship as this one PR because deleting the local client breaks all 22 importers at once, so separate PRs off main would not build. Each of the five commits builds on its own.

  1. refactor(core): map abnegate-http errors into the app error
    • Adds abnegate-http = "0.1.2" as a workspace dependency.
    • Adds one explicit From<abnegate_http::Error> for claudear_core::Error in error.rs: three arms, with a test for each crate variant (see the table below).
    • Adds watcher tests that pin retry_trigger_error_is_transient: a JSON error and an oversized body do not give the retry back, and a real refused connection does.
    • Moves SentryHttpClient (in types.rs, which feat(analysis): so similar-issue suggestions reuse published trial memory #163 also edits) to the crate's HttpResponse. The edit is two lines. Its two implementers move in the same commit so the commit builds: source/sentry.rs, and the regression/sentry.rs test double.
    • Pins tokio-macros at 2.7.0, as refactor(analysis): discover dependencies through abnegate-vcs #168 does, so the lockfile gains no syn 3.
  2. refactor(integrations): move the HTTP consumers onto abnegate-http
    • Moves the 15 integrations consumers: github.rs, gitlab.rs, deploy_qa.rs, discord/{client,thread_manager}.rs, notifier/{discord,slack,sms,telegram,whatsapp}.rs and source/{github,gitlab,helpscout,jira,linear}.rs.
    • Builds every response with HttpResponse::new, because the crate struct is non_exhaustive.
    • The HttpClient test doubles now answer with abnegate_http::Result.
    • GitHub and GitLab clients read bodies up to scm::BODY_LIMIT (64 MiB).
  3. refactor(analysis): move the HTTP consumers onto abnegate-http
    • Covers deploy_qa/tracker.rs, regression/{linear,sentry}.rs and release/{github,tracker}.rs.
    • claudear-analysis now names reqwest directly, for the constructor fallback described below.
    • MockErrorHttpClient fails with a real refused connection (127.0.0.1:1), converted into abnegate_http::Error::Request. It makes the connection through a client it builds once, without a proxy.
    • Adds release::BODY_LIMIT = 8 * ReqwestHttpClient::DEFAULT_BODY_LIMIT (64 MiB).
      • ReleaseClient::new applies it.
      • scm::BODY_LIMIT in claudear-integrations re-exports it, so the GitHub, GitLab and release clients share one value. claudear-analysis cannot depend on claudear-integrations, but integrations already depends on analysis.
  4. refactor(core): delete the local http client
    • Removes http.rs, pub mod http and the src/lib.rs re-export.
  5. test(http): pin the body limits by what the clients read, not by debug output (review follow-up)
    • GitHubClient::new, GitLabClient::new and ReleaseClient::new build the default transport and hand it to a private with_transport, which applies BODY_LIMIT. Production behaviour is unchanged.
    • The tests that read body_limit: … out of ReqwestHttpClient's derived Debug are gone. Each client's limit is now tested by what it reads from a loopback server (see "New tests").
    • The loopback helpers (serve_once, ok_response, loopback_transport) move from claudear-integrations/src/test_support.rs to claudear-analysis/src/test_support.rs, compiled under #[cfg(any(test, feature = "test-support"))]. claudear-integrations turns the feature on for its dev-dependency only, so the release client and the SCM clients share one server. loopback_transport() builds the reqwest client with no_proxy() and leaves the crate's default limit, so the limit under test comes from with_transport.

Error mapping (claudear-core/src/error.rs, one place)

The impl has three arms: Request | UnreadableBody → Http, TooManyRedirects → Network, and everything else → Other(error.to_string()). The tests pin each row:

abnegate_http::Error claudear_core::Error Retried by the watcher Before
Request (transport) Http(reqwest::Error) yes Http, same
UnreadableBody Http(reqwest::Error) yes an empty successful body
TooManyRedirects Network yes Http (only PublicClient raises this variant; the trusted transport still reports redirect loops as Request)
Json Other("JSON parse error: …") no Other("JSON parse error: …"), same
Unsupported(method) Other("POST is not supported by this HTTP client") no Other("POST not supported by this HTTP client")
OversizedBody Other no no cap
InvalidUrl, InvalidHeaderName, InvalidHeaderValue, UnsupportedScheme, EmbeddedCredentials, MissingHost, PrivateAddress, InternalHost, UnfetchableResolution Other no not raised: they come only from PublicClient URL checks, which claudear does not use
a variant added in a later crate release Other no n/a (the crate enum is non_exhaustive)

Json maps to Other instead of Error::Json so the variant and message stay exactly what the local HttpResponse::json produced. A blanket mapping into Http would have made a malformed body look transient.

Constructing the client

The crate's ReqwestHttpClient::new() returns a Result, and the crate has no Default.

  • GitHubClient::new, GitLabClient::new, HelpScoutSource::new, ReleaseClient::new and LinearRegressionChecker::new stay infallible. When the configured client fails to build, they fall back to ReqwestHttpClient::from(reqwest::Client::new()). The local ReqwestHttpClient::new did exactly the same.
  • LinearRegressionChecker::with_embeddings already returned a Result, so it now builds the client first and propagates the build error before it spends an embedding call.
  • Every site uses the trusted transport, never PublicClient, because self-hosted GitLab, Sentry and Jira run on private addresses.

Behaviour differences

These apply to requests that go through the crate's ReqwestHttpClient:

  • Integrations: GitHub, GitLab and HelpScout.
  • Analysis: the release client and tracker, the deploy QA tracker and the Linear regression checker.

The Discord, Slack, SMS, Telegram, WhatsApp, Jira, Linear-source and Sentry clients make their own reqwest calls. They only build the crate's HttpResponse, so their transport behaviour does not change.

  • Body cap. Bodies were read whole; the crate caps them at 8 MiB (DEFAULT_BODY_LIMIT).
    • The GitHub and GitLab clients fetch PR diffs, so they read up to BODY_LIMIT, which is 64 MiB (eight times the crate default).
    • ReleaseClient also reads up to BODY_LIMIT. It is shared by the release tracker and the deploy QA tracker.
      • is_commit_in_release fetches compare/{commit}...{tag}, which carries up to 250 commits and 300 files with patches.
      • Under the 8 MiB default, an oversized comparison would be a non-retried Error::Other, and the release watch would fail on every poll.
    • A body over the cap is now an error (Error::Other, not retried) instead of a success.
    • HelpScout and the Linear regression checker keep the 8 MiB default. Their responses are paginated listings, Linear GraphQL pages and GitHub issue searches.
    • For PR diffs, get_pr_diff errors on a diff over 64 MiB, and the watcher logs "Failed to fetch PR diff for analysis" at debug level and skips the diff analysis.
  • Unreadable bodies. A body that breaks off was returned as an empty successful body; it is now Error::Http.
    • Calls that parse JSON already failed in that case, with a non-retried JSON error. They now fail with a retried Http error.
    • Calls that only check the status now report an error where they reported success. These are merge_pr, close_pr, delete_branch, close_issue and their GitLab counterparts, after a response whose body breaks off.
  • Decoding. Bodies decode as UTF-8 with invalid sequences replaced. reqwest's .text() honoured a charset from Content-Type. Every API involved sends UTF-8.
  • Error text. Transport errors no longer carry the request URL, because the crate strips it so query-string secrets stay out of logs. The unsupported-method message reads "POST is not supported by this HTTP client".
  • Unchanged. The 30s timeout and 10s connect timeout, reqwest's 10-hop redirect policy, proxy environment handling and the absent user agent.
  • Dependency graph.
    • abnegate-http needs tokio 1.53, so tokio moves 1.50.0 → 1.53.2. tokio-macros moves 2.6.0 → 2.7.0, pinned there as in refactor(analysis): discover dependencies through abnegate-vcs #168 because 2.7.2 pulls in syn 3.
    • Patch bumps: mio 1.1.1 → 1.2.4, socket2 0.6.2 → 0.6.5, once_cell 1.21.3 → 1.21.4.
    • abnegate-http 0.1.2 and dashmap 6.2.1 are added.
    • abnegate-http turns on reqwest's multipart and query features workspace-wide.

Crate gaps (follow-ups in abnegate/crates, no shim added here)

  • (a) No Default and no infallible constructor for ReqwestHttpClient. Five constructors repeat ReqwestHttpClient::new().unwrap_or_else(|_| ReqwestHttpClient::from(reqwest::Client::new())). A crate Default would collapse each one to ReqwestHttpClient::default().
  • (b) No convenience constructor for a transport failure. A real Request error is constructible: the regression/linear.rs MockErrorHttpClient (which used to return Error::network("connection refused")) now makes a real refused connection to 127.0.0.1:1 and converts the reqwest error with abnegate_http::Error::from, which maps to the same retried Error::Http. That costs a loopback connect per call. A constructor such as Error::transport(message) would let a test double fail without touching the network.

How it was verified

Review follow-up (aad70a3, on top of the four commits below; no rebase was needed, main is still 95fab34). claudear-verify.sh <worktree> http ready passed: cargo fmt --all -- --check, cargo clippy --all-targets -- -D warnings -A clippy::double_must_use, and cargo test -p claudear-core -p claudear-config -p claudear-storage -p claudear-analysis -p claudear-integrations -p claudear-engine -p claudear (default features, which include sqlite): 10,473 passed, 0 failed, 3 ignored. The red runs for the new limit tests are described under "New tests". This machine's Homebrew now ships OpenSSL 4, which llama.cpp's vendored cpp-httplib does not compile against, so these local runs set CMAKE_DISABLE_FIND_PACKAGE_OpenSSL=TRUE for the llama-cpp-sys-2 build. That only drops HTTPS from llama.cpp's own downloader, which claudear does not use; CI is unaffected.

The original verification of the four migration commits:

All commands ran in the worktree with CARGO_BUILD_BUILD_DIR=/Users/jakebarnby/.cargo/build/shared/claudear-migrate CARGO_INCREMENTAL=0 CARGO_PROFILE_DEV_DEBUG=0 CARGO_PROFILE_TEST_DEBUG=0, default features plus sqlite for tests. The fastembed model came from a local cache copy, and vectorlite from /opt/homebrew/lib/vectorlite.dylib.

  • cargo check --workspace --all-targets passes on each of the four commits on its own.
  • cargo fmt --all -- --check passes.
  • cargo clippy --workspace --all-targets -- -D warnings -A clippy::double_must_use passes.
  • cargo test -p claudear-core -p claudear-integrations -p claudear-analysis -p claudear-engine -p claudear --features sqlite passes (exit 0).
    • 9,353 passed, 0 failed, 3 ignored (the ignored tests were already ignored in integrations).
    • By target: claudear lib 315, claudear bin 11, tests/e2e_real_repo.rs 2, tests/retries.rs 1, tests/shutdown.rs 13, claudear-analysis 2,885, claudear-core 452, claudear-engine 1,367, claudear-integrations 4,305, other targets 2.
    • No doc tests ran.
  • Every test that touches a socket (the loopback server, the refused connections) builds its client with no_proxy(), so an HTTP_PROXY/HTTPS_PROXY in the environment cannot reroute it. I re-ran those tests with HTTP_PROXY, HTTPS_PROXY and ALL_PROXY (upper and lower case) pointing at a dead proxy on 127.0.0.1:9. All 142 selected tests passed: core 7, engine 3, integrations 7, analysis 125 (the regression::linear module, including every MockErrorHttpClient test).

New tests:

  • claudear-core error.rs: one test per crate variant, including that a JSON error keeps the "JSON parse error: " text. The transport variants use a real refused connection.
  • claudear-engine watcher.rs: retry_trigger_error_is_transient is false for a JSON error and for an oversized body, and true for a real refused connection.
  • github.rs, gitlab.rs and release/github.rs: each client is built through the same with_transport that new() uses, with a loopback-only reqwest client, and reads from a loopback server.
    • A body of 8 MiB + 1 byte (one byte over the crate default) is read whole.
    • A declared length of BODY_LIMIT + 1 is refused as OversizedBody { limit: BODY_LIMIT }.
    • github.rs also checks that a body cut short becomes Error::Http.
    • Seen failing. With with_transport temporarily applying BODY_LIMIT / 8 (the crate default, as if the limit were removed), all six limit tests failed: the reads over 8 MiB were refused as OversizedBody { limit: 8388608 }, and the refusals reported the wrong limit. With it applying BODY_LIMIT * 2 (a raised limit), the three refusal tests failed, because the declared length was accepted and the read then failed as unreadable instead. Both mutations were reverted before the commit.

Clean-ups in touched files

  • Section header comments (// ---, // ===, // ═══ banners) are removed from every file this PR touches, with two exceptions:
    • crates/claudear-core/src/types.rs belongs to feat(analysis): so similar-issue suggestions reuse published trial memory #163; this PR keeps to its two-line edit there.
    • crates/claudear-integrations/src/notifier/telegram.rs keeps its headers because a follow-up PR (Telegram HTML escaping) stacks on this branch and edits that file.
    • None of the removed headers sit in or next to a hunk of an open PR (checked against each overlapping PR's patch).
  • Abbreviated names in and next to the changed lines are spelled out:
  • The narrating comments in the GitHub doubles and the Sentry status-boundary test are gone.

Not verified

Overlapping open PRs

From gh pr view <n> --repo appwrite/claudear --json files, intersected with this PR's files:

Rebased on #154, #160 and #166.

🤖 Generated with Claude Code

abnegate and others added 4 commits October 5, 2026 20:33
claudear's local HTTP client is moving to abnegate-http 0.1.2. Its
consumers call the crate's HttpClient and HttpResponse::json inside
functions that return claudear's Result, so the crate error needs one
explicit conversion, and that conversion decides which failures the
watcher retries (retry_trigger_error_is_transient treats Http and
Network as transient).

The mapping keeps every classification the local client had:
- Request and UnreadableBody become Error::Http, as reqwest errors did,
  so they stay transient. The crate strips the URL from these errors,
  so messages no longer repeat a query string.
- TooManyRedirects becomes Error::Network, transient like the reqwest
  redirect error it replaces.
- Everything else becomes Error::Other with the crate's message: Json
  keeps the "JSON parse error: ..." text the local HttpResponse::json
  produced, and Unsupported, OversizedBody and the refused-destination
  variants cannot change on a retry. Mapping Json into Http would have
  made a malformed body look transient and retried it. The last arm
  also covers variants a later release adds, since the crate enum is
  non_exhaustive.

Tests pin each variant's mapping in error.rs, using a real refused
connection (through a client without a proxy) for the transport
variants, and the watcher tests pin that a JSON error and an oversized
body do not give a retry back while a refused connection does.

SentryHttpClient lives in claudear-core's types.rs (also edited by
#163) and answers with an HttpResponse, so its return type moves to the
crate's HttpResponse here, with its two implementers (source/sentry.rs
and the regression/sentry.rs test double); otherwise this commit would
not build. The crate's HttpResponse is non_exhaustive, so they build it
with HttpResponse::new. #147 and #45 also edit source/sentry.rs.

The lockfile gains abnegate-http and dashmap 6. abnegate-http needs
tokio 1.53, so tokio moves 1.50.0 -> 1.53.2 with tokio-macros pinned at
2.7.0 (as #168 does; 2.7.2 would pull in syn 3), and mio, socket2 and
once_cell take patch bumps. #163, #167, #168 and the dependabot PRs
also touch Cargo.toml and Cargo.lock.

The sentry.rs boundary test loses its narrating comments and the file
its section header.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The integrations crate's GitHub, GitLab, HelpScout, Discord, notifier
and source clients used claudear-core's local HttpClient, HttpResponse
and ReqwestHttpClient, which abnegate-http 0.1.2 now provides.

- Imports point at abnegate_http. The crate's HttpResponse is
  non_exhaustive, so every response is built with HttpResponse::new.
- The HttpClient test doubles (github.rs, gitlab.rs, source/github.rs,
  source/gitlab.rs, source/helpscout.rs) answer with
  abnegate_http::Result, the trait's own result type. Production code
  converts with `?` through the one From impl in claudear-core, so
  JSON errors keep their variant and message.
- The crate's ReqwestHttpClient::new returns a Result and the crate has
  no Default. GitHubClient, GitLabClient and HelpScoutSource keep their
  infallible constructors: they fall back to reqwest's default client
  when the configured one fails to build, exactly as the local
  ReqwestHttpClient::new did. The trusted transport is kept on purpose;
  PublicClient would refuse self-hosted GitLab, Sentry and Jira on
  private addresses.
- The crate caps response bodies at 8 MiB, where the local client read
  them whole. GitHubClient and GitLabClient fetch PR diffs, so their
  transport reads up to scm::BODY_LIMIT, eight times the crate default
  (64 MiB). A body over the cap is now an error (Error::Other, not
  retried) rather than a success.

Behaviour of requests that go through ReqwestHttpClient (GitHub,
GitLab, HelpScout) changes in ways the crate brings:
- A body that cannot be read to the end is an error (Error::Http,
  retried) rather than an empty successful body.
- Bodies decode as UTF-8 with invalid sequences replaced, where reqwest
  honoured a charset from Content-Type; every API involved sends UTF-8.
- Transport errors no longer carry the request URL.
- Timeouts (30s, 10s connect), redirects (reqwest's 10 hops), proxy
  handling and the absent user agent are unchanged.
The Discord, Slack, SMS, Telegram, WhatsApp, Jira, Linear and Sentry
clients build HttpResponse from their own reqwest calls, so they keep
their previous body handling.

Tests pin that GitHubClient::new and GitLabClient::new configure their
transport with BODY_LIMIT, and drive a transport with that limit
against a loopback server: an 8 MiB + 1 byte diff is read whole, a
declared length over BODY_LIMIT is refused, and a body cut short is an
Error::Http. The loopback transport is built with no_proxy so an
HTTP_PROXY in the environment cannot reroute the requests.

Touched files also lose their section header comments and the
abbreviated names around the changed lines (k/v in the GitHub and
GitLab doubles, resp/tok/r/e in HelpScout's source,
resp_body in WhatsApp, now text so it no longer shadows the body
parameter). notifier/telegram.rs keeps its headers and
changes only in its imports and HttpResponse construction, because the
Telegram escaping fix stacks on this branch.

Overlaps: #147 (source/sentry.rs, via the first commit), #162
(notifier/discord.rs) and #45 (discord/client.rs, notifiers,
source/{jira,linear,sentry}.rs).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The deploy QA tracker, the Linear regression checker and the release
client and tracker used claudear-core's local HTTP client, which
abnegate-http 0.1.2 now provides.

- Imports point at abnegate_http, responses are built with
  HttpResponse::new (the crate struct is non_exhaustive), and the test
  doubles answer with abnegate_http::Result. Production code converts
  through claudear-core's From impl with `?`.
- ReleaseClient::new and LinearRegressionChecker::new stay infallible
  and fall back to reqwest's default client when the configured one
  fails to build, as the local ReqwestHttpClient::new did; claudear-
  analysis now names reqwest directly for that. The already fallible
  LinearRegressionChecker::with_embeddings builds its client first and
  returns the build error before spending an embedding call.
- The regression/linear.rs MockErrorHttpClient used to fail with
  Error::network("connection refused"). The crate has no convenience
  constructor for that, so the double makes a real refused connection
  to 127.0.0.1:1, through a client it builds once without a proxy, and
  converts it into abnegate_http::Error::Request, which maps to the
  same transient Error::Http.
- The release tracker imports HttpClient and ReqwestHttpClient instead
  of spelling the paths out, its test double indexes responses with
  get() instead of a bounds check, and both files lose their section
  header banners.

ReleaseClient (used by the release and deploy QA trackers) reads bodies
up to release::BODY_LIMIT, eight times the crate default (64 MiB):
is_commit_in_release fetches compare/{commit}...{tag}, which carries up
to 250 commits and 300 files with patches. Under the 8 MiB default an
oversized comparison would be a non-retried Error::Other and fail the
release watch on every poll. scm::BODY_LIMIT in claudear-integrations
now re-exports this constant, so the GitHub, GitLab and release clients
share one value. A test pins that ReleaseClient::new applies it.

The Linear regression checker keeps the 8 MiB default: its responses
are Linear GraphQL pages and GitHub issue searches.

These clients now error on a body cut short instead of returning it
empty, decode bodies as lossy UTF-8, and drop the URL from transport
errors. Timeouts and redirects are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nothing imports claudear_core::http any more: every consumer uses
abnegate-http 0.1.2's HttpClient, HttpResponse and ReqwestHttpClient,
and claudear-core converts the crate's errors in one From impl. The
module, its claudear_core::http path and the claudear::http re-export
in src/lib.rs go, so there is one HTTP client implementation to
maintain. Its HttpResponse tests live on in the crate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@hansi-codes

hansi-codes Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

🟡 Tier B · Needs changes before merging

Limited by an open major finding: Update the Docker toolchain before adding this dependency

Replaces claudear’s local HTTP client with abnegate-http across core, integrations, and analysis, including explicit application error mapping and shared response-body limits for SCM and release requests. Updates the HTTP consumers, test doubles, dependency configuration, and retry-classification tests while removing the former HTTP module and re-exports.

Latest changes: The follow-up replaces Debug-based body-limit assertions with loopback behavior tests, moves the shared loopback helpers into analysis behind a test-support feature, and routes the GitHub, GitLab, and release clients through private transport constructors that apply their limits.

Verdict New comments Fixed Still open
💬 Commented 0 0 1
Fix with agent prompt
### Issue 1
Cargo.toml:154
**Update the Docker toolchain before adding this dependency**

abnegate-http 0.1.2 requires Rust 1.97, but Dockerfile:2 still pins Rust 1.93, so the default image build fails at Cargo's rust-version check. Please land the toolchain update first or include it here rather than merging a dependency that the deployment build cannot compile.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
📂 Walkthrough · 6
File Change
Cargo.toml, Cargo.lock, crates/claudear-{core,analysis,engine,integrations}/Cargo.toml Adds abnegate-http and updates dependency and test-support feature configuration.
crates/claudear-core/src/{error.rs,http.rs,lib.rs,types.rs} Maps abnegate-http errors, updates the Sentry response type, and removes the local HTTP client module and exports.
crates/claudear-engine/src/watcher.rs Adds retry-classification coverage for HTTP, JSON, and oversized-body errors.
crates/claudear-analysis/src/{deploy_qa/tracker.rs,regression/linear.rs,regression/sentry.rs,release/github.rs,release/mod.rs,release/tracker.rs,test_support.rs,lib.rs} Migrates analysis HTTP clients and test doubles, sets the release body limit, and adds shared loopback test support.
crates/claudear-integrations/src/{deploy_qa.rs,discord/client.rs,discord/thread_manager.rs,github.rs,gitlab.rs,notifier/discord.rs,notifier/slack.rs,notifier/sms.rs,notifier/telegram.rs,notifier/whatsapp.rs,scm.rs,source/github.rs,source/gitlab.rs,source/helpscout.rs,source/jira.rs,source/linear.rs,source/sentry.rs} Migrates integration consumers and test doubles to abnegate-http, applies shared SCM body limits, and adopts the analysis loopback test helpers.
src/lib.rs Removes the former HTTP re-export.
⏳ Still open from earlier reviews · 1
  • 🟠 Update the Docker toolchain before adding this dependency · Cargo.toml:154

Reviewed the commits since 1c13990 · Details · Comment @hansi-codes review to re-run, or mention @hansi-codes with a question.

@hansi-codes hansi-codes 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.

🟡 Tier B · 1 blocking finding to address. Summary

Comment thread Cargo.toml
http-body-util = "0.1"

# Shared infrastructure
abnegate-http = "0.1.2"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Update the Docker toolchain before adding this dependency

abnegate-http 0.1.2 requires Rust 1.97, but Dockerfile:2 still pins Rust 1.93, so the default image build fails at Cargo's rust-version check. Please land the toolchain update first or include it here rather than merging a dependency that the deployment build cannot compile.

Prompt To Fix With AI
This is a comment left during a code review.
Path: Cargo.toml
Line: 154

Comment:
**Update the Docker toolchain before adding this dependency**

abnegate-http 0.1.2 requires Rust 1.97, but Dockerfile:2 still pins Rust 1.93, so the default image build fails at Cargo's rust-version check. Please land the toolchain update first or include it here rather than merging a dependency that the deployment build cannot compile.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

🟠 Major · bug · Reply if this doesn't apply.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Agreed, the image cannot build this until the toolchain moves. That change lives in #161, which sets RUST_VERSION=1.98 in the Dockerfile (abnegate-http 0.1.2 needs 1.97). This PR depends on #161 and must merge after it; the body now says "Depends on #161 (Docker toolchain)" at the top and keeps the build-break note. I kept the toolchain bump out of this PR so every crate migration shares one Dockerfile change rather than each carrying its own.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This is still an outstanding build break in this PR’s current tree: the Dockerfile pins Rust 1.93 and uses that version for the builder (Dockerfile, builder stage), while the new dependency is declared here (Cargo.toml). Calling #161 a dependency documents the required merge order, but does not make this tree buildable. Please keep this blocked until #161 lands and this PR is based on the toolchain update, or include that update here; I’ll leave the finding open until then.

Comment thread crates/claudear-analysis/src/release/github.rs Outdated
…g output

The constructor tests read `body_limit: …` out of ReqwestHttpClient's
derived Debug, which the crate can reformat without changing behaviour.
Each client's `new` now hands its transport to a private `with_transport`
that applies BODY_LIMIT, and the tests drive that path against a loopback
server: a body over the crate default is read, and a declared length over
BODY_LIMIT is refused as OversizedBody { limit: BODY_LIMIT }. The tests
inject only the reqwest client, built without a proxy, so an environment
proxy cannot reroute loopback.

The loopback helpers move to claudear-analysis behind a `test-support`
feature so the release client's tests can share them with integrations.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant