Migration 0004 (users, sessions, config_changes, profile_versions, jobs, rating_events.user_id, runs.report_json, issues.issue_json), the issue snapshot writer and loader, the web module skeleton with layout and static assets, axum-login/tower-sessions over a sqlx session store, password-auth users with a CLI, the login throttle, the origin check, security headers, and the public issue pages, archive, Atom feed and robots.txt. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NHyYupFdBiR4VfoUM7NjSM
4.1 KiB
4.1 KiB
Step 1 handoff — foundation
Landed
- Added migration
0004_web.sql: users, SQLite-backed sessions and indexes, rating attribution, config/profile/job history, report/issue snapshots, and the candidate article/run index.RatingEvent/RatedArticlenow carry a nullable user id. - Persisted full
runs.report_json, finalissues.report_json, and a compactissues.issue_jsonwith article bodies removed. The issue loader rehydrates bodies fromarticlesand has a reduced-row fallback for pre-migration issues.GenerateOutcomeexposesrun_id. - Added the
webskeleton, final shared-state shape, Askama layout/error/public templates, embedded CSS/JS/favicon with SHA-256 ETags, security/cache/request headers, andDisabledRunner/MockRunnerstubs. - Added
axum-loginat the required git revision, the local sqlx 0.9 session store, password-auth users/backend, session/auth route layers, role guards, same-origin POST middleware, login governor and cleanup tasks, login/logout, account/password/session revocation, and session-or-Basic file downloads. - Added public latest/archive/issue pages, the stripped
PublicIssueboundary, Atom feed, and robots policy. Anonymous page loads remain session-cookie-free. - Added all
daily-epub userscommands without the pipeline lock, new server configuration/defaults/validation, example config, and README command/route/ reverse-proxy documentation. - Expanded
tests/m7_server.rsto cover env-only public routes, dashboard redirect, CLI admin bootstrap, and a real TCP login/account request.
Deviations and follow-up
rpasswordcould not be added: it is absent from the local Cargo cache and this sandbox cannot resolveindex.crates.io(three retries failed). The CLI currently uses an equivalent Unix/dev/ttyno-echo double prompt and keeps--password-stdin. Replace that helper withrpassword::prompt_passwordafter adding the dependency in a network-enabled environment.- Cargo resolved direct
toml_editto 0.22.27 rather than the plan's observed 0.25.x release; it was selected bycargo addfor the available toolchain and lock graph, not hand-pinned. - The finished issue report is attached immediately after
finish_run, rather than during the earlier issue snapshot write, because publish timing and the final run status are not complete at snapshot time. The stored observable value is the same final serialized report. - The pinned axum-login source confirms
AuthSession::user().await, immutablelogin/logout, the macro route layers, and session key"axum-login.data"; the implementation follows those real APIs. - Full signed-in issue/article rendering and the real
POST /ratehandler are step 2. Step 1 supplies the protected dashboard overview and admin-only 501 rate stub so route-guard tests exercise the final boundary.
Verification
cargo fmt --check: pass.cargo clippy --all-targets -- -D warnings: pass.cargo testwith sandbox-bound tests skipped: 389 passed, 0 failed. Excluded were the four named Anthropic listener tests, the relative-URL listener test, fiveserver::testslistener tests, bothm7_serverTCP tests, and three existing OpenAI fake-server tests that also bind loopback.- Focused
cargo test web:: -- --nocapture: 16 passed, 0 failed. cargo tree -ishows onesqlxversion (0.9.0) and onelibsqlite3-sysversion (0.37.0).
Orchestrator review (2026-09-03)
rpasswordadded (the sandbox had no network);read_password_hiddenis nowrpassword::prompt_password.toml_editmoved to 0.25 as the plan says.- Deviation from plan §8 kept on purpose:
/files/*with no Basic auth configured stays public, exactly as before. The plan wanted a redirect to/loginthere, but the public OPDS feed's acquisition links point at those files and an e-reader cannot log in; acceptance criterion 11 ("/filesbehave as before") and "OPDS clients are unaffected" win. With Basic auth configured, a session cookie of any role bypasses it. - A short new password on
/account/passwordis a 400 form error, not a 500. - Full suite outside the sandbox: 370 lib + all integration tests green.