13. Les fichiers
Une bibliothèque reçoit des papiers : bons de livraison, factures du fournisseur, cartes de membre scannées. Le module n’a pas à inventer une table de pièces jointes : Kewos a un Drive, versionné, rattachable à n’importe quelle fiche, avec ses droits.
Cette étape dépose un bon de livraison, l’attache à une œuvre du catalogue, le corrige, le jette et le repêche.
La règle
Un module n’écrit jamais sa propre table de fichiers. Il appelle kewos/drive, en Python
ou par l’API. Ce que ça vous donne, et que vous n’écrirez pas : le versionnement, l’adressage
par contenu, la corbeille, les partages, les liens publics à durée de vie, l’audit.
Deux choses valent la peine d’être comprises avant d’écrire une ligne.
Un document a une identité stable et des versions immuables. kws_doc porte le nom, le
propriétaire, les liens. Chaque contenu déposé devient une kws_doc_version qu’on ne modifie
plus. Corriger un document, c’est ajouter une version, pas remplacer des octets. L’ancienne
reste lisible, et c’est ce qui rend une reprise possible quand quelqu’un s’est trompé de
scan.
Un lien n’est pas un dossier. On ne range pas un fichier dans une arborescence : on le
rattache à une fiche (library_title n° 1). Les dossiers de l’écran Drive sont
déduits de ces liens. Aucun module ne crée de dossier, et rien ne se retrouve orphelin
quand une fiche disparaît.
Déposer, en le rattachant tout de suite
curl -X POST /api/v1/drive/docs \ -H "Authorization: Bearer $TOKEN" \ -F "file=@delivery-note.pdf" \ -F "name=Delivery note 2026-09" \ -F "model=library_title" \ -F "record_id=1"{ "id": 1, "name": "Delivery note 2026-09", "content_type": "text/plain", "size": 56, "current_version_id": 1, "deleted": false, "links": [{ "model": "library_title", "record_id": "1" }]}Le rattachement au dépôt n’est pas un raccourci d’écriture : le serveur vérifie d’abord que l’appelant a le droit de voir cette fiche. Sans cela, on pourrait planter un document sur la fiche d’un autre, qu’on n’a pas le droit de lire.
Depuis un module, c’est le même geste en Python :
from kewos.drive import create_doc, link_doc
with engine.begin() as conn: doc_id = create_doc( conn, storage, name="Delivery note 2026-09", content=pdf_bytes, content_type="application/pdf", owner_id=user_id, now=now, ) # The link is what makes it findable from the record, and what builds the folder. link_doc(conn, doc_id, model="library_title", record_id="1", by=user_id, now=now)Corriger : une version de plus
curl -X POST /api/v1/drive/docs/1/versions \ -H "Authorization: Bearer $TOKEN" \ -F "file=@delivery-note-corrected.pdf"[ { "number": 2, "size": 77, "content_type": "text/plain" }, { "number": 1, "size": 56, "content_type": "text/plain" }]La version 1 est toujours là et toujours lisible
(GET /api/v1/drive/docs/1/versions/1/content). restore_version la remet en courante, ce
qui, là encore, ajoute une version au lieu d’en effacer une.
Jeter, et jeter vraiment
Deux gestes, et la différence est volontaire :
curl -X POST /api/v1/drive/docs/1/trash # 200 -- reversiblecurl -X POST /api/v1/drive/docs/1/untrash # 200 -- and backcurl -X DELETE /api/v1/drive/docs/1 # 403 -- "data purger role required"La corbeille est un état, réversible, que n’importe quel utilisateur ayant le droit d’écrire
peut poser. L’effacement définitif demande le droit kws_data_purger, et il est audité.
C’est la même règle que partout ailleurs dans Kewos : détruire une donnée n’est pas une
variante de la modifier.
Ce que ça donne
Le document, son rattachement, et le dossier que la fiche s’est fabriqué toute seule :

Le dossier dit « Catalogue · Dune » : le libellé traduit du modèle, puis le nom de
l’œuvre. C’est le serveur qui les résout, en une requête par modèle, parce que le navigateur
n’a qu’un nom de modèle et un identifiant, et qu’il lui faudrait une requête par dossier pour
s’en sortir seul. Jusqu’à hier cet écran affichait library_title · 1.
Vous n’avez rien à faire pour en profiter : le nom vient de ce que votre modèle déclare déjà,
la clé de traduction est celle que votre module traduit déjà (model.library_title).
S’enchaîne avec la lecture de documents
C’est ici que l’étape 9 prend tout son sens : on dépose le bon de livraison scanné dans le Drive, puis on lit son texte.
from kewos.drive import read_currentfrom kewos.ocr import extract_text
content = read_current(conn, storage, doc_id)text = extract_text(content, content_type="application/pdf")Le document reste la pièce ; le texte extrait n’est qu’une lecture. On ne remplace jamais l’un par l’autre : une reconnaissance de caractères se trompe, l’original non.
Et ensuite
Le module est complet : des données, des écrans, des droits, des états, de l’IA, des automatismes et des fichiers. Reste à l’emballer pour quelqu’un d’autre : Livrer.