From e047b98bedd164a850d5851d40d68a65713274ec Mon Sep 17 00:00:00 2001 From: matthieu Date: Sun, 15 Mar 2026 08:48:10 +0100 Subject: [PATCH] docs : update BookStack spec with review fixes Address critical and important review findings: search-in-shelf algorithm detail, unique constraint, TokenEncryptor refactoring, pagination specifics, and technical notes. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../2026-03-15-bookstack-connector-design.md | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/docs/superpowers/specs/2026-03-15-bookstack-connector-design.md b/docs/superpowers/specs/2026-03-15-bookstack-connector-design.md index 501eba1..b59b94b 100644 --- a/docs/superpowers/specs/2026-03-15-bookstack-connector-design.md +++ b/docs/superpowers/specs/2026-03-15-bookstack-connector-design.md @@ -81,8 +81,12 @@ class BookStackApiService - Auth : header `Authorization: Token {tokenId}:{tokenSecret}` - Timeout : 10 secondes - `testConnection()` : GET `/api/docs.json` -- `listShelves()` : GET `/api/shelves` (paginé, récupère toutes les pages) -- `searchInShelf()` : GET `/api/search?query={query}+{type:page|book}` puis filtre côté serveur par shelf ID +- `listShelves()` : GET `/api/shelves` (paginé via `count`/`offset`, pas `page`/`limit` — spécificité BookStack) +- `searchInShelf()` : algorithme en 3 étapes : + 1. GET `/api/shelves/{shelfId}` → récupère la liste des `books` de l'étagère (IDs) + 2. GET `/api/search?query={query} {type:page|book}` → recherche globale (espace entre query et filtre type, BookStack syntax) + 3. Filtre côté PHP : pour les **books**, vérifie que `book.id` est dans la liste de l'étagère ; pour les **pages**, vérifie que `page.book_id` est dans la liste. Exclut les résultats `chapter` et `bookshelf`. + - Note : la liste des books de l'étagère peut être cachée en mémoire pour la durée de la requête. - `getPage()` : GET `/api/pages/{id}` - `getBook()` : GET `/api/books/{id}` @@ -170,6 +174,7 @@ CREATE TABLE task_bookstack_link ( ); CREATE INDEX IDX_task_bookstack_link_task_id ON task_bookstack_link (task_id); +CREATE UNIQUE INDEX UNIQ_task_bookstack_link ON task_bookstack_link (task_id, bookstack_id, bookstack_type); ALTER TABLE project ADD bookstack_shelf_id INT DEFAULT NULL; ALTER TABLE project ADD bookstack_shelf_name VARCHAR(255) DEFAULT NULL; @@ -177,7 +182,14 @@ ALTER TABLE project ADD bookstack_shelf_name VARCHAR(255) DEFAULT NULL; ### Variable d'environnement -Réutilise la même clé de chiffrement que Gitea (`TokenEncryptor` existant) — pas besoin d'une nouvelle clé. +Prérequis : renommer `GITEA_ENCRYPTION_KEY` en `ENCRYPTION_KEY` (générique) dans `TokenEncryptor`, `.env`, et `docker/.env.docker`. Mettre à jour le message d'erreur dans `TokenEncryptor`. Cela permet de réutiliser le même service pour chiffrer les tokens BookStack (deux appels `encrypt()`/`decrypt()` : un pour tokenId, un pour tokenSecret). + +### Notes techniques + +- `BookStackTestConnectionProvider` implémente à la fois `ProviderInterface` et `ProcessorInterface` (même pattern que `GiteaTestConnectionProvider`) +- Les endpoints collection du frontend utilisent `extractHydraMembers()` pour extraire les résultats des réponses Hydra +- Les titres/URLs stockés dans `TaskBookStackLink` sont des snapshots au moment du lien — pas de rafraîchissement automatique (intentionnel) +- Le select étagère dans `ProjectDrawer` n'est affiché que pour les admins (endpoint `ROLE_ADMIN`) ## Frontend @@ -275,6 +287,14 @@ migrations/VersionXXXX.php ``` src/Entity/Project.php (ajout bookstackShelfId, bookstackShelfName) +src/Service/TokenEncryptor.php (renommage GITEA_ENCRYPTION_KEY → ENCRYPTION_KEY) +``` + +### Config — Fichiers modifiés + +``` +.env (renommage GITEA_ENCRYPTION_KEY → ENCRYPTION_KEY) +docker/.env.docker (idem) ``` ### Frontend — Nouveaux fichiers