Aller au contenu

Architecture

Vue d'ensemble de l'organisation du code de ColleC. Pour les concepts métier, voir Concepts.

Couches

ColleC suit une architecture en couches classique :

┌─────────────────────────────────────────────────┐
│  CLI (typer)         │  Web UI (FastAPI/Jinja)  │
├─────────────────────────────────────────────────┤
│           Services métier (api/services/)       │
├─────────────────────────────────────────────────┤
│           Modèle ORM (SQLAlchemy / SQLite)      │
├─────────────────────────────────────────────────┤
│  files     │  importers  │  exporters  │  qa    │
│  renamer   │  derivatives                        │
└─────────────────────────────────────────────────┘
  • CLI et Web UI sont des couches fines : elles parsent les entrées, appellent les services, formatent la sortie. Aucune logique métier dans les routes ou les commandes.
  • Services métier encapsulent toute la logique : validation Pydantic, invariants, transactions. Ils sont composables depuis du code Python (cf. Services).
  • Modèle ORM exprime les invariants en CHECK constraints et ondelete quand SQLite le permet ; les invariants plus riches sont en code (services + contrôles qa).
  • Modules transversaux (files, importers, exporters, qa, renamer, derivatives) encapsulent des responsabilités métier transverses appelées par les services et les CLI.

Arborescence

src/archives_tool/
├── api/
│   ├── routes/         # FastAPI routes web
│   ├── services/       # Logique métier (fonds, collections, items, dashboard, _erreurs, …)
│   ├── deps.py         # Sessions, racines, identité
│   └── templating.py   # Jinja2 + filtres
├── affichage/          # Rendus Rich pour la CLI (montrer, controler)
├── cli.py              # Commandes typer
├── config.py           # Chargement config_local.yaml
├── db.py               # Engine SQLite + pragmas WAL/FK
├── demo/               # Génération d'une base de démonstration
├── derivatives/        # Génération vignettes/aperçus
├── exporters/          # Dublin Core, Nakala CSV, xlsx
├── external/           # Connecteurs externes (V2+ : Nakala, IIIF)
├── files/              # Résolution chemins + hash
├── importers/          # Profils v2 + écrivain transactionnel
├── models/             # SQLAlchemy ORM par domaine
├── profils/            # Schéma Pydantic + loader + générateur
├── qa/                 # 14 contrôles de cohérence
├── renamer/            # Renommage transactionnel + annulation
├── schemas/            # Schemas Pydantic transverses
└── web/                # Templates Jinja2 + statiques

Patterns systématiques

ColleC suit quelques patterns transverses :

  • Pydantic Form models pour toutes les saisies (CLI et UI). Ex. FormulaireFonds, FormulaireItem, FormulaireCollection.
  • Erreurs métier hiérarchiques dans services/_erreurs.py : EntiteIntrouvable, FormulaireInvalide, OperationInterdite.
  • Pattern PRG (Post-Redirect-Get) pour les formulaires web.
  • Périmètre dataclass (renamer.Perimetre) pour les CLI qui ciblent des fonds/collections/items/fichiers, partagé entre renommer et deriver.
  • Invariants explicites vérifiés par tests dédiés et par les contrôles qa.
  • Idempotence systématique sur les services destructifs (suppression, retrait d'item d'une collection, etc.).

Pour le détail de chaque couche : Modèle, Services, Tests.

Choix techniques

Composant Choix
Base de données SQLite (mode WAL pour concurrence en lecture)
Gestion dépendances uv
Validation Pydantic v2
Web FastAPI + Jinja2 + HTMX + Tailwind compilé
Visionneuse OpenSeadragon (V2+ ; V0.9.0 utilise un <img> direct)
CLI Typer + Rich pour le rendu
Documentation MkDocs Material + Mermaid
Tests pytest + ruff
ORM SQLAlchemy 2.x style
Migrations Alembic

Boundaries

Les conventions à respecter :

  • Les services ne font pas d'écriture sur le système de fichiers — réservé aux modules files/, derivatives/, renamer/.
  • Les modules transversaux ne dépendent pas des services (sauf cas justifiés : importers/ecrivain.py réutilise creer_fonds, creer_item pour ne pas dupliquer la logique d'invariant).
  • Les routes web délèguent immédiatement aux services et rendent un template — pas de logique conditionnelle au-delà du flux GET/POST.
  • Les CLI délèguent immédiatement aux services et formatent via Rich — pas de SQL direct.