Skip to content

fix(hashdb, cache)!: harden the public API before the first release - #12

Merged
Crauzer merged 1 commit into
mainfrom
pre-release-api-hardening
Oct 2, 2026
Merged

Crauzer merged 1 commit into
mainfrom
pre-release-api-hardening

Conversation

@Crauzer

@Crauzer Crauzer commented Oct 2, 2026 •

Copy link
Copy Markdown
Member

Pre-release hardening of ltk_hashdb and ltk_mimir_cache. It is rebased in substance onto current main (merged, not force-pushed): the changes main already made since this branch started (key config on Table, runtime layered checks, ExtendedHashDb removal, streaming downloads) are kept as they are. This PR adds only what was still missing. Neither crate is on crates.io yet, so the breaking changes cost nothing now. Item IDs refer to the Rust API Guidelines (C-) and the Microsoft Rust Guidelines (M-).

Safety and robustness

  • Memory blow-up from a crafted file. The seek table may claim frames of up to 1 GiB. open accepted that, and one get then allocated the claimed size. open now rejects frames above MAX_FRAME_SIZE (1 MiB), and the writer refuses larger frame sizes. Regression test: oversized_frame_claim_rejected_on_open.
  • Key config of a single table was never checked. HashStore::open/open_shared and commit now reject a file whose key config is not Table::key_config(), for example a bin table filed under game. Previously only open_layered noticed, and only relative to the first base (C-VALIDATE).
  • commit and gc take &UpdateLock. Previously gc could delete another process's in-progress .download.tmp.
  • Filenames are whitelisted. Version labels must be 1-64 characters from [A-Za-z0-9._-] and not start with .. This blocks NTFS alternate data streams (x:y) and control characters. path_for validates the manifest's filename before joining it.
  • HTTP fetchers:
    • connect and read timeouts;
    • a 512 MiB size limit (max_size, HttpFetchError::TooLarge), checked against Content-Length and while streaming;
    • with_agent/with_client for custom clients;
    • ReqwestFetch::new returns an error instead of falling back to a client that can panic;
    • the reqwest feature no longer enables blocking.
  • open/open_shared retry once if gc deleted the file between reading the manifest and opening it.
  • BuildError::HashKindTooWide: a 64-bit hash kind in a u32 table is rejected by the writer and on open.
  • The corruption proptest now covers compressed tables and probes real keys and try_get/get_batch.

HashDb::open stays a safe mmap with its documented contract, as main has it. M-UNSOUND would prefer an unsafe opener; I kept main's decision.

Semver and future-proofing

  • #[non_exhaustive] on:
    • every error enum in both crates;
    • HashKind, Compression, ArenaOrder, UpdateOutcome, TableStatus and HttpFetchError;
    • the structs with public fields: BuildStats, KeyConfigMismatch, UniverseMismatch, Manifest, Source, TableEntry, CommitItem, GcReport, PlannedTable, TableDiff, CheckReport, UnsupportedTable and UpdateReport (C-STRUCT-PRIVATE).
  • Source is built from Default.
  • zeekstd::Error is wrapped in an opaque CompressionError (M-DONT-LEAK-TYPES, C-STABLE).
  • ltk_mimir_cache re-exports ltk_hashdb. M-FOREIGN-REEXPORTS discourages re-exports but exempts crates split for technical reasons, which covers this pair.
  • Dropped the unused Seek bound on HashDbWriter::build (C-GENERIC).
  • Manifest::read/write_atomic take impl AsRef<Path> (M-IMPL-ASREF).

Docs and packaging

  • Every public item is documented, and both crates enable missing_docs and missing_debug_implementations (C-DEBUG, M-PUBLIC-DEBUG, M-CANONICAL-DOCS).
  • HashDbWriter, UreqFetch and ReqwestFetch now implement Debug.
  • rust-version = "1.89" (needed for File::try_lock, checked with cargo +1.89 check), keywords and categories (C-METADATA).
  • A README for ltk_hashdb, and a rewritten cache README. Both compile as doctests and use absolute links.

Verification

  • cargo fmt --check.
  • cargo clippy --all-targets -D warnings, with default features and with all features.
  • cargo test --workspace --all-features: 207 passed, 0 failed.
  • RUSTDOCFLAGS=-D warnings cargo doc.
  • cargo package -p ltk_hashdb.

This work was done with the help of an LLM.

🤖 Generated with Claude Code

@Crauzer
Crauzer force-pushed the pre-release-api-hardening branch from ffac8dc to 29f1c0c Compare October 2, 2026 12:30
@Crauzer
Crauzer enabled auto-merge (squash) October 2, 2026 12:31
@Crauzer
Crauzer disabled auto-merge October 2, 2026 12:32
@Crauzer
Crauzer merged commit 5e9514a into main Oct 2, 2026
3 checks passed
@Crauzer
Crauzer deleted the pre-release-api-hardening branch October 2, 2026 12:32
@github-actions github-actions Bot mentioned this pull request Oct 2, 2026
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