# Étude 0.0.4 — fondation PostgreSQL partagée ## Objet Cette étude de `0.0.4-alpha.1` décide l'ownership et la première architecture PostgreSQL de SaseDev Knowledge avant toute implémentation de stockage. Elle part exclusivement de la stable Knowledge `v0.0.3` publiée et vérifiée. Elle ne consulte ni n'adopte une nouvelle version de PGR. ## Baseline autoritaire vérifiée La baseline reçue au démarrage est : ```text tag v0.0.3 commit b3823972449150b72905930b806d4d15471cddce archive sasedev-knowledge-v0.0.3.zip SHA-256 82407dc2a83be878daa65692f975681428d0adc721ff249c3c9020e3a9d1f29d report sasedev-knowledge-0.0.3-publish.001-report.md = PASS ``` La vérification de démarrage confirme : - `VERSION = 0.0.3` et `[workspace.package].version = 0.0.3` dans l'archive ; - neuf packages Cargo et aucune crate PostgreSQL déjà matérialisée ; - douze deltas et douze histories `0.0.3`, appariés jusqu'à `rel.1.fix.1 = PASS` ; - Git lecture/écriture contrôlée stable et provider-neutral ; - `ROADMAP.md` engage déjà `0.0.4` comme fondation PostgreSQL partagée ; - `prompts/004-V0_0_4_START_PROMPT.md` est présent dans la stable ; - PGR `v0.1.3` reste uniquement une provenance historique de l'adoption fermée en `0.0.2`. ## Contraintes acquises La fondation doit préserver simultanément : ```text Git vérité du contenu publié PostgreSQL état applicatif transversal et projections reconstructibles knowledge-domain-lib aucun type SQL/Actix/Gitea knowledge-git-api contrats Git provider-neutral knowledge-git-lib configuration physique et opérations Git knowledge-app-lib orchestration applicative knowledge-web-lib composition Web partagée ``` La première implémentation PostgreSQL ne doit pas entraîner par symétrie une nouvelle crate `-api`, un service réseau, trois bases séparées, un ORM complet, un scheduler ou un modèle de contenu final. ## Sources techniques consultées Consultation effectuée le `2026-09-30` sur les documentations publiées des crates comparées : - SQLx `0.9.0` et ses features/MSRV : ; - `PgPool` SQLx : ; - migrations et `migrate!` SQLx : et ; - `tokio-postgres` `0.7.18` : ; - `deadpool-postgres` `0.14.2` : ; - Diesel `2.3.13` : ; - `diesel-async` `0.9.2` : ; - SeaORM `2.0.4` : ; - Refinery `0.9.2` : . ## Comparaison des options Rust État des versions consultées le `2026-09-30` : SQLx `0.9.0`, `tokio-postgres` `0.7.18`, `deadpool-postgres` `0.14.2`, Diesel `2.3.13`, `diesel-async` `0.9.2`, SeaORM `2.0.4` et Refinery `0.9.2`. | Option | Atouts pour Knowledge | Coûts / inadéquations | Décision | |----------------------------------------|---------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------|----------| | `tokio-postgres` + Deadpool + Refinery | driver PostgreSQL async natif, responsabilités séparées, SQL explicite, pool spécialisé et migrations SQL intégrées | trois briques à versionner et intégrer ; la façade Knowledge doit normaliser leurs erreurs | `SELECT` | | SQLx `0.9` | async/Tokio, PostgreSQL natif, pool et migrations intégrés, SQL explicite | toolkit multi-SGBD plus large que le besoin ; MSRV `1.94`; ses macros de requêtes ne sont pas nécessaires ici | `REJECT` | | Diesel + `diesel-async` | typage/DSL fort, écosystème migrations, pooling disponible | modèle ORM/query-builder plus large que le premier schéma et davantage de surface de génération/traits | `REJECT` | | SeaORM | ORM async complet, migrations, relations et modèles riches | surdimensionné avant les modèles/projections `0.0.5`; risque de faire remonter l'ORM dans les contrats | `REJECT` | La sélection privilégie des responsabilités explicitement bornées plutôt qu'un toolkit généraliste. Knowledge cible PostgreSQL comme choix de produit : l'abstraction multi-SGBD de SQLx n'apporte donc pas de valeur attendue pour cette fondation. Le coût de composition de trois briques reste acceptable parce que chacune possède une responsabilité unique et vérifiable. ## Décision de dépendance La première implémentation utilisera `tokio-postgres` comme driver PostgreSQL asynchrone natif, `deadpool-postgres` comme pool et `refinery` comme owner technique des migrations SQL. Aucun ORM n'est sélectionné et aucune abstraction multi-SGBD n'est recherchée. Les versions observées pendant l'étude sont `tokio-postgres 0.7.18`, `deadpool-postgres 0.14.2` et `refinery 0.9.2`. `tokio-postgres` et `deadpool-postgres` déclarent actuellement Rust 2024 avec un MSRV `1.85`; Refinery vise les Rust stable récents. `alpha.2` a revalidé ces versions le `2026-09-30` avant leur ajout au manifest et retient les features minimales `runtime` pour `tokio-postgres`, `rt_tokio_1` pour `deadpool-postgres` et `tokio-postgres` pour Refinery. Tokio `1.53.1` est ajouté uniquement comme runtime de test d'intégration. La séparation est volontaire : ```text tokio-postgres protocole, connexion, requêtes et transactions PostgreSQL deadpool-postgres cycle de vie et mutualisation des connexions refinery découverte, historique et application des migrations SQL ``` La façade publique de `knowledge-store-postgres-lib` masque ces dépendances et normalise leurs erreurs dans le type d'erreur de la crate. Les types `tokio-postgres`, Deadpool ou Refinery ne doivent pas remonter dans `knowledge-domain-lib` ni dans les contrats applicatifs. `alpha.2` matérialise la première connexion avec `tokio_postgres::NoTls` et n'ajoute aucune dépendance TLS prématurée. Si une cible de déploiement PostgreSQL exige TLS, une tranche ultérieure devra sélectionner explicitement l'intégration TLS minimale compatible avec `tokio-postgres` au lieu d'hériter d'un défaut implicite. ## Ownership La responsabilité est suffisamment concrète pour justifier : ```text knowledge-store-postgres-lib ``` À partir d'`alpha.2`, cette crate possède : - construction et lifecycle du pool `deadpool-postgres` ; - migrations SQL de Knowledge ; - mapping SQL des types nécessaires ; - persistance de configuration logique de source ; - persistance de l'état de synchronisation ; - erreurs publiques récupérables de cette frontière. Elle dépendra des types domaine/Git strictement nécessaires, jamais l'inverse. Aucun `knowledge-store-api` n'est créé en `0.0.4-alpha.1`. Si une deuxième implémentation réelle ou un besoin de fake transverse rend plus tard une frontière passive utile, cette décision sera réévaluée à partir d'un usage concret. ## Connexion, pool et secrets La crate de stockage ne lit pas l'environnement. La composition lui fournit une configuration contenant au minimum l'URL PostgreSQL et les paramètres de pool retenus. L'URL peut contenir un secret et respecte donc les invariants suivants : - aucune valeur réelle versionnée ; - aucune URL complète dans les erreurs publiques ou logs ; - aucune valeur par défaut de production codée en dur ; - aucune tentative de fallback vers un fichier, SQLite ou un stockage mémoire si PostgreSQL est indisponible. Le pool est partagé par l'instance applicative qui compose le store. Les trois produits peuvent pointer vers la même base logique sans que chaque launcher réimplémente sa propre couche SQL. ## Premier schéma utile Le premier schéma est volontairement plus petit que l'état futur décrit dans l'architecture. ### `knowledge_sources` ```text source_id TEXT PRIMARY KEY family TEXT NOT NULL git_reference TEXT NOT NULL ``` `source_id` correspond à `SourceId`. `family` représente `ContentFamily` avec une contrainte SQL sur les valeurs supportées. `git_reference` est la référence Git logique à résoudre, pas une URL remote ni un credential. Les valeurs `family` persistées sont `pgr`, `howto`, `snippet` et `project_local`; la migration doit les contraindre explicitement. ### `knowledge_source_sync_state` ```text source_id TEXT PRIMARY KEY REFERENCES knowledge_sources(source_id) ON DELETE CASCADE last_synchronized_revision TEXT NOT NULL ``` La révision stockée représente la dernière révision effectivement acceptée par le cas d'usage de synchronisation. Elle est un état applicatif de comparaison. Git reste capable de fournir l'identité autoritaire et une valeur PostgreSQL perdue ou obsolète conduit à une nouvelle réconciliation, pas à une perte du contenu publié. Le schéma n'ajoute pas encore : - corps ou métadonnées éditoriales de contenu ; - révision indexée séparée avant l'implémentation réelle des projections ; - utilisateurs/sessions ; - propositions/revues ; - jobs ; - audit applicatif ; - moteur de recherche. ## Migrations Les migrations sont des fichiers SQL versionnés sous : ```text crates/knowledge-store-postgres-lib/migrations/ ``` La crate embarque le jeu de migrations au build et expose une opération explicite d'application. Le schéma n'est pas créé implicitement à chaque requête. Les migrations sont forward-only pour cette fondation : une correction de schéma publiée utilise une nouvelle migration. Un rollback destructif automatique n'est pas requis pour fermer `0.0.4`. ## Stratégie de test PostgreSQL Le test réel doit prouver PostgreSQL, pas une imitation en mémoire. La stratégie retenue est : ```text KNOWLEDGE_POSTGRES_TEST_URL -> PostgreSQL local ou service CI explicitement fourni -> création d'un schéma de test unique -> search_path borné à ce schéma -> application des migrations -> tests CRUD / état de synchronisation -> suppression du schéma ``` Cette stratégie évite d'imposer Docker dans la bibliothèque tout en autorisant un service container en CI. L'absence du service requis pendant une gate qui exige le test PostgreSQL est `BLOCKED`, pas `PASS`. Les tests unitaires sans PostgreSQL restent utiles pour les validations de types/configuration qui n'ont pas besoin d'un serveur réel, mais ils ne remplacent pas l'intégration PostgreSQL de migration et persistance. ## Raccord au cas d'usage de synchronisation Le cas d'usage existant `synchronize_repository` reçoit actuellement `previous_revision` de son appelant. `0.0.4` doit conserver cette primitive provider-neutral. Le raccord prévu est une orchestration supplémentaire qui : ```text charge last_synchronized_revision -> appelle synchronize_repository -> enregistre la révision observée après succès ``` Un contrat passif de persistance peut vivre dans `knowledge-app-lib` si `alpha.4` démontre qu'il est nécessaire pour tester cette orchestration sans coupler l'application au driver PostgreSQL. Cette possibilité ne justifie pas à elle seule une crate `knowledge-store-api`. ## Indisponibilité PostgreSQL Les erreurs de connexion, acquisition de pool, migration ou requête sont récupérables et typées à la frontière store. Il n'existe pas de mode où une écriture est annoncée persistée alors que PostgreSQL ne l'est pas. Une future façade publique pourra continuer à servir un contenu Git déjà matérialisé seulement si son cas d'usage n'exige pas le store ; cette politique appartient à la composition de la façade, pas à un fallback interne de la crate de stockage. ## Impact sur les trois applications `0.0.4` ne crée pas trois implémentations ou trois schémas par façade. `knowledge-store-postgres-lib` est le propriétaire partagé et la base logique est commune. Les launchers ne seront modifiés que lorsqu'un cas d'usage runtime exige réellement la connexion. La fondation peut donc être testée indépendamment avant d'ajouter une dépendance de démarrage PostgreSQL à `/` et `/healthz`. ## DEFER conservés Restent explicitement hors scope de `0.0.4` : - formats finaux et parsing PGR/HOWTO/snippet ; - projections de contenu finales et révision indexée détaillée ; - recherche avancée ; - Gitea/forge et webhooks forge-only ; - scheduler/jobs ; - auth, sessions et rôles/capabilities ; - propositions/revues/publication produit ; - templates publics/admin et routes finales ; - quatrième application admin ; - partage multi-processus de la racine Git ; - Git LFS/submodules et rétention avancée. ## Horizon L'étude ne révèle aucune dépendance fausse dans la revue `0.0.3-beta.1`. L'horizon reste donc : ```text 0.0.5 modèles de contenu et projections 0.0.6 templates publics 0.0.7 templates d'administration 0.0.8 lecture publique Actix Web / Maud 0.0.9 administration Actix Web / Maud et autorisation 0.0.10 gestion, proposition, revue et publication ``` ## Conclusion `0.0.4` peut progresser sans REPLAN : l'owner PostgreSQL est démontré, `tokio-postgres`, `deadpool-postgres` et `refinery` couvrent respectivement le driver, le pool et les migrations nécessaires, le premier schéma est borné et reconstructible par rapport à Git, et une stratégie de test PostgreSQL réelle est définie sans imposer un outil de provisioning unique. `alpha.1` a fermé le cadrage en `PASS`. `alpha.2` matérialise maintenant `knowledge-store-postgres-lib`, le trio `tokio-postgres` / `deadpool-postgres` / `refinery`, une configuration/pool sans fuite de secret, la migration initiale des sources et un test PostgreSQL réel isolé par schéma. Les opérations de persistance source/state restent réservées à `alpha.3`.