Collaboration
Collaboration
Périmètre : commentaires sur entités, threads (réponses imbriquées),
mentions @user, réactions emoji, notes internes vs externes,
attachements et inbox de notifications. Le composant CommentThread
est réutilisé sur toutes les fiches (asset, contrat, opportunité, facture,
maintenance…). Source de cette page : docs/14-domain-collab.md.
/api/workspace/comments et /api/workspace/inbox.
Le composant central est CommentThread, inclus dans chaque fiche de domaine.Vocabulaire & entités
| Terme | Entité / Champ | Définition |
|---|---|---|
| Commentaire | Comment | Message texte attaché à une entité (asset, contrat, opportunité, facture…). |
| Thread | Comment.parentCommentId | Réponses imbriquées sous un commentaire parent. |
| Mention | CommentMention | Référence @userId dans le texte — génère une notification. |
| Note interne | Comment.isInternal | Visible uniquement par les membres Pulse, jamais exposée aux portails externes. |
| Réaction | CommentReaction | Emoji (👍 ❤️ ✅ ⚠️ 👀) posé sur un commentaire. |
| Épinglage | Comment.pinnedAt | Un commentaire épinglé au sommet du thread (1 max par thread). |
| Watch | EntityWatch | Abonnement d'un utilisateur aux nouveaux commentaires d'une entité. |
| Inbox | — | Vue agrégée /workspace/inbox : mentions + threads suivis, filtrables. |
Schéma Prisma détaillé dans
docs/04-data-model.md§11.
Écrans
| Écran | Route / Composant | Contenu |
|---|---|---|
Composant CommentThread | Intégré dans chaque fiche | Liste chronologique paginée (50/page), composer markdown, toggle notes internes, réactions, reply, pin. |
| Inbox | /workspace/inbox | Tous les commentaires me mentionnant + threads que je watch ; filtres non lu / mention / période. |
Composant CommentThread — détail
Liste
Chronologique (plus ancien en haut). Pagination si > 50 commentaires (bouton « Voir plus anciens »). Toggle « Notes internes » en filtre.
Composer
Markdown léger : gras / italique / liste / mention / lien.
Drag-drop ou picker pour ajouter des pièces jointes (FileLink).
Autocomplete @... debounce 200 ms, 10 résultats max.
Actions par commentaire
Réactions emoji · Reply (thread enfant) · Édition (15 min) · Suppression (soft) · Pin (modérateur).
Modèle de données (points clés)
Comment.targetType+Comment.targetId: clé polymorphique vers l'entité parente. Index(targetType, targetId)pour les requêtes de récupération de thread.Comment.parentCommentIdnullable :NULL= commentaire racine, non NULL = réponse.Comment.isInternal: filtré côté serveur à chaque lecture ; les portails externes ne reçoivent jamais les notes internes (le filtre n'est jamais délégué au client).Comment.deletedAt: suppression soft — le contenu est effacé, l'auteur et la date sont préservés, affichage « Commentaire supprimé ».- Attachements via
FileLink(cf.docs/13-domain-files.md).
API
Toutes les routes exigent une session authentifiée. Les permissions comment:*
sont vérifiées côté API.
| Méthode | Route | Permission |
|---|---|---|
GET | /api/workspace/comments?targetType=X&targetId=Y | comment:read |
POST | /api/workspace/comments | comment:create |
PATCH | /api/workspace/comments/[id] | comment:update_own ou comment:moderate |
DELETE | /api/workspace/comments/[id] | comment:delete_own ou comment:moderate |
POST | /api/workspace/comments/[id]/reactions | comment:create |
DELETE | /api/workspace/comments/[id]/reactions/[emoji] | comment:create |
POST | /api/workspace/comments/[id]/pin | comment:moderate |
GET | /api/workspace/inbox | (authentifié) |
/api/workspace/commentsAuth Crée un commentaire sur une entité. Si le texte contient des mentions @userId,
des entrées CommentMention sont créées et les notifications correspondantes
sont émises.
Corps (JSON)
asset, contract, opportunity, invoice, maintenance…).true pour une note interne (défaut : false).Requête
curl -s -X POST "$API/api/workspace/comments" \
-H "Content-Type: application/json" -H "Cookie: $SESSION" \
-d '{"targetType":"opportunity","targetId":"opp_…","body":"@alice peux-tu valider ?","isInternal":false}'
Réponse
{
"id": "cmt_…",
"targetType": "opportunity",
"targetId": "opp_…",
"body": "@alice peux-tu valider ?",
"isInternal": false,
"authorId": "usr_…",
"createdAt": "2026-06-16T10:00:00Z",
"mentions": [{ "userId": "usr_alice" }]
}
Workflows
Mention @user
Saisie @nom
→ Autocomplete (debounce 200 ms, 10 résultats) remplace @nom → @userId
→ À la soumission : parsing du body
→ INSERT CommentMention (commentId, userId)
→ Notification in-app + email (selon préférences) : "X vous a mentionné dans [entité]"
Réponse à un commentaire
User B répond à un commentaire de User A (B ≠ A)
→ Comment créé avec parentCommentId = comment de A
→ Notification in-app à A : "B a répondu à votre commentaire dans [entité]"
Watch d'entité
User clique "Suivre" sur une entité
→ INSERT EntityWatch (userId, targetType, targetId)
→ Tout nouveau commentaire sur cette entité → notification in-app au watcher
→ Filtrable selon les préférences de notification de l'utilisateur
Notes internes vs externes
Composer → toggle "Note interne"
→ isInternal = true : serveur filtre à la lecture, portails externes exclus
→ isInternal = false : visible par tous les participants ayant accès à l'entité
(ex : client voit les commentaires de son contrat dans son portail)
Notifications
| Événement | Canal | Destinataire |
|---|---|---|
| Mention dans un commentaire | In-app + email | Utilisateur mentionné |
| Réponse à mon commentaire | In-app | Auteur du commentaire parent |
| Nouveau commentaire sur entité suivie | In-app | Watchers de l'entité |
Règles métier
- Fenêtre d'édition : 15 minutes après la création. Au-delà, le commentaire
est figé sauf pour un modérateur (
comment:moderate). - Suppression soft :
deletedAtposé, contenu effacé, auteur et date préservés ; affichage « Commentaire supprimé ». - Isolation notes internes : filtre appliqué côté serveur à chaque lecture — jamais délégué au client ou au portail externe.
- Mention vers utilisateur désactivé : badge « Utilisateur inconnu » affiché,
la
CommentMentionreste en base. - Épinglage : 1 commentaire épinglé maximum par thread (le précédent est désépinglé automatiquement).
- Attachements : via
FileLink(cf. domaine Files —docs/13-domain-files.md).
Fichiers
Référence technique du domaine Fichiers & GED — upload S3, URL pré-signées, Object Lock Compliance, versioning, partages temporaires et OCR.
Notifications
Référence technique du domaine Notifications — in-app, email transactionnel, SMS, templates, préférences utilisateur et queues persistantes.