92afdc3bf6
Updates the ADR log, architecture, limitations, perf table and README to match what now exists, rather than what was expected. **The perf number was wrong and is now honest.** The M0 figure of 0.279 MB excluded SQLite entirely — the placeholder binary never referenced the crate, so dead-code elimination dropped it. With the daemon actually opening a database it is **1.364 MB**, of which bundled SQLite is ~1.1 MB. That is 1.1 MB of the 5 MB budget spoken for, leaving 3.8 MB for D-Bus, X11 and a UI toolkit. This is the first number that makes the section 5 budget feel like a budget rather than a formality, and it turns ADR-4's bundled-vs-system-linked choice into a real trade-off with a measured price on both sides. - ADR-4 marked accepted and implemented, with that trade-off left open. - ARCHITECTURE.md documents why `blocker-storage` is a sibling crate and not a submodule: the dependency direction is what keeps the zero-dependency purity proof automatic rather than a grep someone can route around. - LIMITATIONS.md drops the stale "storage has no I/O" shortfall and records the bundled-vs-system question instead, plus the fact that `LockState` still always evaluates to Normal. - README status table and layout updated. Co-Authored-By: Claude Code <noreply@anthropic.com>
124 lines
5.3 KiB
Markdown
124 lines
5.3 KiB
Markdown
# Blocker
|
|
|
|
A cross-platform app and website blocker for **Android, Windows and Linux**.
|
|
|
|
One shared Rust core owns every decision. Platform code observes the OS and
|
|
enforces what the core decides. That is what makes the same schedule behave
|
|
identically on all three, and it is testable rather than aspirational — the golden
|
|
decision tables in `tests/` are the parity contract, so a platform disagreeing
|
|
with the core fails the build instead of producing a bug report.
|
|
|
|
## Status
|
|
|
|
**M0 — repository bootstrap.** The core engine exists and is tested; nothing
|
|
enforces anything yet. No platform has a working build.
|
|
|
|
| Milestone | State |
|
|
|---|---|
|
|
| M0 repo bootstrap | in progress |
|
|
| M1 core engine | engine, lock timers and safety guarantees written and tested; SQLite persistence landed in `storage/` |
|
|
| M2-Linux | not started — daemon is a placeholder |
|
|
| M3-Android | not started |
|
|
| M4 conditions | not started |
|
|
| M5 websites | not started |
|
|
| M6 Strict Mode + friction | not started |
|
|
| M7 statistics, settings, releases | not started |
|
|
|
|
Milestone order is Linux-first rather than Android-first. See ADR-15.
|
|
|
|
## What it will do
|
|
|
|
- Schedules of apps, websites and keywords, with time windows, usage limits,
|
|
launch counts, Wi-Fi and location conditions
|
|
- Blocklist and allowlist modes, with strictest-wins when schedules overlap
|
|
- QuickBlock: block a chosen set for a chosen duration
|
|
- Strict Mode and a configurable friction ladder, so turning blocking off takes
|
|
deliberate effort in a weak moment while remaining always possible
|
|
- Local usage statistics
|
|
|
|
## What it will not do
|
|
|
|
This is a friction tool, not a wall. A user with root, ADB, safe mode, a factory
|
|
reset, or desktop admin rights can always remove it, and that is intended. Factory
|
|
reset, safe mode and OS recovery are never interfered with. The goal is to outlast
|
|
an impulse, not to defeat a determined decision.
|
|
|
|
There is also a hardcoded list of things that can never be blocked — the phone and
|
|
dialler, emergency calls and alerts, and on desktop the OS shell and the Settings
|
|
basics needed to keep the machine usable. There is no setting that changes it.
|
|
|
|
See [`docs/LIMITATIONS.md`](docs/LIMITATIONS.md) for all eight platform limits,
|
|
stated plainly, plus the shortfalls in the current code.
|
|
|
|
## Build and test
|
|
|
|
Requires a stable Rust toolchain. The toolchain is pinned in `rust-toolchain.toml`.
|
|
|
|
```sh
|
|
scripts/ci.sh # everything, stops at the first failure
|
|
scripts/ci.sh --keep-going # everything, summarises all failures
|
|
cargo test --workspace # tests only
|
|
cargo build --workspace # build only
|
|
scripts/size-check.sh # the 5 MB stripped daemon gate
|
|
```
|
|
|
|
Build artifacts go to `$HOME/.blocker-target`, outside the repository, so `target/`
|
|
never shows up in `git status` and can be deleted in one command. Override with
|
|
`CARGO_TARGET_DIR`.
|
|
|
|
Two checks skip on a machine without the relevant toolchain — Android without an
|
|
SDK, the secret scan without gitleaks. Both **skip loudly** and are listed in the
|
|
summary as not-passes. A skip is never reported as a pass.
|
|
|
|
## Layout
|
|
|
|
```
|
|
core/ the decision engine — pure, no OS calls, no dependencies
|
|
storage/ SQLite persistence (rusqlite, bundled), fail-open recovery
|
|
tests/ golden decision tables, and the engine purity check
|
|
desktop/daemon/ long-lived observer and enforcer (5 MB budget)
|
|
desktop/ui/ block-screen window, launched on demand
|
|
desktop/platform-linux/ ForegroundWatcher backends, enforcement
|
|
desktop/platform-windows/ same, Windows
|
|
android/ not started
|
|
docs/ architecture, ADRs, limitations, permissions, perf, testing
|
|
scripts/ ci.sh, size-check.sh
|
|
```
|
|
|
|
## Documentation
|
|
|
|
| Document | What it is for |
|
|
|---|---|
|
|
| [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) | The purity contract, `next_wakeup`, and why the engine has no dependencies |
|
|
| [`docs/DECISIONS.md`](docs/DECISIONS.md) | 17 ADRs, including the two still awaiting a decision |
|
|
| [`docs/LIMITATIONS.md`](docs/LIMITATIONS.md) | What the OS will not let us do, and what is not built yet |
|
|
| [`docs/PERMISSIONS.md`](docs/PERMISSIONS.md) | Every permission, and what degrades without it |
|
|
| [`docs/PERF.md`](docs/PERF.md) | Section 5 budgets, and the measurements taken so far |
|
|
| [`docs/TESTING.md`](docs/TESTING.md) | The golden-table contract and the manual checklists |
|
|
| [`CLAUDE.md`](CLAUDE.md) | The project specification. It governs. |
|
|
|
|
## Performance budgets
|
|
|
|
| Metric | Target |
|
|
|---|---|
|
|
| Idle CPU | ~0%, no wakeups without events |
|
|
| Idle RAM (daemon) | ≤ 15 MB RSS |
|
|
| Block latency | ≤ 150 ms |
|
|
| Daemon binary | ≤ 5 MB stripped |
|
|
| APK size | ≤ 10 MB |
|
|
|
|
Currently measured: **1.364 MB** stripped daemon, which includes bundled SQLite.
|
|
Of the 5 MB budget that leaves 3.8 MB for D-Bus, X11 and a UI toolkit — a real
|
|
margin rather than a comfortable one. Enforced in CI from the first commit by
|
|
`scripts/size-check.sh`.
|
|
|
|
## Licence
|
|
|
|
**Not yet chosen.** See ADR-17. Choosing a licence is the owner's decision, and it
|
|
interacts with the UI toolkit choice in ADR-6 (Slint is GPL-3.0 or commercial), so
|
|
it is not something to settle by accident.
|
|
|
|
## A note on origin
|
|
|
|
Blocker is a functional reimplementation of the behaviour of existing app blockers.
|
|
It reuses no third-party name, logo, icon, copy, or screenshot — only behaviour. |