Files
the-daily-epub/docs/plans/briefs/web-dashboard/handoff-step5.md
T
thalladaandClaude Fable 5.1 572056ce3b Web dashboard step 5: settings page with toml_edit writer
Schema derived from Config::default() and the live config, help text for every
shipped key, env locks and presence-only secrets, typed saves that preserve
comments and validate through Config::load before an atomic rename, provider
add/remove, the change history, and config reload on mtime.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NHyYupFdBiR4VfoUM7NjSM
2026-09-03 17:49:48 +00:00

63 lines
3.6 KiB
Markdown

# Step 5 handoff — settings
## Landed
- `src/web/dashboard/settings.rs`: a schema derived by walking serialized
default and live `Config` values, including optional/env-only fields, exact
field kinds and enum choices, derived environment names, source tracking,
README/example-backed help text, stable group order, and dotted-path anchors.
- `/dashboard/settings`: reload-on-mtime with a visible load-error banner and
last-good config retention; secret presence-only rendering, environment
locks, typed inputs, defaults/reset controls, and weight normalization notes.
- Typed `toml_edit` saves that preserve comments/order, collect field errors,
write multiline string arrays, create missing tables, validate through
`Config::load` in `<path>.tmp.<pid>`, preserve permissions, rename atomically,
swap the live config, and record one attributed `config_changes` row per key.
- Provider add/remove flows through the same validated writer, including name
and kind validation, role-reference refusal, placeholder defaults, audit
history, and redaction of a hand-written provider `api_key` from history.
- `/dashboard/settings/history`, newest first at 100 rows per page.
- A step 5 CSS block and reset helper in `app.js`; `/etc/daily-epub` added to
the server unit's `ReadWritePaths`.
- Sixteen settings tests covering every schema and writer case listed in §17,
including router-level rendering and POST behavior through `oneshot`.
## Deviations and notes
- Shipped providers cannot be removed, even when unreferenced. They are members
of `Config::default()`, so deleting their TOML table would immediately restore
the built-in entry and falsely report success. They can be edited or left
unreferenced; custom providers can be removed normally.
- `FieldKind::Enum` owns `Vec<String>` rather than the plan sketch's static
slice because `llm.bulk` and `llm.editor` must include provider names derived
at runtime. The rendered behavior and validation table are unchanged.
- Restart notices also cover `server.public_url`, `server.session_days`,
`server.login_attempts`, and `server.login_window_minutes`, in addition to
the plan sketch's `database_path` and `server.bind`, because those values are
captured when the server/session/throttle layers are built.
- An absent key whose effective value is already the submitted default remains
absent. This reconciles “only changed fields” with the no-JavaScript form
posting every editable field; resetting an explicit non-default file value
still writes the default explicitly.
- Step 6 should call `WebState::reload_if_changed` before starting each job, as
§4.2 requires. Step 5 supplies the shared helper; this branch's jobs module is
intentionally still the parallel-step stub.
- The shared brief's sandbox list omits three pre-existing OpenAI fake-server
tests that bind through the same `curate::llm::tests::serve` helper as its four
named Anthropic tests. The step 1 handoff records those three additional
sandbox failures; they are not settings regressions.
## Verification
- `cargo fmt`: pass.
- `cargo clippy --all-targets -- -D warnings`: pass.
- Focused `cargo test web::dashboard::settings -- --nocapture`: **16 passed,
0 failed**.
- Unfiltered `cargo test`: **379 library tests passed** before the harness
reported the expected loopback-bind failures (the 10 named library tests plus
the three OpenAI tests noted above); no settings test failed.
- `cargo test` with all pre-existing loopback listener tests excluded:
**411 passed, 0 failed, 15 filtered out** (379 library, 7 binary-unit, and 25
integration tests passed; 13 library listener tests and both `m7_server`
tests were filtered).