3 Commits

Author SHA1 Message Date
a15fff86b8 0.0.4-alpha.2.fix.1 2026-10-01 11:34:09 +02:00
095ac37d08 0.0.4-alpha.2 2026-10-01 11:00:00 +02:00
b55eb23dc0 0.0.4-alpha.1 2026-10-01 10:49:09 +02:00
24 changed files with 2124 additions and 28 deletions

View File

@@ -1,5 +1,5 @@
# file: Cargo.toml # file: Cargo.toml
# version: 39 # version: 41
[workspace] [workspace]
resolver = "3" resolver = "3"
@@ -13,10 +13,11 @@ members = [
"crates/knowledge-pgr-server", "crates/knowledge-pgr-server",
"crates/knowledge-howtos-server", "crates/knowledge-howtos-server",
"crates/knowledge-snippets-server", "crates/knowledge-snippets-server",
"crates/knowledge-store-postgres-lib",
] ]
[workspace.package] [workspace.package]
version = "0.0.3" version = "0.0.4-alpha.2.fix.1"
edition = "2024" edition = "2024"
publish = false publish = false
repository = "https://git.sasedev.com/Sasedev/sasedev-knowledge" repository = "https://git.sasedev.com/Sasedev/sasedev-knowledge"

View File

@@ -1,5 +1,5 @@
<!-- file: README.md --> <!-- file: README.md -->
<!-- version: 25 --> <!-- version: 27 -->
# SaseDev Knowledge # SaseDev Knowledge
@@ -15,6 +15,8 @@ La version courante est définie par [`VERSION`](VERSION).
`0.0.3` est la stable du chemin Git générique complet en lecture et écriture contrôlée : lecture/snapshot, création d'un commit candidat isolé, mutations confinées, identité explicite puis push compare-and-exchange protégé par `--force-with-lease` contre l'état distant attendu. Une branche peut être créée uniquement lorsque son absence est attendue ; toute divergence devient un conflit récupérable sans écrasement silencieux. Cette stable reste provider-neutral et n'introduit ni forge obligatoire, ni PostgreSQL, ni rebase/merge automatique, ni workflow produit complet de proposition/publication. `0.0.3` est la stable du chemin Git générique complet en lecture et écriture contrôlée : lecture/snapshot, création d'un commit candidat isolé, mutations confinées, identité explicite puis push compare-and-exchange protégé par `--force-with-lease` contre l'état distant attendu. Une branche peut être créée uniquement lorsque son absence est attendue ; toute divergence devient un conflit récupérable sans écrasement silencieux. Cette stable reste provider-neutral et n'introduit ni forge obligatoire, ni PostgreSQL, ni rebase/merge automatique, ni workflow produit complet de proposition/publication.
`0.0.4-alpha.2` matérialise la première fondation PostgreSQL partagée. `knowledge-store-postgres-lib` possède désormais une configuration explicite, un pool `deadpool-postgres` sur `tokio-postgres`, des migrations SQL embarquées via Refinery et une première migration créant `knowledge_sources` et `knowledge_source_sync_state`. Aucun ORM, fallback de stockage, accès implicite à l'environnement ou raccord launcher n'est introduit ; Git reste autoritaire pour tout contenu publié.
`knowledge-git-lib` implémente `knowledge-git-api::GitRepository` pour des sources physiques enregistrées : mirror contrôlé, refresh avec pruning, résolution d'une référence vers un commit et snapshot/worktree détaché adressé par révision. La création locale du candidat d'`alpha.3` reste séparée de cette sémantique de lecture. Les règles nécessaires au développement courant sont désormais possédées localement sous `docs/rules/`, et les futurs prompts Knowledge ne chargent pas PGR sauf réévaluation explicitement engagée. `knowledge-app-lib` compose maintenant refresh, résolution, comparaison avec la révision précédente et préparation de snapshot en un résultat explicite `Changed` / `Unchanged`, sans persister la dernière révision ni matérialiser de scheduler. `knowledge-git-lib` implémente `knowledge-git-api::GitRepository` pour des sources physiques enregistrées : mirror contrôlé, refresh avec pruning, résolution d'une référence vers un commit et snapshot/worktree détaché adressé par révision. La création locale du candidat d'`alpha.3` reste séparée de cette sémantique de lecture. Les règles nécessaires au développement courant sont désormais possédées localement sous `docs/rules/`, et les futurs prompts Knowledge ne chargent pas PGR sauf réévaluation explicitement engagée. `knowledge-app-lib` compose maintenant refresh, résolution, comparaison avec la révision précédente et préparation de snapshot en un résultat explicite `Changed` / `Unchanged`, sans persister la dernière révision ni matérialiser de scheduler.
## Topologie produit de fondation ## Topologie produit de fondation
@@ -31,11 +33,11 @@ Ces trois launchers restent minces et réutilisent les mêmes crates communes lo
Chaque famille possède au minimum sa propre source Git autoritaire : dépôt `pgr`, dépôt `howtos` et dépôt `snippets`. La configuration doit permettre d'ajouter d'autres sources sans figer le système à exactement trois repositories. Chaque famille possède au minimum sa propre source Git autoritaire : dépôt `pgr`, dépôt `howtos` et dépôt `snippets`. La configuration doit permettre d'ajouter d'autres sources sans figer le système à exactement trois repositories.
PostgreSQL est mutualisable et constitue la baseline retenue pour l'état transversal de la plateforme : comptes, sessions, propositions, synchronisation, index et relations entre familles. Il ne remplace jamais les sources Git comme vérité du contenu publié. PostgreSQL est mutualisable et constitue la baseline retenue pour l'état transversal de la plateforme : comptes, sessions, propositions, synchronisation, index et relations entre familles. `0.0.4-alpha.2` matérialise le premier owner partagé avec `tokio-postgres 0.7.18`, `deadpool-postgres 0.14.2`, Refinery `0.9.2` et une migration SQL versionnée. La bibliothèque de stockage reçoit sa configuration de connexion depuis la composition, ne lit ni ne journalise elle-même des secrets d'environnement et utilise actuellement `NoTls` sans ajouter de backend TLS tant qu'un déploiement ne l'exige pas. PostgreSQL ne remplace jamais les sources Git comme vérité du contenu publié.
Chaque application Web doit pouvoir exposer sa propre surface d'administration protégée pour son domaine. Les chemins HTTP exacts ne sont pas encore figés. Une éventuelle quatrième application d'administration pourra agréger des fonctions transversales, mais elle ne remplacera pas les contrôles d'autorisation propres aux trois serveurs. Chaque application Web doit pouvoir exposer sa propre surface d'administration protégée pour son domaine. Les chemins HTTP exacts ne sont pas encore figés. Une éventuelle quatrième application d'administration pourra agréger des fonctions transversales, mais elle ne remplacera pas les contrôles d'autorisation propres aux trois serveurs.
Le workspace Rust matérialise neuf packages : les trois frontières de fondation `knowledge-domain-lib`, `knowledge-git-api` et `knowledge-sync-api`, le backend `knowledge-git-lib`, la couche application partagée `knowledge-app-lib`, la composition Web `knowledge-web-lib`, puis les trois launchers `knowledge-pgr-server`, `knowledge-howtos-server` et `knowledge-snippets-server`. Les deux crates `-api` restent passives et indépendantes d'Actix, Gitea et PostgreSQL. Le workspace Rust matérialise dix packages : les trois frontières de fondation `knowledge-domain-lib`, `knowledge-git-api` et `knowledge-sync-api`, le backend `knowledge-git-lib`, la couche application partagée `knowledge-app-lib`, la composition Web `knowledge-web-lib`, le stockage `knowledge-store-postgres-lib`, puis les trois launchers `knowledge-pgr-server`, `knowledge-howtos-server` et `knowledge-snippets-server`. Les deux crates `-api` restent passives et indépendantes d'Actix, Gitea et PostgreSQL.
## Frontend de référence et rendu Maud ## Frontend de référence et rendu Maud
@@ -82,9 +84,11 @@ La revue d'horizon de `0.0.3-beta.1` sépare désormais explicitement la constru
- [`docs/studies/004-V0_0_2_GIT_IMPLEMENTATION_STUDY.md`](docs/studies/004-V0_0_2_GIT_IMPLEMENTATION_STUDY.md) — comparaison processus Git / `gix` / `git2` et décision d'implémentation de lecture ; - [`docs/studies/004-V0_0_2_GIT_IMPLEMENTATION_STUDY.md`](docs/studies/004-V0_0_2_GIT_IMPLEMENTATION_STUDY.md) — comparaison processus Git / `gix` / `git2` et décision d'implémentation de lecture ;
- [`docs/studies/006-V0_0_3_GIT_WRITE_STUDY.md`](docs/studies/006-V0_0_3_GIT_WRITE_STUDY.md) — choix de la mission, stratégie de worktree d'écriture et invariants de push gardé ; - [`docs/studies/006-V0_0_3_GIT_WRITE_STUDY.md`](docs/studies/006-V0_0_3_GIT_WRITE_STUDY.md) — choix de la mission, stratégie de worktree d'écriture et invariants de push gardé ;
- [`docs/studies/007-V0_0_3_GIT_WRITE_RECONCILIATION.md`](docs/studies/007-V0_0_3_GIT_WRITE_RECONCILIATION.md) — réconciliation beta du chemin Git d'écriture et revue d'horizon produit PGR/HOWTOs/snippets ; - [`docs/studies/007-V0_0_3_GIT_WRITE_RECONCILIATION.md`](docs/studies/007-V0_0_3_GIT_WRITE_RECONCILIATION.md) — réconciliation beta du chemin Git d'écriture et revue d'horizon produit PGR/HOWTOs/snippets ;
- [`docs/studies/008-V0_0_4_POSTGRES_FOUNDATION_STUDY.md`](docs/studies/008-V0_0_4_POSTGRES_FOUNDATION_STUDY.md) — étude de démarrage PostgreSQL, comparaison des clients/ORM, ownership, premier schéma, migrations et tests ;
- [`docs/plans/001-V0_0_1_FOUNDATION_PLAN.md`](docs/plans/001-V0_0_1_FOUNDATION_PLAN.md) — plan historique de la fondation stable `0.0.1` ; - [`docs/plans/001-V0_0_1_FOUNDATION_PLAN.md`](docs/plans/001-V0_0_1_FOUNDATION_PLAN.md) — plan historique de la fondation stable `0.0.1` ;
- [`docs/plans/002-V0_0_2_GIT_SYNC_PLAN.md`](docs/plans/002-V0_0_2_GIT_SYNC_PLAN.md) — plan historique de la stable `0.0.2`, gates et décisions de fermeture ; - [`docs/plans/002-V0_0_2_GIT_SYNC_PLAN.md`](docs/plans/002-V0_0_2_GIT_SYNC_PLAN.md) — plan historique de la stable `0.0.2`, gates et décisions de fermeture ;
- [`docs/plans/003-V0_0_3_GIT_WRITE_PLAN.md`](docs/plans/003-V0_0_3_GIT_WRITE_PLAN.md) — plan actif de l'écriture Git contrôlée et du push gardé ; - [`docs/plans/003-V0_0_3_GIT_WRITE_PLAN.md`](docs/plans/003-V0_0_3_GIT_WRITE_PLAN.md) — plan historique de la stable `0.0.3`, écriture Git contrôlée et push gardé ;
- [`docs/plans/004-V0_0_4_POSTGRES_FOUNDATION_PLAN.md`](docs/plans/004-V0_0_4_POSTGRES_FOUNDATION_PLAN.md) — plan actif de la fondation PostgreSQL partagée ;
- [`docs/validation/001-VALIDATION_MATRIX.md`](docs/validation/001-VALIDATION_MATRIX.md) — matrice de validation ; - [`docs/validation/001-VALIDATION_MATRIX.md`](docs/validation/001-VALIDATION_MATRIX.md) — matrice de validation ;
- [`prompts/001-V0_0_1_START_PROMPT.md`](prompts/001-V0_0_1_START_PROMPT.md) — prompt de démarrage autoritaire de la release. - [`prompts/001-V0_0_1_START_PROMPT.md`](prompts/001-V0_0_1_START_PROMPT.md) — prompt de démarrage autoritaire de la release.
- [`prompts/002-V0_0_2_START_PROMPT.md`](prompts/002-V0_0_2_START_PROMPT.md) — handoff historique exécuté pour ouvrir `0.0.2` depuis la stable `v0.0.1` vérifiée. - [`prompts/002-V0_0_2_START_PROMPT.md`](prompts/002-V0_0_2_START_PROMPT.md) — handoff historique exécuté pour ouvrir `0.0.2` depuis la stable `v0.0.1` vérifiée.

View File

@@ -1,5 +1,5 @@
<!-- file: RULES.md --> <!-- file: RULES.md -->
<!-- version: 15 --> <!-- version: 17 -->
# Règles SaseDev Knowledge # Règles SaseDev Knowledge
@@ -142,7 +142,17 @@ La baseline de fondation retient une base PostgreSQL logique partagée par les t
Le texte et les métadonnées éditoriales qui constituent le contenu publié restent autoritaires dans Git. Une copie ou projection PostgreSQL de ces données est dérivée et reconstructible. Le texte et les métadonnées éditoriales qui constituent le contenu publié restent autoritaires dans Git. Une copie ou projection PostgreSQL de ces données est dérivée et reconstructible.
Le choix du driver, de l'ORM ou de la stratégie de migration reste différé jusqu'à une tranche qui en a réellement besoin. `0.0.4-alpha.1` sélectionne `tokio-postgres` comme driver PostgreSQL async natif, `deadpool-postgres` comme pool et Refinery comme mécanisme de migrations. `0.0.4-alpha.2` matérialise ces choix avec `tokio-postgres 0.7.18`, `deadpool-postgres 0.14.2` et Refinery `0.9.2`. Knowledge ne sélectionne pas d'ORM ni d'abstraction multi-SGBD : les requêtes restent SQL explicite derrière un owner de stockage partagé. Chaque dépendance doit être ajoutée avec les fonctionnalités Cargo minimales réellement nécessaires : `runtime` pour `tokio-postgres`, `rt_tokio_1` pour `deadpool-postgres` et `tokio-postgres` pour Refinery dans cette première matérialisation.
L'owner réel est `knowledge-store-postgres-lib`. Aucun `knowledge-store-api` séparé n'est créé tant qu'une seconde implémentation remplaçable ou une frontière passive indépendante n'est pas démontrée. Les types du driver, du pool et du migrator restent confinés à cette implémentation.
Les migrations sont des fichiers SQL versionnés possédés par cette crate, appliqués explicitement via Refinery et embarqués avec le binaire. Une migration déjà appliquée est suivie par le mécanisme de migration ; le runtime ne doit pas modifier silencieusement le schéma au fil des requêtes. La première implémentation utilise `tokio_postgres::NoTls` et n'ajoute aucun backend TLS tant qu'une cible de déploiement n'en démontre pas le besoin.
La bibliothèque de stockage reçoit sa configuration de connexion et de pool depuis sa composition. Elle MUST NOT lire directement une variable d'environnement secrète comme source implicite, MUST NOT journaliser une URL de connexion ou des credentials et MUST retourner une erreur récupérable si la connexion ou une migration échoue. Aucune indisponibilité PostgreSQL ne déclenche un fallback caché vers un fichier ou un stockage mémoire.
Le premier schéma de `0.0.4` reste minimal : `knowledge_sources` conserve l'identifiant logique, la famille et la référence Git logique ; `knowledge_source_sync_state` conserve uniquement la dernière révision synchronisée. Il ne stocke ni corps de contenu publié, ni credential Git, ni modèle auth/proposition final, ni projection de contenu anticipée.
À partir d'`0.0.4-alpha.2`, toute gate qui prétend valider les migrations PostgreSQL doit utiliser un PostgreSQL réel fourni explicitement via `KNOWLEDGE_POSTGRES_TEST_URL`. Le test doit isoler son état dans un schéma temporaire et le supprimer après validation ; l'absence du service requis rend la gate `BLOCKED`, jamais `PASS`.
## Frontières documentaires ## Frontières documentaires

View File

@@ -1 +1 @@
0.0.3 0.0.4-alpha.2.fix.1

View File

@@ -0,0 +1,20 @@
# file: crates/knowledge-store-postgres-lib/Cargo.toml
# version: 1
[package]
name = "knowledge-store-postgres-lib"
version.workspace = true
edition.workspace = true
publish.workspace = true
repository.workspace = true
[dependencies]
deadpool-postgres = { version = "0.14.2", default-features = false, features = ["rt_tokio_1"] }
refinery = { version = "0.9.2", default-features = false, features = ["tokio-postgres"] }
tokio-postgres = { version = "0.7.18", default-features = false, features = ["runtime"] }
[dev-dependencies]
tokio = { version = "1.53.1", default-features = false, features = ["macros", "rt-multi-thread"] }
[lints]
workspace = true

View File

@@ -0,0 +1,13 @@
-- file: crates/knowledge-store-postgres-lib/migrations/V1__initial_sources.sql
-- version: 1
CREATE TABLE knowledge_sources (
source_id TEXT PRIMARY KEY,
family TEXT NOT NULL CHECK (family IN ('pgr', 'howto', 'snippet', 'project_local')),
git_reference TEXT NOT NULL
);
CREATE TABLE knowledge_source_sync_state (
source_id TEXT PRIMARY KEY REFERENCES knowledge_sources(source_id) ON DELETE CASCADE,
last_synchronized_revision TEXT NOT NULL
);

View File

@@ -0,0 +1,39 @@
// file: crates/knowledge-store-postgres-lib/src/config.rs
// version: 1
//! Explicit PostgreSQL pool configuration supplied by application composition.
/// Configuration required to construct the shared PostgreSQL store.
///
/// The type intentionally does not implement `Debug` because the database URL may contain a
/// credential. Callers must not log or persist the URL as diagnostic output.
#[derive(Clone)]
pub struct PostgresStoreConfig {
database_url: String,
max_pool_size: usize,
}
impl crate::PostgresStoreConfig {
/// Build a PostgreSQL configuration from an explicit connection URL and maximum pool size.
pub fn new(database_url: &str, max_pool_size: usize) -> Result<crate::PostgresStoreConfig, crate::PostgresStoreError> {
if database_url.trim().is_empty() {
return Err(crate::PostgresStoreError::EmptyDatabaseUrl);
}
if max_pool_size == 0 {
return Err(crate::PostgresStoreError::InvalidPoolSize);
}
return Ok(Self { database_url: database_url.to_owned(), max_pool_size });
}
pub(crate) fn database_url(&self) -> &str {
return self.database_url.as_str();
}
pub(crate) fn max_pool_size(&self) -> usize {
return self.max_pool_size;
}
}
#[cfg(test)]
#[path = "../unit_tests/config.rs"]
mod tests;

View File

@@ -0,0 +1,36 @@
// file: crates/knowledge-store-postgres-lib/src/error.rs
// version: 1
//! Recoverable errors owned by the PostgreSQL storage boundary.
/// Recoverable failure returned by the PostgreSQL storage foundation.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum PostgresStoreError {
/// The explicit database URL is empty or whitespace only.
EmptyDatabaseUrl,
/// The configured pool size is zero.
InvalidPoolSize,
/// The database URL cannot be parsed as PostgreSQL connection configuration.
InvalidDatabaseConfiguration,
/// The connection pool cannot be constructed from the supplied configuration.
PoolBuild,
/// A PostgreSQL connection cannot be acquired from the pool.
PoolAcquisition,
/// The embedded migration set cannot be applied.
Migration,
}
impl std::fmt::Display for crate::PostgresStoreError {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
crate::PostgresStoreError::EmptyDatabaseUrl => return formatter.write_str("PostgreSQL database URL must not be empty"),
crate::PostgresStoreError::InvalidPoolSize => return formatter.write_str("PostgreSQL pool size must be greater than zero"),
crate::PostgresStoreError::InvalidDatabaseConfiguration => return formatter.write_str("PostgreSQL database configuration is invalid"),
crate::PostgresStoreError::PoolBuild => return formatter.write_str("PostgreSQL connection pool could not be constructed"),
crate::PostgresStoreError::PoolAcquisition => return formatter.write_str("PostgreSQL connection could not be acquired"),
crate::PostgresStoreError::Migration => return formatter.write_str("PostgreSQL migrations could not be applied"),
}
}
}
impl std::error::Error for crate::PostgresStoreError {}

View File

@@ -0,0 +1,16 @@
// file: crates/knowledge-store-postgres-lib/src/lib.rs
// version: 1
//! PostgreSQL storage foundation shared by SaseDev Knowledge applications.
//!
//! The crate owns explicit PostgreSQL configuration, the connection pool and versioned migrations.
//! It does not read process environment variables, expose driver types through its public API or
//! replace Git as the authority for published content.
mod config;
mod error;
mod store;
pub use crate::config::PostgresStoreConfig;
pub use crate::error::PostgresStoreError;
pub use crate::store::PostgresStore;

View File

@@ -0,0 +1,44 @@
// file: crates/knowledge-store-postgres-lib/src/store.rs
// version: 1
//! Connection-pool ownership and explicit migration execution.
mod embedded {
refinery::embed_migrations!();
}
/// Shared PostgreSQL store backed by a bounded Deadpool connection pool.
#[derive(Clone)]
pub struct PostgresStore {
pool: deadpool_postgres::Pool,
}
impl crate::PostgresStore {
/// Construct the PostgreSQL store without reading process environment variables.
pub fn new(config: crate::PostgresStoreConfig) -> Result<crate::PostgresStore, crate::PostgresStoreError> {
let postgres_config = match config.database_url().parse::<tokio_postgres::Config>() {
Ok(value) => value,
Err(_) => return Err(crate::PostgresStoreError::InvalidDatabaseConfiguration),
};
let manager = deadpool_postgres::Manager::new(postgres_config, tokio_postgres::NoTls);
let pool = match deadpool_postgres::Pool::builder(manager).max_size(config.max_pool_size()).build() {
Ok(value) => value,
Err(_) => return Err(crate::PostgresStoreError::PoolBuild),
};
return Ok(Self { pool });
}
/// Apply every embedded versioned migration that has not yet been recorded by Refinery.
pub async fn apply_migrations(&self) -> Result<(), crate::PostgresStoreError> {
let mut connection = match self.pool.get().await {
Ok(value) => value,
Err(_) => return Err(crate::PostgresStoreError::PoolAcquisition),
};
let wrapper = std::ops::DerefMut::deref_mut(&mut connection);
let client = std::ops::DerefMut::deref_mut(wrapper);
match embedded::migrations::runner().run_async(client).await {
Ok(_) => return Ok(()),
Err(_) => return Err(crate::PostgresStoreError::Migration),
}
}
}

View File

@@ -0,0 +1,90 @@
// file: crates/knowledge-store-postgres-lib/tests/postgres_migration.rs
// version: 2
//! Integration test for the initial PostgreSQL migration in an isolated schema.
fn test_schema_name() -> String {
let elapsed = match std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH) {
Ok(value) => value,
Err(_) => return format!("knowledge_test_{}", std::process::id()),
};
return format!("knowledge_test_{}_{}", std::process::id(), elapsed.as_nanos());
}
fn database_url_with_search_path(database_url: &str, schema: &str) -> String {
let separator = if database_url.contains('?') { '&' } else { '?' };
return format!("{database_url}{separator}options=-c%20search_path%3D{schema}");
}
async fn connect(database_url: &str) -> Option<tokio_postgres::Client> {
let connection_result = tokio_postgres::connect(database_url, tokio_postgres::NoTls).await;
assert!(connection_result.is_ok(), "test PostgreSQL connection failed");
let (client, connection) = match connection_result {
Ok(value) => value,
Err(_) => return None,
};
let _connection_task = tokio::spawn(async move {
let _connection_result = connection.await;
return;
});
return Some(client);
}
#[tokio::test]
#[ignore = "requires KNOWLEDGE_POSTGRES_TEST_URL"]
async fn initial_migration_runs_in_isolated_schema() {
let database_url_result = std::env::var("KNOWLEDGE_POSTGRES_TEST_URL");
assert!(database_url_result.is_ok(), "KNOWLEDGE_POSTGRES_TEST_URL is required");
let database_url = match database_url_result {
Ok(value) => value,
Err(_) => return,
};
let schema = test_schema_name();
let admin = match connect(database_url.as_str()).await {
Some(value) => value,
None => return,
};
let create_schema = format!("CREATE SCHEMA {schema}");
let create_result = admin.batch_execute(create_schema.as_str()).await;
assert!(create_result.is_ok(), "isolated PostgreSQL schema creation failed");
if create_result.is_err() {
return;
}
let isolated_url = database_url_with_search_path(database_url.as_str(), schema.as_str());
let config_result = knowledge_store_postgres_lib::PostgresStoreConfig::new(isolated_url.as_str(), 2);
assert!(config_result.is_ok(), "PostgreSQL store configuration failed");
let config = match config_result {
Ok(value) => value,
Err(_) => return,
};
let store_result = knowledge_store_postgres_lib::PostgresStore::new(config);
assert!(store_result.is_ok(), "PostgreSQL store construction failed");
let store = match store_result {
Ok(value) => value,
Err(_) => return,
};
let migration_result = store.apply_migrations().await;
assert!(migration_result.is_ok(), "initial PostgreSQL migration failed");
let table_result = admin
.query(
"SELECT table_name FROM information_schema.tables WHERE table_schema = $1 AND table_name IN ('knowledge_sources', 'knowledge_source_sync_state', 'refinery_schema_history') ORDER BY table_name",
&[&schema],
)
.await;
assert!(table_result.is_ok(), "PostgreSQL migration verification query failed");
let table_rows = match table_result {
Ok(value) => value,
Err(_) => return,
};
assert_eq!(table_rows.len(), 3);
if table_rows.len() == 3 {
assert_eq!(table_rows[0].get::<usize, &str>(0), "knowledge_source_sync_state");
assert_eq!(table_rows[1].get::<usize, &str>(0), "knowledge_sources");
assert_eq!(table_rows[2].get::<usize, &str>(0), "refinery_schema_history");
}
drop(store);
let drop_schema = format!("DROP SCHEMA {schema} CASCADE");
let drop_result = admin.batch_execute(drop_schema.as_str()).await;
assert!(drop_result.is_ok(), "isolated PostgreSQL schema cleanup failed");
return;
}

View File

@@ -0,0 +1,23 @@
// file: crates/knowledge-store-postgres-lib/unit_tests/config.rs
// version: 1
#[test]
fn config_rejects_empty_database_url() {
let result = crate::PostgresStoreConfig::new(" ", 4);
assert!(matches!(result, Err(crate::PostgresStoreError::EmptyDatabaseUrl)));
return;
}
#[test]
fn config_rejects_zero_pool_size() {
let result = crate::PostgresStoreConfig::new("postgresql://localhost/knowledge", 0);
assert!(matches!(result, Err(crate::PostgresStoreError::InvalidPoolSize)));
return;
}
#[test]
fn config_accepts_explicit_non_empty_values() {
let result = crate::PostgresStoreConfig::new("postgresql://localhost/knowledge", 4);
assert!(result.is_ok());
return;
}

217
deltas/0.0.4/alpha.1.md Normal file
View File

@@ -0,0 +1,217 @@
<!-- file: deltas/0.0.4/alpha.1.md -->
<!-- version: 1 -->
# Delta 0.0.4-alpha.1 — cadrage de la fondation PostgreSQL partagée
## Baseline requise
Partir de la stable autoritaire réellement publiée :
```text
tag Knowledge v0.0.3
commit Knowledge b3823972449150b72905930b806d4d15471cddce
archive SHA-256 82407dc2a83be878daa65692f975681428d0adc721ff249c3c9020e3a9d1f29d
publish report sasedev-knowledge-0.0.3-publish.001-report.md = PASS
start prompt prompts/004-V0_0_4_START_PROMPT.md
```
Le rapport post-tag fourni confirme la convergence `HEAD/tag distant/commentaire ZIP`, l'intégrité de l'archive, les douze deltas/histories `0.0.3` et `rel.1.fix.1 = PASS`.
PGR `v0.1.3` reste une provenance historique de l'adoption fermée en `0.0.2`. Aucune nouvelle version PGR n'est chargée ou adoptée.
La version devient :
```text
0.0.4-alpha.1
```
## Objet
Fermer le cadrage PostgreSQL avant toute implémentation :
- vérifier la stable `v0.0.3`, ses owners, architecture, deltas/histories, `DEFER` et revue d'horizon ;
- comparer les clients/ORM/migrations Rust actuels ;
- sélectionner `tokio-postgres` comme driver, `deadpool-postgres` comme pool et Refinery comme migrator, sans ORM ;
- retenir `knowledge-store-postgres-lib` comme owner futur du pool, des migrations et de l'état PostgreSQL ;
- borner le premier schéma à `knowledge_sources` et `knowledge_source_sync_state` ;
- définir une configuration injectée sans fuite de secrets et sans fallback caché ;
- définir une stratégie de tests PostgreSQL réels par schéma éphémère ;
- préparer l'étude `008` et le plan `004` ;
- conserver l'horizon produit existant puisqu'aucune dépendance future n'est invalidée.
Aucun code produit, aucune nouvelle crate, aucune dépendance Cargo/npm, aucune migration SQL et aucun fichier Web ne sont ajoutés dans cette tranche.
`CHANGELOG.md` reste inchangé conformément au prompt de démarrage : l'entrée `0.0.4` ne sera préparée qu'à l'approche de la stabilisation.
## Décisions retenues
```text
owner PostgreSQL knowledge-store-postgres-lib (à créer en alpha.2)
driver tokio-postgres 0.7
ORM aucun
pool deadpool-postgres 0.14
migrations SQL versionné + Refinery 0.9
premier schéma source logique + dernière révision synchronisée
test PostgreSQL URL explicite + schéma éphémère isolé
autorité contenu Git
```
Les types de `tokio-postgres`, Deadpool et Refinery restent confinés à `knowledge-store-postgres-lib`. Un backend TLS sera choisi seulement si la connexion de déploiement réellement visée l'exige.
## Horizon
Aucun REPLAN d'horizon n'est nécessaire.
Restent :
```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
```
Gitea/forge, scheduler, recherche avancée, auth, modèles finaux de contenu, administration transverse et sujets Git avancés restent `DEFER`.
## Scope des fichiers
REPLACE :
```text
VERSION
Cargo.toml
README.md
RULES.md
docs/000-README.md
docs/architecture/001-PROJECT_PROFILE.md
docs/architecture/002-KNOWLEDGE_ARCHITECTURE.md
docs/validation/001-VALIDATION_MATRIX.md
```
ADD :
```text
docs/studies/008-V0_0_4_POSTGRES_FOUNDATION_STUDY.md
docs/plans/004-V0_0_4_POSTGRES_FOUNDATION_PLAN.md
deltas/0.0.4/alpha.1.md
```
DELETE : aucun.
`ROADMAP.md`, `CHANGELOG.md`, `prompts/`, `crates/` et `Web/` ne sont pas modifiés.
Aucun history `0.0.4-alpha.1` n'est inclus : il doit refléter uniquement la gate opérateur réelle.
## Gate opérateur
Exécuter depuis la racine du dépôt après application du delta.
### Version et baseline
```bash
test "$(cat VERSION)" = '0.0.4-alpha.1'
grep -F 'version = "0.0.4-alpha.1"' Cargo.toml
grep -F 'Knowledge stable tag v0.0.3' docs/architecture/001-PROJECT_PROFILE.md
grep -F 'Knowledge stable commit b3823972449150b72905930b806d4d15471cddce' docs/architecture/001-PROJECT_PROFILE.md
grep -F 'Knowledge archive SHA-256 82407dc2a83be878daa65692f975681428d0adc721ff249c3c9020e3a9d1f29d' docs/architecture/001-PROJECT_PROFILE.md
grep -F 'Knowledge publish report sasedev-knowledge-0.0.3-publish.001-report.md = PASS' docs/architecture/001-PROJECT_PROFILE.md
test "$(find deltas/0.0.3 -maxdepth 1 -type f -name '*.md' | wc -l)" -eq 12
test "$(find history/0.0.3 -maxdepth 1 -type f -name '*.md' | wc -l)" -eq 12
diff <(find deltas/0.0.3 -maxdepth 1 -type f -name '*.md' -printf '%f\n' | sort) <(find history/0.0.3 -maxdepth 1 -type f -name '*.md' -printf '%f\n' | sort)
grep -A2 '^## Statut$' history/0.0.3/rel.1.fix.1.md | grep -Fx 'PASS'
```
### Cadrage PostgreSQL et autonomie
```bash
test -f docs/studies/008-V0_0_4_POSTGRES_FOUNDATION_STUDY.md
test -f docs/plans/004-V0_0_4_POSTGRES_FOUNDATION_PLAN.md
test -f deltas/0.0.4/alpha.1.md
test ! -e history/0.0.4/alpha.1.md
grep -F '`tokio-postgres` comme driver PostgreSQL' docs/studies/008-V0_0_4_POSTGRES_FOUNDATION_STUDY.md
grep -F '`deadpool-postgres` comme pool' docs/studies/008-V0_0_4_POSTGRES_FOUNDATION_STUDY.md
grep -F '`refinery` comme owner technique des migrations SQL' docs/studies/008-V0_0_4_POSTGRES_FOUNDATION_STUDY.md
grep -F 'knowledge-store-postgres-lib' docs/studies/008-V0_0_4_POSTGRES_FOUNDATION_STUDY.md
grep -F 'knowledge_sources' docs/studies/008-V0_0_4_POSTGRES_FOUNDATION_STUDY.md
grep -F 'knowledge_source_sync_state' docs/studies/008-V0_0_4_POSTGRES_FOUNDATION_STUDY.md
grep -F 'KNOWLEDGE_POSTGRES_TEST_URL' docs/studies/008-V0_0_4_POSTGRES_FOUNDATION_STUDY.md
grep -F 'Ne pas rechercher, charger ni adopter automatiquement une nouvelle version de PGR.' prompts/004-V0_0_4_START_PROMPT.md
grep -F 'PGR `v0.1.3` reste une provenance historique' docs/plans/004-V0_0_4_POSTGRES_FOUNDATION_PLAN.md
test ! -e crates/knowledge-store-postgres-lib
test ! -e migrations
test ! -e history/0.0.4/alpha.1.md
test -z "$(git status --short -- crates Web CHANGELOG.md ROADMAP.md prompts)"
```
### Documentation puis formatage/audits Rust
```bash
git diff --check
python3 -B scripts/audit_markdown_headers.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts deltas history
python3 -B scripts/audit_markdown_links.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts deltas history
python3 -B scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts deltas history
cargo fmt --all
cargo fmt --all -- --check
python3 -B scripts/audit_rust_test_layout.py crates
python3 -B scripts/audit_rust_blank_lines.py crates
python3 -B scripts/audit_rust_item_spacing.py crates
python3 -B scripts/audit_rust_module_order.py crates
python3 -B scripts/audit_rust_trait_import_blocks.py crates
python3 -B scripts/audit_rust_reexport_blocks.py crates
python3 -B scripts/audit_rust_crate_root_facades.py crates
python3 -B scripts/audit_rust_export_completeness.py --root . --summary-only
cargo metadata --format-version 1 --no-deps > /tmp/sasedev-knowledge-0.0.4-alpha.1-metadata.json
cargo check --workspace
```
`alpha.1` ne rejoue pas Clippy, tests workspace, npm/Vite ou smokes HTTP : aucun source Rust, dépendance, frontend ou runtime n'est modifié. `cargo check --workspace` vérifie néanmoins le manifest après promotion de version.
### Structure, horizon et hygiène
```bash
python3 -c 'import json; from pathlib import Path; m=json.loads(Path("/tmp/sasedev-knowledge-0.0.4-alpha.1-metadata.json").read_text()); assert len(m["workspace_members"]) == 9; assert {p["name"] for p in m["packages"]} == {"knowledge-app-lib","knowledge-domain-lib","knowledge-git-api","knowledge-git-lib","knowledge-sync-api","knowledge-web-lib","knowledge-pgr-server","knowledge-howtos-server","knowledge-snippets-server"}; print("Knowledge 0.0.4-alpha.1 workspace audit: clean")'
grep -F -- '- `( ) 0.0.4` — fondation PostgreSQL partagée' ROADMAP.md
grep -F -- '- `(h) 0.0.5` — modèles de contenu et projections' ROADMAP.md
grep -F -- '- `(h) 0.0.10` — gestion, proposition, revue et publication' ROADMAP.md
python3 -c 'from pathlib import Path; roots=[Path("README.md"),Path("RULES.md"),Path("ROADMAP.md"),Path("CHANGELOG.md"),Path("docs"),Path("prompts"),Path("deltas"),Path("history")]; paths=[p for r in roots for p in ([r] if r.is_file() else r.rglob("*")) if p.is_file()]; bad=[str(p) for p in paths if (lambda b: b"\r" in b or not b.endswith(b"\n") or b.endswith(b"\n\n") or any(line != line.rstrip(" \t") for line in b.decode("utf-8").splitlines()))(p.read_bytes())]; assert not bad, bad; print(f"Knowledge 0.0.4-alpha.1 text hygiene: clean ({len(paths)} file(s))")'
test -f Cargo.lock
git check-ignore -q Cargo.lock
if git ls-files --error-unmatch Cargo.lock >/dev/null 2>&1; then echo 'Cargo.lock must remain untracked for Knowledge' >&2; exit 1; fi
test -f Web/knowledge-template-lab/package-lock.json
git add -A
git diff --cached --check
git status --short
```
## Transition
### PASS
Produire séparément :
```text
history/0.0.4/alpha.1.md
```
avec les résultats réellement observés. Après application du history, commit/push `0.0.4-alpha.1`, puis seulement préparer `0.0.4-alpha.2` qui matérialisera la crate PostgreSQL, `tokio-postgres`, `deadpool-postgres`, Refinery et la première migration.
### FAIL / PARTIAL / BLOCKED
Produire le history réel, l'appliquer et le committer avant toute correction.
Une correction bornée au cadrage utilise `0.0.4-alpha.1.fix.1`. Si le diagnostic invalide le driver/pool/migrator retenu, l'ownership, le schéma ou la stratégie de test, exécuter un REPLAN plutôt que d'absorber une architecture différente dans un fix.

View File

@@ -0,0 +1,179 @@
<!-- file: deltas/0.0.4/alpha.2.fix.1.md -->
<!-- version: 1 -->
# Delta 0.0.4-alpha.2.fix.1 — documentation de la crate de test PostgreSQL
## Baseline requise
Partir de `0.0.4-alpha.2` après application, commit et push de son history `FAIL`.
La version devient :
```text
0.0.4-alpha.2.fix.1
```
Le history requis est :
```text
history/0.0.4/alpha.2.md = FAIL
```
## Objet
Corriger uniquement le défaut Clippy observé pendant la gate `alpha.2` : la target d'intégration `tests/postgres_migration.rs` ne possède pas de documentation de crate alors que `missing_docs` est activé et promu en erreur par `-D warnings`.
Le fix ajoute une documentation interne `//!` en tête de cette crate de test.
Aucun code produit, contrat public, dépendance, configuration de pool, migration SQL ou comportement PostgreSQL n'est modifié. La preuve PostgreSQL réelle de `alpha.2` a déjà passé après fourniture explicite de `KNOWLEDGE_POSTGRES_TEST_URL`, mais elle est rejouée pour fermer complètement le fix.
## Scope des fichiers
REPLACE :
```text
VERSION
Cargo.toml
crates/knowledge-store-postgres-lib/tests/postgres_migration.rs
docs/plans/004-V0_0_4_POSTGRES_FOUNDATION_PLAN.md
```
ADD :
```text
deltas/0.0.4/alpha.2.fix.1.md
```
DELETE : aucun.
Les fichiers suivants restent inchangés :
```text
crates/knowledge-store-postgres-lib/src/
crates/knowledge-store-postgres-lib/unit_tests/
crates/knowledge-store-postgres-lib/migrations/
crates/knowledge-store-postgres-lib/Cargo.toml
README.md
RULES.md
ROADMAP.md
CHANGELOG.md
docs/architecture/
docs/studies/
docs/validation/
Web/
prompts/
```
Aucun history `alpha.2.fix.1` n'est inclus dans ce delta.
## Précondition PostgreSQL
La gate requiert toujours une base PostgreSQL de test permettant de créer et supprimer un schéma.
Avant la preuve PostgreSQL, définir explicitement dans le shell opérateur :
```bash
export KNOWLEDGE_POSTGRES_TEST_URL='postgresql://knowledge:knowledge@localhost/knowledge'
```
Adapter l'URL si nécessaire. Ne jamais versionner cette valeur.
Si PostgreSQL n'est pas disponible, classer la gate `BLOCKED` à cette étape ; ne pas convertir cette absence en `PASS`.
## Gate opérateur
Exécuter depuis la racine du dépôt après application du delta.
### Version, history précédent et correction bornée
```bash
test "$(cat VERSION)" = '0.0.4-alpha.2.fix.1'
grep -F 'version = "0.0.4-alpha.2.fix.1"' Cargo.toml
test -f history/0.0.4/alpha.2.md
grep -A2 '^## Statut$' history/0.0.4/alpha.2.md | grep -Fx 'FAIL'
git ls-files --error-unmatch history/0.0.4/alpha.2.md >/dev/null
test -z "$(git status --short -- history/0.0.4/alpha.2.md)"
grep -Fx '//! Integration test for the initial PostgreSQL migration in an isolated schema.' crates/knowledge-store-postgres-lib/tests/postgres_migration.rs
grep -F '### alpha.2.fix.1 — documentation de la crate de test PostgreSQL' docs/plans/004-V0_0_4_POSTGRES_FOUNDATION_PLAN.md
grep -F '`alpha.2` historisée `FAIL`' docs/plans/004-V0_0_4_POSTGRES_FOUNDATION_PLAN.md
grep -F 'autoriser `alpha.3` uniquement après `PASS` complet du fix' docs/plans/004-V0_0_4_POSTGRES_FOUNDATION_PLAN.md
test ! -e history/0.0.4/alpha.2.fix.1.md
git diff --check
```
### Scope négatif
```bash
test -z "$(git diff --name-only -- crates/knowledge-store-postgres-lib/src crates/knowledge-store-postgres-lib/unit_tests crates/knowledge-store-postgres-lib/migrations crates/knowledge-store-postgres-lib/Cargo.toml README.md RULES.md ROADMAP.md CHANGELOG.md docs/architecture docs/studies docs/validation Web prompts)"
```
### Markdown puis séquence Rust
```bash
python3 -B scripts/audit_markdown_headers.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts deltas history
python3 -B scripts/audit_markdown_links.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts deltas history
python3 -B scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts deltas history
cargo fmt --all
cargo fmt --all -- --check
python3 -B scripts/audit_rust_test_layout.py crates
python3 -B scripts/audit_rust_blank_lines.py crates
python3 -B scripts/audit_rust_item_spacing.py crates
python3 -B scripts/audit_rust_module_order.py crates
python3 -B scripts/audit_rust_trait_import_blocks.py crates
python3 -B scripts/audit_rust_reexport_blocks.py crates
python3 -B scripts/audit_rust_crate_root_facades.py crates
python3 -B scripts/audit_rust_export_completeness.py --root . --summary-only
cargo metadata --format-version 1 --no-deps > /tmp/sasedev-knowledge-0.0.4-alpha.2.fix.1-metadata.json
cargo check --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test -p knowledge-store-postgres-lib
cargo test --workspace --all-targets --all-features
```
### Composition workspace
```bash
python3 -c 'import json; from pathlib import Path; m=json.loads(Path("/tmp/sasedev-knowledge-0.0.4-alpha.2.fix.1-metadata.json").read_text()); expected={"knowledge-app-lib","knowledge-domain-lib","knowledge-git-api","knowledge-git-lib","knowledge-sync-api","knowledge-web-lib","knowledge-pgr-server","knowledge-howtos-server","knowledge-snippets-server","knowledge-store-postgres-lib"}; assert len(m["workspace_members"]) == 10; assert {p["name"] for p in m["packages"]} == expected; print("Knowledge 0.0.4-alpha.2.fix.1 workspace audit: clean")'
```
### PostgreSQL réel obligatoire
```bash
test -n "${KNOWLEDGE_POSTGRES_TEST_URL:-}"
cargo test -p knowledge-store-postgres-lib --test postgres_migration -- --ignored --nocapture
```
### Hygiène, lockfiles et staging
```bash
python3 -c 'from pathlib import Path; roots=[Path("README.md"),Path("RULES.md"),Path("ROADMAP.md"),Path("CHANGELOG.md"),Path("Cargo.toml"),Path("VERSION"),Path("docs"),Path("prompts"),Path("deltas"),Path("history"),Path("crates")]; allowed={".md",".rs",".toml",".sql"}; paths=[p for r in roots for p in ([r] if r.is_file() else r.rglob("*")) if p.is_file() and (p.name == "VERSION" or p.suffix in allowed)]; bad=[str(p) for p in paths if (lambda b: b"\r" in b or not b.endswith(b"\n") or b.endswith(b"\n\n") or any(line != line.rstrip(" \t") for line in b.decode("utf-8").splitlines()))(p.read_bytes())]; assert not bad, bad; print(f"Knowledge 0.0.4-alpha.2.fix.1 text hygiene: clean ({len(paths)} file(s))")'
test -f Cargo.lock
git check-ignore -q Cargo.lock
if git ls-files --error-unmatch Cargo.lock >/dev/null 2>&1; then echo 'Cargo.lock must remain untracked for Knowledge' >&2; exit 1; fi
test -f Web/knowledge-template-lab/package-lock.json
git diff --quiet -- Web/knowledge-template-lab/package-lock.json
git add -A
git diff --cached --check
git status --short
```
## Transition
### PASS
Produire `history/0.0.4/alpha.2.fix.1.md`, l'appliquer, commit/push `0.0.4-alpha.2.fix.1`, puis préparer `0.0.4-alpha.3` pour la persistance minimale de source et d'état de synchronisation.
### FAIL / PARTIAL / BLOCKED
Conserver le résultat réel dans son history avant toute nouvelle correction. Un défaut borné supplémentaire utilise `alpha.2.fix.2`. Si le diagnostic invalide l'ownership PostgreSQL, les dépendances retenues, le schéma ou la stratégie d'isolation, effectuer un REPLAN avant de poursuivre.

279
deltas/0.0.4/alpha.2.md Normal file
View File

@@ -0,0 +1,279 @@
<!-- file: deltas/0.0.4/alpha.2.md -->
<!-- version: 1 -->
# Delta 0.0.4-alpha.2 — owner PostgreSQL, pool et première migration
## Baseline requise
Partir de `0.0.4-alpha.1` validée et historisée `PASS` :
```text
version précédente 0.0.4-alpha.1
history requis history/0.0.4/alpha.1.md = PASS
stable autoritaire v0.0.3
owner décidé knowledge-store-postgres-lib
driver décidé tokio-postgres
pool décidé deadpool-postgres
migrator décidé Refinery
```
Le history `alpha.1` doit être committé et poussé avant application du présent delta.
La version devient :
```text
0.0.4-alpha.2
```
## Objet
Matérialiser la première frontière PostgreSQL réelle sans encore raccorder les launchers ou les cas d'usage applicatifs :
- créer `knowledge-store-postgres-lib` comme unique owner PostgreSQL ;
- ajouter `tokio-postgres 0.7.18` comme driver async natif avec uniquement la feature `runtime` ;
- ajouter `deadpool-postgres 0.14.2` comme pool avec uniquement `rt_tokio_1` ;
- ajouter Refinery `0.9.2` avec uniquement son support `tokio-postgres` ;
- utiliser Tokio `1.53.1` uniquement comme runtime de test ;
- recevoir URL PostgreSQL et taille du pool par configuration injectée ;
- ne jamais lire de secret depuis l'environnement dans la crate produit ;
- construire un pool borné et conserver `NoTls` comme choix initial explicite ;
- embarquer `V1__initial_sources.sql` via Refinery ;
- créer uniquement `knowledge_sources` et `knowledge_source_sync_state` ;
- exposer une application explicite des migrations ;
- prouver le chemin sur un PostgreSQL réel isolé par schéma temporaire.
Git reste l'autorité du contenu publié. Cette tranche ne stocke ni corps de contenu, ni credential Git, ni compte, proposition, job, index ou projection finale.
## Dépendances retenues
```text
tokio-postgres 0.7.18 default-features = false, features = ["runtime"]
deadpool-postgres 0.14.2 default-features = false, features = ["rt_tokio_1"]
refinery 0.9.2 default-features = false, features = ["tokio-postgres"]
tokio 1.53.1 dev only, features = ["macros", "rt-multi-thread"]
```
Aucun ORM, TLS backend supplémentaire ou abstraction multi-SGBD n'est introduit.
## Contrat public
La façade crate-root est limitée à :
```text
PostgresStoreConfig
PostgresStore
PostgresStoreError
```
Les types `tokio-postgres`, Deadpool et Refinery restent privés à l'implémentation.
`PostgresStoreConfig` ne fournit aucun getter public de l'URL et n'implémente volontairement pas `Debug`. L'URL peut contenir des credentials et ne doit pas être exposée dans les erreurs ou logs.
## Premier schéma
```text
knowledge_sources
source_id TEXT PRIMARY KEY
family TEXT NOT NULL CHECK pgr/howto/snippet/project_local
git_reference TEXT NOT NULL
knowledge_source_sync_state
source_id TEXT PRIMARY KEY REFERENCES knowledge_sources ON DELETE CASCADE
last_synchronized_revision TEXT NOT NULL
```
Refinery possède sa table technique de suivi des migrations. Aucune autre table métier n'est créée.
## Scope des fichiers
REPLACE :
```text
VERSION
Cargo.toml
README.md
RULES.md
docs/architecture/001-PROJECT_PROFILE.md
docs/architecture/002-KNOWLEDGE_ARCHITECTURE.md
docs/plans/004-V0_0_4_POSTGRES_FOUNDATION_PLAN.md
docs/studies/008-V0_0_4_POSTGRES_FOUNDATION_STUDY.md
docs/validation/001-VALIDATION_MATRIX.md
```
ADD :
```text
crates/knowledge-store-postgres-lib/Cargo.toml
crates/knowledge-store-postgres-lib/src/lib.rs
crates/knowledge-store-postgres-lib/src/config.rs
crates/knowledge-store-postgres-lib/src/error.rs
crates/knowledge-store-postgres-lib/src/store.rs
crates/knowledge-store-postgres-lib/unit_tests/config.rs
crates/knowledge-store-postgres-lib/tests/postgres_migration.rs
crates/knowledge-store-postgres-lib/migrations/V1__initial_sources.sql
deltas/0.0.4/alpha.2.md
```
DELETE : aucun.
Aucun fichier sous `Web/`, les trois launchers, `knowledge-app-lib`, `knowledge-domain-lib`, `knowledge-git-api`, `knowledge-git-lib` ou `knowledge-sync-api` n'est modifié.
Aucun history `0.0.4-alpha.2` n'est inclus : il doit refléter uniquement la gate opérateur réelle.
## Précondition PostgreSQL de la gate
La gate réelle nécessite une base PostgreSQL de test accessible avec les droits de créer et supprimer un schéma. Fournir l'URL uniquement dans l'environnement opérateur :
```bash
export KNOWLEDGE_POSTGRES_TEST_URL='postgresql://...'
```
Ne jamais versionner cette valeur.
Si `KNOWLEDGE_POSTGRES_TEST_URL` est absent ou si PostgreSQL n'est pas joignable, arrêter la gate et classer la tranche `BLOCKED`. Ne pas convertir cette absence en `PASS` ou en test ignoré.
## Gate opérateur
Exécuter depuis la racine du dépôt après application du delta.
### Version, history précédent et scope
```bash
test "$(cat VERSION)" = '0.0.4-alpha.2'
grep -F 'version = "0.0.4-alpha.2"' Cargo.toml
test -f history/0.0.4/alpha.1.md
grep -A2 '^## Statut$' history/0.0.4/alpha.1.md | grep -Fx 'PASS'
git ls-files --error-unmatch history/0.0.4/alpha.1.md >/dev/null
test -z "$(git status --short -- history/0.0.4/alpha.1.md)"
test -d crates/knowledge-store-postgres-lib
test -f crates/knowledge-store-postgres-lib/migrations/V1__initial_sources.sql
test -f deltas/0.0.4/alpha.2.md
test ! -e history/0.0.4/alpha.2.md
test -z "$(git status --short -- Web crates/knowledge-pgr-server crates/knowledge-howtos-server crates/knowledge-snippets-server crates/knowledge-app-lib crates/knowledge-domain-lib crates/knowledge-git-api crates/knowledge-git-lib crates/knowledge-sync-api)"
git diff --check
```
### Dépendances, façade et configuration
```bash
grep -F 'tokio-postgres = { version = "0.7.18", default-features = false, features = ["runtime"] }' crates/knowledge-store-postgres-lib/Cargo.toml
grep -F 'deadpool-postgres = { version = "0.14.2", default-features = false, features = ["rt_tokio_1"] }' crates/knowledge-store-postgres-lib/Cargo.toml
grep -F 'refinery = { version = "0.9.2", default-features = false, features = ["tokio-postgres"] }' crates/knowledge-store-postgres-lib/Cargo.toml
grep -F 'tokio = { version = "1.53.1", default-features = false, features = ["macros", "rt-multi-thread"] }' crates/knowledge-store-postgres-lib/Cargo.toml
test "$(grep -c '^pub use crate::' crates/knowledge-store-postgres-lib/src/lib.rs)" -eq 3
grep -Fx 'pub use crate::config::PostgresStoreConfig;' crates/knowledge-store-postgres-lib/src/lib.rs
grep -Fx 'pub use crate::error::PostgresStoreError;' crates/knowledge-store-postgres-lib/src/lib.rs
grep -Fx 'pub use crate::store::PostgresStore;' crates/knowledge-store-postgres-lib/src/lib.rs
! grep -R -n -E 'std::env|KNOWLEDGE_POSTGRES_TEST_URL' crates/knowledge-store-postgres-lib/src
! grep -R -n -E 'println!|eprintln!|dbg!' crates/knowledge-store-postgres-lib/src
grep -F 'max_pool_size' crates/knowledge-store-postgres-lib/src/config.rs
grep -F 'deadpool_postgres::Manager::new' crates/knowledge-store-postgres-lib/src/store.rs
grep -F 'deadpool_postgres::Pool::builder' crates/knowledge-store-postgres-lib/src/store.rs
grep -F 'tokio_postgres::NoTls' crates/knowledge-store-postgres-lib/src/store.rs
grep -F 'run_async(client)' crates/knowledge-store-postgres-lib/src/store.rs
```
### Migration et test ciblé
```bash
grep -F 'CREATE TABLE knowledge_sources' crates/knowledge-store-postgres-lib/migrations/V1__initial_sources.sql
grep -F "CHECK (family IN ('pgr', 'howto', 'snippet', 'project_local'))" crates/knowledge-store-postgres-lib/migrations/V1__initial_sources.sql
grep -F 'CREATE TABLE knowledge_source_sync_state' crates/knowledge-store-postgres-lib/migrations/V1__initial_sources.sql
grep -F 'REFERENCES knowledge_sources(source_id) ON DELETE CASCADE' crates/knowledge-store-postgres-lib/migrations/V1__initial_sources.sql
grep -F 'last_synchronized_revision TEXT NOT NULL' crates/knowledge-store-postgres-lib/migrations/V1__initial_sources.sql
! grep -E -i '\b(content|body|credential|account|proposal|job)\b' crates/knowledge-store-postgres-lib/migrations/V1__initial_sources.sql
grep -F '#[ignore = "requires KNOWLEDGE_POSTGRES_TEST_URL"]' crates/knowledge-store-postgres-lib/tests/postgres_migration.rs
grep -F 'CREATE SCHEMA' crates/knowledge-store-postgres-lib/tests/postgres_migration.rs
grep -F 'DROP SCHEMA' crates/knowledge-store-postgres-lib/tests/postgres_migration.rs
```
### Markdown puis séquence Rust
```bash
python3 -B scripts/audit_markdown_headers.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts deltas history
python3 -B scripts/audit_markdown_links.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts deltas history
python3 -B scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts deltas history
cargo fmt --all
cargo fmt --all -- --check
python3 -B scripts/audit_rust_test_layout.py crates
python3 -B scripts/audit_rust_blank_lines.py crates
python3 -B scripts/audit_rust_item_spacing.py crates
python3 -B scripts/audit_rust_module_order.py crates
python3 -B scripts/audit_rust_trait_import_blocks.py crates
python3 -B scripts/audit_rust_reexport_blocks.py crates
python3 -B scripts/audit_rust_crate_root_facades.py crates
python3 -B scripts/audit_rust_export_completeness.py --root . --summary-only
cargo metadata --format-version 1 --no-deps > /tmp/sasedev-knowledge-0.0.4-alpha.2-metadata.json
cargo check --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test -p knowledge-store-postgres-lib
cargo test --workspace --all-targets --all-features
```
### Composition workspace
```bash
python3 -c 'import json; from pathlib import Path; m=json.loads(Path("/tmp/sasedev-knowledge-0.0.4-alpha.2-metadata.json").read_text()); expected={"knowledge-app-lib","knowledge-domain-lib","knowledge-git-api","knowledge-git-lib","knowledge-sync-api","knowledge-web-lib","knowledge-pgr-server","knowledge-howtos-server","knowledge-snippets-server","knowledge-store-postgres-lib"}; assert len(m["workspace_members"]) == 10; assert {p["name"] for p in m["packages"]} == expected; print("Knowledge 0.0.4-alpha.2 workspace audit: clean")'
```
### PostgreSQL réel obligatoire
```bash
test -n "${KNOWLEDGE_POSTGRES_TEST_URL:-}"
cargo test -p knowledge-store-postgres-lib --test postgres_migration -- --ignored --nocapture
```
Si la première commande échoue ou si le test ne peut pas joindre PostgreSQL, arrêter ici et reporter `BLOCKED` avec le transcript obtenu.
### Hygiène, lockfiles et staging
```bash
python3 -c 'from pathlib import Path; roots=[Path("README.md"),Path("RULES.md"),Path("ROADMAP.md"),Path("CHANGELOG.md"),Path("Cargo.toml"),Path("VERSION"),Path("docs"),Path("prompts"),Path("deltas"),Path("history"),Path("crates")]; allowed={".md",".rs",".toml",".sql"}; paths=[p for r in roots for p in ([r] if r.is_file() else r.rglob("*")) if p.is_file() and (p.name == "VERSION" or p.suffix in allowed)]; bad=[str(p) for p in paths if (lambda b: b"\r" in b or not b.endswith(b"\n") or b.endswith(b"\n\n") or any(line != line.rstrip(" \t") for line in b.decode("utf-8").splitlines()))(p.read_bytes())]; assert not bad, bad; print(f"Knowledge 0.0.4-alpha.2 text hygiene: clean ({len(paths)} file(s))")'
test -f Cargo.lock
git check-ignore -q Cargo.lock
if git ls-files --error-unmatch Cargo.lock >/dev/null 2>&1; then echo 'Cargo.lock must remain untracked for Knowledge' >&2; exit 1; fi
test -f Web/knowledge-template-lab/package-lock.json
git diff --quiet -- Web/knowledge-template-lab/package-lock.json
git add -A
git diff --cached --check
git status --short
```
## Transition
### PASS
Produire séparément :
```text
history/0.0.4/alpha.2.md
```
avec les résultats réellement observés. Après application du history, commit/push `0.0.4-alpha.2`, puis préparer `0.0.4-alpha.3` pour la persistance minimale de source et d'état de synchronisation.
### FAIL
Produire le history réel et le committer avant correction. Une erreur bornée de code, manifest, migration ou test utilise `0.0.4-alpha.2.fix.1`.
### BLOCKED
Si seul le PostgreSQL réel requis est indisponible, historiser `BLOCKED` sans prétendre que la gate a passé. Ne modifier ni le code ni l'architecture tant qu'aucun défaut n'est démontré ; reprendre la même preuve dès qu'un PostgreSQL de test est disponible.
### REPLAN
Replanifier si la toolchain stable réellement utilisée est incompatible avec les versions retenues, si l'isolation par schéma n'est pas fiable ou si l'ownership PostgreSQL doit être changé.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/000-README.md --> <!-- file: docs/000-README.md -->
<!-- version: 12 --> <!-- version: 13 -->
# Documentation SaseDev Knowledge # Documentation SaseDev Knowledge
@@ -33,12 +33,14 @@
- [`studies/005-V0_0_2_GIT_SYNC_RECONCILIATION.md`](studies/005-V0_0_2_GIT_SYNC_RECONCILIATION.md) — réconciliation beta du chemin Git/synchronisation, `DEFER` conservés et revue d'horizon sans prochaine release réservée. - [`studies/005-V0_0_2_GIT_SYNC_RECONCILIATION.md`](studies/005-V0_0_2_GIT_SYNC_RECONCILIATION.md) — réconciliation beta du chemin Git/synchronisation, `DEFER` conservés et revue d'horizon sans prochaine release réservée.
- [`studies/006-V0_0_3_GIT_WRITE_STUDY.md`](studies/006-V0_0_3_GIT_WRITE_STUDY.md) — décision d'engager l'écriture Git contrôlée, stratégie de worktree et invariants de concurrence. - [`studies/006-V0_0_3_GIT_WRITE_STUDY.md`](studies/006-V0_0_3_GIT_WRITE_STUDY.md) — décision d'engager l'écriture Git contrôlée, stratégie de worktree et invariants de concurrence.
- [`studies/007-V0_0_3_GIT_WRITE_RECONCILIATION.md`](studies/007-V0_0_3_GIT_WRITE_RECONCILIATION.md) — réconciliation beta du chemin Git d'écriture, DEFER reclassés et horizon produit des trois sites. - [`studies/007-V0_0_3_GIT_WRITE_RECONCILIATION.md`](studies/007-V0_0_3_GIT_WRITE_RECONCILIATION.md) — réconciliation beta du chemin Git d'écriture, DEFER reclassés et horizon produit des trois sites.
- [`studies/008-V0_0_4_POSTGRES_FOUNDATION_STUDY.md`](studies/008-V0_0_4_POSTGRES_FOUNDATION_STUDY.md) — comparaison PostgreSQL de démarrage `0.0.4`, décision `tokio-postgres`/Deadpool/Refinery, ownership, schéma minimal, migrations et tests éphémères.
## Plans ## Plans
- [`plans/001-V0_0_1_FOUNDATION_PLAN.md`](plans/001-V0_0_1_FOUNDATION_PLAN.md) — plan historique de la stable de fondation `0.0.1`. - [`plans/001-V0_0_1_FOUNDATION_PLAN.md`](plans/001-V0_0_1_FOUNDATION_PLAN.md) — plan historique de la stable de fondation `0.0.1`.
- [`plans/002-V0_0_2_GIT_SYNC_PLAN.md`](plans/002-V0_0_2_GIT_SYNC_PLAN.md) — plan historique de la stable Git générique et synchronisation de lecture `0.0.2`. - [`plans/002-V0_0_2_GIT_SYNC_PLAN.md`](plans/002-V0_0_2_GIT_SYNC_PLAN.md) — plan historique de la stable Git générique et synchronisation de lecture `0.0.2`.
- [`plans/003-V0_0_3_GIT_WRITE_PLAN.md`](plans/003-V0_0_3_GIT_WRITE_PLAN.md) — plan historique de la stable `0.0.3`, écriture Git contrôlée et push gardé. - [`plans/003-V0_0_3_GIT_WRITE_PLAN.md`](plans/003-V0_0_3_GIT_WRITE_PLAN.md) — plan historique de la stable `0.0.3`, écriture Git contrôlée et push gardé.
- [`plans/004-V0_0_4_POSTGRES_FOUNDATION_PLAN.md`](plans/004-V0_0_4_POSTGRES_FOUNDATION_PLAN.md) — plan actif de la fondation PostgreSQL partagée `0.0.4`.
## Validation ## Validation

View File

@@ -1,20 +1,22 @@
<!-- file: docs/architecture/001-PROJECT_PROFILE.md --> <!-- file: docs/architecture/001-PROJECT_PROFILE.md -->
<!-- version: 18 --> <!-- version: 20 -->
# Profil du projet Knowledge # Profil du projet Knowledge
## Baseline autoritaire ## Baseline autoritaire
La stable produit depuis laquelle `0.0.3` est ouverte est : La stable produit depuis laquelle `0.0.4` est ouverte est :
```text ```text
Knowledge stable tag v0.0.2 Knowledge stable tag v0.0.3
Knowledge stable commit 183d354a67bec6d2d512c4898f5189759a6120b0 Knowledge stable commit b3823972449150b72905930b806d4d15471cddce
Knowledge archive SHA-256 0e518c7eaad115811cccc8fb2b38a1e68150ec985c2ca72ec08a9ca5bbb202ce Knowledge archive SHA-256 82407dc2a83be878daa65692f975681428d0adc721ff249c3c9020e3a9d1f29d
Knowledge publish report sasedev-knowledge-0.0.2-publish.001-report.md = PASS Knowledge publish report sasedev-knowledge-0.0.3-publish.001-report.md = PASS
Knowledge start prompt prompts/003-V0_0_3_START_PROMPT.md Knowledge start prompt prompts/004-V0_0_4_START_PROMPT.md
``` ```
L'archive taggée `v0.0.3` a été vérifiée avant le cadrage `0.0.4-alpha.1` : `VERSION` et le workspace Cargo valent `0.0.3`, les douze deltas et douze histories `0.0.3` sont appariés, `rel.1.fix.1 = PASS` clôt la release et le commentaire ZIP contient le commit stable ci-dessus.
La fondation `0.0.1` a été construite sous PGR `v0.1.1`. Cette identité reste historique dans les artefacts `0.0.1`. La fondation `0.0.1` a été construite sous PGR `v0.1.1`. Cette identité reste historique dans les artefacts `0.0.1`.
Le démarrage explicite de `0.0.2` a réévalué PGR et a retenu la stable suivante comme source d'adoption : Le démarrage explicite de `0.0.2` a réévalué PGR et a retenu la stable suivante comme source d'adoption :
@@ -91,7 +93,7 @@ Le détail de la migration depuis les owners PGR `v0.1.3`, y compris les décisi
| Synchronisation sans webhook | `KEEP-LOCAL` | explicite/périodique convergent vers le même cas d'usage ; hooks/webhooks restent accélérateurs | | Synchronisation sans webhook | `KEEP-LOCAL` | explicite/périodique convergent vers le même cas d'usage ; hooks/webhooks restent accélérateurs |
| Scheduler périodique concret | `DEFER` | créer seulement lorsque son owner runtime/lifecycle est démontré | | Scheduler périodique concret | `DEFER` | créer seulement lorsque son owner runtime/lifecycle est démontré |
| Dernière révision observée en `0.0.2` | `KEEP-LOCAL` | fournie par l'appelant et retournée par le cas d'usage ; pas de pseudo-persistance locale | | Dernière révision observée en `0.0.2` | `KEEP-LOCAL` | fournie par l'appelant et retournée par le cas d'usage ; pas de pseudo-persistance locale |
| PostgreSQL | `KEEP-LOCAL` | une base logique partagée future pour état transversal/projections ; jamais vérité du contenu Git publié | | PostgreSQL | `KEEP-LOCAL` | une base logique partagée ; `0.0.4` matérialise sa première fondation sans déplacer la vérité éditoriale de Git |
| Rust stable / édition 2024 | `ADOPT` | owner local `docs/rules/510-RUST_CARGO.md` | | Rust stable / édition 2024 | `ADOPT` | owner local `docs/rules/510-RUST_CARGO.md` |
| Workspace Cargo | `ADOPT` | configuration locale + owner `510-RUST_CARGO.md` | | Workspace Cargo | `ADOPT` | configuration locale + owner `510-RUST_CARGO.md` |
| `Cargo.lock` | `KEEP-LOCAL` | généré localement et ignoré ; manifests Cargo versionnés | | `Cargo.lock` | `KEEP-LOCAL` | généré localement et ignoré ; manifests Cargo versionnés |
@@ -105,8 +107,8 @@ Le détail de la migration depuis les owners PGR `v0.1.3`, y compris les décisi
| Racine frontend | `KEEP-LOCAL` | package partagé `Web/knowledge-template-lab/` | | Racine frontend | `KEEP-LOCAL` | package partagé `Web/knowledge-template-lab/` |
| Templates statiques Web | `KEEP-LOCAL` | harness de conception/validation ; rendu runtime Maud | | Templates statiques Web | `KEEP-LOCAL` | harness de conception/validation ; rendu runtime Maud |
| Intégration manifest Vite / Maud | `KEEP-LOCAL` | matérialisée dans `knowledge-web-lib` | | Intégration manifest Vite / Maud | `KEEP-LOCAL` | matérialisée dans `knowledge-web-lib` |
| Driver/ORM PostgreSQL | `DEFER` | reprendre à la première implémentation persistante réelle | | Toolkit PostgreSQL | `KEEP-LOCAL` | `tokio-postgres` + `deadpool-postgres`, async/Tokio et SQL explicite ; aucun ORM sélectionné |
| Migrations PostgreSQL | `DEFER` | reprendre avec le premier schéma réel | | Migrations PostgreSQL | `KEEP-LOCAL` | SQL versionné possédé par `knowledge-store-postgres-lib`, appliqué explicitement via Refinery |
| Moteur de recherche | `DEFER` | commencer par capacités PostgreSQL/index applicatif lorsque ce scope sera engagé | | Moteur de recherche | `DEFER` | commencer par capacités PostgreSQL/index applicatif lorsque ce scope sera engagé |
| Fournisseur d'auth externe | `DEFER` | reprendre lorsque le workflow utilisateur l'exige | | Fournisseur d'auth externe | `DEFER` | reprendre lorsque le workflow utilisateur l'exige |
| Surface admin par application | `KEEP-LOCAL` | chaque serveur protège ses opérations privilégiées ; URL exacte différée | | Surface admin par application | `KEEP-LOCAL` | chaque serveur protège ses opérations privilégiées ; URL exacte différée |
@@ -129,16 +131,18 @@ knowledge-web-lib composition Actix/Maud/Vite partagée
knowledge-pgr-server launcher PGR mince knowledge-pgr-server launcher PGR mince
knowledge-howtos-server launcher HOWTOs mince knowledge-howtos-server launcher HOWTOs mince
knowledge-snippets-server launcher snippets mince knowledge-snippets-server launcher snippets mince
knowledge-store-postgres-lib pool, migrations et état applicatif PostgreSQL partagé
``` ```
`knowledge-git-lib` devient réelle en `0.0.2-alpha.2` puis implémente le chemin de lecture Git dans `alpha.3`. `knowledge-app-lib` devient réelle en `0.0.2-alpha.5` : l'orchestration refresh / résolution / comparaison / snapshot confirme une responsabilité application partagée distincte du backend Git et des launchers. `knowledge-git-lib` devient réelle en `0.0.2-alpha.2` puis implémente le chemin de lecture Git dans `alpha.3`. `knowledge-app-lib` devient réelle en `0.0.2-alpha.5` : l'orchestration refresh / résolution / comparaison / snapshot confirme une responsabilité application partagée distincte du backend Git et des launchers.
`0.0.4-alpha.2` matérialise `knowledge-store-postgres-lib` comme responsabilité réelle : configuration explicite, pool `deadpool-postgres`, migrations Refinery et premier schéma partagé. Aucun `knowledge-store-api` symétrique n'est introduit.
Les responsabilités suivantes restent candidates et non matérialisées : Les responsabilités suivantes restent candidates et non matérialisées :
```text ```text
knowledge-store-postgres-lib état applicatif PostgreSQL partagé knowledge-forge-gitea-lib adapter Gitea optionnel
knowledge-forge-gitea-lib adapter Gitea optionnel knowledge-logging-lib diagnostics partagés, seulement sur besoin multi-runtime réel
knowledge-logging-lib diagnostics partagés, seulement sur besoin multi-runtime réel
``` ```
Règles de création : Règles de création :
@@ -177,3 +181,25 @@ Restent différés après `0.0.2` : adapter Gitea, PostgreSQL/migrations, moteur
La revue d'horizon `0.0.2-beta.1` n'avait réservé aucune release suivante. L'ouverture explicite de `0.0.3` a consommé uniquement le `DEFER` d'écriture Git contrôlée : worktree d'écriture isolé, commit candidat et push de branche gardé. Rebase/merge automatique et workflow complet de proposition restent différés. La revue d'horizon `0.0.2-beta.1` n'avait réservé aucune release suivante. L'ouverture explicite de `0.0.3` a consommé uniquement le `DEFER` d'écriture Git contrôlée : worktree d'écriture isolé, commit candidat et push de branche gardé. Rebase/merge automatique et workflow complet de proposition restent différés.
La revue `0.0.3-beta.1` sélectionne désormais la fondation PostgreSQL partagée comme prochaine mission `0.0.4`, sans préchoisir son driver/ORM avant l'étude de démarrage. Elle réordonne ensuite l'horizon produit pour rendre visibles les phases de modèles/projections, templates publics, templates admin, intégration Actix/Maud puis workflow de gestion/publication. Gitea, scheduler, recherche avancée, quatrième application admin et partage multi-processus restent différés tant que leurs déclencheurs ne sont pas matérialisés. La revue `0.0.3-beta.1` sélectionne désormais la fondation PostgreSQL partagée comme prochaine mission `0.0.4`, sans préchoisir son driver/ORM avant l'étude de démarrage. Elle réordonne ensuite l'horizon produit pour rendre visibles les phases de modèles/projections, templates publics, templates admin, intégration Actix/Maud puis workflow de gestion/publication. Gitea, scheduler, recherche avancée, quatrième application admin et partage multi-processus restent différés tant que leurs déclencheurs ne sont pas matérialisés.
## Ouverture `0.0.4` — fondation PostgreSQL partagée
Après publication vérifiée de `v0.0.3`, `0.0.4-alpha.1` consomme les `DEFER` portant sur le toolkit PostgreSQL et les migrations.
La décision locale est :
```text
owner knowledge-store-postgres-lib
driver tokio-postgres 0.7.18
modèle SQL explicite, sans ORM
pool deadpool-postgres 0.14.2
migrations SQL versionné + Refinery 0.9.2
premier état source logique + dernière révision synchronisée
autorité contenu Git
```
`alpha.2` matérialise cette décision avec une façade crate-root limitée à `PostgresStoreConfig`, `PostgresStore` et `PostgresStoreError`, plus `V1__initial_sources.sql`. La configuration est injectée ; la crate ne lit pas `KNOWLEDGE_POSTGRES_TEST_URL` ni une autre variable d'environnement. La première connexion utilise `NoTls` et un backend TLS reste différé tant qu'un déploiement n'en démontre pas le besoin.
La configuration physique Git reste possédée par `knowledge-git-lib`. Le premier schéma PostgreSQL ne stocke pas de credentials Git et ne transforme pas les URLs/paths physiques en vérité métier.
Les `DEFER` Gitea/forge, scheduler, recherche avancée, auth/capabilities, formats finaux de contenu, quatrième application admin, partage multi-processus de racine Git, LFS/submodules et rétention avancée restent inchangés. L'horizon `0.0.5` à `0.0.10` reste cohérent et n'est pas replanifié par cette étude.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/architecture/002-KNOWLEDGE_ARCHITECTURE.md --> <!-- file: docs/architecture/002-KNOWLEDGE_ARCHITECTURE.md -->
<!-- version: 18 --> <!-- version: 20 -->
# Architecture de fondation Knowledge # Architecture de fondation Knowledge
@@ -36,6 +36,8 @@ knowledge-app-lib cas d'usage partagé de synchronisation Changed/Unchanged
Les deux crates `-api` sont justifiées par des implémentations réellement remplaçables ou multiples. Elles restent sans runtime, sans logging propre et sans dépendance à Actix, Gitea ou PostgreSQL. Les deux crates `-api` sont justifiées par des implémentations réellement remplaçables ou multiples. Elles restent sans runtime, sans logging propre et sans dépendance à Actix, Gitea ou PostgreSQL.
`0.0.4-alpha.2` matérialise `knowledge-store-postgres-lib` comme owner concret du pool, des migrations et de l'état PostgreSQL partagé. La crate masque `tokio-postgres`, Deadpool et Refinery derrière sa façade publique et aucun `knowledge-store-api` symétrique n'est introduit sans besoin de substitution démontré.
Les tests unitaires Rust sont désormais placés hors de `src/` sous `unit_tests/`, conformément à la convention locale Knowledge sélectionnée sur l'option permise par PGR. Les tests unitaires Rust sont désormais placés hors de `src/` sous `unit_tests/`, conformément à la convention locale Knowledge sélectionnée sur l'option permise par PGR.
Le workspace est une application déployable à train de release unique. Knowledge choisit néanmoins de conserver `Cargo.lock` comme état généré local et ignoré par Git ; les manifests Cargo portent le contrat versionné des dépendances. Les artefacts Cargo sont dirigés hors du dépôt vers `../builds/sasedev-knowledge/target/`. Le workspace est une application déployable à train de release unique. Knowledge choisit néanmoins de conserver `Cargo.lock` comme état généré local et ignoré par Git ; les manifests Cargo portent le contrat versionné des dépendances. Les artefacts Cargo sont dirigés hors du dépôt vers `../builds/sasedev-knowledge/target/`.
@@ -149,7 +151,7 @@ Les données générées résident hors du dépôt applicatif et hors des dépô
Le backend reçoit explicitement `<git-state-root>` ; il n'utilise aucun défaut implicite sous le workspace. Une variable de déploiement telle que `KNOWLEDGE_GIT_STATE_ROOT` pourra alimenter la composition, mais la librairie reçoit un chemin et ne lit pas elle-même l'environnement. Le backend reçoit explicitement `<git-state-root>` ; il n'utilise aucun défaut implicite sous le workspace. Une variable de déploiement telle que `KNOWLEDGE_GIT_STATE_ROOT` pourra alimenter la composition, mais la librairie reçoit un chemin et ne lit pas elle-même l'environnement.
`source-key` est une clé sûre dérivée par l'implémentation. En `alpha.2`, elle encode de manière déterministe les octets UTF-8 du `SourceId` sous une forme hexadécimale préfixée ; un `SourceId` ou une URL remote ne sont jamais interpolés directement comme chemin de filesystem. `source-key` est une clé sûre dérivée par l'implémentation Git. Depuis `0.0.2-alpha.2`, elle encode de manière déterministe les octets UTF-8 du `SourceId` sous une forme hexadécimale préfixée ; un `SourceId` ou une URL remote ne sont jamais interpolés directement comme chemin de filesystem.
Pendant `0.0.2`, une racine d'état appartient exclusivement à une instance backend/processus. Le partage simultané d'une même racine entre plusieurs processus reste `DEFER` jusqu'à matérialisation d'un verrouillage inter-processus. Pendant `0.0.2`, une racine d'état appartient exclusivement à une instance backend/processus. Le partage simultané d'une même racine entre plusieurs processus reste `DEFER` jusqu'à matérialisation d'un verrouillage inter-processus.
@@ -248,7 +250,7 @@ Un webhook peut être perdu ou dupliqué. Le commit Git résolu reste l'identit
La synchronisation partagée est une responsabilité de couche application, distincte du backend Git et des producteurs de signaux. `0.0.2-alpha.5` confirme cette responsabilité et matérialise `knowledge-app-lib` comme owner du cas d'usage provider-neutral ; les launchers n'ont pas à dupliquer cette orchestration. La synchronisation partagée est une responsabilité de couche application, distincte du backend Git et des producteurs de signaux. `0.0.2-alpha.5` confirme cette responsabilité et matérialise `knowledge-app-lib` comme owner du cas d'usage provider-neutral ; les launchers n'ont pas à dupliquer cette orchestration.
Sans PostgreSQL dans cette release, la dernière révision connue n'est pas stockée dans un fichier ad hoc caché. Le cas d'usage reçoit `previous_revision` de l'appelant et retourne explicitement la révision observée ainsi qu'un résultat `Changed` ou `Unchanged`. La future persistance pourra remplacer cet état appelant sans modifier la frontière Git. Le cas d'usage de synchronisation existant continue de recevoir `previous_revision` de l'appelant et retourne explicitement la révision observée ainsi qu'un résultat `Changed` ou `Unchanged`. `0.0.4-alpha.2` matérialise seulement le store et le schéma ; le raccord de cette persistance au cas d'usage reste réservé à `alpha.4`, sans modifier la frontière Git.
La cause `Periodic` reste supportée par `knowledge-sync-api`, mais `0.0.2-alpha.1` ne désigne pas encore de scheduler concret. Un scheduler n'est matérialisé que si son lifecycle/runtime est démontré ; lorsqu'il existe, il appelle exactement le même cas d'usage que la voie explicite. La cause `Periodic` reste supportée par `knowledge-sync-api`, mais `0.0.2-alpha.1` ne désigne pas encore de scheduler concret. Un scheduler n'est matérialisé que si son lifecycle/runtime est démontré ; lorsqu'il existe, il appelle exactement le même cas d'usage que la voie explicite.
@@ -300,7 +302,30 @@ La baseline retient **une base PostgreSQL logique partagée** par les trois appl
Ce choix est justifié par l'état transversal : identités, sessions, propositions, synchronisation, relations entre familles, index et recherche. Il évite trois bases divergentes pour des concepts qui appartiennent à la même plateforme. Ce choix est justifié par l'état transversal : identités, sessions, propositions, synchronisation, relations entre familles, index et recherche. Il évite trois bases divergentes pour des concepts qui appartiennent à la même plateforme.
PostgreSQL MAY contenir des documents/index/métadonnées dérivés et assurer une première capacité de recherche. Aucun moteur de recherche externe n'est sélectionné en `0.0.1`. ### Fondation matérialisée pour `0.0.4`
`0.0.4-alpha.1` sélectionne le toolkit ; `0.0.4-alpha.2` matérialise `knowledge-store-postgres-lib` avec `tokio-postgres 0.7.18`, `deadpool-postgres 0.14.2` et Refinery `0.9.2`. La façade publique reste limitée à `PostgresStoreConfig`, `PostgresStore` et `PostgresStoreError`. Les types du driver, du pool et du migrator ne remontent ni dans le domaine ni dans les contrats applicatifs, et aucun `knowledge-store-api` symétrique n'est introduit sans seconde implémentation démontrée.
La configuration est injectée par la composition : la crate reçoit une URL PostgreSQL et une taille maximale de pool. Elle ne lit pas directement les variables d'environnement du processus, n'expose pas l'URL par son API publique et ne journalise jamais l'URL ou les credentials. Une configuration invalide, une acquisition de pool ou une migration impossible produit une erreur récupérable ; aucun fallback fichier/mémoire ne masque l'indisponibilité PostgreSQL. La première implémentation utilise `tokio_postgres::NoTls`; un backend TLS ne sera ajouté que lorsqu'une cible de déploiement le justifiera.
Le premier schéma utile est volontairement borné :
```text
knowledge_sources
source_id TEXT PRIMARY KEY
family TEXT NOT NULL CHECK (pgr/howto/snippet/project_local)
git_reference TEXT NOT NULL
knowledge_source_sync_state
source_id TEXT PRIMARY KEY REFERENCES knowledge_sources(source_id) ON DELETE CASCADE
last_synchronized_revision TEXT NOT NULL
```
`git_reference` est la référence Git logique à suivre ; la localisation physique locale/remote et les credentials restent hors de cette table et sous les frontières de configuration appropriées. La dernière révision synchronisée est un état applicatif, pas une nouvelle autorité de contenu : elle peut être reconstruite/réconciliée à partir de Git et une valeur obsolète provoque au pire une resynchronisation.
La migration `V1__initial_sources.sql` est embarquée au build et appliquée uniquement via `PostgresStore::apply_migrations`; Refinery conserve son historique dans PostgreSQL. Le test d'intégration réel reste `#[ignore]` pour ne pas transformer tout `cargo test` en dépendance externe implicite. La gate PostgreSQL vérifie explicitement `KNOWLEDGE_POSTGRES_TEST_URL`, crée un schéma unique, borne le `search_path` de la connexion du store, exécute la migration, vérifie `knowledge_sources`, `knowledge_source_sync_state` et `refinery_schema_history`, puis supprime le schéma. L'absence du service requis rend la gate `BLOCKED`.
PostgreSQL MAY contenir ultérieurement des documents/index/métadonnées dérivés et assurer une première capacité de recherche. Le corps publié et ses métadonnées éditoriales autoritaires restent dans Git. `0.0.4` ne matérialise pas encore le parsing/projection final prévu par l'horizon `0.0.5`.
Les enregistrements dérivés doivent porter au minimum l'identité de famille/source et la révision Git afin de savoir exactement quel contenu ils représentent. Les enregistrements dérivés doivent porter au minimum l'identité de famille/source et la révision Git afin de savoir exactement quel contenu ils représentent.
@@ -399,6 +424,23 @@ Le push distant gardé reste réservé à `alpha.4`. `alpha.3` ne met à jour au
PostgreSQL, workflow complet de proposition, auth/admin, parsing final et adapter Gitea restent des missions distinctes. PostgreSQL, workflow complet de proposition, auth/admin, parsing final et adapter Gitea restent des missions distinctes.
## Ouverture `0.0.4` — persistance partagée
La stable `v0.0.3` ayant fermé le chemin Git générique, `0.0.4` matérialise la première persistance partagée nécessaire aux prochains cas d'usage sans déplacer l'autorité éditoriale.
La trajectoire retenue est :
```text
alpha.1 étude, ownership, schéma, migrations et tests
alpha.2 crate PostgreSQL + pool + première migration
alpha.3 persistance source logique + état de synchronisation
alpha.4 raccord applicatif de la révision précédente persistée
beta réconciliation + horizon
rc/rel stabilisation et publication
```
Le raccord applicatif futur doit conserver la primitive `synchronize_repository` provider-neutral : la persistance fournit la révision précédente et reçoit la révision observée, mais ne devient ni un backend Git ni une condition pour interpréter l'identité du commit.
## 10. Administration ## 10. Administration
L'administration Web est une interface vers les mêmes cas d'usage que l'édition locale Git, pas une deuxième source de vérité. L'administration Web est une interface vers les mêmes cas d'usage que l'édition locale Git, pas une deuxième source de vérité.

View File

@@ -0,0 +1,231 @@
<!-- file: docs/plans/004-V0_0_4_POSTGRES_FOUNDATION_PLAN.md -->
<!-- version: 3 -->
# Plan 0.0.4 — fondation PostgreSQL partagée
## Statut et sources
Release ouverte depuis la stable autoritaire :
```text
Knowledge tag v0.0.3
Knowledge commit b3823972449150b72905930b806d4d15471cddce
Knowledge SHA-256 82407dc2a83be878daa65692f975681428d0adc721ff249c3c9020e3a9d1f29d
publish report sasedev-knowledge-0.0.3-publish.001-report.md = PASS
start prompt prompts/004-V0_0_4_START_PROMPT.md
```
Le plan est actif à partir de `0.0.4-alpha.1`. PGR `v0.1.3` reste une provenance historique et aucune adoption PGR nouvelle n'est engagée.
## Mission
Matérialiser la première fondation PostgreSQL partagée de Knowledge afin de conserver un état transversal minimal pour les sources et la synchronisation, avec migrations reproductibles et tests PostgreSQL réels, sans déplacer la vérité éditoriale hors de Git.
À la clôture de `0.0.4`, le workspace doit posséder un owner PostgreSQL concret et partagé, un premier schéma versionné, un pool/configuration injectables et un chemin persistant pour la dernière révision synchronisée utilisable par l'orchestration applicative.
## État acquis et questions ouvertes
Acquis depuis `0.0.3` :
- Git générique de lecture et snapshot ;
- écriture Git contrôlée et push gardé ;
- `knowledge-app-lib` pour la synchronisation provider-neutral ;
- trois launchers Web et composition Maud/Vite ;
- base PostgreSQL logique partagée déjà retenue par l'architecture ;
- horizon produit `0.0.5` à `0.0.10` révisable.
Décisions de `alpha.1` :
- `tokio-postgres` sélectionné comme driver, `deadpool-postgres` comme pool et Refinery comme migrator, sans ORM ;
- `knowledge-store-postgres-lib` retenu comme owner ;
- migrations SQL versionnées possédées par la crate ;
- premier schéma limité aux sources logiques et à la dernière révision synchronisée ;
- test PostgreSQL via URL explicitement fournie et schéma éphémère isolé ;
- aucune lecture implicite de secrets par la crate et aucun fallback de stockage.
Décisions matérialisées par `alpha.2` :
- façade publique minimale `PostgresStoreConfig` / `PostgresStore` / `PostgresStoreError` ;
- pool borné par `max_pool_size` sans exposition de types Deadpool ;
- versions revalidées `tokio-postgres 0.7.18`, `deadpool-postgres 0.14.2`, Refinery `0.9.2` et Tokio test `1.53.1`, avec features minimales `runtime`, `rt_tokio_1` et `tokio-postgres` respectivement ;
- migration `V1__initial_sources.sql` embarquée et appliquée explicitement ;
- premier backend sans TLS via `NoTls`, sans dépendance TLS prématurée ;
- test réel de migration isolé par schéma et déclenché explicitement par la gate.
Questions laissées aux tranches suivantes :
- besoin réel d'un contrat passif de persistance dans `knowledge-app-lib` pour le raccord `alpha.4` ;
- backend TLS à sélectionner uniquement si le déploiement visé l'exige ;
- paramètres supplémentaires de pool uniquement sur besoin runtime observé.
## Scope
`0.0.4` couvre :
- une crate PostgreSQL partagée réelle ;
- `tokio-postgres` PostgreSQL/Tokio avec pool `deadpool-postgres` ;
- première migration reproductible ;
- persistance de `SourceId`, `ContentFamily`, référence Git logique et dernière révision synchronisée ;
- erreurs récupérables sans fuite de credentials ;
- tests unitaires ciblés et intégration PostgreSQL réelle ;
- raccord applicatif minimal permettant d'utiliser l'état persistant sans modifier le contrat Git ;
- documentation durable, beta, RC et fermeture stable.
## Hors scope
Restent hors `0.0.4` :
- corps/métadonnées éditoriales publiées en PostgreSQL comme vérité ;
- modèles de contenu finaux et parsing complet ;
- projections finales/indexation détaillée ;
- recherche avancée ;
- Gitea/forge et webhooks spécifiques ;
- scheduler/jobs ;
- auth/session/rôles/capabilities ;
- propositions/revues/publication produit ;
- templates publics/admin et routes finales ;
- quatrième application admin ;
- rebase/merge automatique ;
- partage multi-processus de la racine Git ;
- LFS/submodules et rétention avancée.
## Stratégie de validation
La validation reste proportionnée à chaque tranche.
Les invariants documentaires et Rust continuent d'utiliser :
```text
Markdown + hygiène texte
cargo fmt --all
cargo fmt --all -- --check
audits Rust locaux
cargo metadata / cargo check
Clippy strict
tests ciblés puis workspace lorsque le contrat devient transverse
git diff --check / git diff --cached --check
```
À partir de la première migration, une gate PostgreSQL réelle devient obligatoire. Elle utilise `KNOWLEDGE_POSTGRES_TEST_URL`, isole chaque exécution dans un schéma temporaire et nettoie cet état après test. Si la tranche requiert cette preuve et qu'aucun PostgreSQL n'est disponible, le statut est `BLOCKED`.
Les gates Web/npm ne sont pas rejouées pour les alphas sans diff `Web/` ou contrat Web. Les phases de stabilisation peuvent imposer une non-régression runtime globale.
## Trajectoire prévisionnelle
### alpha.1 — baseline, étude et cadrage
- vérifier intégralement `v0.0.3` et `publish.001` ;
- relire owners, architecture, deltas/histories, `DEFER` et horizon ;
- confirmer l'autonomie normative Knowledge ;
- comparer les options PostgreSQL actuelles ;
- décider le driver `tokio-postgres`, le pool `deadpool-postgres`, Refinery, l'owner, le schéma, la configuration et la stratégie de test ;
- créer l'étude `008`, le présent plan et le delta ;
- ne modifier aucun code produit, dépendance ou migration ;
- autoriser `alpha.2` seulement après `PASS` opérateur.
### alpha.2 — owner PostgreSQL, pool et première migration
- créer `knowledge-store-postgres-lib` avec façade crate-root conforme ;
- ajouter uniquement les dépendances/features nécessaires de `tokio-postgres`, `deadpool-postgres`, Refinery et Tokio ;
- matérialiser la configuration explicite de connexion/pool et les erreurs publiques sans fuite de secret ;
- ajouter `migrations/` sous la crate et la migration initiale `knowledge_sources` + `knowledge_source_sync_state` ;
- exposer une opération explicite d'application des migrations ;
- prouver la migration sur PostgreSQL réel avec schéma de test isolé ;
- ne raccorder encore aucun launcher si aucun use case runtime ne l'exige.
### alpha.2.fix.1 — documentation de la crate de test PostgreSQL
- conserver `alpha.2` historisée `FAIL` à cause de Clippy strict ;
- ajouter uniquement la documentation de crate manquante dans `tests/postgres_migration.rs` ;
- ne modifier ni le code produit, ni le schéma, ni les dépendances, ni la façade publique ;
- rejouer Clippy strict, les tests Rust et la preuve PostgreSQL réelle ;
- autoriser `alpha.3` uniquement après `PASS` complet du fix.
### alpha.3 — persistance de source et état de synchronisation
- matérialiser les opérations minimales de création/mise à jour/lecture de configuration logique ;
- convertir `ContentFamily`, `SourceId`, référence logique et `GitRevision` sans faire remonter les types PostgreSQL/Deadpool/Refinery au domaine ;
- lire et enregistrer `last_synchronized_revision` ;
- tester insertion, mise à jour, absence d'état, contraintes et isolation des sources sur PostgreSQL réel ;
- prouver qu'aucun corps de contenu ou credential Git n'est persisté par ce schéma.
### alpha.4 — raccord applicatif persistant
- conserver `synchronize_repository` comme primitive provider-neutral ;
- ajouter seulement le contrat applicatif nécessaire pour charger/enregistrer la révision précédente sans dépendance au driver/pool/migrator dans `knowledge-app-lib` ;
- implémenter ce contrat côté `knowledge-store-postgres-lib` ;
- composer un cas d'usage persistant qui charge l'état, synchronise via Git et enregistre la révision uniquement après succès ;
- tester Changed/Unchanged, première synchronisation et absence d'écriture après erreur Git/store ;
- ne pas ajouter scheduler, projection de contenu ou route Web.
### beta.1 — réconciliation et revue d'horizon
- réconcilier le schéma, l'API, le lifecycle et les tests réellement obtenus ;
- vérifier que Git reste l'autorité du contenu et que le state PostgreSQL est reconstructible ;
- préparer `CHANGELOG.md` en `0.0.4 (candidate)` seulement à ce stade ;
- réévaluer `0.0.5` modèles/projections et au moins `0.0.6` / `0.0.7` ;
- préparer `prompts/005-V0_0_5_START_PROMPT.md` uniquement si la prochaine mission reste suffisamment décidée ;
- rejouer les preuves PostgreSQL et non-régression workspace nécessaires à la stabilisation.
### rc.1 — candidate stable
- geler le scope ;
- rejouer la gate complète Rust/PostgreSQL applicable ;
- vérifier migrations depuis un schéma vide, persistance source/state et raccord applicatif ;
- vérifier deltas/histories, hors-scope et hygiène de livraison ;
- rejouer la non-régression Web/runtime exigée par la phase de stabilisation ;
- n'introduire aucune fonctionnalité nouvelle.
### rel.1 — promotion stable pré-tag
- promouvoir mécaniquement `VERSION` et workspace vers `0.0.4` ;
- finaliser changelog, README, roadmap et plan depuis le résultat réellement acquis ;
- vérifier le handoff `0.0.5` seulement s'il a été autorisé par la revue beta ;
- rejouer la gate stable complète ;
- produire le history observé avant commit stable/tag ;
- ne fabriquer aucun rapport post-tag avant publication réelle.
## Déclencheurs de REPLAN
REPLAN avant de poursuivre si :
- les versions retenues de `tokio-postgres`, `deadpool-postgres` ou Refinery sont incompatibles avec la toolchain stable réellement utilisée ou les lints locaux ;
- le premier schéma exige déjà de stocker le corps éditorial publié pour fonctionner ;
- une seconde implémentation de store rend une frontière `-api` réellement nécessaire ;
- le raccord applicatif crée une dépendance cyclique ou oblige le domaine à dépendre du driver, du pool ou du migrator ;
- la stratégie de test par schéma isolé ne peut pas prouver les migrations de manière fiable ;
- une connexion PostgreSQL devient une dépendance obligatoire de tous les launchers sans cas d'usage qui la justifie ;
- un scheduler, worker ou service réseau supplémentaire devient nécessaire pour fermer la mission ;
- une tranche atteint `.fix.3`.
La conclusion du REPLAN utilise `CONTINUE`, `SPLIT`, `CONTINUE-NEXT-SESSION` ou `ABANDON`.
## Clôture et transition
`0.0.4` est fermable lorsque :
- `knowledge-store-postgres-lib` est un owner réel et testé ;
- une base PostgreSQL vide peut être migrée de manière reproductible ;
- les sources logiques et leur dernière révision synchronisée sont persistées ;
- le pool et les erreurs ne fuient aucun secret ;
- l'indisponibilité PostgreSQL n'est jamais masquée par un fallback ;
- l'orchestration peut utiliser la révision persistée sans coupler le domaine à SQL ;
- Git reste l'autorité de toute donnée éditoriale publiée ;
- beta/RC ont fermé les non-régressions et l'horizon.
À l'ouverture, seule `alpha.1` est matérialisée. Aucun history `0.0.4` n'existe avant la gate opérateur de cette tranche.
## Revue d'horizon
L'étude `alpha.1` ne modifie pas l'horizon issu de `0.0.3-beta.1` :
```text
0.0.5 modèles de contenu et projections PGR/HOWTO/snippet
0.0.6 templates publics des trois sites
0.0.7 templates d'administration des trois sites
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
```
La revue beta de `0.0.4` devra confirmer ou replanifier au minimum `0.0.5`, `0.0.6` et `0.0.7` à partir de la persistance réellement obtenue.

View File

@@ -0,0 +1,255 @@
<!-- file: docs/studies/008-V0_0_4_POSTGRES_FOUNDATION_STUDY.md -->
<!-- version: 2 -->
# É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 : <https://docs.rs/crate/sqlx/0.9.0/source/Cargo.toml.orig> ;
- `PgPool` SQLx : <https://docs.rs/sqlx/0.9.0/sqlx/postgres/type.PgPool.html> ;
- migrations et `migrate!` SQLx : <https://docs.rs/sqlx/0.9.0/sqlx/migrate/index.html> et <https://docs.rs/sqlx/0.9.0/sqlx/macro.migrate.html> ;
- `tokio-postgres` `0.7.18` : <https://docs.rs/tokio-postgres/0.7.18/tokio_postgres/> ;
- `deadpool-postgres` `0.14.2` : <https://docs.rs/deadpool-postgres/0.14.2/deadpool_postgres/> ;
- Diesel `2.3.13` : <https://docs.rs/crate/diesel/2.3.13> ;
- `diesel-async` `0.9.2` : <https://docs.rs/crate/diesel-async/0.9.2> ;
- SeaORM `2.0.4` : <https://docs.rs/crate/sea-orm/2.0.4> ;
- Refinery `0.9.2` : <https://docs.rs/crate/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`.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/validation/001-VALIDATION_MATRIX.md --> <!-- file: docs/validation/001-VALIDATION_MATRIX.md -->
<!-- version: 41 --> <!-- version: 43 -->
# Matrice de validation Knowledge # Matrice de validation Knowledge
@@ -1017,3 +1017,56 @@ La première tranche de `0.0.3` est une gate de cadrage sans code produit. Elle
La baseline Web n'est pas rejouée automatiquement dans cette tranche, car aucun fichier sous `Web/` ni contrat runtime Web n'est modifié et la stable `0.0.2` a déjà acquis sa gate complète. La baseline Web n'est pas rejouée automatiquement dans cette tranche, car aucun fichier sous `Web/` ni contrat runtime Web n'est modifié et la stable `0.0.2` a déjà acquis sa gate complète.
Un `PASS` de `0.0.3-alpha.1` autorise uniquement la préparation de `0.0.3-alpha.2`. Un autre statut doit d'abord être conservé dans son history puis conduire à un fix borné ou à un REPLAN. Un `PASS` de `0.0.3-alpha.1` autorise uniquement la préparation de `0.0.3-alpha.2`. Un autre statut doit d'abord être conservé dans son history puis conduire à un fix borné ou à un REPLAN.
## Gate de `0.0.4-alpha.1`
La première tranche de `0.0.4` est une gate de cadrage sans code produit, dépendance PostgreSQL Rust ni migration. Elle doit prouver :
- `VERSION = 0.0.4-alpha.1` et `[workspace.package].version` identique ;
- baseline `v0.0.3` identifiée par commit `b3823972449150b72905930b806d4d15471cddce`, SHA-256 `82407dc2a83be878daa65692f975681428d0adc721ff249c3c9020e3a9d1f29d` et `publish.001 = PASS` ;
- douze deltas et douze histories `0.0.3` appariés, avec `rel.1.fix.1 = PASS` ;
- aucun chargement/adoption PGR nouveau ;
- étude `008` et plan `004` présents ;
- `tokio-postgres`, `deadpool-postgres`, Refinery, `knowledge-store-postgres-lib`, le schéma minimal et la stratégie de test explicitement décidés ;
- aucun `knowledge-store-postgres-lib`, aucune migration et aucune nouvelle dépendance réellement ajoutés dans `alpha.1` ;
- aucun diff sous `crates/` ou `Web/` et aucun changement du changelog stable `0.0.3` ;
- roadmap/horizon `0.0.5` à `0.0.10` inchangés parce que l'étude ne révèle aucune dépendance fausse ;
- audits Markdown et hygiène texte propres ;
- `cargo fmt --all` puis `cargo fmt --all -- --check` exécutés avant les audits Rust ;
- audits Rust locaux propres ;
- `cargo metadata` et `cargo check --workspace` propres ;
- `Cargo.lock` local ignoré/non suivi et `package-lock.json` Web inchangé/versionné ;
- `git diff --cached --check` propre avant commit.
Clippy, tests workspace, npm/Vite et smokes HTTP ne sont pas requis par cette tranche : elle ne modifie ni source Rust, ni dépendance, ni frontend, ni runtime. La gate vérifie néanmoins `cargo check --workspace` après la promotion de version du manifest.
Un `PASS` autorise uniquement `0.0.4-alpha.2`. Un autre statut est historisé puis conduit à un fix borné ou à un REPLAN.
## Gate de `0.0.4-alpha.2`
La deuxième tranche matérialise le premier owner PostgreSQL réel. Elle doit prouver :
- `VERSION = 0.0.4-alpha.2` et `[workspace.package].version` identique ;
- `history/0.0.4/alpha.1.md` présent avec statut `PASS` et committé avant application ;
- workspace composé exactement de dix packages, avec `knowledge-store-postgres-lib` comme seul nouveau membre ;
- `tokio-postgres 0.7.18` avec `runtime`, `deadpool-postgres 0.14.2` avec `rt_tokio_1`, Refinery `0.9.2` avec `tokio-postgres` et Tokio test `1.53.1` ajouté uniquement à la crate PostgreSQL ;
- façade crate-root limitée à `PostgresStoreConfig`, `PostgresStore` et `PostgresStoreError` ;
- configuration injectée, sans lecture d'environnement ni getter public de l'URL PostgreSQL ;
- pool `deadpool-postgres` borné par `max_pool_size`, driver `tokio-postgres` et première connexion `NoTls` ;
- migration `V1__initial_sources.sql` embarquée via Refinery et appliquée seulement par `PostgresStore::apply_migrations` ;
- tables `knowledge_sources` et `knowledge_source_sync_state` avec contrainte des familles et cascade de suppression de l'état de synchronisation ;
- aucun corps de contenu, credential Git, compte, proposition, job ou projection finale ajouté au schéma ;
- test unitaire de configuration sans PostgreSQL ;
- test d'intégration PostgreSQL réel isolé dans un schéma unique et exécuté explicitement avec `KNOWLEDGE_POSTGRES_TEST_URL` ;
- absence de PostgreSQL réel pendant cette gate classée `BLOCKED`, jamais masquée par un skip ;
- aucun diff sous `Web/`, les trois launchers, `knowledge-app-lib`, `knowledge-git-api`, `knowledge-git-lib`, `knowledge-sync-api` ou `knowledge-domain-lib` ;
- audits Markdown et hygiène texte propres ;
- `cargo fmt --all` puis `cargo fmt --all -- --check` exécutés avant les audits Rust ;
- audits Rust locaux propres sur les dix crates ;
- `cargo metadata`, `cargo check`, Clippy strict, tests ciblés store et tests workspace propres ;
- `Cargo.lock` local ignoré/non suivi et `package-lock.json` Web inchangé/versionné ;
- `git diff --cached --check` propre avant commit.
La gate ne rejoue pas npm/Vite/HTTP : aucun fichier Web, launcher ou contrat runtime Web n'est modifié. Le test PostgreSQL marqué `#[ignore]` reste exclu des tests workspace ordinaires et est rejoué explicitement avec `--ignored` dans la gate afin que la dépendance externe soit volontaire et visible.
Un `PASS` autorise uniquement `0.0.4-alpha.3`. Un `FAIL` de code ou migration produit un fix borné ; une incompatibilité de toolchain/dépendances, une impossibilité d'isoler correctement le test PostgreSQL ou un besoin de modifier l'ownership déclenche un REPLAN.

140
history/0.0.4/alpha.1.md Normal file
View File

@@ -0,0 +1,140 @@
<!-- file: history/0.0.4/alpha.1.md -->
<!-- version: 1 -->
# History 0.0.4-alpha.1 — baseline, étude et cadrage PostgreSQL
## Statut
PASS
La gate opérateur de `0.0.4-alpha.1` exécutée le `2026-09-30` est complète et propre. La tranche ouvre la fondation PostgreSQL partagée depuis la stable autoritaire `v0.0.3`, fixe l'owner et les choix techniques de stockage, sans créer encore de crate PostgreSQL, migration ou dépendance runtime.
## Baseline autoritaire vérifiée
Les contrôles opérateur confirment la baseline documentée :
```text
Knowledge stable tag v0.0.3
Knowledge stable commit b3823972449150b72905930b806d4d15471cddce
Knowledge archive SHA-256 82407dc2a83be878daa65692f975681428d0adc721ff249c3c9020e3a9d1f29d
Knowledge publish report sasedev-knowledge-0.0.3-publish.001-report.md = PASS
```
Les douze deltas et douze histories `0.0.3` sont présents et appariés. `history/0.0.3/rel.1.fix.1.md` est `PASS`.
## Version et cadrage
```text
VERSION 0.0.4-alpha.1
Cargo workspace version 0.0.4-alpha.1
étude docs/studies/008-V0_0_4_POSTGRES_FOUNDATION_STUDY.md
plan docs/plans/004-V0_0_4_POSTGRES_FOUNDATION_PLAN.md
delta deltas/0.0.4/alpha.1.md
history alpha.1 avant gate absent
```
Les décisions vérifiées sont :
```text
driver PostgreSQL tokio-postgres
pool deadpool-postgres
migrations Refinery + SQL versionné
ORM aucun
owner knowledge-store-postgres-lib
premier schéma knowledge_sources + knowledge_source_sync_state
test PostgreSQL KNOWLEDGE_POSTGRES_TEST_URL + schéma isolé
autorité du contenu Git
```
PGR `v0.1.3` reste une provenance historique : aucun chargement ou adoption PGR nouveau n'est engagé.
## Scope négatif confirmé
La gate confirme :
```text
crates/knowledge-store-postgres-lib absent
migrations/ absent
history/0.0.4/alpha.1.md avant gate absent
aucun diff crates/ PASS
aucun diff Web/ PASS
aucun diff CHANGELOG.md PASS
aucun diff ROADMAP.md PASS
aucun diff prompts/ PASS
```
L'horizon `0.0.5` à `0.0.10` reste inchangé.
## Markdown, formatage et audits Rust
```text
git diff --check PASS
Markdown header audit clean (128 file(s))
Markdown link audit clean (86 local link(s), 128 file(s))
Markdown table audit clean (5 table(s), 128 file(s))
cargo fmt --all PASS
cargo fmt --all -- --check PASS
Rust test-layout audit clean (9 crate(s))
Rust blank-line audit clean (36 file(s))
Rust item-spacing audit clean (36 file(s))
Rust module-order audit clean (36 file(s))
Rust trait-import-block audit clean (36 file(s))
Rust re-export-block audit clean (36 file(s))
Rust crate-root facade audit clean (6 crate root(s))
Rust export completeness audit 0 candidate(s) across 9 package(s)
```
## Cargo et structure workspace
```text
cargo metadata --format-version 1 --no-deps PASS
workspace_members 9
cargo check --workspace PASS
```
Les neuf packages observés sont exactement :
```text
knowledge-app-lib
knowledge-domain-lib
knowledge-git-api
knowledge-git-lib
knowledge-sync-api
knowledge-web-lib
knowledge-pgr-server
knowledge-howtos-server
knowledge-snippets-server
```
Clippy, tests workspace, npm/Vite et smokes HTTP n'étaient pas requis par cette tranche documentaire et n'ont pas été annoncés comme exécutés.
## Hygiène et lockfiles
```text
Knowledge 0.0.4-alpha.1 text hygiene clean (128 file(s))
Cargo.lock présent localement, ignoré, non suivi
Web package-lock.json présent
git diff --cached --check PASS
```
Le staging final observé avant ajout du présent history est exactement :
```text
M Cargo.toml
M README.md
M RULES.md
M VERSION
A deltas/0.0.4/alpha.1.md
M docs/000-README.md
M docs/architecture/001-PROJECT_PROFILE.md
M docs/architecture/002-KNOWLEDGE_ARCHITECTURE.md
A docs/plans/004-V0_0_4_POSTGRES_FOUNDATION_PLAN.md
A docs/studies/008-V0_0_4_POSTGRES_FOUNDATION_STUDY.md
M docs/validation/001-VALIDATION_MATRIX.md
```
## Décision
`0.0.4-alpha.1` est `PASS`.
`0.0.4-alpha.2` peut maintenant matérialiser `knowledge-store-postgres-lib`, les dépendances PostgreSQL sélectionnées, le pool/configuration explicites et la première migration versionnée, avec preuve sur PostgreSQL réel dans un schéma de test isolé.

View File

@@ -0,0 +1,155 @@
<!-- file: history/0.0.4/alpha.2.fix.1.md -->
<!-- version: 1 -->
# History 0.0.4-alpha.2.fix.1 — documentation de la crate de test PostgreSQL
## Statut
PASS
La gate opérateur de `0.0.4-alpha.2.fix.1` exécutée le `2026-10-01` est complète et propre. Le fix corrige uniquement le lint `missing_docs` observé sur la target d'intégration PostgreSQL de `alpha.2`, sans modifier le code produit, le schéma SQL, les dépendances ni la façade publique.
## Baseline opérateur
`alpha.2` historisée `FAIL` a été committée puis poussée avant application du fix :
```text
history/0.0.4/alpha.2.md FAIL
commit 095ac37
message 0.0.4-alpha.2
branch master
push origin/master PASS
```
La première tentative de `git push origin master` a été interrompue pendant la saisie d'identifiants. La seconde a réussi et a avancé `origin/master` de `b55eb23` à `095ac37`.
## Correction bornée
Les contrôles initiaux confirment :
```text
VERSION 0.0.4-alpha.2.fix.1
Cargo workspace version 0.0.4-alpha.2.fix.1
history/0.0.4/alpha.2.md présent, suivi, FAIL
history/0.0.4/alpha.2.fix.1.md avant gate absent
documentation de crate //! présente
git diff --check PASS
scope négatif PASS
```
Le plan actif conserve explicitement `alpha.2 = FAIL` et n'autorise `alpha.3` qu'après `PASS` complet du présent fix.
Aucun diff n'est observé sous :
```text
crates/knowledge-store-postgres-lib/src/
crates/knowledge-store-postgres-lib/unit_tests/
crates/knowledge-store-postgres-lib/migrations/
crates/knowledge-store-postgres-lib/Cargo.toml
README.md
RULES.md
ROADMAP.md
CHANGELOG.md
docs/architecture/
docs/studies/
docs/validation/
Web/
prompts/
```
## Markdown, formatage et audits Rust
```text
Markdown header audit clean (132 file(s))
Markdown link audit clean (86 local link(s), 132 file(s))
Markdown table audit clean (5 table(s), 132 file(s))
cargo fmt --all PASS
cargo fmt --all -- --check PASS
Rust test-layout audit clean (10 crate(s))
Rust blank-line audit clean (42 file(s))
Rust item-spacing audit clean (42 file(s))
Rust module-order audit clean (42 file(s))
Rust trait-import-block audit clean (42 file(s))
Rust re-export-block audit clean (42 file(s))
Rust crate-root facade audit clean (7 crate root(s))
Rust export completeness audit 0 candidate(s) across 10 package(s)
```
## Cargo, Clippy et tests
```text
cargo metadata --format-version 1 --no-deps PASS
cargo check --workspace PASS
cargo clippy --workspace --all-targets
--all-features -- -D warnings PASS
workspace_members 10
```
Le défaut `missing_docs` de `alpha.2` est donc fermé par Clippy strict.
Tests ciblés de la crate PostgreSQL :
```text
config unit tests 3 PASS
postgres_migration 1 ignored, gate explicite requise
doc-tests 0
```
Tests workspace :
```text
knowledge-app-lib 3 PASS
knowledge-domain-lib 3 PASS
knowledge-git-api 7 PASS
knowledge-git-lib 8 unit + 6 integration PASS
knowledge-sync-api 1 PASS
knowledge-web-lib 4 PASS
knowledge-store-postgres-lib 3 PASS + 1 intégration ignorée
launchers 0 test chacun
```
Aucun warning `missing_docs` n'est observé pendant ces commandes.
## Preuve PostgreSQL réelle
La précondition opérateur `KNOWLEDGE_POSTGRES_TEST_URL` est présente pendant la gate du fix.
La commande obligatoire :
```text
cargo test -p knowledge-store-postgres-lib --test postgres_migration -- --ignored --nocapture
```
produit :
```text
initial_migration_runs_in_isolated_schema PASS
1 passed; 0 failed
```
La migration initiale, le schéma temporaire isolé et son nettoyage restent donc prouvés sur PostgreSQL réel après la correction documentaire.
## Hygiène et lockfiles
```text
Knowledge 0.0.4-alpha.2.fix.1 text hygiene clean (187 file(s))
Cargo.lock présent localement, ignoré, non suivi
Web package-lock.json présent et inchangé
git diff --cached --check PASS
```
Le staging final observé avant ajout du présent history est exactement :
```text
M Cargo.toml
M VERSION
M crates/knowledge-store-postgres-lib/tests/postgres_migration.rs
A deltas/0.0.4/alpha.2.fix.1.md
M docs/plans/004-V0_0_4_POSTGRES_FOUNDATION_PLAN.md
```
## Décision
`0.0.4-alpha.2.fix.1` est `PASS`.
Le défaut de validation de `alpha.2` est fermé sans changement fonctionnel. `0.0.4-alpha.3` peut maintenant matérialiser la persistance minimale de configuration de source et d'état de synchronisation sur le schéma PostgreSQL déjà validé.

221
history/0.0.4/alpha.2.md Normal file
View File

@@ -0,0 +1,221 @@
<!-- file: history/0.0.4/alpha.2.md -->
<!-- version: 1 -->
# History 0.0.4-alpha.2 — owner PostgreSQL, pool et première migration
## Statut
FAIL
La gate opérateur de `0.0.4-alpha.2` exécutée le `2026-10-01` échoue sur Clippy strict : la crate de test d'intégration `crates/knowledge-store-postgres-lib/tests/postgres_migration.rs` ne possède pas de documentation de crate alors que `missing_docs` est activé et promu en erreur par `-D warnings`.
La fondation PostgreSQL compile, les tests Rust hors Clippy passent, et la migration réelle finit par passer sur PostgreSQL après définition explicite de `KNOWLEDGE_POSTGRES_TEST_URL`. Le statut reste néanmoins `FAIL`, car la gate obligatoire Clippy n'est pas propre.
## Baseline opérateur
`alpha.1` `PASS` a été historisé, committé et poussé avant application de `alpha.2` :
```text
history/0.0.4/alpha.1.md PASS
commit b55eb23
message 0.0.4-alpha.1
branch master
push origin/master PASS
```
Le push observé a avancé `origin/master` de `b382397` à `b55eb23`.
## Version, scope et dépendances
Les contrôles initiaux passent :
```text
VERSION 0.0.4-alpha.2
Cargo workspace version 0.0.4-alpha.2
history/0.0.4/alpha.1.md présent, suivi, PASS
history/0.0.4/alpha.2.md avant gate absent
knowledge-store-postgres-lib présent
V1__initial_sources.sql présent
git diff --check PASS
surfaces hors scope propres
```
Les versions et features observées sont exactement :
```text
tokio-postgres 0.7.18 default-features=false, runtime
deadpool-postgres 0.14.2 default-features=false, rt_tokio_1
refinery 0.9.2 default-features=false, tokio-postgres
tokio dev 1.53.1 default-features=false, macros + rt-multi-thread
```
La façade publique contient exactement :
```text
PostgresStoreConfig
PostgresStoreError
PostgresStore
```
La crate produit ne lit pas `KNOWLEDGE_POSTGRES_TEST_URL`, ne lit pas directement l'environnement et ne contient pas de `println!`, `eprintln!` ou `dbg!`.
## Migration initiale
Les contrôles statiques de la migration passent :
```text
knowledge_sources présent
family CHECK pgr/howto/snippet/project_local
knowledge_source_sync_state présent
FK source_id ON DELETE CASCADE présente
last_synchronized_revision NOT NULL présent
contenu/body/credential/account/
proposal/job absents de la migration
```
Le test d'intégration possède bien son marqueur `ignore`, crée un schéma isolé et le supprime avec `DROP SCHEMA ... CASCADE`.
## Markdown, formatage et audits Rust
```text
Markdown header audit clean (130 file(s))
Markdown link audit clean (86 local link(s), 130 file(s))
Markdown table audit clean (5 table(s), 130 file(s))
cargo fmt --all PASS
cargo fmt --all -- --check PASS
Rust test-layout audit clean (10 crate(s))
Rust blank-line audit clean (42 file(s))
Rust item-spacing audit clean (42 file(s))
Rust module-order audit clean (42 file(s))
Rust trait-import-block audit clean (42 file(s))
Rust re-export-block audit clean (42 file(s))
Rust crate-root facade audit clean (7 crate root(s))
Rust export completeness audit 0 candidate(s) across 10 package(s)
```
## Cargo, Clippy et tests
La résolution des nouvelles dépendances et la compilation workspace passent :
```text
cargo metadata --format-version 1 --no-deps PASS
cargo check --workspace PASS
workspace_members 10
```
Les dix packages observés sont exactement les neuf packages historiques plus `knowledge-store-postgres-lib`.
La première défaillance obligatoire survient pendant Clippy :
```text
cargo clippy --workspace --all-targets --all-features -- -D warnings FAIL
```
Erreur observée :
```text
error: missing documentation for the crate
crates/knowledge-store-postgres-lib/tests/postgres_migration.rs
-D missing-docs implied by -D warnings
```
Les tests exécutés après cet échec passent fonctionnellement mais reproduisent le warning de documentation :
```text
cargo test -p knowledge-store-postgres-lib
unit tests PASS (3)
postgres_migration ignored (1, gate explicite requise)
cargo test --workspace --all-targets --all-features
workspace PASS
postgres_migration ignored (1)
```
Tests workspace observés :
```text
knowledge-app-lib 3 PASS
knowledge-domain-lib 3 PASS
knowledge-git-api 7 PASS
knowledge-git-lib 8 unit + 6 integration PASS
knowledge-sync-api 1 PASS
knowledge-web-lib 4 PASS
knowledge-store-postgres-lib 3 PASS + 1 intégration ignorée
launchers 0 test chacun
```
## Preuve PostgreSQL réelle
Une première invocation explicite du test ignoré a été effectuée alors que `KNOWLEDGE_POSTGRES_TEST_URL` n'était pas encore définie. Le test a correctement refusé l'exécution :
```text
KNOWLEDGE_POSTGRES_TEST_URL is required
postgres_migration FAILED
```
Cette première tentative ne révèle pas un défaut PostgreSQL du produit ; elle constate une précondition opérateur absente.
L'opérateur a ensuite défini :
```text
KNOWLEDGE_POSTGRES_TEST_URL=postgresql://knowledge:knowledge@localhost/knowledge
```
puis rejoué exactement le test réel :
```text
cargo test -p knowledge-store-postgres-lib --test postgres_migration -- --ignored --nocapture
```
Résultat :
```text
initial_migration_runs_in_isolated_schema PASS
1 passed; 0 failed
```
La migration initiale, l'isolation par schéma et le nettoyage sont donc prouvés sur PostgreSQL réel. Le warning `missing_docs` reste toutefois présent pendant cette exécution.
## Hygiène et lockfiles
```text
Knowledge 0.0.4-alpha.2 text hygiene clean (185 file(s))
Cargo.lock présent localement, ignoré, non suivi
Web package-lock.json présent et inchangé
git diff --cached --check PASS
```
Le staging final observé avant ajout du présent history est exactement :
```text
M Cargo.toml
M README.md
M RULES.md
M VERSION
A crates/knowledge-store-postgres-lib/Cargo.toml
A crates/knowledge-store-postgres-lib/migrations/V1__initial_sources.sql
A crates/knowledge-store-postgres-lib/src/config.rs
A crates/knowledge-store-postgres-lib/src/error.rs
A crates/knowledge-store-postgres-lib/src/lib.rs
A crates/knowledge-store-postgres-lib/src/store.rs
A crates/knowledge-store-postgres-lib/tests/postgres_migration.rs
A crates/knowledge-store-postgres-lib/unit_tests/config.rs
A deltas/0.0.4/alpha.2.md
M docs/architecture/001-PROJECT_PROFILE.md
M docs/architecture/002-KNOWLEDGE_ARCHITECTURE.md
M docs/plans/004-V0_0_4_POSTGRES_FOUNDATION_PLAN.md
M docs/studies/008-V0_0_4_POSTGRES_FOUNDATION_STUDY.md
M docs/validation/001-VALIDATION_MATRIX.md
```
## Diagnostic
Le défaut est borné à l'en-tête documentaire de la crate de test d'intégration. Les autres tests d'intégration du dépôt utilisent déjà une documentation de crate `//! ...`, ce qui satisfait le lint `missing_docs` appliqué aux targets de test.
Aucun retour opérateur ne justifie de modifier le driver, le pool, Refinery, la façade publique, le schéma SQL, les migrations ou le plan d'ownership. Aucun REPLAN n'est requis.
## Décision
`0.0.4-alpha.2` est `FAIL`.
La correction autorisée est `0.0.4-alpha.2.fix.1`, bornée à l'ajout de la documentation de crate manquante dans `tests/postgres_migration.rs` et au suivi version/plan. Elle doit rejouer Clippy strict, les tests workspace et la preuve PostgreSQL réelle avant d'autoriser `alpha.3`.