diff --git a/Cargo.lock b/Cargo.lock index 8771dfe..8a942ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1918,7 +1918,7 @@ dependencies = [ [[package]] name = "mybibli" -version = "1.18.0" +version = "1.19.0" dependencies = [ "argon2", "askama", diff --git a/Cargo.toml b/Cargo.toml index 5f2c792..878fe69 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mybibli" -version = "1.18.0" +version = "1.19.0" edition = "2024" license = "AGPL-3.0-or-later" diff --git a/README.md b/README.md index eb3f1fa..832f332 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [](https://github.com/guycorbaz/mybibli/releases) [](LICENSE) [](https://hub.docker.com/r/gcorbaz/mybibli) -[](https://hub.docker.com/r/gcorbaz/mybibli/tags) +[](https://hub.docker.com/r/gcorbaz/mybibli/tags) [](https://github.com/guycorbaz/mybibli/issues) [](https://github.com/guycorbaz/mybibli/commits/main) [](https://github.com/guycorbaz/mybibli/stargazers) @@ -17,7 +17,7 @@ > 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 @@ -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):
@@ -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.
diff --git a/ROADMAP.md b/ROADMAP.md
index ec0f0b3..78aae81 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -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.
diff --git a/_bmad-output/implementation-artifacts/sprint-status.yaml b/_bmad-output/implementation-artifacts/sprint-status.yaml
index de8daef..bca23a8 100644
--- a/_bmad-output/implementation-artifacts/sprint-status.yaml
+++ b/_bmad-output/implementation-artifacts/sprint-status.yaml
@@ -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
diff --git a/docs/dockerhub-overview.md b/docs/dockerhub-overview.md
index 1f649e2..6fbece9 100644
--- a/docs/dockerhub-overview.md
+++ b/docs/dockerhub-overview.md
@@ -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
diff --git a/docs/manual/en/01-installation.tex b/docs/manual/en/01-installation.tex
index b54a0b2..925601b 100644
--- a/docs/manual/en/01-installation.tex
+++ b/docs/manual/en/01-installation.tex
@@ -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}
diff --git a/docs/manual/en/08-upgrade-migration.tex b/docs/manual/en/08-upgrade-migration.tex
index c93fb5d..bdf1335 100644
--- a/docs/manual/en/08-upgrade-migration.tex
+++ b/docs/manual/en/08-upgrade-migration.tex
@@ -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,
diff --git a/docs/manual/en/main.tex b/docs/manual/en/main.tex
index 1434c10..5261396 100644
--- a/docs/manual/en/main.tex
+++ b/docs/manual/en/main.tex
@@ -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}
diff --git a/docs/manual/fr/01-installation.tex b/docs/manual/fr/01-installation.tex
index 12887a1..dc03ce8 100644
--- a/docs/manual/fr/01-installation.tex
+++ b/docs/manual/fr/01-installation.tex
@@ -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}
diff --git a/docs/manual/fr/08-upgrade-migration.tex b/docs/manual/fr/08-upgrade-migration.tex
index 539d7d4..08ba17e 100644
--- a/docs/manual/fr/08-upgrade-migration.tex
+++ b/docs/manual/fr/08-upgrade-migration.tex
@@ -141,13 +141,83 @@ \section{Lire les notes de version}
\item un paragraphe résumant le changement ;
\item l'impact migration (aucun / additif / breaking) ;
\item un lien vers le diff contre le tag précédent ;
- \item les PDF de ce manuel (anglais + français) en pièce jointe
- une fois le build PDF de release câblé dans la CI.
+ \item ce manuel en PDF, anglais et français, joint à la publication
+ elle-même --- l'exemplaire qui correspond à cette version.
\end{itemize}
Lisez les notes avant de mettre à jour. Les breaking changes
portent une étiquette \emph{Breaking} bien visible.
+\section{Nouveautés de la 1.19.0}\label{sec:whats-new-1.19.0}
+
+La version 1.19.0 est une version mineure sur la 1.18.0.
+\emph{Aucune migration} --- on récupère l'image, on redémarre, c'est
+tout. Elle porte les trois demandes de changement issues d'une revue de
+sécurité menée sur le code de la 1.18.0, ainsi que le travail de
+documentation que cette revue a rendu nécessaire.
+
+\begin{itemize}
+ \item \textbf{\#478 \string— la corbeille restaure vraiment.} Le
+ panneau Corbeille affichait un bouton \emph{Restaurer} depuis la
+ 1.2.0. Il pointait vers une adresse à laquelle l'application n'a
+ jamais répondu : cliquer dessus ne faisait rien du tout --- ni
+ restauration, ni message d'erreur, rien. Si vous avez un jour
+ supprimé un titre par erreur, ouvert la corbeille et trouvé ce
+ bouton inerte, il l'était.
+
+ Il fonctionne. Une suppression malencontreuse se rattrape, et
+ l'élément revient là où il était. Quand les relations de la
+ notice ont changé pendant son séjour à la corbeille --- un titre
+ réaffecté à une autre série, par exemple --- mybibli demande
+ confirmation avant d'effacer le lien devenu caduc, au lieu de
+ trancher à votre place.
+
+ \item \textbf{\#480 \string— les comptes de développement ne laissent
+ plus de trace.} Une installation neuve a toujours embarqué deux
+ comptes de développement, \texttt{admin/admin} et
+ \texttt{librarian/librarian}, que l'application retire au premier
+ démarrage pour que l'assistant d'installation puisse s'exécuter
+ (section~\ref{sec:upgrade-1.1.0}). « Retirer » voulait dire
+ jusqu'ici \emph{mettre à la corbeille} : les lignes y restaient
+ trente jours, mots de passe intacts --- des mots de passe publiés
+ dans la politique de sécurité du projet. Avec le bouton
+ Restaurer de \#478 devenu fonctionnel, un administrateur aurait
+ pu les restaurer de bonne foi et rendre les clés de la maison.
+
+ Ils sont désormais supprimés pour de bon, avec la session de
+ développement pré-enregistrée. Une instance qui monte depuis la
+ 1.18.0 ou antérieure nettoie ce que son ancien démarrage avait
+ laissé, dès le premier lancement après la mise à jour. Rien ne
+ change pour qui a changé le mot de passe seedé : ce compte-là est
+ laissé tranquille, comme il l'a toujours été.
+
+ \item \textbf{\#479 \string— une couverture ne peut plus épuiser le
+ serveur.} Les fichiers de couverture étaient déjà plafonnés à
+ 10~Mio. Cela plafonne le \emph{fichier}, ce qui ne dit rien de la
+ mémoire : quelques centaines d'octets d'image peuvent décrire
+ légitimement une image de plusieurs gigaoctets, et la décoder
+ aurait fait tomber le conteneur --- avec toutes les requêtes en
+ cours. Le décodeur travaille maintenant sous un budget fixe et
+ refuse ce qui le dépasse, en le disant. Une photo prise avec
+ n'importe quel téléphone passe toujours.
+
+ Cela compte surtout là où les images ne sont pas les vôtres :
+ les couvertures téléchargées auprès des bibliothèques et
+ catalogues de la chaîne de métadonnées.
+\end{itemize}
+
+\begin{note}
+\textbf{Rien à faire à la mise à jour.} Aucun changement de schéma,
+aucun changement de configuration, aucune étape manuelle. Prenez votre
+sauvegarde habituelle par habitude plutôt que par nécessité.
+\end{note}
+
+Cette version met aussi la documentation en accord avec le logiciel :
+K10plus dans le chapitre des fournisseurs, le flux d'audit des rayons
+décrit tel qu'il fonctionne réellement, des sections de référence pour
+les étiquettes de gestion et pour la valorisation, et une référence des
+routes qui les couvre toutes au lieu de la moitié.
+
\section{Nouveautés de la 1.18.0}\label{sec:whats-new-1.18.0}
La version 1.18.0 est une mineure sur la 1.17.0. \emph{Une migration
diff --git a/docs/manual/fr/main.tex b/docs/manual/fr/main.tex
index 84ac9c7..85985fd 100644
--- a/docs/manual/fr/main.tex
+++ b/docs/manual/fr/main.tex
@@ -98,7 +98,7 @@
% ---- Métadonnées du document ---------------------------------------
\title{\Huge\bfseries mybibli\\[6pt]\Large Manuel utilisateur}
\author{Les auteurs de mybibli\\\small \texttt{https://github.com/guycorbaz/mybibli}}
-\date{Version 1.18.0 — \today}
+\date{Version 1.19.0 — \today}
% =====================================================================
\begin{document}
diff --git a/docs/manual/mybibli-manual-en.pdf b/docs/manual/mybibli-manual-en.pdf
index 5d9c751..aced77a 100644
Binary files a/docs/manual/mybibli-manual-en.pdf and b/docs/manual/mybibli-manual-en.pdf differ
diff --git a/docs/manual/mybibli-manual-fr.pdf b/docs/manual/mybibli-manual-fr.pdf
index 26c879b..854f065 100644
Binary files a/docs/manual/mybibli-manual-fr.pdf and b/docs/manual/mybibli-manual-fr.pdf differ
diff --git a/website/about.html b/website/about.html
index 1832fa3..531406a 100644
--- a/website/about.html
+++ b/website/about.html
@@ -63,7 +63,7 @@
mybibli
- v1.18.0
+ v1.19.0