Skip to content

feat: OPDS v1 server — acquisition feeds, Basic auth, interface-scoped listeners - #142

Closed
phildenhoff wants to merge 8 commits into
mainfrom
stack-2-opds-runtime
Closed

phildenhoff wants to merge 8 commits into
mainfrom
stack-2-opds-runtime

Conversation

@phildenhoff

@phildenhoff phildenhoff commented Sep 17, 2026

Copy link
Copy Markdown
Member

CDL-27: let OPDS reader apps (KOReader, Moon+, …) browse and download from the active Calibre library over the local network, on the user's terms — a selected interface or all ordinary local networks, never more.

What changed

New citadel-opds crate (Tauri-independent, so the headless host can reuse it):

  • OPDS 1.x Atom catalog — root navigation, all/recent/unread, author/series/tag facets, search via OpenSearch, paginated feeds
  • Acquisition endpoints stream book files (range requests, 416 handling) and covers, resolved by opaque book IDs through libcalibre; client-supplied strings never reach a path
  • HTTP Basic auth that stores only an Argon2id verifier (0600 credential file), with a rejection cache keyed on an HMAC of the header and constant-time padding so failures are indistinguishable by timing
  • Listeners bind concrete usable addresses (IPv4, global/ULA IPv6) on the selected interfaces and reconcile on a monitor loop — fail closed to Waiting when the interface disappears, never widen to wildcard

Plus citadel-server, a headless host binary for packaged QA, and the Tauri wiring: Sharing settings pane, commands, and state.

Reviewer focus

  • auth.rs — the padding/target-duration logic is subtle; it's unit-tested but a second pair of eyes helps
  • service.rs — the listener reconciliation loop (apply_plan/monitor_service) is where the fail-closed guarantees live
  • network.rs — interface classification is product policy, not a security boundary (per ADR 0002)

Validation

57 crate tests (feeds, auth middleware, listener lifecycle, real-library loopback). Packaged smoke test against the signed nightly — IPv4 + IPv6 200s on every route, 401s with WWW-Authenticate on bad credentials — recorded in docs/opds-validation.md (that doc lands later in this stack).

Stack

#142 (this) → #143 genres → #144 hardening → #137 docs.

@phildenhoff
phildenhoff added this pull request to stack #145 September 17, 2026 18:59
@phildenhoff phildenhoff changed the title stack 2 opds runtime feat: OPDS v1 server — acquisition feeds, Basic auth, interface-scoped listeners Sep 17, 2026
@github-actions

Copy link
Copy Markdown

libcalibre Test Coverage Report

Overall coverage: 83.69%

📊 Download HTML Report

Coverage breakdown available in the artifacts.

@github-actions

Copy link
Copy Markdown

libcalibre Test Coverage Report

Overall coverage: 83.69%

📊 Download HTML Report

Coverage breakdown available in the artifacts.

@github-actions

Copy link
Copy Markdown

libcalibre Test Coverage Report

Overall coverage: 83.69%

📊 Download HTML Report

Coverage breakdown available in the artifacts.

@github-actions

Copy link
Copy Markdown

libcalibre Test Coverage Report

Overall coverage: 83.69%

📊 Download HTML Report

Coverage breakdown available in the artifacts.

@github-actions

Copy link
Copy Markdown

libcalibre Test Coverage Report

Overall coverage: 83.69%

📊 Download HTML Report

Coverage breakdown available in the artifacts.

@github-actions

Copy link
Copy Markdown

libcalibre Test Coverage Report

Overall coverage: 83.69%

📊 Download HTML Report

Coverage breakdown available in the artifacts.

Base automatically changed from stack-1-toolchain to main September 17, 2026 22:50
@github-actions

Copy link
Copy Markdown

libcalibre Test Coverage Report

Overall coverage: 83.69%

📊 Download HTML Report

Coverage breakdown available in the artifacts.

@phildenhoff

Copy link
Copy Markdown
Member Author

Superseded: the OPDS v1 stack was restructured for reviewability - see stack #156 (#146#155). This layer's content is absorbed into the new stack.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant