9a5c529a8e
Implements ADR-4 (CLAUDE.md section 3, `rusqlite` bundled). Schedules, lock state, disable attempts and usage buckets now persist across restarts. **Why a new crate rather than a module inside `blocker-core`.** The purity contract says the engine does no I/O, and `tests/purity.rs` enforces that mechanically by failing if `blocker-core` has any dependency at all. Putting rusqlite in `blocker-core` would have forced that check to degrade into a source-text grep — something a careful developer can route around and nobody reads in six months. `blocker-storage` depends on `blocker-core`; the reverse edge does not exist, so the zero-dependency proof stays automatic. Both crates sit in the same layer of the section 2 diagram: storage is shared by every platform and contains no platform code. **Schema is relational, not JSON-in-a-text-column.** `schedule_target` and `schedule_condition` are separate tables because target rows are queried by target, and an index on a JSON string is not a plan. Serialisation is hand-written in `storage/src/codec.rs` — `serde` is not a section 3 dependency, and section 0 rule 3 requires asking before adding one. **Fail open, verified end to end** (section 1.5.4). Corruption moves the damaged file aside and starts clean, keeping the original for diagnosis. Confirmed against the real binary, not only in tests: ``` $ printf 'SQLite format 3\x00 not a database' > .../blocker.db $ blocker-daemon blocker-daemon: database was corrupt and has been moved to .../blocker.db.corrupt; starting clean, so no schedules are active until you re-add them EXIT=0 ``` A truncated file is covered separately — that is what a power loss during a write actually produces, and it fails differently from garbage bytes. **Two bugs this PR's own tests caught:** 1. `prune_usage` anchored its cutoff on `MIN(day_index)`, the oldest row. Since that row is by definition the one being tested, the cutoff always sat before it and the delete matched nothing — the table grew forever, which is the slow disk leak the function exists to prevent. Now anchored on `MAX`. 2. An off-by-one in the same function: with a strict `<` against `newest - keep_days`, the boundary day was kept too, yielding `keep_days + 1` rows. Both are covered by `old_usage_is_pruned`. **Cost, measured rather than assumed:** the stripped daemon goes from 0.279 MB to **1.364 MB** with SQLite actually linked in — bundled SQLite is ~1.1 MB of the 5 MB budget, leaving 3.8 MB for D-Bus, X11 and a UI toolkit. That is a real margin rather than a comfortable one, and it makes ADR-4's bundled-vs-system trade-off a genuine open question rather than a settled one. The M0 figure of 0.279 MB excluded SQLite entirely, because dead-code elimination dropped a crate the placeholder binary never referenced. Co-Authored-By: Claude Code <noreply@anthropic.com>
156 lines
3.7 KiB
TOML
156 lines
3.7 KiB
TOML
# This file is automatically @generated by Cargo.
|
|
# It is not intended for manual editing.
|
|
version = 4
|
|
|
|
[[package]]
|
|
name = "bitflags"
|
|
version = "2.13.2"
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06"
|
|
|
|
[[package]]
|
|
name = "blocker-core"
|
|
version = "0.1.0"
|
|
|
|
[[package]]
|
|
name = "blocker-daemon"
|
|
version = "0.1.0"
|
|
dependencies = [
|
|
"blocker-core",
|
|
"blocker-storage",
|
|
]
|
|
|
|
[[package]]
|
|
name = "blocker-platform-linux"
|
|
version = "0.1.0"
|
|
dependencies = [
|
|
"blocker-core",
|
|
]
|
|
|
|
[[package]]
|
|
name = "blocker-platform-windows"
|
|
version = "0.1.0"
|
|
dependencies = [
|
|
"blocker-core",
|
|
]
|
|
|
|
[[package]]
|
|
name = "blocker-storage"
|
|
version = "0.1.0"
|
|
dependencies = [
|
|
"blocker-core",
|
|
"rusqlite",
|
|
]
|
|
|
|
[[package]]
|
|
name = "blocker-tests"
|
|
version = "0.1.0"
|
|
dependencies = [
|
|
"blocker-core",
|
|
]
|
|
|
|
[[package]]
|
|
name = "blocker-ui"
|
|
version = "0.1.0"
|
|
|
|
[[package]]
|
|
name = "cc"
|
|
version = "1.5.1"
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
checksum = "f360145194ee8e21db5ee7f3fcd4fe52210864c75c985dae33218202c8bbe040"
|
|
dependencies = [
|
|
"find-msvc-tools",
|
|
"shlex",
|
|
]
|
|
|
|
[[package]]
|
|
name = "fallible-iterator"
|
|
version = "0.3.0"
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
|
|
|
|
[[package]]
|
|
name = "fallible-streaming-iterator"
|
|
version = "0.1.9"
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
|
|
|
|
[[package]]
|
|
name = "find-msvc-tools"
|
|
version = "0.1.14"
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
checksum = "aedcfb3409746eddb02b9e19ebda1c3394f759a152e48ee875a0844d1b955484"
|
|
|
|
[[package]]
|
|
name = "foldhash"
|
|
version = "0.1.5"
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
|
|
|
[[package]]
|
|
name = "hashbrown"
|
|
version = "0.15.5"
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
|
dependencies = [
|
|
"foldhash",
|
|
]
|
|
|
|
[[package]]
|
|
name = "hashlink"
|
|
version = "0.10.0"
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1"
|
|
dependencies = [
|
|
"hashbrown",
|
|
]
|
|
|
|
[[package]]
|
|
name = "libsqlite3-sys"
|
|
version = "0.35.0"
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
checksum = "133c182a6a2c87864fe97778797e46c7e999672690dc9fa3ee8e241aa4a9c13f"
|
|
dependencies = [
|
|
"cc",
|
|
"pkg-config",
|
|
"vcpkg",
|
|
]
|
|
|
|
[[package]]
|
|
name = "pkg-config"
|
|
version = "0.3.34"
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548"
|
|
|
|
[[package]]
|
|
name = "rusqlite"
|
|
version = "0.37.0"
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
checksum = "165ca6e57b20e1351573e3729b958bc62f0e48025386970b6e4d29e7a7e71f3f"
|
|
dependencies = [
|
|
"bitflags",
|
|
"fallible-iterator",
|
|
"fallible-streaming-iterator",
|
|
"hashlink",
|
|
"libsqlite3-sys",
|
|
"smallvec",
|
|
]
|
|
|
|
[[package]]
|
|
name = "shlex"
|
|
version = "2.0.1"
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
|
|
|
[[package]]
|
|
name = "smallvec"
|
|
version = "1.16.2"
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
checksum = "f9395f0f0eee849a9b707b2f06bb92a6a422090e2123bb2ef8e87a0e61892a8e"
|
|
|
|
[[package]]
|
|
name = "vcpkg"
|
|
version = "0.2.15"
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|