#![cfg_attr(
    not(test),
    deny(
        clippy::unwrap_used,
        clippy::expect_used,
        clippy::todo,
        clippy::unimplemented,
        clippy::panic
    )
)]
#![allow(
    clippy::module_name_repetitions,
    clippy::must_use_candidate,
    clippy::missing_errors_doc
)]
//! # scanclient
//!
//! High-performance, connection-pooled, and observable HTTP client designed specifically
//! for Santh security scanning tools.
//!
//! This crate wraps `reqwest` to provide unified rate-limiting, bounded response bodies,
//! automatic retries on scanner-relevant status codes, proxy support, redirect SSRF
//! protections, and specific security scanning configurations.
//!
//! `scanclient` is scanning-focused: rate limiting, target management, safe redirect
//! handling, and finding-friendly response collection. `scanclient` is stealth-focused:
//! fingerprint evasion, header rotation, and TLS profile mutation. They compose rather
//! than compete.
//!
//! ## Safe defaults
//!
//! **Input size:** Response bodies are capped at `HttpConfig::max_body_size`
//! (default 10 MiB = `10 * 1024 * 1024` bytes, enforced in
//! `ScanResponse::from_response`). The cap is checked on both
//! `Content-Length` and the running stream total; a `ResponseBodyTooLarge`
//! error is returned before the entire body is buffered. Setting
//! `max_body_size = 0` is rejected at client-construction time with
//! `Error::InvalidMaxBodySize`.
//!
//! **Recursion depth:** No recursive algorithms exist in this crate. Redirect
//! following is iterative and bounded by `HttpConfig::max_redirects` (default 5).
//!
//! **Outbound network:** All outbound HTTP(S) connections go through
//! `reqwest` + `hickory-dns`. Redirect targets are validated against the bogon
//! list before the connection is opened; redirects to private, loopback,
//! link-local, and other non-public addresses are blocked with
//! `Error::RedirectBlocked`.
//!
//! **Process spawning:** None. No child processes, shell commands, or
//! `std::process::Command` calls are made anywhere in this crate.
//!
//! **Filesystem writes:** None at runtime. The only filesystem access is in
//! `HttpConfig::from_file` (a read of a user-supplied TOML path) and in
//! doc-test examples. No log files, temp files, or cache files are written.
//!
//! **Credential exposure:** Proxy credentials (`proxy_user` / `proxy_password`)
//! are placed in the `Proxy-Authorization` request header and are never logged
//! or written to disk. The `Debug` impl for `ScanClient` uses
//! `finish_non_exhaustive()` so the inner `reqwest::Client` (which holds
//! built-in auth) is omitted from formatted output.
//!
//! ## Architecture
//! - [`ScanClient`]: The main orchestration client.
//! - [`HttpConfig`]: Configuration options for proxies, timeouts, and rate limits.
//! - [`ScanResponse`]: A tailored response object capturing timing and status.
//!
//! ## Quick Start
//!
//! ```rust
//! use scanclient::config::HttpConfig;
//!
//! let config = HttpConfig::default();
//! assert_eq!(config.timeout_secs, 10);
//! assert_eq!(config.max_retries, 3);
//! assert!(config.tls_verify);
//!
//! // Load from TOML
//! let custom = HttpConfig::from_toml("timeout_secs = 30").unwrap();
//! assert_eq!(custom.timeout_secs, 30);
//! ```

#![warn(missing_docs)]
#![forbid(unsafe_code)]
#![warn(clippy::pedantic)]
#![allow(clippy::must_use_candidate)]
#![allow(clippy::missing_errors_doc)]
#![allow(clippy::missing_panics_doc)]
#![allow(clippy::needless_pass_by_value)]

pub mod adaptive_rate;
pub mod auth;
pub mod camouflage;
pub mod client;
pub mod config;
pub mod dns_resolver;
pub mod error;
pub mod header_injection;
pub mod http_transport;
pub mod metrics;
pub mod pool;
pub mod request;
pub mod response;
pub mod retry;
pub mod smuggling;
pub mod tls_profiles;
// URL string utilities (`resolve_url`, `clean_url`,
// `registrable_domain`, `dedup_host_key`, `strip_www_host`). Used
// to be copy-pasted across golemn, karyx, scald, and sear with
// silent drift - including a karyx bug where the resolver
// swallowed attacker-controlled absolute URLs. Canonical home is
// scanclient because every shipping consumer already depends on
// it transitively, and the `url = "2"` crate is already a
// scanclient dep, so no new dependency surface is added.
pub mod urlutil;
// TLS-impersonate profile substrate (MASTER_PLAN Phase 08).
// Type-level contract - the `ImpersonateProfile` enum, CLI
// parser, and supported-set hint that every scanner reaches for
// when it wants wire-identical browser ClientHello. The
// `wreq`-backed implementation lands in a follow-up commit
// behind the `tls-impersonate` cargo feature so default builds
// pay zero `boring-sys` build cost.
pub mod tls_impersonate;
pub mod tls_impersonate_stealth;
// Canonical bogon / non-public IP classification - single source
// of truth for SSRF policy across every scanner. Lifted from
// `wafrift_types::bogon` (MASTER_PLAN Phase 08 step 2/N) so the
// wreq-backed stealth client can refuse private upstreams
// without forcing every consumer to re-implement the predicate.
pub mod bogon;

pub use http_transport::{HttpTransport, HttpTransportOptions};

pub use client::ScanClient;
pub use config::{HttpConfig, HttpConfigError};
pub use error::{Error, Result};
pub use response::ScanResponse;

/// Re-export for consumers migrating off direct `reqwest` workspace deps.
pub use reqwest;

pub use tls_impersonate_stealth::{StealthClient, StealthError, StealthResponse};
