Repository navigation
feat(opds): optional Basic auth, wired as the all-networks gate - #161
Conversation
libcalibre Test Coverage ReportOverall coverage: 80.16% Coverage breakdown available in the artifacts. |
0f5956d to
0232379
Compare
libcalibre Test Coverage ReportOverall coverage: 80.16% Coverage breakdown available in the artifacts. |
0232379 to
6890c0a
Compare
libcalibre Test Coverage ReportOverall coverage: 80.16% Coverage breakdown available in the artifacts. |
|
Two ADRs landed with this PR: 0003 records that OPDS credentials are machine-local (app-data, one set per install, never travel with the library), and 0004 supersedes ADR 0002 — the sharing model is now two modes (Local networks / All interfaces, the latter wildcard + credentials-gated) with an explicit state machine and no interface picker. 0002's status line notes the partial supersession; its body is untouched. Both follow Plato's structural checklist (drivers, rejected alternatives, blunt consequences, reopening conditions). |
6890c0a to
3d2bcd2
Compare
libcalibre Test Coverage ReportOverall coverage: 80.16% Coverage breakdown available in the artifacts. |
3d2bcd2 to
3c40582
Compare
libcalibre Test Coverage ReportOverall coverage: 80.16% Coverage breakdown available in the artifacts. |
3c40582 to
45f8ce5
Compare
libcalibre Test Coverage ReportOverall coverage: 80.16% Coverage breakdown available in the artifacts. |
45f8ce5 to
3fb199d
Compare
libcalibre Test Coverage ReportOverall coverage: 80.16% Coverage breakdown available in the artifacts. |
3fb199d to
515991e
Compare
libcalibre Test Coverage ReportOverall coverage: 80.16% Coverage breakdown available in the artifacts. |
515991e to
13d8bdf
Compare
libcalibre Test Coverage ReportOverall coverage: 80.16% Coverage breakdown available in the artifacts. |
13d8bdf to
2019d4e
Compare
libcalibre Test Coverage ReportOverall coverage: 80.16% Coverage breakdown available in the artifacts. |
Basic authentication for the OPDS server: generated credentials (username + password) persisted with the library, optional per share start, enforced as axum basic-auth middleware on every route. This PR also completes the all-networks gate the state machine introduced: - credentials configured is the input to BindPolicy.allow_global, so AllInterfaces starts only when a password exists - clearing credentials while sharing on all interfaces forces sharing to stop - sharing on the local network never requires credentials
2019d4e to
945ab92
Compare
libcalibre Test Coverage ReportOverall coverage: 80.16% Coverage breakdown available in the artifacts. |
Rebuilds the sharing settings pane on the state-machine service and the credential surface from #161: - Mode choice, not a picker: Local network (exact private/ULA binds, never needs credentials) vs All networks (wildcard, enabled only once a credential set exists). The per-interface picker is gone. - Credentials: status / configure (hand-set) / generate-and-set / clear. Generated passwords are shown once, colour-chunked (word | digits+symbol | word, middle chunk bold) so they transcribe cleanly onto e-readers. - Status comes from the state-machine projection: Running shows catalog addresses; Waiting explains that sharing starts when a network appears; Failed surfaces the reason and returns to the form. - Copy per the agreed drafts; settings schema gains the sharing block (v2 -> v3 migration); web builds get no OPDS client at all. The old #151 branch is superseded by this one.
Problem
The state machine (#160) left
allInterfacesbehind anAuthRequiredgate with no key: there was no way to configure credentials, and no path for the mode to ever start. Sharing on every network the computer can reach must not be reachable without a password, and the settings UI (#151) needs the credential surface to exist.What this does
word+ three digits (2–9) + one URL-safe symbol (! * - = ~ $) +word, e.g.jaw295=art— sized for the online-only attacker (network round trip + a deliberately slow verify), typeable on an e-reader, and displayed once at generation (the plaintext is never stored). Symbols are URL-safe because readers paste credentials intohttp://user:pass@host/logins;# ? @ % +get mangled by URL parsing.BindPolicy.allow_globalnow derives from credentials configured — AllInterfaces without credentials →AuthRequired. Clearing credentials while sharing is active stops sharing immediately; any credential change while sharing is not Stopped stops sharing (a Waiting poll or in-flight start must not bind with stale credentials).Testing
56 tests pass. New: the gate (
all_interfaces_requires_credentials_until_auth_allows_it), clearing-credentials-stops-sharing, credential-change-while-waiting stops the poll, generated-password shape/charset/blocklist, credential store persistence/permissions/idempotent-clear, and the auth middleware suite (parser, challenge withcharset=UTF-8, cache bounding, disabled-bypass). All state-machine and bind tests from #160 unchanged and green.Notes