Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mybibli"
version = "1.18.0"
version = "1.19.0"
edition = "2024"
license = "AGPL-3.0-or-later"

Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@
[![Version](https://img.shields.io/github/v/tag/guycorbaz/mybibli?label=version&sort=semver&color=blue)](https://github.com/guycorbaz/mybibli/releases)
[![License: AGPL v3](https://img.shields.io/badge/license-AGPL--3.0--or--later-lightgrey)](LICENSE)
[![Docker Pulls](https://img.shields.io/docker/pulls/gcorbaz/mybibli?logo=docker&label=docker%20pulls)](https://hub.docker.com/r/gcorbaz/mybibli)
[![Docker Image Size](https://img.shields.io/docker/image-size/gcorbaz/mybibli/1.18.0?logo=docker&label=image%20size)](https://hub.docker.com/r/gcorbaz/mybibli/tags)
[![Docker Image Size](https://img.shields.io/docker/image-size/gcorbaz/mybibli/1.19.0?logo=docker&label=image%20size)](https://hub.docker.com/r/gcorbaz/mybibli/tags)
[![Open Issues](https://img.shields.io/github/issues/guycorbaz/mybibli?logo=github)](https://github.com/guycorbaz/mybibli/issues)
[![Last Commit](https://img.shields.io/github/last-commit/guycorbaz/mybibli/main?logo=github)](https://github.com/guycorbaz/mybibli/commits/main)
[![Stars](https://img.shields.io/github/stars/guycorbaz/mybibli?logo=github&style=flat)](https://github.com/guycorbaz/mybibli/stargazers)
[![Rust](https://img.shields.io/badge/rust-2024-orange?logo=rust)](https://www.rust-lang.org/)

> Personal library cataloging for home collectors.

**Status:** in production since v1.1.1 (2026-05-14). 10 epics shipped; project is in GH-issue-driven polish mode. Current release: `v1.18.0`. Pre-built images on Docker Hub at [`gcorbaz/mybibli`](https://hub.docker.com/r/gcorbaz/mybibli). See [ROADMAP.md](ROADMAP.md) for what's coming next.
**Status:** in production since v1.1.1 (2026-05-14). 10 epics shipped; project is in GH-issue-driven polish mode. Current release: `v1.19.0`. Pre-built images on Docker Hub at [`gcorbaz/mybibli`](https://hub.docker.com/r/gcorbaz/mybibli). See [ROADMAP.md](ROADMAP.md) for what's coming next.

## What it is

Expand All @@ -38,7 +38,7 @@ Built for collectors who want more than a spreadsheet:

## Screenshots

Live production install (`v1.18.0`, household NAS, 140+ volumes catalogued and growing):
Live production install (`v1.19.0`, household NAS, 140+ volumes catalogued and growing):

<p align="center">
<img src="docs/screenshots/01-home-desktop.png" alt="mybibli home page — search bar, genre filters, dashboard counters, and a recent-additions strip with cover thumbnails." width="780">
Expand Down Expand Up @@ -411,7 +411,7 @@ Versioned under `_bmad-output/`:

mybibli has been live in production since v1.1.1 (2026-05-14) on the household NAS that drove the project. v1.0.0 shipped after Epic 9 close (2026-05-10) as the first production-ready build; v1.1.0 added the seed-gate + audit trio (mandatory install floor — see "Installation notes" above); the themed minors v1.2 through v1.8 then delivered the original feature roadmap (browse & find, wishlist, HTTP API, valuation & stats, catalog hygiene, de/it locales + runtime logging, cover handling), each followed by production-driven patch trains. Since v1.8 the project runs in GH-issue-driven polish mode.

**Current release: `v1.18.0`** (2026-08-18) — management labels ([#443](https://github.com/guycorbaz/mybibli/issues/443)): an admin-defined vocabulary a librarian applies to titles *and* volumes from one shared list, with a `/labels` page that drills down to what carries each label. Labels stay internal — a visitor never sees them. One additive migration; the navigation bar now switches to its menu below 1024px, because the new entry no longer fitted on a tablet.
**Current release: `v1.19.0`** (2026-09-11) — the three change requests of a security review run against the 1.18.0 code, and the documentation work it made necessary. [#478](https://github.com/guycorbaz/mybibli/issues/478): the Trash panel's Restore button, which had pointed at an unregistered route since 1.2.0 and silently did nothing, now restores. [#480](https://github.com/guycorbaz/mybibli/issues/480): the seeded development accounts are deleted outright at first boot instead of being parked in the Trash with their published passwords intact — which #478 would otherwise have made restorable. [#479](https://github.com/guycorbaz/mybibli/issues/479): a cover decode runs under a fixed allocation budget, so an image that is small on the wire and enormous once decoded is refused rather than taking the container down. **No migration.** The preceding release, `v1.18.0` (2026-08-18), added management labels ([#443](https://github.com/guycorbaz/mybibli/issues/443)).

**Release-by-release history lives in [ROADMAP.md](ROADMAP.md)** — one section per version, and the canonical copy. It is deliberately not repeated here: the [GitHub releases page](https://github.com/guycorbaz/mybibli/releases) carries the same notes as published artifacts, chapter 8 of the [user manual](docs/manual/) carries them offline, and the [website roadmap](https://guycorbaz.github.io/mybibli/roadmap.html) tells the same story for a different audience. See [`epics.md`](_bmad-output/planning-artifacts/epics.md) for the epic breakdown and [`sprint-status.yaml`](_bmad-output/implementation-artifacts/sprint-status.yaml) for the story-by-story state.

Expand Down
68 changes: 51 additions & 17 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,28 +32,62 @@ mybibli follows [Semantic Versioning](https://semver.org/) 2.0.

## Now

**Current stable: [`v1.18.0`](https://github.com/guycorbaz/mybibli/releases/tag/v1.18.0)**
(2026-08-18) — management labels ([#443](https://github.com/guycorbaz/mybibli/issues/443)):
an admin-defined vocabulary a librarian applies to titles *and* volumes
from one shared list, with a `/labels` page of its own. One additive
migration. The section below has the detail; every release before it has
its own section further down, and this is the file that carries them —
the README quotes only the current release, and the website tells the
**Current stable: [`v1.19.0`](https://github.com/guycorbaz/mybibli/releases/tag/v1.19.0)**
(2026-09-11) — the three change requests of a security review run against
the 1.18.0 code, and the documentation work it made necessary. **No
migration.** The section below has the detail; every release before it
has its own section further down, and this is the file that carries them
— the README quotes only the current release, and the website tells the
same story for a different audience.

**Merged on `main`, not yet released** — the three change requests from
the 2026-08-18 security review:
[#480](https://github.com/guycorbaz/mybibli/issues/480) the seed gate
hard-deletes its artefacts instead of parking them in the Trash,
[#478](https://github.com/guycorbaz/mybibli/issues/478) the Trash panel's
Restore button reaches a route that exists, and
[#479](https://github.com/guycorbaz/mybibli/issues/479) a cover decode
runs under an allocation budget. No migration. The version they ship
under is not decided yet.

**Open issues: none.** The tracker has been empty since the review
closed. New work starts from a fresh report.

## v1.19.0 — the security review *(shipped)*

Shipped 2026-09-11. Three change requests, **no migration**, one
documentation sweep. The review that produced them was run on 2026-08-18
against the v1.18.0 code, with a stated attacker model: local network
plus a private tunnel, never a port forwarded to the internet.

- [#478](https://github.com/guycorbaz/mybibli/issues/478) — **the Trash
panel's Restore button reaches a route that exists.** It had rendered
a link to `/admin/trash/{table}/{id}/restore` since story 8-6; that
route was never registered, so every click returned a 404 that HTMX
does not swap — no restore, no error, nothing at all. The route is
registered as POST rather than the GET the button emitted, so it rides
the CSRF layer; where restoring would clash with a relationship formed
since the deletion, a modal names the conflict before clearing it.
The suite had stayed green throughout because `TrashService::restore`
was only ever called from `#[cfg(test)]`.
- [#480](https://github.com/guycorbaz/mybibli/issues/480) — **the seed
gate hard-deletes its artefacts.** It had soft-deleted the seeded
`admin` / `librarian` rows, leaving them in the Trash for thirty days
with the passwords published in `SECURITY.md` intact, plus a session
row whose token is in the git history. Harmless while Restore was
broken; #478 is what made it urgent, and the two had to land in that
order. Upgrading instances purge whatever their old gate left behind.
- [#479](https://github.com/guycorbaz/mybibli/issues/479) — **a cover
decode runs under an allocation budget.** The 10 MiB cap bounded the
compressed bytes, not the memory: a few hundred bytes of PNG can
declare gigabytes of RGBA, and the OOM killer would take the container
down with every request in flight. 64 MiB and a 10 000 px per-side
ceiling; the download side now streams with a hard cap instead of
trusting `Content-Length`. The path that matters is the provider
chain, where the bytes are not ours.

Also in this release: the CI actions are pinned by commit SHA with a
daily RustSec advisory scan ([#481](https://github.com/guycorbaz/mybibli/pull/481)),
the network posture is stated where an operator will actually read it
([#482](https://github.com/guycorbaz/mybibli/pull/482)), the
community-health files landed
([#477](https://github.com/guycorbaz/mybibli/pull/477)), and a
documentation audit closed fourteen findings across every surface
([#487](https://github.com/guycorbaz/mybibli/pull/487)) — K10plus finally
documented, the shelf-audit chapter describing the feature that shipped
three releases ago rather than a workaround, a route reference covering
all 148 routes instead of 82.

## v1.18.0 — management labels *(shipped)*

Shipped 2026-08-18. One issue, **one additive migration**, three reviewed tranches.
Expand Down
2 changes: 1 addition & 1 deletion _bmad-output/implementation-artifacts/sprint-status.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# generated: 2026-03-29
# last_updated: 2026-08-18 (v1.18.0 — minor on v1.17.0. #443 management labels: an admin-defined vocabulary applied to titles AND volumes from one shared list, with a /labels page and drill-down; Librarian+ only. One additive migration (labels, title_labels, volume_labels). Nav bar switches to the menu at lg instead of md. Release history: ROADMAP.md)
# last_updated: 2026-09-11 (v1.19.0 — minor on v1.18.0, no migration. The three change requests of the 2026-08-18 security review: #478 the Trash Restore button reaches a route that exists, #480 the seeded dev accounts are hard-deleted at first boot instead of parked in the Trash, #479 a cover decode runs under an allocation budget. Plus a documentation audit across every surface.)
# project: mybibli
# project_key: NOKEY
# tracking_system: file-system
Expand Down
2 changes: 1 addition & 1 deletion docs/dockerhub-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ Both `mybibli-covers` and `mybibli-logs` can be swapped from Docker-named volume
## Tags

- `:latest` — tracks the highest semver release tag.
- `:1.18.0` (current), `:1.17.0`, `:1.16.0` and every prior release tag back to `:1.1.0` — specific releases. Pin to a specific tag in production-style setups; tracking `:latest` is reasonable for homelab. The full tag list is on the [Tags tab](https://hub.docker.com/r/gcorbaz/mybibli/tags).
- `:1.19.0` (current), `:1.18.0`, `:1.17.0` and every prior release tag back to `:1.1.0` — specific releases. Pin to a specific tag in production-style setups; tracking `:latest` is reasonable for homelab. The full tag list is on the [Tags tab](https://hub.docker.com/r/gcorbaz/mybibli/tags).
- **No `:dev`, no `:main`, no `:beta` published** — tagged releases only.

## Docs
Expand Down
4 changes: 2 additions & 2 deletions docs/manual/en/01-installation.tex
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ \subsection*{1. Get the compose file and \texttt{.env}}

\begin{lstlisting}
mkdir -p /srv/mybibli && cd /srv/mybibli
curl -O https://raw.githubusercontent.com/guycorbaz/mybibli/v1.18.0/docker-compose.yml
curl -O https://raw.githubusercontent.com/guycorbaz/mybibli/v1.18.0/.env.example
curl -O https://raw.githubusercontent.com/guycorbaz/mybibli/v1.19.0/docker-compose.yml
curl -O https://raw.githubusercontent.com/guycorbaz/mybibli/v1.19.0/.env.example
cp .env.example .env
\end{lstlisting}

Expand Down
70 changes: 68 additions & 2 deletions docs/manual/en/08-upgrade-migration.tex
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,79 @@ \section{Reading the release notes}
\item a one-paragraph summary of the change set;
\item the migration impact (none / additive / breaking);
\item a link to the diff against the previous tag;
\item attached PDFs of this manual (English + French) once the
release-time PDF build is wired into CI.
\item this manual as PDF, English and French, attached to the
release itself --- the copy that matches that exact version.
\end{itemize}

Read the notes before upgrading. Breaking changes are tagged with a
prominent \emph{Breaking} label.

\section{What's new in 1.19.0}\label{sec:whats-new-1.19.0}

Version 1.19.0 is a minor release on 1.18.0. \emph{No migration} ---
pull the image, restart, done. It carries the three change requests of
a security review conducted on the 1.18.0 code, plus the documentation
work that review made necessary.

\begin{itemize}
\item \textbf{\#478 \string— the Trash can actually restore now.}
The Trash panel had shown a \emph{Restore} button since 1.2.0.
It pointed at an address the application never answered on, so
clicking it did nothing at all: no restore, no error message,
nothing. If you ever deleted a title by accident, opened the
Trash and wondered why the button seemed dead --- it was.

It works. Deleted something by mistake, restore it, and it
returns where it was. When the record's relationships changed
while it sat in the trash --- a title reassigned to another
series, say --- mybibli asks before clearing the stale link
rather than deciding for you.

\item \textbf{\#480 \string— the development accounts leave no
trace.} A fresh install has always shipped two development
accounts, \texttt{admin/admin} and
\texttt{librarian/librarian}, which the application removes at
first boot so the setup wizard can run (section
\ref{sec:upgrade-1.1.0}). Removed, until now, meant
\emph{moved to the Trash}: the rows sat there for thirty days
with their passwords intact --- passwords published in this
project's own security policy. With \#478 making the Restore
button work, an administrator could have restored them in good
faith and handed the house keys back.

They are now deleted outright, along with the pre-set
development session. An instance upgrading from 1.18.0 or
earlier clears whatever its old boot left behind, on the first
start after the upgrade. Nothing changes for an operator who
rotated the seeded password: that account is left alone, as it
always was.

\item \textbf{\#479 \string— a cover image cannot exhaust the
server.} Cover files were already capped at 10~MiB. That caps
the \emph{file}, which says nothing about memory: a few hundred
bytes of image can legitimately describe a picture of several
gigabytes, and decoding it would have taken the container down
--- along with every request in flight. The decoder now works
under a fixed budget and refuses anything beyond it with a
message saying so. A photograph from any phone still passes.

This matters most where the images are not yours: covers
downloaded from the libraries and catalogues in the metadata
chain.
\end{itemize}

\begin{note}
\textbf{Nothing to do on upgrade.} No schema change, no configuration
change, no manual step. Take your usual backup out of habit rather than
necessity.
\end{note}

This release also brings the documentation in line with the software:
K10plus in the provider chapter, the shelf-audit workflow described as
it actually works, reference sections for management labels and for
valuation, and a route reference that covers every route rather than
half of them.

\section{What's new in 1.18.0}\label{sec:whats-new-1.18.0}

Version 1.18.0 is a minor release on 1.17.0. \emph{One automatic,
Expand Down
2 changes: 1 addition & 1 deletion docs/manual/en/main.tex
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
% ---- Document metadata ----------------------------------------------
\title{\Huge\bfseries mybibli\\[6pt]\Large User Manual}
\author{The mybibli authors\\\small \texttt{https://github.com/guycorbaz/mybibli}}
\date{Version 1.18.0 — \today}
\date{Version 1.19.0 — \today}

% =====================================================================
\begin{document}
Expand Down
4 changes: 2 additions & 2 deletions docs/manual/fr/01-installation.tex
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ \subsection*{1. Récupérer le fichier compose et le \texttt{.env}}

\begin{lstlisting}
mkdir -p /srv/mybibli && cd /srv/mybibli
curl -O https://raw.githubusercontent.com/guycorbaz/mybibli/v1.18.0/docker-compose.yml
curl -O https://raw.githubusercontent.com/guycorbaz/mybibli/v1.18.0/.env.example
curl -O https://raw.githubusercontent.com/guycorbaz/mybibli/v1.19.0/docker-compose.yml
curl -O https://raw.githubusercontent.com/guycorbaz/mybibli/v1.19.0/.env.example
cp .env.example .env
\end{lstlisting}

Expand Down
Loading