Architecture
Un moteur générique, un domaine en YAML, une seule image Docker.
Vue d’ensemble
navigateur ──► Spring Boot (BFF, API REST, fichiers statiques Angular) ──► PostgreSQL 17
│ └─► disque /data/files
└─► config/ (YAML lus au démarrage)
| Dossier | Contenu |
|---|---|
config/ |
le domaine : aspects, types, liens, modèles, vues, dashboards, revues |
backend/ |
Spring Boot 4 (Java 25) : API REST, moteur de définitions, moteur de vues, PostgreSQL par jOOQ |
frontend/ |
Angular 22 (composants autonomes, signals, sans zone.js) : Material, Formly, AG Grid, Tiptap |
backup/ |
service de sauvegarde (scripts sh dans un conteneur PostgreSQL) |
deploy/ |
Caddy et essai de déploiement |
docs/ |
cahier des fonctionnalités, ADR, backlog, ce site (docs/site) |
Une seule image Docker : le build Angular est servi comme ressources statiques par Spring Boot.
Le moteur générique
Le code ne connaît aucun type métier (pas de if (aspect == "facture")). Le moteur de définitions lit config/ au démarrage, valide chaque fichier contre un méta-schéma (backend/src/main/resources/definitions/meta/), contrôle les références croisées (un type qui cite un aspect inconnu est ignoré) et expose les définitions à l’API. Un fichier invalide est ignoré et signalé ; il ne fait jamais tomber l’application, et la version précédente reste en service quand elle existe (voir la santé de la configuration, GET /api/definitions/status).
Un comportement spécifique passe par une définition YAML : workflow, report rapide, valeurs par défaut, prochaine action, masquage jusqu’à une date… Les actions et règles du jalon 3 pourront appeler un handler Java référencé depuis le YAML.
Données
| Table | Rôle |
|---|---|
node |
titre, type, corps Markdown, parent, dates, inbox, corbeille, recherche plein texte |
node_aspect |
un JSONB par aspect porté, avec la version de l’aspect |
node_link |
liens typés, liens wiki (wiki) |
node_tag |
tags, avec leur origine (saisie ou corps) |
node_file, file_blob |
fichiers rattachés, contenus adressés par SHA-256 |
node_event |
journal de toutes les modifications (avant / après) |
Règles :
- Valider à l’écriture, tolérer à la lecture : les données d’aspect sont validées contre le JSON Schema à l’écriture ; une donnée ancienne non conforme reste lisible, et une valeur inchangée ne bloque pas l’écriture des autres champs.
- Toute modification écrit un
node_eventdans la même transaction. - Schéma : uniquement par migrations Flyway
V<n>__<description>.sql, jamais modifiées après coup. - Accès : jOOQ partout, sans JPA ni génération de code (ADR 0003).
Moteur de vues
Une vue (config/views/) est traduite en SQL paramétré : aspects joints une fois chacun, condition where dans un langage fermé (pas de SpEL), tri avec les vides en dernier. Les champs calculés (unblockedAt, prochaine action) sont des sous-requêtes construites depuis les définitions, valeurs liées.
Sécurité
Modèle BFF : Spring Boot est le client OIDC (Authentik en production) ; le navigateur n’a qu’un cookie de session et le cookie CSRF XSRF-TOKEN, renvoyé dans l’en-tête X-XSRF-TOKEN. Le profil dev désactive la sécurité. Les fichiers déposés sont servis avec une liste blanche de types affichables, nosniff et une CSP stricte.
Contrat API
Le backend publie son contrat OpenAPI (Swagger UI en dev : /swagger-ui.html). Le front utilise un client généré (frontend/src/app/api/), jamais de DTO écrit à la main ; frontend/openapi.json est l’instantané versionné du contrat.