util/crc32.hpp — header-only CRC-32 (zlib polynomial, reflected), used to integrity-check the sidecar. meta/veloxpart — the <name>.veloxpart.meta resume file (docs/04 §5). Little-endian, versioned, CRC-32 over the whole record. Layout: magic, version, flags, total_size, downloaded, url set (original/effective/ mirrors), etag/last-modified/content-type, segment records (start, end INCLUSIVE, completed), optional sha256 streaming-hash blob. parse_veloxpart() is the attacker-facing surface (the file sits in a world-writable-ish download dir) and is total on any byte string: CRC checked before any field is interpreted; magic, a version it understands, every count and length bounded by a hard cap AND checked against the remaining buffer; ByteReader latches on overrun; trailing bytes rejected. Every malformation is meta_corrupt / meta_version_unsupported, never a crash or an unbounded allocation. serialize_veloxpart() is deterministic (unchanged sidecar isn't rewritten). File helpers write atomically (temp + rename) and fdatasync the file and its directory. Tests: crc32 known vector; full + minimal round-trips; deterministic serialize; file round-trip; and a truncation/corruption table — bad magic, CRC mismatch (payload and CRC-field flips), future version, truncation at every stage, hostile url_count / segment_count / lp_string length (the case the brief singles out), trailing bytes, impossible segment.completed. tools/fuzz/fuzz_veloxpart — feeds raw bytes and bytes-with-valid-CRC (so the field parser and ByteReader bounds checks are actually reached), and round-trip-stability-checks anything accepted. Ran 1.1M execs clean under ASan+UBSan+libFuzzer (clang++-21); fuzz_content_disposition and fuzz_url likewise re-run to 1.1M. tools/fuzz gains a -runs=0 seed-replay CTest smoke per target (regression tripwire; the campaign stays manual). Fuzz-found and fixed: parse_content_disposition could emit a filename containing NUL / control bytes from a mangled filename* ext-value — strip_path only removed path separators. Now sanitize_leaf() also drops C0 controls and DEL (rules/ still owns the authoritative sanitize; `..` and printable-unsafe content pass through as before). Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HPPSGhiArbvQgwC2DNiURS
libveloxcore — public API
Status: M1 in progress. Only util/ is landed. The download-facing API
(DownloadSpec, DownloadTask, probe, typed callbacks) arrives with later stages and
is reviewed by DAEMON before M2 (AGENT-CORE DoD).
Layering (CLAUDE.md §3): this library knows nothing about JSON, SQL, Qt, or RPC. Input is
a spec value; output is bytes on disk plus typed callbacks. DAEMON projects engine state
onto the wire contract's TaskSummary / TaskDetail / events — see
core/docs/proto-requests-m1.md for the shapes that projection needs frozen.
Every header under core/include/vdm/ compiles standalone (-Wall -Wextra -Wpedantic -Werror, C++23). Clean under ASan/UBSan and TSan.
util/ — foundations
vdm/util/error.hpp
enum class Error — the engine-wide failure taxonomy (network / HTTP / content / local
I/O / metadata / probe / retry / internal). This is CORE's own vocabulary; it is not
a wire type. error_name(Error) gives a stable snake_case string; is_retryable(Error)
is the advisory retry hint the task policy consults.
struct ErrorInfo { Error code; std::string context; int http_status; bool retryable; Error cause; } — the payload carried by every failed Result. .to_string() renders
"<name>: <context> (HTTP <n>)".
vdm/util/result.hpp
Result<T> — return-based error channel, a thin wrapper over
std::expected<T, ErrorInfo>. Errors are returned, never thrown, on anything that
runs during a transfer.
Result<int> r = 42;/Result<int> r = Err{Error::timeout, "..."};/Result<T> r = Error::not_found;r.has_value(),explicit operator bool,r.value()/*r/r->,r.error(),r.code(),r.value_or(x)- monadic
and_then/transform/transform_error(forward tostd::expected) Result<void>specialization;vdm::ok()success sentinelVDM_TRY(expr)— return the error ifexprfailedVDM_TRY_ASSIGN(auto x, expr)— bind the value or return the error
vdm/util/bytes.hpp
Byte / ByteSpan / ConstByteSpan aliases; as_bytes(string_view) /
as_chars(span). Little-endian fixed-width codec load_le<T> / store_le<T> and a
bounds-checked sequential ByteReader (.u8/.u16/.u32/.u64, .raw(n), .lp_string(),
.overran()). Built for the .veloxpart.meta reader and the 4-byte NM framing; every
read is bounds-checked and latches on overrun (reader-first, fuzz-ready).
vdm/util/event_bus.hpp
EventBus — typed, thread-safe in-process pub/sub. subscribe<E>(fn) -> Token,
publish<E>(ev) (synchronous, calling thread, registration order), unsubscribe(Token),
and RAII subscribe_scoped<E> returning a Subscription. Handlers may (un)subscribe or
publish during dispatch. Handlers must not throw. Not a hot-path structure — progress is
coalesced to ≤4 Hz upstream.
vdm/util/thread_pool.hpp
ThreadPool — fixed-size std::jthread pool for bounded off-loop work (hashing, fsync
batches, DNS pre-resolve). submit(fn, args...) -> std::future<R>; propagates exceptions
through the future; drains already-queued tasks on destruction. Not the transfer
loop — net/ will own one curl_multi per dedicated worker.
vdm/util/log.hpp
Sink interface — core does no I/O itself. LogSink abstract base; DAEMON installs one
via set_log_sink(), default discards. CallbackSink adapter (with a min-level filter).
VDM_LOG_{TRACE,DEBUG,INFO,WARN,ERROR}(category, fmt, args...) — std::format syntax,
only formatted when a sink is installed and wants the level.