Skip to content

Releases: daniloaguiarbr/duckduckgo-search-cli

v0.7.7 — GAP-WS-49 fix: TLS fingerprint emulation restored

14 Jun 10:36

Choose a tag to compare

duckduckgo-search-cli v0.7.7

GAP-WS-49 (CRITICAL, runtime) — v0.7.6 closed cargo install but real queries returned ZERO results silently. This patch restores the Chrome/Safari TLS fingerprint emulation that bypasses DDG's anomaly-modal.

What's new in v0.7.7

Critical runtime fix (GAP-WS-49)

  • Zero-result regression fixed. v0.7.6 passed all --probe and --probe-deep smoke tests (status 200/ok) while real queries silently returned resultados: 0 with cascade_level: 0 and usou_endpoint_fallback: false. Local reproduction: 6/6 queries returned 0 results with 1.0–1.6s latency.
  • Root cause: wreq 6.0.0-rc.29 does not bundle the emulation feature. The Chrome/Safari TLS fingerprint emulation lived only in wreq-util 3.0.0-rc.12 via default = ["emulation"]. v0.7.6 removed wreq-util (along with the brotli feature) to close GAP-WS-48, and without emulation, wreq 6.0.0-rc.29 with BoringSSL plain produces a JA3/JA4 fingerprint that Cloudflare Bot Management detects. DDG serves anomaly-modal HTML (45 occurrences) to any client without a real browser fingerprint.
  • Cross-confirmation: curl with real browser headers (User-Agent: Chrome/120, Accept-Encoding: br, Sec-Fetch-*) also received anomaly-modal at test time (2026-06-14 09:25 UTC), confirming the upstream tightening.
  • Fix:
    1. Re-added wreq-util 3.0.0-rc.12 with default-features = false, features = ["emulation"].
    2. Re-added "brotli" feature to wreq (required by emulation).
    3. Added 3 direct dep pins to Cargo.toml to force compatible versions in cargo install:
      • brotli-decompressor = "=5.0.1" — last version with hard alloc-no-stdlib = "2.0" pin, before 5.0.2 widened to >=2.0.4, <4.
      • alloc-no-stdlib = "=2.0.4" — exact version brotli 8.0.3 hard-requires.
      • brotli = { version = "8.0.3", default-features = false } — no std feature, doesn't pull alloc-stdlib 0.2.3.
    4. cargo update -p alloc-no-stdlib@3.0.0 --precise 2.0.4 removes 3.0.0 from the lockfile.
  • Post-fix validation:
    • cargo tree --offline — graph contains exactly alloc-no-stdlib v2.0.4 and brotli-decompressor v5.0.1, zero 3.0.0/0.2.3.
    • cargo build --release --offline — success in 24.04s.
    • cargo install --path . --locked --offline — success in 34.32s, binary functional.
    • 292 lib tests pass.
    • Real query "rust async runtime" (local) — quantidade_resultados: 5, latency 1087ms, real results.

⚠️ GAP-WS-48 residual: cargo install without --locked still fails

Because cargo install regenerates the lockfile, the solver adds BOTH alloc-no-stdlib 2.0.4 (from the direct pin) and alloc-no-stdlib 3.0.0 (from brotli-decompressor 5.0.2 or transitive alloc-stdlib 0.2.3). This triggers the same E0277 as GAP-WS-48. Users must use --locked:

cargo install duckduckgo-search-cli --version 0.7.7 --locked

The committed Cargo.lock was prepared with cargo update -p alloc-no-stdlib@3.0.0 --precise 2.0.4 to make --locked produce a clean graph.

Impact

  • Binary: +160KB (brotli 8.0.3 + brotli-decompressor 5.0.1 + wreq-util 3.0.0-rc.12).
  • cargo install build time: ~24s (vs ~37s v0.7.6).
  • Supply chain surface: +3 crates.
  • Functionality restored: real queries return 5+ results with a TLS fingerprint identical to real Chrome/Safari (subject to DDG's tightening state).

Install

cargo install duckduckgo-search-cli --version 0.7.7 --locked

What's NOT changed

  • No CLI changes
  • No JSON schema changes
  • No skill file semantic changes (only version bump + GAP-WS-49 documentation)

Verification

  • cargo build --release --offline — success in 24.04s
  • cargo install --path . --locked --offline — success in 34.32s
  • cargo test --lib --offline — 292 passed; 0 failed
  • cargo fmt --check — clean
  • cargo clippy --all-targets --offline -- -D warnings — clean
  • Query test (local): quantidade_resultados: 5, real results

See CHANGELOG.md for the full GAP-WS-49 narrative.

v0.7.6 — fix cargo install break (GAP-WS-48, alloc-no-stdlib conflict)

14 Jun 09:09

Choose a tag to compare

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog,
and this project adheres to Semantic Versioning.

[0.7.6] - 2026-06-14

Fixed (CRITICAL, build)

  • GAP-WS-48 (CRITICAL, install) — cargo install quebrou em 2026-06-14 por conflito alloc-no-stdlib 2.0.4 vs 3.0.0. Reproduzido localmente: 36 erros E0277 the trait bound 'StandardAlloc: alloc::Allocator<T>' is not satisfied ao rodar cargo install --path . (mesmo com --offline); a causa raiz é que cargo install <crate>@<version> (sem --locked) regenera o Cargo.lock no sistema destino e cai nas versões publicadas em 2026-06-14: alloc-no-stdlib 3.0.0, alloc-stdlib 0.2.3 (alloc-no-stdlib = ">=2.0.4, <4.0.0") e brotli-decompressor 5.0.2. O brotli 8.0.3 (não atualizado, ainda requer alloc-no-stdlib = "2.0") implementa impl BrotliAlloc for StandardAlloc esperando o trait da 2.0.4, mas o StandardAlloc de alloc-stdlib 0.2.3 é compilado contra 3.0.0 — colisão trait-bind em enc/reader.rs, enc/writer.rs e enc/combined_alloc.rs.
  • Causa raiz em 2 camadas: (CR1) o wreq-util 3.0.0-rc.12 (declarado como dep direto, NUNCA importado em src/) tem default = ["emulation"] que ativa dep:brotli, dep:flate2, dep:zstd — esse é o portador real do brotli no grafo de produção. A feature brotli do wreq foi apenas secundária. (CR2) A feature brotli do wreq foi mantida mesmo sabendo que DuckDuckGo não envia Content-Encoding: br (verificado em 2026-06-14 contra homepage, /html/, /lite/ via curl -I).
  • Fix aplicado:
    1. Removida a dep wreq-util = "3.0.0-rc" do Cargo.toml (era dead code).
    2. Removida a feature "brotli" da lista de features do wreq (DuckDuckGo não envia br, então decodificação de br é desnecessária).
    3. Atualizado o comentário do wreq no Cargo.toml para documentar a remoção e referenciar o incidente.
  • Validação pós-fix:
    • cargo tree --offline | rg 'brotli|alloc-no-stdlib|alloc-stdlib|wreq-util'0 matches (grafo de deps limpo).
    • cargo install --path . --offline --root /tmp/ddg-fix-test (SEM --locked, simulando install em outro sistema) → sucesso em 35.7s, binário funcional, JSON schema preservado.
    • cargo install --path . --locked --offlinesucesso (caminho de CI com lock travado).
    • cargo build --releasesucesso em 37.14s (5.92s mais rápido que v0.7.5 pela ausência do brotli e brotli-decompressor).
  • Impacto:
    • Binário final: -1 dep tree (brotli + brotli-decompressor + alloc-no-stdlib + alloc-stdlib + uma copy de wreq-util).
    • Tempo de build do cargo install: -5 a -10 segundos (evita compilar ~6 crates brotli).
    • Superfície de supply chain: -6 crates.
    • Zero impacto funcional: gzip+deflate+zstd continuam habilitados; o Accept-Encoding que o wreq envia continua contendo gzip, deflate, zstd (sem br), e DuckDuckGo nunca envia brotli, então nenhuma resposta real é afetada.
  • Cargo.toml version bump: 0.7.5 → 0.7.6.

[0.7.5] - 2026-06-14

Fixed (audit batch 2026-06-14)

  • P1-audit-1 (MEDIUM, error contract)src/lib.rs execute_deep_research was using println!("{json}") directly, violating the documented rule that output.rs is the only module with println! (lib.rs doc-table line 34). Now delegates to output::print_line_stdout which handles BrokenPipe cleanly (silent success on | head, generic error on real I/O failure). Closes the audit finding that the JSON contract for deep-research was bypassing the central output abstraction.
  • P1-audit-2 (LOW, code clarity) — Removed the unreachable!("handled above") arm in the subcommand dispatch by folding the DeepResearch branch into the main match (and dropping the preceding if let Some(Subcommand::DeepResearch(...)) early-return). The compile-time exhaustiveness check now covers the variant without panicking on dispatch.
  • P1-audit-3 (LOW, exit code semantics)CliError::Cancelled now maps to exit code 130 (POSIX: 128 + SIGINT(2)) instead of 1 (generic error). Shell sessions can now distinguish user-initiated Ctrl-C from real runtime failures, and process supervisors (e.g. CI runners, set -e scripts) treat cancellation as exit 130 per convention.
  • P1-audit-4 (LOW, error code mapping) — Three string error code mappings were semantically wrong: InvalidConfigselector_config_invalid (should be invalid_config); PathErrorselector_config_invalid (should be path_error); BrokenPipehttp_error (should be broken_pipe). New constants added: codes::INVALID_CONFIG, codes::PATH_ERROR, codes::BROKEN_PIPE. All three string mappings now use their dedicated constant. Consumers parsing the error field of the JSON output can now route on the precise failure mode.
  • P2-audit-5 (LOW, documentation drift)#![doc(html_root_url = "https://docs.rs/duckduckgo-search-cli/0.7.4")] was lagging the Cargo.toml version. Updated to 0.7.5. Closes the docs.rs cross-link drift.
  • P2-audit-7 (MEDIUM, distribution hygiene)Cargo.toml [build-dependencies] now includes clap and clap_mangen = "0.2". The existing build.rs was extended to call a new generate_man_page() function that emits duckduckgo-search-cli.1 in OUT_DIR using a best-effort mirror of the src/cli.rs CLI definition. The man page is a packaging convenience (not build-critical); failures are logged to stderr but do not panic the build. A future refactor will extract the CLI definition into a shared module to eliminate the mirror.
  • P3-audit-11 (LOW, CI drift)Cross.toml listed armv7-unknown-linux-musleabihf as a developer convenience target, but the comment also claimed "5 principais" targets were covered by release.yml (false: release.yml only covers x86_64-unknown-linux-musl and aarch64-apple-darwin). Removed the armv7-unknown-linux-musleabihf block and updated the comments to accurately reflect which targets are CI-covered vs. dev-only. No release behavior change.

Test coverage delta

  • src/error.rs::tests — added assertions for Cancelled.exit_code() == 130, Cancelled.error_code() == "cancelled", BrokenPipe.error_code() == "broken_pipe", PathError.error_code() == "path_error", InvalidConfig.error_code() == "invalid_config". Total error::tests: 5 tests, all pass.

Fixed

  • GAP-WS-29 (CRITICAL, build experience, Windows)cargo install on native Windows MSVC without the C++ CMake tools for Windows sub-component of the Visual Studio Installer previously failed minutes into the BoringSSL build with the cryptic failed to execute command: program not found / is 'cmake' not installed?. The build.rs preflight is now extended to detect this and abort in SECONDS with the exact fix (winget install -e --id Kitware.Cmake OR Visual Studio Installer → Modify → Workloads → Desktop development with C++ → expand → check C++ CMake tools for Windows). New escape hatch: DDG_SKIP_CMAKE_CHECK=1. Root cause: the workload C++ build tools does NOT include the C++ CMake tools sub-component — the latter must be selected manually.
  • GAP-WS-30 (CRITICAL, build experience, Windows) — BoringSSL CMake uses the Visual Studio 17 2022 generator which requires cl.exe (compiler) and link.exe (linker). The build.rs preflight now detects both and aborts with the fix (open a Developer PowerShell for VS 2022, or run Launch-VsDevShell.ps1). MSVC is NOT auto-installed (5+ GB download, too intrusive). New escape hatch: DDG_SKIP_MSVC_CHECK=1.
  • GAP-WS-31 (CRITICAL, build experience, Windows) — BoringSSL perlasm generator emits crypto assembly in NASM format and requires perl.exe. The build.rs preflight now detects perl and reports the fix (winget install -e --id StrawberryPerl.StrawberryPerl). New escape hatch: DDG_SKIP_PERL_CHECK=1.
  • GAP-WS-32 (CRITICAL, documentation)skill/duckduckgo-search-cli-en/SKILL.md line 561 and skill/duckduckgo-search-cli-pt/SKILL.md line 565 still claimed "Pre-built binaries from cargo install are unaffected" / "Binários pré-compilados do cargo install não são afetados". This was already false in v0.7.4 (only llms.txt and README*.md were corrected); now corrected in the skills too. crates.io NEVER distributes binaries; cargo install always compiles from source.
  • GAP-WS-33 (MEDIUM, documentation) — Skill frontmatter said "Released 2026-06-08" (v0.7.3 date) while the binary is v0.7.4 of 2026-06-11. Now both EN and PT skills say "Released 2026-06-14 (v0.7.5)".
  • GAP-WS-34 (MEDIUM, documentation) — Skills only listed Linux build prerequisites. Now mention the four Windows prerequisites (NASM, CMake, MSVC, Perl) and the new build.rs preflight + escape hatches.
  • GAP-WS-35 (MEDIUM, documentation)llms-full.txt (line 273-305, embedding of docs/HOW_TO_USE.md) claimed "Pre-built binaries require no Rust installation" without qualifying that this is ONLY true for GitHub Releases binaries. cargo install always requires Rust and always compiles from source. Now qualified.
  • GAP-WS-36 (MEDIUM, documentation)docs/CROSS_PLATFORM.md line 193 and README.md line 336 and README.pt-BR.md line 428 claimed "VS Build Tools with C++ workload provides CMake". The C++ workload does NOT provide CMake — that is a separate sub-component. Now corrected in all three files.
  • GAP-WS-37 (MEDIUM, build)build.rs v0.7.4 only checked for NASM. Now checks for the four BoringSSL build prerequisites (nasm, cmake, cl.exe, link.exe, perl) and supports four independent escape hatches.

Added

  • scripts/check-windows-toolchain.ps1 — standalone diagnostic (no installs) that checks all 7 tools (cargo, rustc, cmake, nasm, cl.exe, link.exe, perl) and emits text or JSON output. Exit code 0 if all present, 1 otherwise. Useful for support tickets and CI gates.
  • `docs/INST...
Read more

v0.7.5 — 4-tool Windows preflight + docs/INSTALL-WINDOWS + audit batch

14 Jun 08:21

Choose a tag to compare

Changelog

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog,
and this project adheres to Semantic Versioning.

[0.7.5] - 2026-06-14

Fixed (audit batch 2026-06-14)

  • P1-audit-1 (MEDIUM, error contract)src/lib.rs execute_deep_research was using println!("{json}") directly, violating the documented rule that output.rs is the only module with println! (lib.rs doc-table line 34). Now delegates to output::print_line_stdout which handles BrokenPipe cleanly (silent success on | head, generic error on real I/O failure). Closes the audit finding that the JSON contract for deep-research was bypassing the central output abstraction.
  • P1-audit-2 (LOW, code clarity) — Removed the unreachable!("handled above") arm in the subcommand dispatch by folding the DeepResearch branch into the main match (and dropping the preceding if let Some(Subcommand::DeepResearch(...)) early-return). The compile-time exhaustiveness check now covers the variant without panicking on dispatch.
  • P1-audit-3 (LOW, exit code semantics)CliError::Cancelled now maps to exit code 130 (POSIX: 128 + SIGINT(2)) instead of 1 (generic error). Shell sessions can now distinguish user-initiated Ctrl-C from real runtime failures, and process supervisors (e.g. CI runners, set -e scripts) treat cancellation as exit 130 per convention.
  • P1-audit-4 (LOW, error code mapping) — Three string error code mappings were semantically wrong: InvalidConfigselector_config_invalid (should be invalid_config); PathErrorselector_config_invalid (should be path_error); BrokenPipehttp_error (should be broken_pipe). New constants added: codes::INVALID_CONFIG, codes::PATH_ERROR, codes::BROKEN_PIPE. All three string mappings now use their dedicated constant. Consumers parsing the error field of the JSON output can now route on the precise failure mode.
  • P2-audit-5 (LOW, documentation drift)#![doc(html_root_url = "https://docs.rs/duckduckgo-search-cli/0.7.4")] was lagging the Cargo.toml version. Updated to 0.7.5. Closes the docs.rs cross-link drift.
  • P2-audit-7 (MEDIUM, distribution hygiene)Cargo.toml [build-dependencies] now includes clap and clap_mangen = "0.2". The existing build.rs was extended to call a new generate_man_page() function that emits duckduckgo-search-cli.1 in OUT_DIR using a best-effort mirror of the src/cli.rs CLI definition. The man page is a packaging convenience (not build-critical); failures are logged to stderr but do not panic the build. A future refactor will extract the CLI definition into a shared module to eliminate the mirror.
  • P3-audit-11 (LOW, CI drift)Cross.toml listed armv7-unknown-linux-musleabihf as a developer convenience target, but the comment also claimed "5 principais" targets were covered by release.yml (false: release.yml only covers x86_64-unknown-linux-musl and aarch64-apple-darwin). Removed the armv7-unknown-linux-musleabihf block and updated the comments to accurately reflect which targets are CI-covered vs. dev-only. No release behavior change.

Test coverage delta

  • src/error.rs::tests — added assertions for Cancelled.exit_code() == 130, Cancelled.error_code() == "cancelled", BrokenPipe.error_code() == "broken_pipe", PathError.error_code() == "path_error", InvalidConfig.error_code() == "invalid_config". Total error::tests: 5 tests, all pass.

Fixed

  • GAP-WS-29 (CRITICAL, build experience, Windows)cargo install on native Windows MSVC without the C++ CMake tools for Windows sub-component of the Visual Studio Installer previously failed minutes into the BoringSSL build with the cryptic failed to execute command: program not found / is 'cmake' not installed?. The build.rs preflight is now extended to detect this and abort in SECONDS with the exact fix (winget install -e --id Kitware.Cmake OR Visual Studio Installer → Modify → Workloads → Desktop development with C++ → expand → check C++ CMake tools for Windows). New escape hatch: DDG_SKIP_CMAKE_CHECK=1. Root cause: the workload C++ build tools does NOT include the C++ CMake tools sub-component — the latter must be selected manually.
  • GAP-WS-30 (CRITICAL, build experience, Windows) — BoringSSL CMake uses the Visual Studio 17 2022 generator which requires cl.exe (compiler) and link.exe (linker). The build.rs preflight now detects both and aborts with the fix (open a Developer PowerShell for VS 2022, or run Launch-VsDevShell.ps1). MSVC is NOT auto-installed (5+ GB download, too intrusive). New escape hatch: DDG_SKIP_MSVC_CHECK=1.
  • GAP-WS-31 (CRITICAL, build experience, Windows) — BoringSSL perlasm generator emits crypto assembly in NASM format and requires perl.exe. The build.rs preflight now detects perl and reports the fix (winget install -e --id StrawberryPerl.StrawberryPerl). New escape hatch: DDG_SKIP_PERL_CHECK=1.
  • GAP-WS-32 (CRITICAL, documentation)skill/duckduckgo-search-cli-en/SKILL.md line 561 and skill/duckduckgo-search-cli-pt/SKILL.md line 565 still claimed "Pre-built binaries from cargo install are unaffected" / "Binários pré-compilados do cargo install não são afetados". This was already false in v0.7.4 (only llms.txt and README*.md were corrected); now corrected in the skills too. crates.io NEVER distributes binaries; cargo install always compiles from source.
  • GAP-WS-33 (MEDIUM, documentation) — Skill frontmatter said "Released 2026-06-08" (v0.7.3 date) while the binary is v0.7.4 of 2026-06-11. Now both EN and PT skills say "Released 2026-06-14 (v0.7.5)".
  • GAP-WS-34 (MEDIUM, documentation) — Skills only listed Linux build prerequisites. Now mention the four Windows prerequisites (NASM, CMake, MSVC, Perl) and the new build.rs preflight + escape hatches.
  • GAP-WS-35 (MEDIUM, documentation)llms-full.txt (line 273-305, embedding of docs/HOW_TO_USE.md) claimed "Pre-built binaries require no Rust installation" without qualifying that this is ONLY true for GitHub Releases binaries. cargo install always requires Rust and always compiles from source. Now qualified.
  • GAP-WS-36 (MEDIUM, documentation)docs/CROSS_PLATFORM.md line 193 and README.md line 336 and README.pt-BR.md line 428 claimed "VS Build Tools with C++ workload provides CMake". The C++ workload does NOT provide CMake — that is a separate sub-component. Now corrected in all three files.
  • GAP-WS-37 (MEDIUM, build)build.rs v0.7.4 only checked for NASM. Now checks for the four BoringSSL build prerequisites (nasm, cmake, cl.exe, link.exe, perl) and supports four independent escape hatches.

Added

  • scripts/check-windows-toolchain.ps1 — standalone diagnostic (no installs) that checks all 7 tools (cargo, rustc, cmake, nasm, cl.exe, link.exe, perl) and emits text or JSON output. Exit code 0 if all present, 1 otherwise. Useful for support tickets and CI gates.
  • docs/INSTALL-WINDOWS.md (EN) + docs/INSTALL-WINDOWS.pt-BR.md (PT) — step-by-step guide covering 5 installation methods (VS Installer + standalone; all-winget standalone; Chocolatey; helper script; standalone diagnostic). Includes troubleshooting for each of the 4 GAPs and the DDG_SKIP_*_CHECK escape hatches.

Changed

  • scripts/install-windows.ps1 — refactored to use generic Find-Tool and Install-Tool helpers; now detects and auto-installs CMake (Kitware.Cmake) and Perl (StrawberryPerl.StrawberryPerl) in addition to NASM. MSVC is NOT auto-installed (too large); the script prints the exact Launch-VsDevShell.ps1 instruction instead. New --check-only mode produces a tabular report suitable for CI gates.
  • build.rs — 4 detector functions (nasm_in_path, cmake_in_path, cl_in_path, link_in_path, perl_in_path) + 2 known_*dir functions. The preflight fires 4 panic messages with actionable fixes when a tool is missing. 4 independent escape hatches.
  • .github/workflows/ci.yml + .github/workflows/release.yml — Windows jobs now verify CMake, install Perl, and verify MSVC Build Tools (in addition to the existing NASM step).
  • Cargo.toml version bump: 0.7.4 → 0.7.5.

No runtime changes

  • Same CLI flags, same JSON schema, same default behavior as v0.7.4. crates.io still ships NO pre-built binaries.

[0.7.4] - 2026-06-11

Fixed

  • GAP-WS-28 — cargo install falhava no Windows nativo por NASM ausente.
    Erro literal: CMake Error at CMakeLists.txt:374 (enable_language): No CMAKE_ASM_NASM_COMPILER could be found, surgindo MINUTOS após o início do build do BoringSSL, sem indicar a correção. Causa raiz em 4 camadas: (CR1) o CMakeLists.txt do BoringSSL exige enable_language(ASM_NASM) quando NOT OPENSSL_NO_ASM em Windows x86/x86_64; (CR2) o build script do btls-sys v0.5.6 TEM um ramo OPENSSL_NO_ASM=YES para Windows (build/main.rs:314-318), mas ele é INALCANÇÁVEL em builds nativos pelo early-return host == target (build/main.rs:231); (CR3) o instalador do NASM não ajusta o PATH e o Visual Studio não inclui nasm.exe; (CR4) a documentação afirmava incorretamente que binários Windows eram pre-built (crates.io não distribui binários). Ver gaps.md GAP-WS-28.
  • Novo build.rs com preflight fail-fast: em target windows-msvc nativo, detecta nasm.exe ausente do PATH e aborta em SEGUNDOS com instrução exata (winget install -e --id NASM.NASM + ajuste de PATH + referência ao script). Detecta NASM instalado fora do PATH em diretórios conhecidos. Escape hatch: DDG_SKIP_NASM_CHECK=1. Cross-compile não é afetado (usa o caminho OPENSSL_NO_ASM do btls-sys).

Added

  • scripts/install-windows.ps1 — instalação automatizada e consentida no Windows: detecta NASM, instala via winget (fallback choco), corrige o PATH da sessão e roda cargo install duckduckgo-search-cli --locked repa...
Read more

Release v0.7.0

07 Jun 12:33

Choose a tag to compare

Release v0.6.11

05 Jun 23:44

Choose a tag to compare

Release v0.6.10

05 Jun 23:09

Choose a tag to compare

Release v0.6.9

05 Jun 22:32

Choose a tag to compare

Release v0.6.8

05 Jun 21:28

Choose a tag to compare

Release v0.6.7

05 Jun 20:17

Choose a tag to compare

v0.6.6: docs.rs build fix

05 Jun 10:40

Choose a tag to compare

Changelog

All notable changes to this project are documented in this file.

The format is based on Keep a Changelog,
and this project adheres to Semantic Versioning.

[0.6.6] - 2026-06-05

Fixed

  • docs.rs build failure (Build #3487310) caused by #[doc(cfg(...))] becoming unstable
    • Removed #[cfg_attr(docsrs, doc(cfg(feature = "chrome")))] from src/lib.rs:70
    • Root cause: in Oct 2025 the Rust team merged doc_auto_cfg into doc_cfg (rust-lang/rust#43781),
      making #[doc(cfg(...))] require #![feature(doc_cfg)] (nightly-only) on the crate root.
      The build failed with error[E0658]: #[doc(cfg)] is experimental on nightly 1.98.0.
    • The feature gating itself is preserved: #[cfg(feature = "chrome")] still excludes
      pub mod browser from default builds. The module-level docstring in src/browser.rs
      already documents the feature requirement explicitly.
    • cargo doc --all-features and RUSTDOCFLAGS="--cfg docsrs" cargo doc --all-features
      both pass without warning or error.

[0.6.5] - 2026-06-05

Fixed

  • MP-26 — Windows HANDLE cast broken in windows-sys 0.59+ (src/platform.rs:51-63)
    • HANDLE mudou de isize para *mut c_void upstream (microsoft/windows-rs, raw-window-handle#171)
    • Substituído handle != 0 && handle != usize::MAX por !handle.is_null() && handle != INVALID_HANDLE_VALUE
    • Removidos casts inválidos handle as isize (a assinatura moderna aceita HANDLE direto)
    • Atualizado o // SAFETY: comment para documentar nulidade e sentinela Win32
  • CI: validate falhava em todos os 3 SOs (Linux/macOS/Windows) por 6 erros de clippy
    • clippy::doc_markdown (PowerShell, rules_rust.md, TempDir) em src/platform.rs e src/browser.rs
    • clippy::needless_return em src/browser.rs:149
    • missing_debug_implementations em src/browser.rs:223 (ChromeBrowser) e src/content_fetch.rs (CircuitBreakerMap)

Added

  • WS-11 — Property-based invariants for HTML parsers (src/extraction.rs +5 testes)
    • Invariante: inputs vazios/quebrados retornam Vec vazio sem panic
    • Invariante: positions são densos e 1-based
    • Invariante: URLs absolutos (http/https) ou vazios
    • Invariante: extração é idempotente
    • Invariante: HTML malformado não causa panic
    • Zero dependência nova (apenas stdlib + #[test])
  • WS-12 — Per-host circuit breaker (src/content_fetch.rs)
    • Threshold: 3 falhas consecutivas abrem o circuito
    • Cooldown: 30s antes de half-open probe
    • Integração em enrich_with_content antes de cada fetch
    • BreakerDecision::{Allow, Reject} para inspeção
    • Zero dependência nova (std::sync::Mutex<HashMap>)
  • WS-23 — Retry-After header test (tests/integration_wiremock.rs)
    • Mock retorna 429 com retry-after: 2
    • Asserção: elapsed_ms >= 1500 (delay mínimo respeitado)
    • Usa wiremock 0.6 já em dev-deps
  • WS-25 — indicatif ProgressBar para crawls longos (src/content_fetch.rs)
    • indicatif = "0.18" adicionado
    • Bar com template [{elapsed_precise}] {bar:40.cyan/blue} {pos:>4}/{len:4} {msg}
    • Auto-detecta TTY (esconde em pipes)
    • progress.finish_and_clear() ao final
  • Lints preventivos FFI (Cargo.toml)
    • improper_ctypes = "deny" (rejeita casts FFI inválidos)
    • improper_ctypes_definitions = "deny" (rejeita definições incorretas)

Tests

  • 333 testes passando (243 lib + 24 + 3 + 5 + 10 + 10 + 14 + 18 + 6 doc)
  • 6 novos testes de invariantes em extraction.rs (WS-11)
  • 4 novos testes de circuit breaker em content_fetch.rs (WS-12)
  • 1 novo teste de Retry-After em integration_wiremock.rs (WS-23)
  • cargo fmt --all --check clean
  • cargo clippy --all-targets --all-features --locked -- -D warnings clean
  • cargo publish --dry-run --locked --allow-dirty clean

[0.6.4] - 2026-06-03

Added

  • WS-26 — Adaptive anti-bot identity rotation (new src/identity.rs module)
    • 12-identity pool (4 browser families × 3 platforms) for adaptive rotation
    • IdentityProfile::shuffled_headers() produces seed-deterministic header order
    • IdentityPool::rotate_on_block() implements a 5-level cascade: same identity → same family/different platform → different family/same platform → different family+platform → random
    • BrowserFamily and Platform enums with canonical English names
    • 5 unit tests covering pool size, cascade level, determinism, header shape, tag stability
  • New CLI flags (additive, no breaking changes)
    • --probe — pre-flight health check (sends 1 minimal request, reports status/latency/Set-Cookie as JSON)
    • --identity-profile — pin the session to a specific identity (auto, chrome-win, chrome-mac, chrome-linux, edge-win, firefox-linux, safari-mac). auto is default.
  • New JSON metadata fields (additive, Option + skip_serializing_if = "Option::is_none")
    • metadados.identidade_usada — string tag of the identity that produced the response
    • metadados.nivel_cascata — cascade level reached during the request

Changed

  • Version rollback: 0.7.0 (unpublished) → 0.6.4 to preserve the in-development feature set under a stable patch number
  • All existing CLI flags, JSON output schemas, and exit codes remain unchanged — strictly additive changes

Tests

  • 5 new identity unit tests (313 total tests passing, up from 308)
  • All 224 lib tests + 83 integration tests + 6 doc tests pass
  • cargo clippy --lib --bins -- -D warnings clean
  • cargo fmt --check clean

[0.7.0] - 2026-06-01

Changed

  • Complete internationalization: ~600 identifiers renamed PT→EN across 15 source files (struct fields, local variables, parameters, production functions, test functions)
  • Module fetch_conteudo renamed to content_fetch
  • Test files integracao_*.rs renamed to integration_*.rs
  • Replaced anyhow with typed CliError across all 11 modules — zero external error crate dependency
  • output.rs: all formatting functions renamed (formatar_*format_*, escrever_*write_*)
  • config_init.rs: struct fields renamed with #[serde(rename)] to preserve JSON backwards compatibility
  • search.rs: RetryResult and AggregatedSearchResult fields renamed PT→EN
  • types.rs: Config fields perfil_browser/corresponde_plataforma_ua/caminho_chromebrowser_profile/match_platform_ua/chrome_path

Added

  • Loom concurrency tests (tests/loom_atomics.rs) — validates AtomicBool visibility across threads
  • Criterion benchmarks (benches/extraction_bench.rs) — HTML extraction performance baselines
  • Doc comments for all 70 previously undocumented public items — zero missing_docs warnings
  • .ingest-queue.sqlite added to .gitignore and Cargo.toml exclude

Fixed

  • RUSTSEC-2026-0097: updated rand 0.8.5 → 0.8.6
  • RUSTSEC-2026-0104: updated rustls-webpki 0.103.12 → 0.103.13

Security

  • deny.toml: added skip-tree for 30 transitive duplicate crates (chromiumoxide, scraper, console-subscriber ecosystems)

Known Limitations

  • Loom tests require RUSTFLAGS="--cfg loom" which conflicts with hyper-util — tests compile but cannot run until upstream resolves the cfg conflict
  • JSON output field names remain in Portuguese Brazilian (posicao, titulo, resultados, etc.) — BY DESIGN since v0.2.0

[0.6.3] - 2026-04-17

Changed

  • Translated all 96 doc comments (/// and //!) across 19 source files from Portuguese to English — docs.rs now renders fully in English for international crates.io audience.
  • No code behavior, public API, or JSON output fields changed.

[0.6.2] - 2026-04-17

Added

  • 19 novos arquivos de documentação — conformidade completa com rules_rust_documentacao.md (28 gaps G01-G28)
  • Documentação bilíngue EN+PT: HOW_TO_USE, CROSS_PLATFORM, AGENTS-GUIDE, COOKBOOK.pt-BR, INTEGRATIONS.pt-BR
  • CODE_OF_CONDUCT.md + CODE_OF_CONDUCT.pt-BR.md — Contributor Covenant 2.1
  • README.pt-BR.md, CHANGELOG.pt-BR.md, CONTRIBUTING.pt-BR.md, SECURITY.pt-BR.md
  • docs/AGENTS.pt-BR.md — guia imperativo para LLMs em português
  • docs/AGENTS-GUIDE.md + docs/AGENTS-GUIDE.pt-BR.md — guia persuasivo bilíngue
  • llms.txt — arquivo compacto de orientação para LLMs (< 50 KB)
  • llms-full.txt — concatenação completa de docs para contexto longo de LLMs
  • eval-queries.json × 2 — 20 queries de avaliação EN + 20 PT-BR para skill testing

Changed

  • README.md — link para README.pt-BR.md + quick install antes da linha 30
  • CONTRIBUTING.md — MSRV Rust 1.75 explícito + PR checklist 8 itens + branching strategy + nextest
  • SECURITY.md — tabela de versão específica v0.6.2 + política de embargo 90 dias + zero bold + zero emojis
  • skill/SKILL.md (EN+PT) — seção Workflow com 5 passos numerados verificáveis

[0.6.1] - 2026-04-17

Fixed

  • --timeout 0 now returns exit 2 (invalid config) instead of executing a search with zero timeout and returning exit 5.
  • --output /tmp/../../etc/passwd now returns exit 2 (invalid config) instead of exit 1 (runtime OS error) — path traversal validation moved to montar_configuracoes(), before the pipeline starts.

Added

  • validar_timeout_segundos() method on CliArgs — rejects values of 0 with a descriptive error.
  • Early path traversal check in montar_configuracoes() — calls paths::validate_output_path() at config validation time, not at write time.
  • 2 E2E regression tests: timeout_zero_retorna_exit_2 and output_com_path_traversal_retorna_exit_2.
  • 1 unit test: validar_timeout_segundos_rejeita_zero.

[0.6.0] - 2026-04-16

Security

  • Browser fingerprint profiles per-family previnem detecção anti-bot do DuckDuckGo.
  • Headers Sec-Fetch-* e Client Hints por família imitam sessão de navegador real.
  • Accept-Language com q-values RFC 7231 elimina fingerprint de UA genérico.
  • Detecção de bloqueio silencioso com limiar de 5 KB previne resultados truncados.

Added

  • BrowserFamily enum — v...
Read more