Releases: daniloaguiarbr/duckduckgo-search-cli
v0.7.7 — GAP-WS-49 fix: TLS fingerprint emulation restored
duckduckgo-search-cli v0.7.7
GAP-WS-49 (CRITICAL, runtime) — v0.7.6 closed
cargo installbut real queries returned ZERO results silently. This patch restores the Chrome/Safari TLS fingerprint emulation that bypasses DDG'sanomaly-modal.
What's new in v0.7.7
Critical runtime fix (GAP-WS-49)
- Zero-result regression fixed. v0.7.6 passed all
--probeand--probe-deepsmoke tests (status 200/ok) while real queries silently returnedresultados: 0withcascade_level: 0andusou_endpoint_fallback: false. Local reproduction: 6/6 queries returned 0 results with 1.0–1.6s latency. - Root cause:
wreq 6.0.0-rc.29does not bundle theemulationfeature. The Chrome/Safari TLS fingerprint emulation lived only inwreq-util 3.0.0-rc.12viadefault = ["emulation"]. v0.7.6 removedwreq-util(along with thebrotlifeature) to close GAP-WS-48, and without emulation,wreq 6.0.0-rc.29with BoringSSL plain produces a JA3/JA4 fingerprint that Cloudflare Bot Management detects. DDG servesanomaly-modalHTML (45 occurrences) to any client without a real browser fingerprint. - Cross-confirmation:
curlwith real browser headers (User-Agent: Chrome/120,Accept-Encoding: br,Sec-Fetch-*) also receivedanomaly-modalat test time (2026-06-14 09:25 UTC), confirming the upstream tightening. - Fix:
- Re-added
wreq-util 3.0.0-rc.12withdefault-features = false, features = ["emulation"]. - Re-added
"brotli"feature towreq(required byemulation). - Added 3 direct dep pins to
Cargo.tomlto force compatible versions incargo install:brotli-decompressor = "=5.0.1"— last version with hardalloc-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 }— nostdfeature, doesn't pullalloc-stdlib 0.2.3.
cargo update -p alloc-no-stdlib@3.0.0 --precise 2.0.4removes 3.0.0 from the lockfile.
- Re-added
- Post-fix validation:
cargo tree --offline— graph contains exactlyalloc-no-stdlib v2.0.4andbrotli-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 --lockedThe 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 installbuild 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 --lockedWhat'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.04scargo install --path . --locked --offline— success in 34.32scargo test --lib --offline— 292 passed; 0 failedcargo fmt --check— cleancargo 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)
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 installquebrou em 2026-06-14 por conflitoalloc-no-stdlib 2.0.4 vs 3.0.0. Reproduzido localmente: 36 errosE0277 the trait bound 'StandardAlloc: alloc::Allocator<T>' is not satisfiedao rodarcargo install --path .(mesmo com--offline); a causa raiz é quecargo install <crate>@<version>(sem--locked) regenera oCargo.lockno 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") ebrotli-decompressor 5.0.2. Obrotli 8.0.3(não atualizado, ainda requeralloc-no-stdlib = "2.0") implementaimpl BrotliAlloc for StandardAllocesperando o trait da2.0.4, mas oStandardAllocdealloc-stdlib 0.2.3é compilado contra3.0.0— colisão trait-bind emenc/reader.rs,enc/writer.rseenc/combined_alloc.rs. - Causa raiz em 2 camadas: (CR1) o
wreq-util 3.0.0-rc.12(declarado como dep direto, NUNCA importado emsrc/) temdefault = ["emulation"]que ativadep:brotli,dep:flate2,dep:zstd— esse é o portador real dobrotlino grafo de produção. A featurebrotlidowreqfoi apenas secundária. (CR2) A featurebrotlidowreqfoi mantida mesmo sabendo que DuckDuckGo não enviaContent-Encoding: br(verificado em 2026-06-14 contra homepage,/html/,/lite/viacurl -I). - Fix aplicado:
- Removida a dep
wreq-util = "3.0.0-rc"doCargo.toml(era dead code). - Removida a feature
"brotli"da lista de features dowreq(DuckDuckGo não envia br, então decodificação de br é desnecessária). - Atualizado o comentário do
wreqnoCargo.tomlpara documentar a remoção e referenciar o incidente.
- Removida a dep
- 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 --offline→ sucesso (caminho de CI com lock travado).cargo build --release→ sucesso em 37.14s (5.92s mais rápido que v0.7.5 pela ausência dobrotliebrotli-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+zstdcontinuam habilitados; oAccept-Encodingque owreqenvia continua contendogzip, deflate, zstd(sembr), e DuckDuckGo nunca envia brotli, então nenhuma resposta real é afetada.
Cargo.tomlversion 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.rsexecute_deep_researchwas usingprintln!("{json}")directly, violating the documented rule thatoutput.rsis the only module withprintln!(lib.rs doc-table line 34). Now delegates tooutput::print_line_stdoutwhich handlesBrokenPipecleanly (silent success on| head, generic error on real I/O failure). Closes the audit finding that the JSON contract fordeep-researchwas bypassing the central output abstraction. - P1-audit-2 (LOW, code clarity) — Removed the
unreachable!("handled above")arm in the subcommand dispatch by folding theDeepResearchbranch into the mainmatch(and dropping the precedingif 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::Cancellednow maps to exit code130(POSIX: 128 + SIGINT(2)) instead of1(generic error). Shell sessions can now distinguish user-initiated Ctrl-C from real runtime failures, and process supervisors (e.g. CI runners,set -escripts) treat cancellation asexit 130per convention. - P1-audit-4 (LOW, error code mapping) — Three string error code mappings were semantically wrong:
InvalidConfig→selector_config_invalid(should beinvalid_config);PathError→selector_config_invalid(should bepath_error);BrokenPipe→http_error(should bebroken_pipe). New constants added:codes::INVALID_CONFIG,codes::PATH_ERROR,codes::BROKEN_PIPE. All three string mappings now use their dedicated constant. Consumers parsing theerrorfield 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 to0.7.5. Closes the docs.rs cross-link drift. - P2-audit-7 (MEDIUM, distribution hygiene) —
Cargo.toml[build-dependencies]now includesclapandclap_mangen = "0.2". The existingbuild.rswas extended to call a newgenerate_man_page()function that emitsduckduckgo-search-cli.1inOUT_DIRusing a best-effort mirror of thesrc/cli.rsCLI 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.tomllistedarmv7-unknown-linux-musleabihfas a developer convenience target, but the comment also claimed "5 principais" targets were covered byrelease.yml(false: release.yml only coversx86_64-unknown-linux-muslandaarch64-apple-darwin). Removed thearmv7-unknown-linux-musleabihfblock 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 forCancelled.exit_code() == 130,Cancelled.error_code() == "cancelled",BrokenPipe.error_code() == "broken_pipe",PathError.error_code() == "path_error",InvalidConfig.error_code() == "invalid_config". Totalerror::tests: 5 tests, all pass.
Fixed
- GAP-WS-29 (CRITICAL, build experience, Windows) —
cargo installon 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 crypticfailed to execute command: program not found / is 'cmake' not installed?. Thebuild.rspreflight is now extended to detect this and abort in SECONDS with the exact fix (winget install -e --id Kitware.CmakeOR 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.rspreflight now detects both and aborts with the fix (open a Developer PowerShell for VS 2022, or runLaunch-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.rspreflight 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.mdline 561 andskill/duckduckgo-search-cli-pt/SKILL.mdline 565 still claimed "Pre-built binaries fromcargo installare unaffected" / "Binários pré-compilados docargo installnão são afetados". This was already false in v0.7.4 (onlyllms.txtandREADME*.mdwere corrected); now corrected in the skills too. crates.io NEVER distributes binaries;cargo installalways 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.rspreflight + escape hatches. - GAP-WS-35 (MEDIUM, documentation) —
llms-full.txt(line 273-305, embedding ofdocs/HOW_TO_USE.md) claimed "Pre-built binaries require no Rust installation" without qualifying that this is ONLY true for GitHub Releases binaries.cargo installalways requires Rust and always compiles from source. Now qualified. - GAP-WS-36 (MEDIUM, documentation) —
docs/CROSS_PLATFORM.mdline 193 andREADME.mdline 336 andREADME.pt-BR.mdline 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.rsv0.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...
v0.7.5 — 4-tool Windows preflight + docs/INSTALL-WINDOWS + audit batch
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.rsexecute_deep_researchwas usingprintln!("{json}")directly, violating the documented rule thatoutput.rsis the only module withprintln!(lib.rs doc-table line 34). Now delegates tooutput::print_line_stdoutwhich handlesBrokenPipecleanly (silent success on| head, generic error on real I/O failure). Closes the audit finding that the JSON contract fordeep-researchwas bypassing the central output abstraction. - P1-audit-2 (LOW, code clarity) — Removed the
unreachable!("handled above")arm in the subcommand dispatch by folding theDeepResearchbranch into the mainmatch(and dropping the precedingif 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::Cancellednow maps to exit code130(POSIX: 128 + SIGINT(2)) instead of1(generic error). Shell sessions can now distinguish user-initiated Ctrl-C from real runtime failures, and process supervisors (e.g. CI runners,set -escripts) treat cancellation asexit 130per convention. - P1-audit-4 (LOW, error code mapping) — Three string error code mappings were semantically wrong:
InvalidConfig→selector_config_invalid(should beinvalid_config);PathError→selector_config_invalid(should bepath_error);BrokenPipe→http_error(should bebroken_pipe). New constants added:codes::INVALID_CONFIG,codes::PATH_ERROR,codes::BROKEN_PIPE. All three string mappings now use their dedicated constant. Consumers parsing theerrorfield 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 to0.7.5. Closes the docs.rs cross-link drift. - P2-audit-7 (MEDIUM, distribution hygiene) —
Cargo.toml[build-dependencies]now includesclapandclap_mangen = "0.2". The existingbuild.rswas extended to call a newgenerate_man_page()function that emitsduckduckgo-search-cli.1inOUT_DIRusing a best-effort mirror of thesrc/cli.rsCLI 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.tomllistedarmv7-unknown-linux-musleabihfas a developer convenience target, but the comment also claimed "5 principais" targets were covered byrelease.yml(false: release.yml only coversx86_64-unknown-linux-muslandaarch64-apple-darwin). Removed thearmv7-unknown-linux-musleabihfblock 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 forCancelled.exit_code() == 130,Cancelled.error_code() == "cancelled",BrokenPipe.error_code() == "broken_pipe",PathError.error_code() == "path_error",InvalidConfig.error_code() == "invalid_config". Totalerror::tests: 5 tests, all pass.
Fixed
- GAP-WS-29 (CRITICAL, build experience, Windows) —
cargo installon 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 crypticfailed to execute command: program not found / is 'cmake' not installed?. Thebuild.rspreflight is now extended to detect this and abort in SECONDS with the exact fix (winget install -e --id Kitware.CmakeOR 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.rspreflight now detects both and aborts with the fix (open a Developer PowerShell for VS 2022, or runLaunch-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.rspreflight 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.mdline 561 andskill/duckduckgo-search-cli-pt/SKILL.mdline 565 still claimed "Pre-built binaries fromcargo installare unaffected" / "Binários pré-compilados docargo installnão são afetados". This was already false in v0.7.4 (onlyllms.txtandREADME*.mdwere corrected); now corrected in the skills too. crates.io NEVER distributes binaries;cargo installalways 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.rspreflight + escape hatches. - GAP-WS-35 (MEDIUM, documentation) —
llms-full.txt(line 273-305, embedding ofdocs/HOW_TO_USE.md) claimed "Pre-built binaries require no Rust installation" without qualifying that this is ONLY true for GitHub Releases binaries.cargo installalways requires Rust and always compiles from source. Now qualified. - GAP-WS-36 (MEDIUM, documentation) —
docs/CROSS_PLATFORM.mdline 193 andREADME.mdline 336 andREADME.pt-BR.mdline 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.rsv0.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 theDDG_SKIP_*_CHECKescape hatches.
Changed
scripts/install-windows.ps1— refactored to use genericFind-ToolandInstall-Toolhelpers; 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 exactLaunch-VsDevShell.ps1instruction instead. New--check-onlymode 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) + 2known_*dirfunctions. 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.tomlversion 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 installfalhava 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 exigeenable_language(ASM_NASM)quandoNOT OPENSSL_NO_ASMem Windows x86/x86_64; (CR2) o build script dobtls-sysv0.5.6 TEM um ramoOPENSSL_NO_ASM=YESpara Windows (build/main.rs:314-318), mas ele é INALCANÇÁVEL em builds nativos pelo early-returnhost == target(build/main.rs:231); (CR3) o instalador do NASM não ajusta o PATH e o Visual Studio não incluinasm.exe; (CR4) a documentação afirmava incorretamente que binários Windows eram pre-built (crates.io não distribui binários). Vergaps.mdGAP-WS-28. - Novo
build.rscom preflight fail-fast: em targetwindows-msvcnativo, detectanasm.exeausente 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 caminhoOPENSSL_NO_ASMdo btls-sys).
Added
scripts/install-windows.ps1— instalação automatizada e consentida no Windows: detecta NASM, instala viawinget(fallbackchoco), corrige o PATH da sessão e rodacargo install duckduckgo-search-cli --lockedrepa...
Release v0.7.0
Full Changelog: v0.6.11...v0.7.0
Release v0.6.11
Full Changelog: v0.6.10...v0.6.11
Release v0.6.10
Full Changelog: v0.6.9...v0.6.10
Release v0.6.9
Full Changelog: v0.6.8...v0.6.9
Release v0.6.8
Full Changelog: v0.6.7...v0.6.8
Release v0.6.7
Full Changelog: v0.6.6...v0.6.7
v0.6.6: docs.rs build fix
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")))]fromsrc/lib.rs:70 - Root cause: in Oct 2025 the Rust team merged
doc_auto_cfgintodoc_cfg(rust-lang/rust#43781),
making#[doc(cfg(...))]require# on the crate root.
The build failed witherror[E0658]: #[doc(cfg)] is experimentalon nightly1.98.0. - The feature gating itself is preserved:
#[cfg(feature = "chrome")]still excludes
pub mod browserfrom default builds. The module-level docstring insrc/browser.rs
already documents the feature requirement explicitly. cargo doc --all-featuresandRUSTDOCFLAGS="--cfg docsrs" cargo doc --all-features
both pass without warning or error.
- Removed
[0.6.5] - 2026-06-05
Fixed
- MP-26 — Windows HANDLE cast broken in
windows-sys 0.59+(src/platform.rs:51-63)HANDLEmudou deisizepara*mut c_voidupstream (microsoft/windows-rs,raw-window-handle#171)- Substituído
handle != 0 && handle != usize::MAXpor!handle.is_null() && handle != INVALID_HANDLE_VALUE - Removidos casts inválidos
handle as isize(a assinatura moderna aceitaHANDLEdireto) - Atualizado o
// SAFETY:comment para documentar nulidade e sentinela Win32
- CI:
validatefalhava em todos os 3 SOs (Linux/macOS/Windows) por 6 erros de clippy- 3×
clippy::doc_markdown(PowerShell,rules_rust.md,TempDir) emsrc/platform.rsesrc/browser.rs - 1×
clippy::needless_returnemsrc/browser.rs:149 - 2×
missing_debug_implementationsemsrc/browser.rs:223(ChromeBrowser) esrc/content_fetch.rs(CircuitBreakerMap)
- 3×
Added
- WS-11 — Property-based invariants for HTML parsers (
src/extraction.rs+5 testes)- Invariante: inputs vazios/quebrados retornam
Vecvazio 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])
- Invariante: inputs vazios/quebrados retornam
- 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_contentantes de cada fetch BreakerDecision::{Allow, Reject}para inspeção- Zero dependência nova (
std::sync::Mutex<HashMap>)
- WS-23 —
Retry-Afterheader test (tests/integration_wiremock.rs)- Mock retorna 429 com
retry-after: 2 - Asserção:
elapsed_ms >= 1500(delay mínimo respeitado) - Usa
wiremock0.6 já em dev-deps
- Mock retorna 429 com
- WS-25 —
indicatifProgressBar 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 --checkcleancargo clippy --all-targets --all-features --locked -- -D warningscleancargo publish --dry-run --locked --allow-dirtyclean
[0.6.4] - 2026-06-03
Added
- WS-26 — Adaptive anti-bot identity rotation (new
src/identity.rsmodule)- 12-identity pool (4 browser families × 3 platforms) for adaptive rotation
IdentityProfile::shuffled_headers()produces seed-deterministic header orderIdentityPool::rotate_on_block()implements a 5-level cascade: same identity → same family/different platform → different family/same platform → different family+platform → randomBrowserFamilyandPlatformenums 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).autois default.
- New JSON metadata fields (additive,
Option+skip_serializing_if = "Option::is_none")metadados.identidade_usada— string tag of the identity that produced the responsemetadados.nivel_cascata— cascade level reached during the request
Changed
- Version rollback:
0.7.0(unpublished) →0.6.4to 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 warningscleancargo fmt --checkclean
[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_conteudorenamed tocontent_fetch - Test files
integracao_*.rsrenamed tointegration_*.rs - Replaced
anyhowwith typedCliErroracross 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 compatibilitysearch.rs:RetryResultandAggregatedSearchResultfields renamed PT→ENtypes.rs:Configfieldsperfil_browser/corresponde_plataforma_ua/caminho_chrome→browser_profile/match_platform_ua/chrome_path
Added
- Loom concurrency tests (
tests/loom_atomics.rs) — validatesAtomicBoolvisibility across threads - Criterion benchmarks (
benches/extraction_bench.rs) — HTML extraction performance baselines - Doc comments for all 70 previously undocumented public items — zero
missing_docswarnings .ingest-queue.sqliteadded to.gitignoreandCargo.tomlexclude
Fixed
- RUSTSEC-2026-0097: updated
rand0.8.5 → 0.8.6 - RUSTSEC-2026-0104: updated
rustls-webpki0.103.12 → 0.103.13
Security
deny.toml: addedskip-treefor 30 transitive duplicate crates (chromiumoxide, scraper, console-subscriber ecosystems)
Known Limitations
- Loom tests require
RUSTFLAGS="--cfg loom"which conflicts withhyper-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 0now returns exit 2 (invalid config) instead of executing a search with zero timeout and returning exit 5.--output /tmp/../../etc/passwdnow returns exit 2 (invalid config) instead of exit 1 (runtime OS error) — path traversal validation moved tomontar_configuracoes(), before the pipeline starts.
Added
validar_timeout_segundos()method onCliArgs— rejects values of 0 with a descriptive error.- Early path traversal check in
montar_configuracoes()— callspaths::validate_output_path()at config validation time, not at write time. - 2 E2E regression tests:
timeout_zero_retorna_exit_2andoutput_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-Languagecom q-values RFC 7231 elimina fingerprint de UA genérico.- Detecção de bloqueio silencioso com limiar de 5 KB previne resultados truncados.
Added
BrowserFamilyenum — v...