Skip to content

feat: add the web interface for works, libraries, and copies - #5

Merged
nkboedecker merged 4 commits into
mainfrom
claude/phase-3
Nov 2, 2026
Merged

nkboedecker merged 4 commits into
mainfrom
claude/phase-3

Conversation

@nkboedecker

@nkboedecker nkboedecker commented Nov 2, 2026 •

Copy link
Copy Markdown
Owner

Summary

Add server-rendered pages for Phase 3, as thin layers over the existing service functions, so a page can't do anything the API can't. Each page offers only what the policy layer allows, and the service layer checks again on every request.

  • Browser sign-in and sign-out, with cookie sessions stored by hash and a CSRF token on every form.
  • Pages to list, view, add, edit, and delete works, libraries, and copies, and to add an edition to a work.
  • Library members now show by name, through a new display_name field in the API's members response.

Phase 3 is not finished. Tags, shelves, reading status, ratings, reviews, notes, loa still to come.

Checklist

  • The PR title is a Conventional Commit.
  • Tests are added, including an authorization-denied test for each endpoint.
  • Docs are updated.
  • CHANGELOG.md has a line under Unreleased.
  • Commits are signed and have a Signed-off-by line.

Breaking changes

None. The added display_name field in the members response is additive.

Security-sensitive areas

  • Authentication: browser sessions, the sign-in form's CSRF protection, and security headers.
  • Authorization: role checks on every new page. Outsiders get the same page for a hidden record as for a missing one.

AI assistance

Claude Code wrote the code. The maintainer reviewed and made the commits.

Add server-rendered pages for Phase 3, starting with sign-in and a
searchable, paged works list, built as a thin layer over the existing
service functions so it can't do anything the API can't.

- Add cookie-based web sessions, stored by hash, with a 14-day
  lifetime and a synchronizer CSRF token per session.
- Use a double-submit cookie for the sign-in form itself, since it
  runs before a session exists.
- Split accounts.login into sign_in and issue_login_token so the UI
  can authenticate without issuing a bearer token.
- Add Jinja2 templates, static assets, and security headers
  (CSP, no-sniff, no-store) for all non-API routes.
- Add a @ui_route decorator and parity tests that confirm each page
  declares and calls the same service function as its matching API
  operation.

Assisted-by: Claude Code
Signed-off-by: Natalie Boedecker <git@boedecker.dev>
Move the works list route into a new works module and add detail,
create, edit, and delete pages, reusing the existing catalog service
functions so the UI still can't do anything the API can't.

- Show editing links to non-guests and the delete form only to admins,
  while leaving the actual authorization to the policy layer.
- Add form helpers that trim text to None for blank optional fields
  and turn validation errors into field-level messages without
  echoing submitted values back verbatim.
- Require a ticked confirmation checkbox before deleting a work.

Assisted-by: Claude Code
Signed-off-by: Natalie Boedecker <git@boedecker.dev>
Let people manage libraries and their copies from the browser, as thin
layers over the existing service functions, so a page offers only what
the policy layer allows and the server still checks every request.

- Add pages to list, view, create, edit, and delete a library.
- Add pages to view, add, edit, and delete a copy, and to add an
  edition to a work, because a copy is added from an edition.
- Show each library's members by name, and add display_name to the
  members response in the API.
- Add a service function that returns the user's role in each library.
- Add shared test helpers for signed-in users and a sample library.

Assisted-by: Claude Code
Signed-off-by: Natalie Boedecker <git@boedecker.dev>
@nkboedecker nkboedecker changed the title feat: build the web interface foundation feat: add the web interface for works, libraries, and copies Nov 2, 2026
@nkboedecker
nkboedecker marked this pull request as ready for review November 2, 2026 13:06
@nkboedecker
nkboedecker merged commit 2daa418 into main Nov 2, 2026
11 checks passed
@nkboedecker
nkboedecker deleted the claude/phase-3 branch November 2, 2026 13:06
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