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) <noreply@anthropic.com>
This commit is contained in:
2026-03-15 08:48:10 +01:00
parent 758c9f6fbd
commit e047b98bed

View File

@@ -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