0.0.4-alpha.2
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# file: Cargo.toml
|
||||
# version: 40
|
||||
# version: 41
|
||||
|
||||
[workspace]
|
||||
resolver = "3"
|
||||
@@ -13,10 +13,11 @@ members = [
|
||||
"crates/knowledge-pgr-server",
|
||||
"crates/knowledge-howtos-server",
|
||||
"crates/knowledge-snippets-server",
|
||||
"crates/knowledge-store-postgres-lib",
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.0.4-alpha.1"
|
||||
version = "0.0.4-alpha.2"
|
||||
edition = "2024"
|
||||
publish = false
|
||||
repository = "https://git.sasedev.com/Sasedev/sasedev-knowledge"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: README.md -->
|
||||
<!-- version: 26 -->
|
||||
<!-- version: 27 -->
|
||||
|
||||
# SaseDev Knowledge
|
||||
|
||||
@@ -15,7 +15,7 @@ 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.4-alpha.1` ouvre la fondation PostgreSQL partagée sans code de persistance prématuré. L'étude de démarrage retient `tokio-postgres` comme driver PostgreSQL async natif, `deadpool-postgres` pour le pool et Refinery pour les migrations versionnées, sans ORM ni nouvelle crate `-api`. L'owner retenu pour l'implémentation est `knowledge-store-postgres-lib`, à matérialiser à partir d'`alpha.2`; le premier schéma est borné à la configuration logique des sources et à leur dernière révision synchronisée. Git reste autoritaire pour tout contenu publié.
|
||||
`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.
|
||||
|
||||
@@ -33,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.
|
||||
|
||||
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.1` sélectionne `tokio-postgres`, `deadpool-postgres`, Refinery et une base logique partagée ; la bibliothèque de stockage recevra sa configuration de connexion depuis la composition et ne lira ni ne journalisera elle-même des secrets d'environnement. PostgreSQL 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.
|
||||
|
||||
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
|
||||
|
||||
|
||||
12
RULES.md
12
RULES.md
@@ -1,5 +1,5 @@
|
||||
<!-- file: RULES.md -->
|
||||
<!-- version: 16 -->
|
||||
<!-- version: 17 -->
|
||||
|
||||
# Règles SaseDev Knowledge
|
||||
|
||||
@@ -142,15 +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.
|
||||
|
||||
`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. 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.
|
||||
`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 retenu est `knowledge-store-postgres-lib`, à matérialiser seulement à partir d'`0.0.4-alpha.2`. 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.
|
||||
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 embarquables 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.
|
||||
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 : configuration logique des sources et dernière révision synchronisée. Il ne stocke ni corps de contenu publié, ni modèle auth/proposition final, ni projection de contenu anticipée.
|
||||
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
|
||||
|
||||
|
||||
20
crates/knowledge-store-postgres-lib/Cargo.toml
Normal file
20
crates/knowledge-store-postgres-lib/Cargo.toml
Normal 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
|
||||
@@ -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
|
||||
);
|
||||
39
crates/knowledge-store-postgres-lib/src/config.rs
Normal file
39
crates/knowledge-store-postgres-lib/src/config.rs
Normal 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;
|
||||
36
crates/knowledge-store-postgres-lib/src/error.rs
Normal file
36
crates/knowledge-store-postgres-lib/src/error.rs
Normal 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 {}
|
||||
16
crates/knowledge-store-postgres-lib/src/lib.rs
Normal file
16
crates/knowledge-store-postgres-lib/src/lib.rs
Normal 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;
|
||||
44
crates/knowledge-store-postgres-lib/src/store.rs
Normal file
44
crates/knowledge-store-postgres-lib/src/store.rs
Normal 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),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
// file: crates/knowledge-store-postgres-lib/tests/postgres_migration.rs
|
||||
// version: 1
|
||||
|
||||
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;
|
||||
}
|
||||
23
crates/knowledge-store-postgres-lib/unit_tests/config.rs
Normal file
23
crates/knowledge-store-postgres-lib/unit_tests/config.rs
Normal 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;
|
||||
}
|
||||
279
deltas/0.0.4/alpha.2.md
Normal file
279
deltas/0.0.4/alpha.2.md
Normal 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é.
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/architecture/001-PROJECT_PROFILE.md -->
|
||||
<!-- version: 19 -->
|
||||
<!-- version: 20 -->
|
||||
|
||||
# Profil du projet Knowledge
|
||||
|
||||
@@ -131,15 +131,12 @@ knowledge-web-lib composition Actix/Maud/Vite partagée
|
||||
knowledge-pgr-server launcher PGR mince
|
||||
knowledge-howtos-server launcher HOWTOs 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.
|
||||
|
||||
`0.0.4-alpha.1` retient comme prochaine responsabilité réelle, sans encore la matérialiser dans cette tranche :
|
||||
|
||||
```text
|
||||
knowledge-store-postgres-lib pool, migrations et état applicatif PostgreSQL partagé
|
||||
```
|
||||
`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 :
|
||||
|
||||
@@ -192,17 +189,17 @@ Après publication vérifiée de `v0.0.3`, `0.0.4-alpha.1` consomme les `DEFER`
|
||||
La décision locale est :
|
||||
|
||||
```text
|
||||
owner prévu knowledge-store-postgres-lib
|
||||
driver tokio-postgres 0.7
|
||||
owner knowledge-store-postgres-lib
|
||||
driver tokio-postgres 0.7.18
|
||||
modèle SQL explicite, sans ORM
|
||||
pool deadpool-postgres 0.14
|
||||
migrations SQL versionné + Refinery 0.9
|
||||
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
|
||||
```
|
||||
|
||||
Aucune crate n'est créée pendant `alpha.1`. La tranche établit seulement l'étude et le plan qui autoriseront `alpha.2` après gate opérateur `PASS`.
|
||||
`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. La configuration de connexion PostgreSQL est injectée par la composition, non lue implicitement par la future crate de stockage.
|
||||
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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/architecture/002-KNOWLEDGE_ARCHITECTURE.md -->
|
||||
<!-- version: 19 -->
|
||||
<!-- version: 20 -->
|
||||
|
||||
# Architecture de fondation Knowledge
|
||||
|
||||
@@ -36,7 +36,7 @@ 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.
|
||||
|
||||
`0.0.4-alpha.1` retient `knowledge-store-postgres-lib` comme prochain owner concret du pool, des migrations et de l'état PostgreSQL partagé. Cette crate n'est pas encore créée dans la tranche de cadrage et aucun `knowledge-store-api` symétrique n'est introduit sans besoin de substitution démontré.
|
||||
`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.
|
||||
|
||||
@@ -151,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.
|
||||
|
||||
`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.
|
||||
|
||||
@@ -250,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.
|
||||
|
||||
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.
|
||||
|
||||
@@ -302,28 +302,28 @@ 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.
|
||||
|
||||
### Fondation sélectionnée pour `0.0.4`
|
||||
### Fondation matérialisée pour `0.0.4`
|
||||
|
||||
`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. La future crate `knowledge-store-postgres-lib` possédera la composition de ces trois responsabilités, la conversion de leurs erreurs en erreurs publiques récupérables et les opérations PostgreSQL concrètes. Knowledge ne sélectionne pas d'ORM, ne recherche pas d'abstraction multi-SGBD et n'introduit pas de `knowledge-store-api` tant qu'une seconde implémentation de stockage ou une frontière passive réellement indépendante n'est pas démontrée.
|
||||
`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 de stockage reçoit une URL/options de connexion et des paramètres de pool. Elle ne lit pas directement les variables d'environnement du processus et ne journalise jamais l'URL ou les credentials. Une connexion ou migration impossible retourne une erreur ; aucun fallback fichier/mémoire ne masque l'indisponibilité PostgreSQL.
|
||||
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
|
||||
git_reference TEXT NOT NULL
|
||||
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)
|
||||
source_id TEXT PRIMARY KEY REFERENCES knowledge_sources(source_id) ON DELETE CASCADE
|
||||
last_synchronized_revision TEXT NOT NULL
|
||||
```
|
||||
|
||||
`family` reste aligné sur `ContentFamily` et sera contraint aux valeurs supportées par le domaine. `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.
|
||||
`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.
|
||||
|
||||
Les migrations sont des fichiers SQL versionnés placés sous l'owner de stockage et appliqués explicitement par Refinery. La stratégie de test utilise une URL PostgreSQL de test fournie explicitement et un schéma unique éphémère par exécution ; la gate doit être `BLOCKED` si le service PostgreSQL requis n'est pas disponible, jamais convertir cette absence en test artificiellement passé. Le même mécanisme peut cibler un PostgreSQL local ou un service PostgreSQL éphémère de CI sans rendre Docker obligatoire pour la bibliothèque.
|
||||
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`.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/plans/004-V0_0_4_POSTGRES_FOUNDATION_PLAN.md -->
|
||||
<!-- version: 1 -->
|
||||
<!-- version: 2 -->
|
||||
|
||||
# Plan 0.0.4 — fondation PostgreSQL partagée
|
||||
|
||||
@@ -43,12 +43,20 @@ Décisions de `alpha.1` :
|
||||
- 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.
|
||||
|
||||
Questions laissées aux tranches d'implémentation :
|
||||
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 :
|
||||
|
||||
- surface publique minimale exacte de `PostgresStore` et de sa configuration ;
|
||||
- paramètres de pool utiles au produit sans exposer les types Deadpool ;
|
||||
- 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.
|
||||
- backend TLS à sélectionner uniquement si le déploiement visé l'exige ;
|
||||
- paramètres supplémentaires de pool uniquement sur besoin runtime observé.
|
||||
|
||||
## Scope
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/studies/008-V0_0_4_POSTGRES_FOUNDATION_STUDY.md -->
|
||||
<!-- version: 1 -->
|
||||
<!-- version: 2 -->
|
||||
|
||||
# Étude 0.0.4 — fondation PostgreSQL partagée
|
||||
|
||||
@@ -78,7 +78,7 @@ La sélection privilégie des responsabilités explicitement bornées plutôt qu
|
||||
|
||||
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` doit néanmoins revalider les versions stables compatibles au moment exact de leur ajout au manifest, conformément à la politique locale de dépendances, sans downgrade silencieux.
|
||||
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 :
|
||||
|
||||
@@ -90,7 +90,7 @@ 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.
|
||||
|
||||
Un backend TLS n'est pas figé par `alpha.1`. Si la cible de déploiement PostgreSQL exige TLS, la tranche qui matérialise la connexion doit sélectionner explicitement l'intégration TLS minimale compatible avec `tokio-postgres` au lieu d'hériter d'un défaut implicite.
|
||||
`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
|
||||
|
||||
@@ -100,7 +100,7 @@ La responsabilité est suffisamment concrète pour justifier :
|
||||
knowledge-store-postgres-lib
|
||||
```
|
||||
|
||||
Cette crate possédera :
|
||||
À partir d'`alpha.2`, cette crate possède :
|
||||
|
||||
- construction et lifecycle du pool `deadpool-postgres` ;
|
||||
- migrations SQL de Knowledge ;
|
||||
@@ -252,4 +252,4 @@ L'horizon reste donc :
|
||||
|
||||
`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` ne crée encore aucune crate, dépendance ou migration. Après son `PASS` opérateur, `alpha.2` peut matérialiser `knowledge-store-postgres-lib`, le trio `tokio-postgres` / `deadpool-postgres` / `refinery` et la première migration.
|
||||
`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`.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/validation/001-VALIDATION_MATRIX.md -->
|
||||
<!-- version: 42 -->
|
||||
<!-- version: 43 -->
|
||||
|
||||
# Matrice de validation Knowledge
|
||||
|
||||
@@ -1041,3 +1041,32 @@ La première tranche de `0.0.4` est une gate de cadrage sans code produit, dépe
|
||||
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.
|
||||
|
||||
221
history/0.0.4/alpha.2.md
Normal file
221
history/0.0.4/alpha.2.md
Normal 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`.
|
||||
Reference in New Issue
Block a user