ADR 0109 – Archiver un projet
Accepté (2026-10-17, vague 3 du document d'idées)
ADR 0109 – Archiver un projet
Statut : Accepté (2026-10-17, vague 3 du document d’idées)
Un projet terminé encombre l’arbre et les vues, mais le mettre à la corbeille dit « à supprimer ». Il faut un état intermédiaire : « rangé », hors de vue, mais retrouvable.
Décision
État « archivé » : la colonne node.archived_at
La colonne existait depuis V1__init.sql sans être utilisée : aucune migration. Un nœud archivé garde son parent, ses aspects, ses liens et ses fichiers ; il n’est pas dans la corbeille (deleted_at reste nul).
- Propagation : archiver un nœud archive aussi ses descendants hors corbeille qui ne l’étaient pas, avec la même date (
now()d’une seule requête récursive). Ainsi les requêtes de l’arbre et des vues n’ont qu’une conditionarchived_at is null, sans remonter la hiérarchie. - Désarchiver remet le nœud et les descendants archivés avec la même date : ceux rangés à part, avant ou après, restent archivés. Un nœud archivé avec un ancêtre archivé se désarchive par cet ancêtre (409 sinon, avec le titre de l’ancêtre).
- Idempotent dans les deux sens : déjà archivé, rien ne change (et pas de jeton d’annulation).
- Rattachés par un champ : les tâches d’un projet ne sont pas ses enfants dans l’arbre, elles le désignent par
tache.projet. La clé d’aspectarchiveWith: [tache.projet]deconfig/aspects/projet.yaml(champs référence, contrôlés au chargement) fait suivre l’archivage aux nœuds dont ce champ désigne un nœud archivé, et à leurs propres enfants. Même date, donc même désarchivage. Sans la clé, seule la hiérarchie compte. - Générique : n’importe quel nœud peut être archivé ; aucun nom d’aspect, de statut ni de type dans le code. Le choix de quoi archiver (un projet terminé) est celui de l’utilisateur ; une action rapide ou un effet d’état pourra l’automatiser plus tard.
Ce que l’archivage masque, et ce qu’il laisse
| Surface | Archivé |
|---|---|
| Arbre (enfants, racines, nombre d’enfants) | masqué |
Vues, dashboards, compteurs (ViewRepository.fetch/count) |
masqué |
| Santé d’un projet (ADR 0108) | les tâches archivées ne comptent plus |
| Progression des enfants (ADR 0026), prochaine action (ADR 0037) | les archivés ne comptent plus et ne sont plus proposés |
Recherche simple GET /api/nodes, /count |
masqué, sauf avec q : la recherche par texte les retrouve (archived: true dans le résultat, « archivé » dans la palette et la liste) |
archived=true |
seulement les archives ; sans q, seulement les racines d’archivage (ni les enfants d’un archivé, ni les nœuds archivés en même temps que celui que désigne leur champ archiveWith) |
| Liens, rétroliens, mentions, fiche, journal | inchangés (le nœud reste lisible et référençable) |
| Export, sauvegarde | inchangés |
Journal
Chaque nœud touché reçoit un node_event dans la même transaction : node.archived / node.unarchived, avec descendants (nombre) sur le nœud choisi et with (id de ce nœud) sur les descendants. Ces événements ne sont pas des modifications locales pour les connecteurs (ADR 0047) : archiver une tâche synchronisée ne bloque pas la version suivante.
API
Pas de route dédiée : deux opérations de l’API des lots (ADR 0041), ARCHIVE et UNARCHIVE, donc l’« Annuler » de l’ADR 0049 (l’annulation d’un archivage désarchive, et inversement). Nouveau paramètre archived de la recherche, archivedAt dans NodeView, archived dans NodeSummary.
Interface
- Fiche : bouton « Archiver » (« Désarchiver » si archivée) avec « Annuler » ; bandeau « Archivé le … » avec « Désarchiver ». La fiche reste ouverte.
- Section « Archives » (
/archives) : menu de l’arborescence et commande de palette « Aller à : Archives ». Racines d’archivage, filtre par texte, « Désarchiver » avec « Annuler ».
Alternatives écartées
- Statut « archivé » dans l’aspect
projet: lie la fonctionnalité à un aspect (contraire à la règle « le domaine vit dansconfig/») et ne masque ni les enfants ni les autres nœuds. - Masquer par ancêtre à la lecture (CTE récursive dans chaque requête d’arbre et de vue) : coûteux partout et fragile ; la propagation à l’écriture la remplace par une condition triviale.
- Réutiliser la corbeille : « supprimer » et « ranger » n’ont pas le même sens ; la corbeille se purge.
- Tag
archive: visible comme n’importe quel tag, filtrable par erreur, pas masqué de l’arbre.
Limites connues
- Un nœud créé ou déplacé sous un parent archivé n’est pas archivé : il reste invisible dans l’arbre (son parent l’est) mais apparaît dans les vues.
- Une tâche rattachée à un projet après son archivage n’est pas archivée (comme un enfant créé après).
- La section « Archives » n’a pas de pagination au-delà de 200 résultats : on affine par texte.