# Shared brief — web dashboard implementation agents You are implementing one step of `docs/plans/2026-09-03-web-dashboard.md` in the `daily-epub` Rust crate. Read that plan **in full** before writing code — every decision in it is settled (§0), and §2 records verified facts about the crates and the host. Also read `docs/plans/2026-08-15-implementation-notes.md` (conventions: runtime sqlx queries with manual row mapping, `jiff` for time with RFC3339 UTC strings in SQLite, `thiserror`/`anyhow` errors, askama templates, no network in tests, rustfmt defaults, no `unwrap()` outside tests, tracing spans). ## Ground rules - Work on the current branch (`web-dashboard`) in place. Do **not** commit; the orchestrator reviews and commits. Do not create branches or stash. - Do not edit earlier migrations (`0001`–`0003`). Step 1 creates `migrations/0004_web.sql`; later steps may append a new migration file only if the plan says so. - Templates for the web live in `src/web/templates/` (`.html`, HTML-escaped by default); `askama.toml` lists both template dirs. EPUB templates in `src/epub/templates/` are untouched. - Every `|safe` in a template must be one of the sanitized inputs listed in plan §16; user text is never `|safe`. - The existing routes (`/r/…`, `/opds…`, `/files/…`, `/healthz`, `/issues.json`) and their tests keep working unchanged. - Tests: unit tests inline per module; router tests with `tower::ServiceExt::oneshot` against `server::router(...)` over a temp DB (`tempfile`), never the network, never systemd. Add the tests the plan's §17 lists for your step. - Keep `cargo fmt`, `cargo clippy --all-targets -- -D warnings` and `cargo test` green. Finish with those three commands and report their output. - **Sandbox note:** inside your sandbox `bind()` on 127.0.0.1 is forbidden, so exactly these pre-existing tests fail there and must be ignored: `curate::llm::tests::anthropic_*` (4), `extract::tests::relative_urls_resolve_against_the_url_we_landed_on`, `server::tests::*` (5 that bind a listener), and any test in `tests/m7_server.rs`. Do not "fix" them. Any **new** router test must use `oneshot` and not bind. The orchestrator runs the full suite outside the sandbox. - Don't gold-plate: implement what the plan says for your step and nothing from later steps beyond stubs the plan explicitly asks for. Where the plan's sketch and the real crate API disagree, follow the real API (read the crate source in `~/.cargo/registry` or `~/.cargo/git`) and note the deviation. - When you finish, write a short handoff at `docs/plans/briefs/web-dashboard/handoff-step.md`: what landed, deviations from the plan and why, anything left for the next step, test counts. ## Parallel steps (added after step 2) From step 3 on, steps may run **in parallel in separate git worktrees**, so file ownership matters: - `src/web/dashboard/mod.rs` already declares one submodule per page group (`runs`, `articles`, `ratings`, `profile`, `settings`, `jobs`, `stats`, `users`), each exposing `routes() -> Router` that the dashboard router merges under the admin layer. Put your routes in **your** submodule's `routes()`; do not touch `web::router` in `src/web/mod.rs` for dashboard routes. Only step 3 edits the `overview` handler in `dashboard/mod.rs`. - You own: your `src/web/dashboard/.rs` files, your templates under `src/web/templates/dashboard/`, partials you introduce, your tests. - Shared files you may touch **additively only** (no reformatting, reordering or renaming of existing code): `src/web/mod.rs` (helpers), `src/db.rs` (new query helpers appended inside `impl Db`), `src/main.rs`, `src/lib.rs`, `Cargo.toml`, `src/web/static/app.css` and `app.js` (append a block at the end under a `/* step N: … */` comment), `src/web/templates/layout.html`. Keep such edits small so merges stay trivial. - If your worktree is on its own branch, finish by committing **one** commit on that branch (message `Web dashboard step N: …`); the orchestrator merges. If you are on `web-dashboard` itself, do not commit.