Fichiers & GED
Fichiers & GED
Périmètre : upload/download S3 (Scaleway), URL pré-signées, classement multi-entités
(FileLink), versioning, partages temporaires (FileShare), OCR optionnel
et conformité légale (Object Lock Compliance 10 ans pour factures et contrats).
/api/workspace/files/* ; la bibliothèque globale est à
/workspace/files. En développement le stockage utilise le driver filesystem (répertoire
.uploads/) ; en production Scaleway Object Storage fr-par. Source : docs/13-domain-files.md.Vocabulaire & entités
| Terme | Entité | Définition |
|---|---|---|
| Fichier | File | Objet stocké dans un bucket S3 ; métadonnées conservées en base. |
| Bucket | StorageBucket | Conteneur S3, un ou plusieurs par organisation selon le type de contenu. |
| Lien | FileLink | Association fichier ↔ entité cible (asset, contrat, facture, opportunité…). |
| Partage | FileShare | URL publique signée et expirable d'un fichier. |
| Version | FileVersion | Ancienne révision d'un fichier (versioning optionnel par bucket). |
Le modèle complet est dans
docs/04-data-model.md§10. UnFileLinkest unique par(fileId, targetType, targetId, category).
Écrans
| Écran | Route | Contenu |
|---|---|---|
| Bibliothèque fichiers | /workspace/files | DataTable : nom, type MIME, taille, entité liée, uploadeur, date ; filtres, recherche FTS (si OCR). |
| Section Documents (inline) | Fiches entités | FileLink par fiche : drag-drop, catégorisation, épinglage, aperçu inline. |
| Partage temporaire | /share/[token] | Page publique avec preview + download ; protection mot de passe optionnelle. |
Architecture buckets
documents-default
Documents généraux (devis, photos…). Object Lock désactivé. Versioning activé.
invoices-archive
Factures émises (PDF + Factur-X). Object Lock Compliance 10 ans. Versioning activé.
contracts-archive
Contrats signés. Object Lock Compliance 10 ans. Versioning activé.
signatures-evidence
Preuves de signature (export Yousign). Object Lock Compliance 10 ans.
audit-archive
Export mensuel audit log. Object Lock Compliance 10 ans.
temp-uploads
Uploads transitoires avant validation finale. Pas d'Object Lock. TTL 24 h.
invoices-archive, contracts-archive, signatures-evidence
et audit-archive sont configurés en mode Object Lock Compliance avec une rétention de
10 ans. Aucun objet ne peut être supprimé avant expiration, même par le compte root
Scaleway. Cette contrainte est irréversible une fois posée sur le bucket.Sécurité stockage
- Chiffrement at-rest (Scaleway SSE-S3) et in-transit (HTTPS uniquement).
- Aucun bucket accessible en accès public direct : tout passe par URL pré-signée (TTL 15 min par défaut).
- Validation MIME type + extension à l'upload.
- Taille max par défaut 50 MB (paramétrable par bucket ou type d'usage).
- Scan antivirus asynchrone (ClamAV self-hosted ou Scaleway Cloud) sur les uploads suspects.
- Quota de stockage par organisation :
Organization.storageQuotaBytes.
Modèle de données (points clés)
File.status:PENDING(upload en cours) →READY(confirmé côté S3) → soft-deleted.- Un
FileLinkest créé dès le statutPENDING, mais les listings par cible ne montrent que les fichiersREADY. File.ocrText: texte extrait par OCR, indexé en FTS PostgreSQL pour la recherche dans le contenu.FileShare.downloadCount: incrémenté à chaque téléchargement,downloadLimitoptionnel.- La déduplication est scoped au bucket (les rétentions Object Lock diffèrent d'un bucket à l'autre ; pas de déduplication inter-buckets ni inter-organisations).
API
Toutes les routes exigent une session valide et la permission indiquée (RBAC).
| Méthode | Route | Permission |
|---|---|---|
POST | /api/workspace/files/upload-url | file:upload |
POST | /api/workspace/files/[id]/complete | file:upload |
GET | /api/workspace/files | file:read |
GET | /api/workspace/files/[id] | file:read |
GET | /api/workspace/files/[id]/download-url | file:read |
POST | /api/workspace/files/[id]/replace | file:upload |
DELETE | /api/workspace/files/[id] | file:delete |
POST | /api/workspace/files/[id]/share | file:share |
DELETE | /api/workspace/files/shares/[id] | file:share |
GET | /share/[token] | Public (vérification token + mot de passe) |
POST | /api/workspace/files/[id]/link | file:upload |
DELETE | /api/workspace/files/links/[id] | file:delete |
/api/workspace/files/upload-urlAuth Initialise un upload : valide la cible, contrôle le quota et le MIME, applique la déduplication SHA-256,
génère une URL pré-signée S3 PUT (TTL 30 min) et crée le File en statut PENDING.
Corps (JSON)
facture-2026-01.pdf).documents-default, invoices-archive, …).asset, contract, invoice, …). Obligatoire avec targetId.targetType.photo-face, contract-pdf, delivery-receipt, …).Requête
curl -s -X POST "$API/api/workspace/files/upload-url" \
-H "Content-Type: application/json" -H "Cookie: $SESSION" \
-d '{"filename":"bon-livraison.pdf","mimeType":"application/pdf","sizeBytes":184320,"bucket":"documents-default","targetType":"asset","targetId":"ast_123","category":"delivery-receipt"}'
Réponse
{
"fileId": "fil_…",
"presignedUrl": "https://s3.fr-par.scw.cloud/…?X-Amz-Signature=…",
"expiresAt": "2026-06-16T10:30:00Z",
"deduplicated": false
}
Workflows
Upload signé (flux nominal)
1. Client calcule SHA-256 du fichier
2. POST /upload-url → { presignedUrl, fileId } (File PENDING créé, FileLink posé)
3. Client PUT directement vers S3 (évite le transit serveur)
4. POST /[id]/complete { etag }
→ serveur vérifie présence S3, calcule checksum, File.status = READY
5. Job async : scan antivirus + OCR si éligible
Si sha256 fourni et doublon détecté dans le même bucket/org → réponse { deduplicated: true, fileId },
le client saute le PUT et le /complete.
Download via URL pré-signée
1. GET /[id]/download-url
→ serveur vérifie RBAC + appartenance à une entité accessible par le user
2. Retourne { url, expiresAt } (TTL 15 min)
3. Client suit l'URL → S3 directement
4. Accès logué (AccessLog si activé)
Proxy filesystem en développement
En environnement development, le driver filesystem remplace S3. Le serveur expose :
PUT /dev-upload→ écrit dans.uploads/GET /dev-download→ sert le fichier local
Les URL pré-signées sont relatives (même origine) pour que le proxy fonctionne sans CORS.
L'aperçu PDF inline nécessite X-Frame-Options: SAMEORIGIN (le middleware global pose DENY —
penser à l'override sur le proxy).
Object Lock Compliance 10 ans (factures & contrats)
Les buckets invoices-archive, contracts-archive, signatures-evidence et audit-archive
sont configurés une seule fois à la création du bucket avec la politique de rétention
COMPLIANCE / 3 650 jours. Une fois un objet écrit :
- Aucune API (y compris root) ne peut le supprimer avant la date d'expiration.
- Le versioning est actif : chaque remplacement crée une nouvelle version ; l'ancienne reste protégée.
- La suppression logique (
File.deletedAt) n'a aucun effet sur l'objet S3 sous-jacent.
Versioning
Quand l'action "Remplacer" est déclenchée sur un fichier :
- L'ancien fichier devient
FileVersion(référence S3 conservée). - Le nouveau fichier prend la place dans le
FileLink. - L'historique reste consultable dans la section Documents de la fiche.
Suppression
- Logique :
File.deletedAt = now(), liensFileLinkdétachés dans la même transaction. - Physique : job
file-physical-delete(quotidien) purge les fichiers soft-deleted depuis > 30 j, sauf si le bucket est en Object Lock (suppression physique alors impossible). - L'UI affiche le nombre de fiches concernées avant confirmation (
GET /files/[id]/links).
OCR (optionnel)
- Déclenché sur upload PDF / image (sauf flag
skipOcr) → job asyncfile-ocr. - Texte extrait stocké dans
File.ocrText, indexé en FTS PostgreSQL. - Provider : Mastra self-hosted ou Veryfi/Rossum pour les factures fournisseur.
Règles métier
- Taille max upload : 50 MB par défaut, paramétrable par bucket ou type d'usage.
- MIME whitelist par bucket (
invoices-archiven'accepte queapplication/pdf). - Isolation multi-tenant stricte : un user ne voit que les fichiers de ses organisations.
FileLinkunique par(fileId, targetType, targetId, category).- Quota de stockage par organisation :
Organization.storageQuotaBytes. - Bucket Object Lock : suppression impossible avant expiration de la rétention.
- Job
file-cleanup-pending: purge les fichiers restésPENDING(upload avorté) et leurs liens.