v0.3.6-pre.012
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
# file: Cargo.toml
|
||||
# version: 412
|
||||
# version: 413
|
||||
|
||||
[workspace]
|
||||
resolver = "3"
|
||||
members = ["crates/ksp-app-config-desk", "crates/ksp-app-solprices-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-interface-lib", "crates/ksp-job-api", "crates/ksp-job-backfill-lib", "crates/ksp-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-program-api", "crates/ksp-store-api", "crates/ksp-store-lib", "crates/ksp-store-postgres-lib", "crates/ksp-wallet-lib"]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.3.6-pre.11"
|
||||
version = "0.3.6-pre.12"
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: README.md -->
|
||||
<!-- version: 7 -->
|
||||
<!-- version: 8 -->
|
||||
|
||||
# Khadhroony Solana Project
|
||||
|
||||
@@ -47,6 +47,12 @@ Les besoins du trading constituent une priorité produit à court terme mais ne
|
||||
- Aucun `rust-toolchain.toml` n'est utilisé.
|
||||
- Les environnements et contraintes des démonstrations doivent être visibles dans leur nomenclature lorsqu'ils ne sont pas sélectionnables.
|
||||
|
||||
## Fondations opérationnelles actuelles
|
||||
|
||||
La couche RAW dispose d'une façade Store backend-neutral et d'un premier job historique concret. `ksp-job-api` porte les contrats passifs communs des jobs bornés ; `ksp-job-backfill-lib` compose Transport observé et Store pour découvrir, hydrater et persister des transactions historiques RAW avec concurrence bornée, checkpoint contigu caller-owned, annulation coopérative et snapshots latest-value.
|
||||
|
||||
Ces contrats restent distincts des futurs workers continus : un job borné n'est ni un service worker ni un pipeline générique imposé aux autres couches.
|
||||
|
||||
## Points d'entrée
|
||||
|
||||
- [`RULES.md`](RULES.md) — index des règles normatives ;
|
||||
|
||||
72
crates/ksp-job-api/README.md
Normal file
72
crates/ksp-job-api/README.md
Normal file
@@ -0,0 +1,72 @@
|
||||
<!-- file: crates/ksp-job-api/README.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# ksp-job-api
|
||||
|
||||
`ksp-job-api` fournit les contrats passifs et runtime-neutral communs aux jobs bornés de KSP.
|
||||
|
||||
La crate possède l'identité logique d'un job, son lifecycle terminable, l'intention d'annulation coopérative et le contrat latest-value utilisé pour observer un snapshot complet. Elle ne possède aucun runtime concret, aucune politique métier de backfill, aucun Transport, aucun Store et aucun Worker.
|
||||
|
||||
## Responsabilités
|
||||
|
||||
La façade crate-root expose :
|
||||
|
||||
- `JobId` et `JobKindCode`, bornés et validés ;
|
||||
- `JobState` et `JobCompletion` ;
|
||||
- `JobLifecycle`, propriétaire des transitions admises ;
|
||||
- `JobCancellationToken`, cloneable et idempotent ;
|
||||
- `JobNotificationSequence`, strictement monotone et sans wrap silencieux ;
|
||||
- `JobNotification<S>`, valeur observable complète à une position donnée ;
|
||||
- `JobSnapshotSource`, contrat runtime-neutral de lecture courante et attente d'une valeur plus récente ;
|
||||
- les codes d'erreur Job et les types `Error`/`Result` communs de Core.
|
||||
|
||||
## Lifecycle
|
||||
|
||||
Le lifecycle admis reste explicitement borné :
|
||||
|
||||
```text
|
||||
Created
|
||||
| | +----------------------> Cancelled
|
||||
v
|
||||
Running
|
||||
| | +----> Cancelling -----> Cancelled
|
||||
| | | | +---------> Failed
|
||||
| +-------------> Completed(Complete|Partial)
|
||||
|
|
||||
+------------------------> Completed(Complete|Partial)
|
||||
+------------------------> Failed
|
||||
```
|
||||
|
||||
Tout état terminal est immuable. Une transition invalide retourne `ERROR_CODE_JOB_TRANSITION_INVALID` sans modifier l'état source.
|
||||
|
||||
## Observation latest-value
|
||||
|
||||
`JobSnapshotSource` n'impose ni callback, ni queue d'événements, ni runtime async particulier. Un listener peut :
|
||||
|
||||
1. lire la valeur complète courante ;
|
||||
2. mémoriser sa `JobNotificationSequence` ;
|
||||
3. attendre une valeur plus récente ;
|
||||
4. recevoir directement la dernière valeur complète, même si plusieurs mises à jour intermédiaires ont été coalescées.
|
||||
|
||||
Le snapshot concret appartient au job qui implémente la source. `ksp-job-api` ne connaît pas son contenu.
|
||||
|
||||
## Annulation
|
||||
|
||||
`JobCancellationToken` représente uniquement une intention coopérative partagée. Il ne tue pas une tâche, n'annule pas une I/O par lui-même et ne décide pas du résultat terminal. Le runtime concret reste responsable d'observer le token aux frontières sûres et de publier son état final.
|
||||
|
||||
## Firewall
|
||||
|
||||
La dépendance normale est volontairement minimale :
|
||||
|
||||
```text
|
||||
ksp-job-api
|
||||
-> ksp-core-lib
|
||||
```
|
||||
|
||||
La crate ne dépend pas de Tokio, Futures, Transport, Store, Config, Logging, serde ni d'une crate de job concret.
|
||||
|
||||
## Documentation
|
||||
|
||||
- [`USAGE.md`](USAGE.md) — utilisation durable des contrats Job ;
|
||||
- [`../../docs/architecture/003-COMPONENT_CONTRACTS.md`](../../docs/architecture/003-COMPONENT_CONTRACTS.md) — contrats de composants ;
|
||||
- [`../../docs/architecture/009-ACQUISITION_WORKERS_AND_JOBS.md`](../../docs/architecture/009-ACQUISITION_WORKERS_AND_JOBS.md) — séparation workers/jobs et premier backfill RAW.
|
||||
141
crates/ksp-job-api/USAGE.md
Normal file
141
crates/ksp-job-api/USAGE.md
Normal file
@@ -0,0 +1,141 @@
|
||||
<!-- file: crates/ksp-job-api/USAGE.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Utilisation de ksp-job-api
|
||||
|
||||
Cette page décrit la façade publique durable de `ksp-job-api`. Les consumers utilisent uniquement les exports du crate-root.
|
||||
|
||||
## Construire une identité de job
|
||||
|
||||
```rust
|
||||
fn job_identity() -> ksp_job_api::Result<(ksp_job_api::JobId, ksp_job_api::JobKindCode)> {
|
||||
let id = match ksp_job_api::JobId::new("raw-backfill-mainnet-0001") {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let kind = match ksp_job_api::JobKindCode::new("raw_transaction_backfill") {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
return std::result::Result::Ok((id, kind));
|
||||
}
|
||||
```
|
||||
|
||||
`JobId` identifie un job logique et ses reprises contrôlées. `JobKindCode` identifie une famille de jobs. Les deux sont bornés et utilisent un alphabet sûr ; leur `Debug` n'est pas une surface destinée à transporter un payload métier.
|
||||
|
||||
## Piloter un lifecycle passif
|
||||
|
||||
```rust
|
||||
fn lifecycle(id: ksp_job_api::JobId, kind: ksp_job_api::JobKindCode) -> ksp_job_api::Result<ksp_job_api::JobLifecycle> {
|
||||
let mut lifecycle = ksp_job_api::JobLifecycle::new(id, kind);
|
||||
if let std::result::Result::Err(error) = lifecycle.start() {
|
||||
return std::result::Result::Err(error);
|
||||
}
|
||||
if let std::result::Result::Err(error) = lifecycle.complete(ksp_job_api::JobCompletion::Complete) {
|
||||
return std::result::Result::Err(error);
|
||||
}
|
||||
return std::result::Result::Ok(lifecycle);
|
||||
}
|
||||
```
|
||||
|
||||
Le producer ne doit pas forcer un état directement. Il utilise les opérations de `JobLifecycle`, qui refusent les transitions hors matrice.
|
||||
|
||||
Pour une annulation observée pendant l'exécution :
|
||||
|
||||
```rust
|
||||
if let std::result::Result::Err(error) = lifecycle.mark_cancelling() {
|
||||
return std::result::Result::Err(error);
|
||||
}
|
||||
if let std::result::Result::Err(error) = lifecycle.mark_cancelled() {
|
||||
return std::result::Result::Err(error);
|
||||
}
|
||||
```
|
||||
|
||||
## Partager une intention d'annulation
|
||||
|
||||
```rust
|
||||
let token = ksp_job_api::JobCancellationToken::new();
|
||||
let listener = token.clone();
|
||||
|
||||
assert!(!listener.is_cancellation_requested());
|
||||
assert!(token.request_cancellation());
|
||||
assert!(listener.is_cancellation_requested());
|
||||
assert!(!token.request_cancellation());
|
||||
```
|
||||
|
||||
Le premier appel qui change l'état retourne `true`. Les demandes suivantes sont idempotentes et retournent `false`.
|
||||
|
||||
Le token ne doit pas être interprété comme une primitive de kill : le runtime concret décide où l'annulation peut interrompre l'admission ou une attente et quelles opérations déjà engagées doivent être drainées.
|
||||
|
||||
## Publier une valeur latest-value
|
||||
|
||||
Un producer concret peut construire une notification complète :
|
||||
|
||||
```rust
|
||||
#[derive(Clone)]
|
||||
struct Snapshot {
|
||||
completed: usize,
|
||||
}
|
||||
|
||||
let id = ksp_job_api::JobId::new("job-0001")?;
|
||||
let kind = ksp_job_api::JobKindCode::new("example")?;
|
||||
let sequence = ksp_job_api::JobNotificationSequence::initial();
|
||||
let notification = ksp_job_api::JobNotification::new(
|
||||
id,
|
||||
kind,
|
||||
sequence,
|
||||
ksp_job_api::JobState::Running,
|
||||
Snapshot { completed: 0 },
|
||||
);
|
||||
|
||||
assert_eq!(notification.sequence().value(), 0);
|
||||
assert_eq!(notification.state(), ksp_job_api::JobState::Running);
|
||||
```
|
||||
|
||||
Le `Debug` de `JobNotification<S>` masque volontairement le snapshot. Le type concret `S` doit lui-même rester sûr à exposer lorsque le consumer accède explicitement à `snapshot()`.
|
||||
|
||||
## Implémenter une source de snapshots
|
||||
|
||||
Une implémentation concrète possède son runtime et expose seulement le contrat `JobSnapshotSource` :
|
||||
|
||||
```rust
|
||||
async fn observe<S>(source: &S)
|
||||
where
|
||||
S: ksp_job_api::JobSnapshotSource,
|
||||
{
|
||||
let current = source.current();
|
||||
let observed = current.sequence();
|
||||
let newer = source.wait_for_change(observed).await;
|
||||
assert!(newer.sequence().is_after(observed));
|
||||
}
|
||||
```
|
||||
|
||||
`wait_for_change` retourne la dernière valeur complète connue après coalescence éventuelle. Un consumer ne doit donc pas supposer qu'il recevra chaque mise à jour intermédiaire.
|
||||
|
||||
## Faire avancer une séquence
|
||||
|
||||
```rust
|
||||
let first = ksp_job_api::JobNotificationSequence::initial();
|
||||
let second = match first.next() {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
assert!(second.is_after(first));
|
||||
```
|
||||
|
||||
L'épuisement de `u64` est une erreur explicite ; la séquence ne wrappe jamais silencieusement.
|
||||
|
||||
## Frontières à respecter
|
||||
|
||||
Ne pas ajouter à `ksp-job-api` :
|
||||
|
||||
```text
|
||||
Tokio/Futures runtime concret
|
||||
Transport ou Store
|
||||
Config/Logging
|
||||
DTO métier d'un job précis
|
||||
scheduler, worker ou control plane
|
||||
persistence de checkpoint
|
||||
```
|
||||
|
||||
Ces responsabilités appartiennent aux crates concrètes et à la composition supérieure.
|
||||
123
crates/ksp-job-backfill-lib/README.md
Normal file
123
crates/ksp-job-backfill-lib/README.md
Normal file
@@ -0,0 +1,123 @@
|
||||
<!-- file: crates/ksp-job-backfill-lib/README.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# ksp-job-backfill-lib
|
||||
|
||||
`ksp-job-backfill-lib` implémente le premier job historique concret de KSP : un backfill borné de transactions Solana vers la couche RAW durable.
|
||||
|
||||
La crate compose les contrats Job, Transport observé et Store backend-neutral sans posséder leurs politiques internes. Elle couvre l'admission, la découverte historique, l'hydratation `getTransaction`, la conversion RAW v1, la persistance atomique, la concurrence bornée, la frontier contiguë, le checkpoint caller-owned, l'annulation coopérative et les snapshots latest-value.
|
||||
|
||||
## Identité
|
||||
|
||||
L'identité logique d'une transaction reste :
|
||||
|
||||
```text
|
||||
(RawNetworkId, RawTransactionSignature)
|
||||
```
|
||||
|
||||
Le rôle HTTP, le provider, l'endpoint et le protocole ne font pas partie de cette identité. Ils décrivent la sélection et/ou la provenance d'acquisition.
|
||||
|
||||
Le fingerprint d'un scope est déterministe sur sa sémantique de découverte et son réseau ; il n'intègre pas `JobId`, provider, endpoint, protocole ou rôle Transport.
|
||||
|
||||
## Scopes
|
||||
|
||||
Quatre scopes sont exposés :
|
||||
|
||||
```text
|
||||
LatestAddress
|
||||
BeforeAddress
|
||||
AfterAddress
|
||||
ExplicitSignatures
|
||||
```
|
||||
|
||||
La requête borne explicitement page size, nombre de pages, nombre de candidats et concurrence d'hydratation. Les signatures explicites sont dédupliquées de façon stable à la première occurrence.
|
||||
|
||||
## Hydratation et RAW v1
|
||||
|
||||
L'hydratation passe uniquement par la voie observée de `ksp-onchain-transport-lib`.
|
||||
|
||||
Un résultat disponible produit en mémoire :
|
||||
|
||||
- un `RawTransaction` canonique ;
|
||||
- une `RawTransactionObservation` liée à la même référence logique ;
|
||||
- une provenance contenant le provider et l'endpoint réellement gagnants ;
|
||||
- un payload JSON canonique `ksp.solana.raw_transaction`, version `1` ;
|
||||
- un digest SHA-256 des bytes canoniques.
|
||||
|
||||
Un `getTransaction = null` devient `BackfillHydrationOutcome::Missing` et ne fabrique ni payload ni provenance.
|
||||
|
||||
## Persistance
|
||||
|
||||
La persistance utilise exclusivement `ksp-store-lib` avec `default-features = false` côté dépendance de crate :
|
||||
|
||||
```text
|
||||
ksp-job-backfill-lib
|
||||
-> ksp-store-lib
|
||||
-X-> backend imposé par le job
|
||||
```
|
||||
|
||||
Le chemin d'écriture est l'acquisition atomique `RawTransaction + RawTransactionObservation` en mode normal. La crate distingue insertion, déjà présent, tombstone purgé, observation nouvelle/existante, missing et conflit. Un conflit de contenu n'est jamais converti en succès idempotent.
|
||||
|
||||
## Concurrence et checkpoint
|
||||
|
||||
L'exécution maintient au plus `hydration_concurrency` candidats actifs. Les terminaisons hors ordre sont réconciliées par index stable ; le checkpoint n'avance que sur un préfixe **contigu** d'outcomes durablement sûrs.
|
||||
|
||||
`BackfillCheckpoint` est opaque et caller-owned. Il lie :
|
||||
|
||||
```text
|
||||
JobId
|
||||
scope fingerprint
|
||||
completed contiguous prefix
|
||||
private Before resume cursor
|
||||
```
|
||||
|
||||
La crate ne persiste pas elle-même ce checkpoint. Une reprise crash-safe durable nécessite donc que le caller choisisse explicitement où conserver le checkpoint retourné.
|
||||
|
||||
## Runtime et annulation
|
||||
|
||||
`BackfillJobRuntime` est un coordinator single-run. `BackfillJobHandle` peut être cloné pour :
|
||||
|
||||
- demander une annulation coopérative ;
|
||||
- lire l'état de cette demande ;
|
||||
- obtenir une source latest-value indépendante.
|
||||
|
||||
L'annulation arrête l'admission de nouveau travail et peut interrompre certaines attentes pré-Store. Une persistance Store déjà soumise est toujours drainée avant publication terminale.
|
||||
|
||||
Les snapshots exposent uniquement des compteurs, phases, boundary, checkpoint et code d'échec sûrs ; ils ne contiennent ni payload RAW, ni URL/credential Transport.
|
||||
|
||||
## Dépendances
|
||||
|
||||
Les dépendances normales sont :
|
||||
|
||||
```text
|
||||
ksp-core-lib
|
||||
ksp-job-api
|
||||
ksp-logging-lib
|
||||
ksp-onchain-transport-lib
|
||||
ksp-store-lib (default-features = false)
|
||||
futures-util
|
||||
serde_json
|
||||
sha2
|
||||
tokio (macros + sync, détail runtime privé)
|
||||
```
|
||||
|
||||
La crate ne dépend pas de Config, `ksp-store-api` directement, `ksp-store-postgres-lib` ni d'un SDK provider.
|
||||
|
||||
## Hors périmètre
|
||||
|
||||
La crate ne possède pas :
|
||||
|
||||
- application desktop ou CLI ;
|
||||
- Worker API / worker live ;
|
||||
- retry, pacing ou sélection d'endpoint Transport ;
|
||||
- backend Store concret ;
|
||||
- decoding Program ou matérialisation CORE/DECODE/SPECIALIZED ;
|
||||
- table dédiée de checkpoint ;
|
||||
- control plane Job générique.
|
||||
|
||||
## Documentation
|
||||
|
||||
- [`USAGE.md`](USAGE.md) — construction des scopes/requêtes, runtime, snapshots et reprise ;
|
||||
- [`../ksp-job-api/README.md`](../ksp-job-api/README.md) — contrats Job runtime-neutral ;
|
||||
- [`../../docs/architecture/009-ACQUISITION_WORKERS_AND_JOBS.md`](../../docs/architecture/009-ACQUISITION_WORKERS_AND_JOBS.md) — architecture durable acquisition/jobs ;
|
||||
- [`../../docs/architecture/008-DATA_MATERIALIZATION_AND_STORE.md`](../../docs/architecture/008-DATA_MATERIALIZATION_AND_STORE.md) — frontière RAW/Store.
|
||||
206
crates/ksp-job-backfill-lib/USAGE.md
Normal file
206
crates/ksp-job-backfill-lib/USAGE.md
Normal file
@@ -0,0 +1,206 @@
|
||||
<!-- file: crates/ksp-job-backfill-lib/USAGE.md -->
|
||||
<!-- version: 2 -->
|
||||
|
||||
# Utilisation de ksp-job-backfill-lib
|
||||
|
||||
Cette page décrit l'utilisation durable de la façade publique de `ksp-job-backfill-lib`. Elle suppose qu'un caller a déjà construit un `HttpTransportPool` et un `Store` compatibles avec le même réseau logique.
|
||||
|
||||
## Construire une signature et un scope
|
||||
|
||||
```rust
|
||||
let anchor = match ksp_job_backfill_lib::BackfillSignature::new(
|
||||
"1111111111111111111111111111111111111111111111111111111111111111",
|
||||
) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
|
||||
let address = ksp_core_lib::Pubkey::new_from_array([7_u8; 32]);
|
||||
let scope = ksp_job_backfill_lib::BackfillScope::before_address(address, anchor);
|
||||
```
|
||||
|
||||
Les autres formes sont :
|
||||
|
||||
```rust
|
||||
let latest = ksp_job_backfill_lib::BackfillScope::latest_address(address);
|
||||
let before = ksp_job_backfill_lib::BackfillScope::before_address(address, anchor.clone());
|
||||
let after = ksp_job_backfill_lib::BackfillScope::after_address(address, anchor.clone());
|
||||
let explicit = ksp_job_backfill_lib::BackfillScope::explicit_signatures(vec![anchor]);
|
||||
```
|
||||
|
||||
`ExplicitSignatures` déduplique la liste en conservant la première occurrence. Les scopes address utilisent `getSignaturesForAddress` ; le scope explicite n'effectue aucune découverte address.
|
||||
|
||||
## Construire une requête bornée
|
||||
|
||||
```rust
|
||||
fn request(scope: ksp_job_backfill_lib::BackfillScope) -> ksp_core_lib::Result<ksp_job_backfill_lib::BackfillRequest> {
|
||||
let job_id = match ksp_job_api::JobId::new("raw-backfill-0001") {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let network = match ksp_store_lib::RawNetworkId::new("mainnet") {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let role = ksp_onchain_transport_lib::HttpRoleName::new("historical");
|
||||
|
||||
return ksp_job_backfill_lib::BackfillRequest::new(
|
||||
job_id,
|
||||
network,
|
||||
role,
|
||||
ksp_job_backfill_lib::BackfillCommitment::Finalized,
|
||||
scope,
|
||||
500,
|
||||
20,
|
||||
5_000,
|
||||
16,
|
||||
std::option::Option::None,
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Bornes publiques :
|
||||
|
||||
```text
|
||||
page_size 1 ..= 1_000
|
||||
max_pages 1 ..= 10_000
|
||||
max_candidates 1 ..= 10_000
|
||||
hydration_concurrency 1 ..= 64
|
||||
```
|
||||
|
||||
Le `min_context_slot` n'est pas admis pour `ExplicitSignatures`.
|
||||
|
||||
## Comprendre le fingerprint
|
||||
|
||||
```rust
|
||||
let fingerprint = request.scope_fingerprint();
|
||||
let bytes: &[u8; 32] = fingerprint.as_bytes();
|
||||
```
|
||||
|
||||
Le fingerprint représente le scope sémantique et le réseau. Il ne change pas uniquement parce que le rôle Transport, le provider ou l'endpoint d'acquisition change.
|
||||
|
||||
Ne pas utiliser le fingerprint comme identité de transaction : l'identité durable reste `(network, signature)`.
|
||||
|
||||
## Exécuter le runtime complet
|
||||
|
||||
```rust
|
||||
async fn run_backfill(
|
||||
request: ksp_job_backfill_lib::BackfillRequest,
|
||||
transport: &ksp_onchain_transport_lib::HttpTransportPool,
|
||||
store: &ksp_store_lib::Store,
|
||||
) -> ksp_core_lib::Result<ksp_job_backfill_lib::BackfillJobSnapshot> {
|
||||
let runtime = match ksp_job_backfill_lib::BackfillJobRuntime::new(request) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
return runtime.run(transport, store).await;
|
||||
}
|
||||
```
|
||||
|
||||
Le Store et la requête doivent cibler le même `RawNetworkId`. Un mismatch est rejeté avant l'écriture.
|
||||
|
||||
## Observer la progression
|
||||
|
||||
Obtenir le handle avant de déplacer le runtime dans `run` :
|
||||
|
||||
```rust
|
||||
let runtime = ksp_job_backfill_lib::BackfillJobRuntime::new(request)?;
|
||||
let handle = runtime.handle();
|
||||
let snapshots = handle.snapshots();
|
||||
|
||||
let current = ksp_job_api::JobSnapshotSource::current(&snapshots);
|
||||
let observed = current.sequence();
|
||||
let newer = ksp_job_api::JobSnapshotSource::wait_for_change(&snapshots, observed).await;
|
||||
|
||||
assert!(newer.sequence().is_after(observed));
|
||||
```
|
||||
|
||||
Chaque listener peut cloner sa propre `BackfillSnapshotSource`. La source est latest-value : plusieurs mises à jour intermédiaires peuvent être coalescées, mais la valeur retournée est toujours un snapshot complet.
|
||||
|
||||
Les compteurs publics du snapshot couvrent notamment :
|
||||
|
||||
```text
|
||||
candidates_selected / admitted / finished
|
||||
entities_inserted / existing / purged
|
||||
observations_inserted / existing
|
||||
missing / conflicts / holes
|
||||
maximum_in_flight
|
||||
contiguous_completed
|
||||
checkpoint
|
||||
failure_code
|
||||
```
|
||||
|
||||
## Demander une annulation
|
||||
|
||||
```rust
|
||||
let accepted = handle.cancel();
|
||||
if accepted {
|
||||
assert!(handle.is_cancellation_requested());
|
||||
}
|
||||
```
|
||||
|
||||
L'annulation est coopérative. Elle peut stopper de nouvelles admissions et certaines attentes avant persistance. Une écriture Store déjà soumise est drainée ; le caller ne doit donc pas supposer qu'une demande d'annulation rend immédiatement toutes les opérations in-flight inexistantes.
|
||||
|
||||
Une demande faite après publication terminale est rejetée (`false`).
|
||||
|
||||
## Reprendre avec un checkpoint
|
||||
|
||||
Le snapshot ou le batch d'exécution peut fournir un `BackfillCheckpoint` sûr. Pour une reprise contrôlée :
|
||||
|
||||
```rust
|
||||
let resumed = match request.with_checkpoint(checkpoint) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
```
|
||||
|
||||
Le checkpoint doit appartenir au même `JobId` et au même fingerprint de scope.
|
||||
|
||||
Sémantique de reprise :
|
||||
|
||||
```text
|
||||
LatestAddress repart du latest courant ; frontier contiguë conservée dans le nouveau run
|
||||
BeforeAddress reprend avec le dernier cursor before prouvé
|
||||
AfterAddress rejoue le scope et saute seulement le préfixe contigu prouvé
|
||||
ExplicitSignatures rejoue la liste et saute seulement le préfixe contigu prouvé
|
||||
```
|
||||
|
||||
`BackfillCheckpoint` n'est pas persisté automatiquement. Si le caller exige une reprise après crash/process restart, il doit stocker ce checkpoint dans une surface durable appropriée puis le réinjecter explicitement.
|
||||
|
||||
## Utiliser les primitives séparément
|
||||
|
||||
La façade expose aussi les étapes pour des compositions/tests spécialisés :
|
||||
|
||||
```text
|
||||
discover_backfill_candidates
|
||||
hydrate_backfill_candidate
|
||||
persist_backfill_hydration
|
||||
execute_backfill_discovery
|
||||
```
|
||||
|
||||
`hydrate_backfill_candidate` ne persiste rien. `persist_backfill_hydration` n'effectue aucun appel Transport. `execute_backfill_discovery` combine hydratation/persistance sur un résultat de découverte déjà validé.
|
||||
|
||||
Pour un flux applicatif normal qui veut lifecycle + snapshots + annulation, préférer `BackfillJobRuntime::run`.
|
||||
|
||||
## Interpréter les outcomes de persistance
|
||||
|
||||
Les outcomes distinguent explicitement :
|
||||
|
||||
```text
|
||||
entity: Inserted | AlreadyPresent | SkippedPurged | Conflict
|
||||
observation: Inserted | AlreadyPresent | NotRecorded | NotApplicable
|
||||
```
|
||||
|
||||
`Missing` ne provoque aucune écriture Store. Un conflit de contenu reste observable comme conflit et ne doit pas être traité comme une relance idempotente réussie.
|
||||
|
||||
## Frontières à respecter
|
||||
|
||||
Le caller ne doit pas :
|
||||
|
||||
- pré-lire le Store pour décider s'il faut hydrater une transaction ;
|
||||
- appeler directement `ksp-store-postgres-lib` depuis le job ;
|
||||
- ajouter une politique de retry/pacing qui concurrence Transport ;
|
||||
- utiliser provider/endpoint comme identité transactionnelle ;
|
||||
- inventer une provenance pour `getTransaction = null` ;
|
||||
- interpréter un checkpoint caller-owned comme une garantie de persistence crash-safe automatique ;
|
||||
- utiliser le job RAW comme decoder Program ou processor CORE.
|
||||
204
deltas/0.3.6/pre.012.md
Normal file
204
deltas/0.3.6/pre.012.md
Normal file
@@ -0,0 +1,204 @@
|
||||
<!-- file: deltas/0.3.6/pre.012.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta `0.3.6-pre.012` — réconciliation documentaire finale Job/Backfill
|
||||
|
||||
## 1. Base requise
|
||||
|
||||
Base directe attendue :
|
||||
|
||||
```text
|
||||
0.3.6-pre.11
|
||||
```
|
||||
|
||||
Le gate technique final de `pre.011` est fermé : format en mode check, audits Rust/Markdown, `cargo check --workspace`, Clippy workspace/all-targets/all-features avec `-D warnings` et tests workspace/all-targets/all-features passent. Le run opérateur agrège `1_404` tests passés, `0` échec et `15` tests explicitement ignorés/opt-in. Les graphes Cargo de `ksp-job-api` et `ksp-job-backfill-lib` ainsi que l'inventaire des doublons workspace ont été exécutés et revus.
|
||||
|
||||
## 2. Objectif
|
||||
|
||||
Réconcilier exclusivement la documentation durable avec la surface Job/Backfill effectivement validée, sans rouvrir le comportement Rust ni commencer la publication.
|
||||
|
||||
La tranche couvre :
|
||||
|
||||
```text
|
||||
README racine
|
||||
README/USAGE de ksp-job-api
|
||||
README/USAGE de ksp-job-backfill-lib
|
||||
index documentaires
|
||||
architectures concernées par Jobs/Backfill
|
||||
plan 027
|
||||
validation 023
|
||||
```
|
||||
|
||||
Elle ne modifie aucun `src/**`, test, manifeste de crate, dépendance, feature, Config, Store, Transport, `CHANGELOG.md`, `ROADMAP.md` ou prompt suivant.
|
||||
|
||||
## 3. Version
|
||||
|
||||
Conformément au workflow de prerelease non-fix :
|
||||
|
||||
```text
|
||||
workspace.package.version = 0.3.6-pre.12
|
||||
```
|
||||
|
||||
Aucune autre propriété Cargo n'est modifiée.
|
||||
|
||||
## 4. Contrat durable `ksp-job-api`
|
||||
|
||||
Le nouveau README décrit la crate comme API passive et runtime-neutral possédant :
|
||||
|
||||
```text
|
||||
JobId / JobKindCode
|
||||
JobState / JobCompletion / JobLifecycle
|
||||
JobCancellationToken
|
||||
JobNotificationSequence / JobNotification<S>
|
||||
JobSnapshotSource / JobSnapshotFuture
|
||||
```
|
||||
|
||||
Le nouveau USAGE fournit des exemples de consommation via la façade crate-root pour l'identité, le lifecycle, l'annulation et le contrat latest-value. Il ne contient aucune note de prerelease, preuve de gate ou historique de version.
|
||||
|
||||
La frontière de dépendance reste explicite : dépendance normale uniquement vers `ksp-core-lib`, aucune dépendance Transport/Store/Tokio ou domaine métier.
|
||||
|
||||
## 5. Contrat durable `ksp-job-backfill-lib`
|
||||
|
||||
Le README et le USAGE décrivent désormais la surface concrète du premier job historique RAW :
|
||||
|
||||
```text
|
||||
4 scopes : LatestAddress / BeforeAddress / AfterAddress / ExplicitSignatures
|
||||
identité logique = (RawNetworkId, Signature)
|
||||
fingerprint sémantique indépendant du JobId et de la source Transport
|
||||
hydratation getTransaction observée
|
||||
RAW transaction format v1 déterministe
|
||||
persistance atomique via ksp-store-lib en mode Normal
|
||||
concurrence d'hydratation bornée
|
||||
frontier contiguë
|
||||
checkpoint caller-owned
|
||||
runtime concret + handle + snapshots latest-value
|
||||
annulation coopérative avec drainage des persistances Store déjà soumises
|
||||
```
|
||||
|
||||
La documentation distingue explicitement un checkpoint retourné au caller d'une persistance crash-safe automatique : la crate ne possède pas de stockage durable de checkpoint.
|
||||
|
||||
Le Store reste consommé uniquement par `ksp-store-lib` avec `default-features = false`; aucun backend physique ou `ksp-store-api` n'est exposé aux consommateurs Backfill.
|
||||
|
||||
## 6. Architecture et inventaires
|
||||
|
||||
Les documents durables suivants sont réconciliés avec le vertical désormais prouvé :
|
||||
|
||||
```text
|
||||
docs/architecture/002-LAYERS_AND_DEPENDENCIES.md
|
||||
docs/architecture/003-COMPONENT_CONTRACTS.md
|
||||
docs/architecture/004-COMPONENT_INVENTORY.md
|
||||
docs/architecture/005-DEPENDENCY_GRAPH.md
|
||||
docs/architecture/009-ACQUISITION_WORKERS_AND_JOBS.md
|
||||
docs/architecture/010-APPS_SERVICES_SCENARIOS_AND_CONTROL.md
|
||||
```
|
||||
|
||||
Ils enregistrent notamment :
|
||||
|
||||
- `ksp-job-api` comme API Job passive et runtime-neutral ;
|
||||
- `ksp-job-backfill-lib` comme première implementation concrète bornée, distincte d'un worker live permanent ;
|
||||
- les frontières Transport/Store/Job ;
|
||||
- la responsabilité caller-owned du checkpoint ;
|
||||
- les dépendances runtime privées du Backfill ;
|
||||
- l'absence de justification actuelle pour une couche générique de contrôle supplémentaire.
|
||||
|
||||
`004-COMPONENT_INVENTORY.md` introduit le statut durable `Implémenté` pour une surface techniquement validée mais pas encore publiée stable et l'applique aux deux composants Job de `0.3.6`.
|
||||
|
||||
## 7. Index et README racine
|
||||
|
||||
Les index `docs/`, `docs/plans/` et `docs/validation/` référencent désormais les documents actuels jusqu'aux plans `027` et validations `023`.
|
||||
|
||||
Le README racine décrit la fondation opérationnelle actuelle Store/Job/Backfill sans journaliser les prereleases.
|
||||
|
||||
## 8. Hors scope préservé
|
||||
|
||||
```text
|
||||
CHANGELOG.md
|
||||
ROADMAP.md
|
||||
prompt 0.3.7
|
||||
src/**
|
||||
tests/**
|
||||
Cargo.toml de crates
|
||||
dépendances/features
|
||||
nouveau runtime
|
||||
nouveau backend Store
|
||||
application Backfill Desk
|
||||
worker live
|
||||
smoke live PostgreSQL
|
||||
```
|
||||
|
||||
La préparation `CHANGELOG` / `ROADMAP` / prompt reste réservée à `pre.013`.
|
||||
|
||||
## 9. Fichiers ajoutés
|
||||
|
||||
```text
|
||||
crates/ksp-job-api/README.md
|
||||
crates/ksp-job-api/USAGE.md
|
||||
crates/ksp-job-backfill-lib/README.md
|
||||
crates/ksp-job-backfill-lib/USAGE.md
|
||||
deltas/0.3.6/pre.012.md
|
||||
```
|
||||
|
||||
## 10. Fichiers modifiés
|
||||
|
||||
```text
|
||||
Cargo.toml
|
||||
README.md
|
||||
docs/000-README.md
|
||||
docs/architecture/002-LAYERS_AND_DEPENDENCIES.md
|
||||
docs/architecture/003-COMPONENT_CONTRACTS.md
|
||||
docs/architecture/004-COMPONENT_INVENTORY.md
|
||||
docs/architecture/005-DEPENDENCY_GRAPH.md
|
||||
docs/architecture/009-ACQUISITION_WORKERS_AND_JOBS.md
|
||||
docs/architecture/010-APPS_SERVICES_SCENARIOS_AND_CONTROL.md
|
||||
docs/plans/000-README.md
|
||||
docs/plans/027-V0_3_6_JOB_API_BACKFILL_PLAN.md
|
||||
docs/validation/000-README.md
|
||||
docs/validation/023-V0_3_6_JOB_API_BACKFILL.md
|
||||
```
|
||||
|
||||
## 11. Fichiers supprimés
|
||||
|
||||
Aucun.
|
||||
|
||||
## 12. Validations de génération
|
||||
|
||||
Les contrôles statiques applicables sont rejoués sur l'overlay complet :
|
||||
|
||||
```text
|
||||
python3 scripts/audit_rust_workspace_rules.py
|
||||
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.3.6
|
||||
python3 scripts/tests/test_audit_markdown_tables.py
|
||||
contrôle différentiel exact contre pre.011
|
||||
contrôle des versions d'en-tête
|
||||
contrôle que src/tests/manifests de crates restent byte-identical
|
||||
replay exact de l'archive sur pre.011
|
||||
```
|
||||
|
||||
Cargo/rustc/rustfmt ne sont pas disponibles dans l'environnement de génération ; aucun nouveau résultat Cargo post-overlay n'est revendiqué ici. Les preuves techniques larges restent celles du gate `pre.011`.
|
||||
|
||||
## 13. Gate opérateur après application
|
||||
|
||||
```bash
|
||||
cargo fmt --all -- --check
|
||||
python3 scripts/audit_rust_workspace_rules.py
|
||||
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.3.6
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets
|
||||
cargo test -p ksp-job-api
|
||||
cargo test -p ksp-job-backfill-lib
|
||||
```
|
||||
|
||||
Aucun `cargo tree`, test workspace all-features ou smoke live n'est requis par cette tranche documentaire ; ces preuves sont déjà fermées par `pre.011` et aucun graphe de dépendance n'est modifié.
|
||||
|
||||
## 14. Questions ouvertes
|
||||
|
||||
Aucune question de design pour `0.3.6`.
|
||||
|
||||
## 15. Suite
|
||||
|
||||
Après gate documentaire vert :
|
||||
|
||||
```text
|
||||
0.3.6-pre.013 — préparation publication minimale + prompt 0.3.7
|
||||
0.3.6-rel.001 — stabilisation/tag v0.3.6
|
||||
```
|
||||
File diff suppressed because one or more lines are too long
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/architecture/002-LAYERS_AND_DEPENDENCIES.md -->
|
||||
<!-- version: 8 -->
|
||||
<!-- version: 9 -->
|
||||
|
||||
# Couches et dépendances KSP
|
||||
|
||||
@@ -27,7 +27,7 @@ Les niveaux architecturaux N1–N4 décrivent les familles de composants du proj
|
||||
|
||||
- `ksp-store-api` / `ksp-store-lib` ;
|
||||
- `ksp-materializer-api` / implementations lorsque DECODE s'ouvre ;
|
||||
- `ksp-job-api` et jobs ;
|
||||
- `ksp-job-api`, `ksp-job-backfill-lib` puis les jobs concrets introduits par les couches ;
|
||||
- `ksp-worker-api` et workers ;
|
||||
- processors/pipelines spécialisés réellement réutilisés.
|
||||
|
||||
@@ -138,11 +138,11 @@ Des applications spécialisées sont ajoutées au fur et à mesure pour valider
|
||||
|
||||
## Workers et jobs
|
||||
|
||||
Un worker est un service continu/autonome ; un job est borné/terminable.
|
||||
Un worker est un service continu/autonome ; un job est borné/terminable. `ksp-job-api` porte le lifecycle commun et l'observation latest-value sans runtime concret. Le premier job, `ksp-job-backfill-lib`, fournit un runtime single-run historique vers RAW ; il compose Transport et Store sans devenir worker ni service permanent.
|
||||
|
||||
Ils utilisent des APIs lifecycle distinctes et ne s'appellent pas entre eux pour transférer les payloads du data plane.
|
||||
Workers et jobs utilisent des APIs lifecycle distinctes et ne s'appellent pas entre eux pour transférer les payloads du data plane. Un checkpoint de job peut être caller-owned sans devenir automatiquement une persistence de control plane.
|
||||
|
||||
Le Store reste le point durable de synchronisation entre couches de processing.
|
||||
Le Store reste le point durable de synchronisation des données entre couches de processing ; les snapshots Job décrivent l'état opérationnel du job et ne remplacent pas les données RAW persistées.
|
||||
|
||||
## Firewall des dépendances externes
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/architecture/003-COMPONENT_CONTRACTS.md -->
|
||||
<!-- version: 12 -->
|
||||
<!-- version: 13 -->
|
||||
|
||||
# Contrats initiaux des composants KSP
|
||||
|
||||
@@ -180,13 +180,13 @@ Les workers DECODE/SPECIALIZED sont introduits avec les groupes Program réels,
|
||||
|
||||
## Jobs
|
||||
|
||||
`ksp-job-api` est la lifecycle API des travaux déclenchés/terminables.
|
||||
`ksp-job-api` est l'API passive et runtime-neutral des travaux bornés/terminables. Elle possède `JobId`, `JobKindCode`, le lifecycle `Created/Running/Cancelling/Completed/Cancelled/Failed`, l'intention d'annulation coopérative et le contrat latest-value `JobNotification` / `JobSnapshotSource`. Sa dépendance normale reste exclusivement `ksp-core-lib`.
|
||||
|
||||
Le premier job retenu est le backfill RAW.
|
||||
Le premier job concret est `ksp-job-backfill-lib`. Il couvre un backfill historique `RawTransaction` : quatre scopes bornés, découverte/hydratation Transport observée, conversion RAW v1, persistance atomique par `ksp-store-lib`, concurrence bornée, frontier/checkpoint contigus caller-owned, annulation coopérative et snapshots complets sûrs. Il ne dépend ni de Config, ni d'un backend Store concret, ni d'un Worker.
|
||||
|
||||
Les jobs de replay suivent ensuite les frontières durables ouvertes : RAW -> CORE, CORE -> DECODE, DECODE -> SPECIALIZED.
|
||||
Les jobs de replay suivants pourront suivre les frontières durables ouvertes : RAW -> CORE, CORE -> DECODE, DECODE -> SPECIALIZED. Ils ne sont pas forcés d'adopter le contrat métier du backfill RAW ; seuls les contrats vraiment communs appartiennent à `ksp-job-api`.
|
||||
|
||||
Aucune `ksp-job-control-lib` n'est prévue sans duplication concrète.
|
||||
Aucune `ksp-job-control-lib` n'est créée sans duplication concrète.
|
||||
|
||||
## Scenarios
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/architecture/004-COMPONENT_INVENTORY.md -->
|
||||
<!-- version: 28 -->
|
||||
<!-- version: 31 -->
|
||||
|
||||
# Inventaire initial des composants KSP
|
||||
|
||||
@@ -10,6 +10,7 @@ Ce document maintient l'inventaire synthétique des composants retenus ou presse
|
||||
## Statuts
|
||||
|
||||
- `Stable` — implémenté et publié ;
|
||||
- `Implémenté` — présent et techniquement validé, en attente de publication stable ;
|
||||
- `Retenu` — composant/contrat décidé ;
|
||||
- `Pressenti` — direction décidée mais périmètre exact à confirmer ;
|
||||
- `À la demande` — créé seulement au premier besoin réel ;
|
||||
@@ -36,11 +37,11 @@ Ce document maintient l'inventaire synthétique des composants retenus ou presse
|
||||
| Program API | `ksp-program-api` | API | Stable | `0.2.14` | contrats extensibles Program |
|
||||
| Program impl. | `ksp-program-lib` | lib | Retenu | vertical slices ultérieurs | implementations Program officielles |
|
||||
| Program extension | `ksp-program-<name>-lib` | lib externe | À la demande | dès besoin | implementation externe de `ksp-program-api` |
|
||||
| Store API | `ksp-store-api` | API | Retenu | `0.3.1` | RAW transaction/account, observations, queries, outcomes, rétention et capabilities backend |
|
||||
| Store runtime | `ksp-store-lib` | lib | Retenu | `0.3.2`–`0.3.4` | fondation puis conformance RAW par slices, dispatch features/config |
|
||||
| Store PostgreSQL | `ksp-store-postgres-lib` | lib | Retenu | `0.3.2`–`0.3.4` | fondation, RawTransaction puis RawAccountState/complétude |
|
||||
| Job lifecycle | `ksp-job-api` | API | Retenu | `0.3.6` | lifecycle des jobs terminables |
|
||||
| Backfill | `ksp-job-backfill-lib` | lib | Retenu | `0.3.6` | Job borné : découverte/hydratation historique vers RAW via Transport + `ksp-store-lib` |
|
||||
| Store API | `ksp-store-api` | API | Stable | `0.3.1` | RAW transaction/account, observations, queries, outcomes, rétention et capabilities backend |
|
||||
| Store runtime | `ksp-store-lib` | lib | Stable | `0.3.2`–`0.3.4` | façade backend-neutral et conformance RAW 10/10 |
|
||||
| Store PostgreSQL | `ksp-store-postgres-lib` | lib | Stable | `0.3.2`–`0.3.4` | backend référence : fondation, RawTransaction et RawAccountState |
|
||||
| Job lifecycle | `ksp-job-api` | API | Implémenté | `0.3.6` | identité/lifecycle/annulation/notifications latest-value runtime-neutral |
|
||||
| Backfill | `ksp-job-backfill-lib` | lib | Implémenté | `0.3.6` | backfill `RawTransaction` borné via Transport observé + Store, checkpoint et runtime |
|
||||
| Backfill Desk | nom à fixer | app | Retenu | `0.3.7` | contrôle/inspection du backfill RAW |
|
||||
| Worker lifecycle | `ksp-worker-api` | API | Retenu | fin couche RAW | lifecycle des services continus |
|
||||
| RAW worker | `ksp-worker-raw-retriever` ou nom révisé | worker | Retenu | fin couche RAW | acquisition live vers RAW |
|
||||
@@ -149,9 +150,8 @@ Market Desk est progressive : V1 après les DEX prioritaires, puis enrichissemen
|
||||
|
||||
## Questions restantes
|
||||
|
||||
- noms exacts de Price Desk et Backfill Desk ;
|
||||
- surface exacte Yellowstone après audit normatif de `0.2.9-pre.001` ;
|
||||
- nom exact de Backfill Desk ;
|
||||
- nécessité future d'un pool automatique WS ;
|
||||
- types exacts `ksp-program-api`/`ksp-materializer-api`/`ksp-store-api` ;
|
||||
- types exacts `ksp-materializer-api` lors de l'ouverture DECODE ;
|
||||
- nom/packaging précis du premier RAW worker et du CORE normalizer ;
|
||||
- granularité des workers DECODE/SPECIALIZED par groupe.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/architecture/005-DEPENDENCY_GRAPH.md -->
|
||||
<!-- version: 19 -->
|
||||
<!-- version: 20 -->
|
||||
|
||||
# Graphe de dépendances KSP
|
||||
|
||||
@@ -375,10 +375,14 @@ ksp-job-backfill-lib
|
||||
-> ksp-core-lib
|
||||
-> ksp-logging-lib
|
||||
-> ksp-onchain-transport-lib
|
||||
-> ksp-store-lib # façade backend-neutral ; dépendance sans feature backend imposée
|
||||
-> ksp-store-lib # default-features = false ; aucun backend imposé
|
||||
-> futures-util / tokio # runtime privé du job, jamais dans ksp-job-api
|
||||
-> serde_json / sha2 # canonicalisation RAW v1 et digest
|
||||
```
|
||||
|
||||
Il remplit RAW et ne décode aucun programme. Il ne dépend pas de Config : l'application supérieure construit explicitement Transport, Store et la requête Job. Le réseau appartient au scope/à l'identité durable ; rôle, provider, endpoint et protocole restent des choix ou provenances d'acquisition et ne deviennent jamais une clé de transaction.
|
||||
Il remplit RAW et ne décode aucun programme. Il ne dépend pas de Config : la composition supérieure construit explicitement Transport, Store et `BackfillRequest`. Le réseau appartient au scope/à l'identité durable `(network, signature)` ; rôle, provider, endpoint et protocole restent des choix ou provenances d'acquisition et ne deviennent jamais une clé de transaction.
|
||||
|
||||
`ksp-job-api` ne dépend en retour d'aucun runtime ou domaine concret. `ksp-job-backfill-lib` ne dépend ni directement de `ksp-store-api`, ni de `ksp-store-postgres-lib`; la façade Store demeure l'unique frontière runtime de persistance.
|
||||
|
||||
## Workers
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/architecture/009-ACQUISITION_WORKERS_AND_JOBS.md -->
|
||||
<!-- version: 9 -->
|
||||
<!-- version: 10 -->
|
||||
|
||||
# Acquisition, workers, jobs et pipelines spécialisés
|
||||
|
||||
@@ -78,12 +78,17 @@ D1 RAW
|
||||
|
||||
Le job :
|
||||
|
||||
- utilise `ksp-job-api` pour son lifecycle ;
|
||||
- gère scope/range/pagination/checkpoint ;
|
||||
- porte explicitement le réseau logique du Store dans le scope et dans l'identité de chaque transaction candidate ;
|
||||
- traite rôle HTTP, provider, endpoint et protocole comme sélection/provenance d'acquisition, jamais comme identité transactionnelle ;
|
||||
- n'effectue aucun décodage Program ;
|
||||
- n'écrit pas directement des faits CORE/DECODE/SPECIALIZED.
|
||||
- utilise `ksp-job-api` pour identité, lifecycle, annulation abstraite et observation latest-value ;
|
||||
- expose `LatestAddress`, `BeforeAddress`, `AfterAddress` et `ExplicitSignatures` avec bornes explicites de pages/candidats/concurrence ;
|
||||
- porte explicitement le réseau logique du Store dans le scope et dans l'identité `(network, signature)` de chaque transaction candidate ;
|
||||
- exclut rôle HTTP, provider, endpoint et protocole du fingerprint sémantique et de l'identité transactionnelle ;
|
||||
- hydrate uniquement via la voie observée `getTransaction`, afin de conserver la provenance du provider/endpoint réellement gagnant ;
|
||||
- produit un RAW v1 canonique déterministe puis persiste transaction + observation atomiquement via `ksp-store-lib` en mode normal ;
|
||||
- respecte les tombstones `Purged`, distingue missing/conflit/idempotence et ne pré-lit pas le Store avant hydratation ;
|
||||
- limite les hydrations concurrentes, avance seulement une frontier contiguë durable et retourne un checkpoint opaque caller-owned ;
|
||||
- arrête coopérativement les nouvelles admissions lors d'une annulation et draine une persistence Store déjà soumise ;
|
||||
- publie des snapshots latest-value sûrs sans payload RAW ni secrets/URLs Transport ;
|
||||
- n'effectue aucun décodage Program et n'écrit aucun fait CORE/DECODE/SPECIALIZED.
|
||||
|
||||
### Worker RAW live
|
||||
|
||||
@@ -240,31 +245,27 @@ Une capability comme `reconfigure` n'est pas imposée à tous les workers.
|
||||
|
||||
## Job API
|
||||
|
||||
`ksp-job-api` reste distinct de Worker API.
|
||||
`ksp-job-api` reste distinct de Worker API et volontairement runtime-neutral.
|
||||
|
||||
Concepts candidats :
|
||||
Contrats communs actuels :
|
||||
|
||||
```text
|
||||
JobId
|
||||
JobDescriptor
|
||||
JobKindCode
|
||||
JobState
|
||||
JobProgress
|
||||
JobOutcome
|
||||
JobCapabilities
|
||||
JobCompletion
|
||||
JobLifecycle
|
||||
JobCancellationToken
|
||||
JobNotificationSequence
|
||||
JobNotification<Snapshot>
|
||||
JobSnapshotSource
|
||||
```
|
||||
|
||||
Un job est borné/terminable et peut exposer selon besoin :
|
||||
Le lifecycle commun est borné aux transitions explicitement validées entre `Created`, `Running`, `Cancelling` et les états terminaux `Completed(Complete|Partial)`, `Cancelled`, `Failed`. Il ne définit ni `pause`, ni `resume`, ni scheduler, ni runtime d'exécution générique.
|
||||
|
||||
```text
|
||||
start
|
||||
pause
|
||||
resume
|
||||
cancel
|
||||
status
|
||||
progress
|
||||
```
|
||||
`JobSnapshotSource` suit une sémantique latest-value : un listener lit une valeur complète courante puis peut attendre une séquence plus récente ; les valeurs intermédiaires peuvent être coalescées. Le snapshot métier reste possédé par le job concret.
|
||||
|
||||
Les types exacts sont décidés à `0.3.6` avec le premier vrai backfill, après clôture des trois slices Store/PostgreSQL `0.3.2`–`0.3.4` et de la tranche Interface `0.3.5`.
|
||||
L'annulation commune est une intention coopérative. Le job concret décide quelles attentes peuvent être interrompues et quelles opérations engagées doivent être drainées.
|
||||
|
||||
Aucune `ksp-job-control-lib` n'est créée sans duplication concrète.
|
||||
|
||||
@@ -309,15 +310,11 @@ Les états exacts seront définis avec le premier processor durable, mais doiven
|
||||
|
||||
## Reprise après crash
|
||||
|
||||
Un worker/job doit reconstruire son état depuis :
|
||||
Un worker/job qui promet une reprise après crash doit reconstruire son état depuis des données durables : inputs persistés, claims/leases/outcomes lorsqu'ils existent, cursors/checkpoints et versions de processor.
|
||||
|
||||
- inputs persistés ;
|
||||
- claims/leases ;
|
||||
- outcomes ;
|
||||
- cursors/checkpoints ;
|
||||
- versions de processor.
|
||||
Le premier backfill RAW retourne un `BackfillCheckpoint` caller-owned lié au `JobId` et au fingerprint de scope. La crate ne persiste pas ce checkpoint elle-même : tant qu'un caller ne l'enregistre pas durablement, il s'agit d'une primitive de reprise contrôlée, pas d'une promesse crash-safe automatique.
|
||||
|
||||
La mémoire du processus ne constitue jamais l'unique source de reprise.
|
||||
La mémoire du processus ne constitue jamais l'unique source d'une garantie de reprise durable.
|
||||
|
||||
## Logging
|
||||
|
||||
@@ -346,7 +343,9 @@ ksp-job-backfill-lib
|
||||
-> ksp-core-lib
|
||||
-> ksp-logging-lib
|
||||
-> ksp-onchain-transport-lib
|
||||
-> ksp-store-lib # façade Store ; aucun backend imposé par la crate Job
|
||||
-> ksp-store-lib # façade Store ; default-features=false côté Job
|
||||
-> futures-util/tokio # runtime privé de Backfill
|
||||
-> serde_json/sha2 # RAW v1 canonique + digest
|
||||
```
|
||||
|
||||
### RAW worker
|
||||
@@ -393,8 +392,7 @@ selon les capacités réellement introduites.
|
||||
|
||||
- nom final de la crate pipeline RAW si la réutilisation justifie une crate dédiée ;
|
||||
- nom final du worker RAW ;
|
||||
- contrat exact de `ksp-job-api` ;
|
||||
- modèle de claim/lease PostgreSQL ;
|
||||
- modèle de claim/lease PostgreSQL pour les futurs processors continus ;
|
||||
- taille de batch et stratégie backpressure ;
|
||||
- découpage des workers DECODE/SPECIALIZED par groupe lorsque les premiers groupes existent ;
|
||||
- mécanisme IPC des applications de contrôle futures.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/architecture/010-APPS_SERVICES_SCENARIOS_AND_CONTROL.md -->
|
||||
<!-- version: 7 -->
|
||||
<!-- version: 8 -->
|
||||
|
||||
# Applications, services, scenarios et control plane
|
||||
|
||||
@@ -356,15 +356,13 @@ Le choix du mécanisme exact est reporté à la release fonctionnelle concernée
|
||||
|
||||
## Jobs
|
||||
|
||||
Les jobs restent distincts des workers.
|
||||
Les jobs restent distincts des workers. `ksp-job-api` fournit les contrats runtime-neutral communs ; le premier job concret `ksp-job-backfill-lib` est une bibliothèque single-run, pas un service worker autonome.
|
||||
|
||||
Une app spécialisée peut déclencher/suivre un job concret via `ksp-job-api` et la composition adaptée.
|
||||
Une app spécialisée peut construire les ressources Config/Transport/Store, créer un `BackfillJobRuntime`, conserver son `BackfillJobHandle`, observer les snapshots latest-value et demander une annulation coopérative. Elle ne réimplémente ni découverte/hydratation, ni frontier/checkpoint, ni persistance RAW.
|
||||
|
||||
Aucune `ksp-job-control-lib` générique n'est introduite.
|
||||
Aucune `ksp-job-control-lib` générique n'est introduite. Le handle concret suffit tant qu'aucune duplication entre plusieurs jobs ne justifie une couche de gouvernance commune.
|
||||
|
||||
Le fait qu'un worker soit un process/service indépendant ne force pas les jobs à adopter exactement le même modèle de déploiement.
|
||||
|
||||
Le packaging/exécution des jobs sera déterminé avec les premiers jobs réels.
|
||||
Le fait qu'un worker soit un process/service indépendant ne force pas les jobs à adopter exactement le même modèle de déploiement. Le packaging des futurs jobs reste décidé par leur besoin réel ; le premier backfill prouve qu'un runtime de bibliothèque composable est suffisant pour un job déclenché par une application.
|
||||
|
||||
## Scenarios : logique dans la bibliothèque
|
||||
|
||||
@@ -547,7 +545,7 @@ control/application adapters
|
||||
|
|
||||
+--> ksp-worker-control-lib --> ksp-worker-api --> worker service
|
||||
|
|
||||
+--> ksp-job-api -----------> concrete job
|
||||
+--> ksp-job-api -----------> ksp-job-backfill-lib / concrete jobs
|
||||
|
|
||||
+--> ksp-scenario-<domain>-lib
|
||||
```
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/plans/000-README.md -->
|
||||
<!-- version: 70 -->
|
||||
<!-- version: 71 -->
|
||||
|
||||
# Plans KSP
|
||||
|
||||
@@ -33,6 +33,9 @@ Un plan décrit le périmètre, les décisions déjà acquises, les questions ou
|
||||
- [`022-V0_3_1_STORE_RAW_PLAN.md`](022-V0_3_1_STORE_RAW_PLAN.md) — plan candidat réconcilié de `0.3.1 — Store API RAW foundation`; il fixe `ksp-store-api` seul, les modèles transaction/account + observations, queries/outcomes/capabilities, rétention/tombstone, la frontière event-only/Interface et le report de `ksp-store-lib` + PostgreSQL à `0.3.2`.
|
||||
- [`023-V0_3_2_STORE_POSTGRES_FOUNDATION_PLAN.md`](023-V0_3_2_STORE_POSTGRES_FOUNDATION_PLAN.md) — plan candidat réconcilié de `0.3.2 — Store/PostgreSQL runtime foundation`; il fixe le split façade/backend, `std.store` multi-target réseau-spécifique, tokio-postgres/Deadpool/Rustls, migrations metadata-only, health/readiness, live PostgreSQL et les reports des vertical slices RAW vers `0.3.3`/`0.3.4`.
|
||||
- [`024-V0_3_3_STORE_POSTGRES_RAW_TRANSACTION_PLAN.md`](024-V0_3_3_STORE_POSTGRES_RAW_TRANSACTION_PLAN.md) — plan candidat réconcilié de `0.3.3 — Store/PostgreSQL RawTransaction vertical slice`; il fixe V001, binding réseau, mappings entiers exacts, écritures/observations atomiques, pagination keyset/cursor, rétention/tombstone/ForceRehydrate, hardening et preuve PostgreSQL 17.
|
||||
- [`025-V0_3_4_STORE_POSTGRES_RAW_ACCOUNT_PLAN.md`](025-V0_3_4_STORE_POSTGRES_RAW_ACCOUNT_PLAN.md) — plan historique clôturé de `0.3.4 — Store/PostgreSQL RawAccountState + complétude RAW`; il complète le backend/façade à dix capabilities RAW et ferme V002.
|
||||
- [`026-V0_3_5_INTERFACE_ACQUISITION_EVENTS_PLAN.md`](026-V0_3_5_INTERFACE_ACQUISITION_EVENTS_PLAN.md) — plan historique clôturé de `0.3.5 — Interface acquisition events`; il fixe les faits passifs provider-neutral `SlotLifecycleEvent` et `TransactionExecutionEvent` sans runtime ni persistence.
|
||||
- [`027-V0_3_6_JOB_API_BACKFILL_PLAN.md`](027-V0_3_6_JOB_API_BACKFILL_PLAN.md) — plan candidat de `0.3.6 — Job API + RAW transaction backfill`; il fixe le contrat Job runtime-neutral, les quatre scopes historiques, RAW v1, provenance observée, persistance Store normale, concurrence/frontier/checkpoint et runtime latest-value annulable.
|
||||
|
||||
Le `pre.001` de chaque release fonctionnelle peut introduire son propre plan détaillé lorsque la release s'ouvre.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/plans/027-V0_3_6_JOB_API_BACKFILL_PLAN.md -->
|
||||
<!-- version: 24 -->
|
||||
<!-- version: 25 -->
|
||||
|
||||
# Plan v0.3.6 — Job API et premier backfill RAW
|
||||
|
||||
@@ -528,17 +528,17 @@ La tranche n'élargit aucune API de production et ne modifie aucune dépendance
|
||||
|
||||
### `pre.011` — Gate technique final
|
||||
|
||||
**Statut : matérialisé ; gate opérateur final à exécuter.**
|
||||
**Statut : réalisé ; gate opérateur final intégralement vert.**
|
||||
|
||||
Budget cible : **15-20 min**. Entrée : hardening `pre.010` intégralement vert avec 47 unitaires + 20 canaries. La tranche ne rouvre aucun code, test fonctionnel, manifeste de crate, dépendance, README/USAGE, CHANGELOG/ROADMAP ou prompt suivant ; elle synchronise uniquement la version workspace, le plan, la validation et son delta.
|
||||
|
||||
Le gate final rejoue le workspace en configuration large : format en mode check, audits Rust/Markdown, `cargo check --workspace`, Clippy `--all-targets --all-features -- -D warnings`, tests `--workspace --all-targets --all-features`, puis graphes de `ksp-job-api`, `ksp-job-backfill-lib` et doublons workspace. Les arbres sont ici justifiés par la clôture technique finale même sans nouveau changement de dépendances dans `pre.011`. Le smoke PostgreSQL reste opt-in et conditionnel à une URI dédiée explicitement disponible ; son absence ne bloque pas la preuve déterministe. Sortie attendue : preuve technique finale consignée, sans réconciliation documentaire durable avant `pre.012`.
|
||||
Le gate final rejoue le workspace en configuration large : format en mode check, audits Rust/Markdown, `cargo check --workspace`, Clippy `--all-targets --all-features -- -D warnings`, tests `--workspace --all-targets --all-features`, puis graphes de `ksp-job-api`, `ksp-job-backfill-lib` et doublons workspace. Les arbres sont ici justifiés par la clôture technique finale même sans nouveau changement de dépendances dans `pre.011`. Le gate opérateur est vert : audits propres, check/Clippy sans warning, `1_404` tests passés et `15` tests explicitement ignorés/opt-in sans aucun échec ; les graphes Job restent conformes et l'inventaire `cargo tree --duplicates` a été revu sans défaut propre au vertical Job nécessitant une correction. Le smoke PostgreSQL dédié n'a pas été exécuté faute d'URI explicitement fournie et reste non bloquant. Sortie : preuve technique finale fermée avant réconciliation documentaire.
|
||||
|
||||
### `pre.012` — Réconciliation documentaire finale
|
||||
|
||||
**Statut : planifié.**
|
||||
**Statut : matérialisé ; gate documentaire à exécuter.**
|
||||
|
||||
Budget cible : **10-15 min**. Entrée : gate technique final vert. Aligner architecture, index, README, USAGE, plan et validation sur la surface prouvée. Sortie : documentation durable cohérente, sans CHANGELOG, ROADMAP ni prompt suivant.
|
||||
Budget cible : **10-15 min**. Entrée : gate technique final vert. La tranche crée les README/USAGE durables de `ksp-job-api` et `ksp-job-backfill-lib`, réconcilie les architectures Jobs/Backfill, les index `docs/`, le README racine, ce plan et la validation sur la surface réellement prouvée. Elle documente notamment le lifecycle Job exact, la sémantique latest-value, les quatre scopes, l'identité `(network, signature)`, la provenance observée, RAW v1, la persistence Store normale, la frontier/checkpoint caller-owned, les limites de reprise crash-safe et l'annulation avec drainage Store. Sortie attendue : documentation durable cohérente et version-neutral côté USAGE, sans CHANGELOG, ROADMAP ni prompt suivant.
|
||||
|
||||
### `pre.013` — Préparation de publication minimale
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/validation/000-README.md -->
|
||||
<!-- version: 34 -->
|
||||
<!-- version: 35 -->
|
||||
|
||||
# Validations KSP
|
||||
|
||||
@@ -29,3 +29,6 @@ Documents :
|
||||
- [`018-V0_3_1_STORE_RAW.md`](018-V0_3_1_STORE_RAW.md) — matrice candidate finale de `0.3.1 — Store API RAW foundation` : modèles transaction/account, observations, capabilities backend, pagination sans policy executor, outcomes, rétention/tombstone, hardening, gate complet `pre.008` et reports explicites vers `0.3.2+`.
|
||||
- [`019-V0_3_2_STORE_POSTGRES_FOUNDATION.md`](019-V0_3_2_STORE_POSTGRES_FOUNDATION.md) — matrice candidate finale de `0.3.2 — Store/PostgreSQL runtime foundation` : feature graph, settings/Config, pool/TLS, migrations metadata-only, health, hardening, graphes, builds Tauri et preuve PostgreSQL réelle major 17.
|
||||
- [`020-V0_3_3_STORE_POSTGRES_RAW_TRANSACTION.md`](020-V0_3_3_STORE_POSTGRES_RAW_TRANSACTION.md) — matrice candidate finale de `0.3.3 — Store/PostgreSQL RawTransaction vertical slice` : six capabilities backend/façade, V001 et compatibilité schéma, atomicité/idempotence/conflit, keyset/cursor, rétention/races/rehydrate, hardening et replay PostgreSQL 17 final.
|
||||
- [`021-V0_3_4_STORE_POSTGRES_RAW_ACCOUNT.md`](021-V0_3_4_STORE_POSTGRES_RAW_ACCOUNT.md) — matrice finale de `0.3.4 — RawAccountState + complétude RAW` : quatre capabilities account supplémentaires, V002, pagination/idempotence et conformance Store 10/10.
|
||||
- [`022-V0_3_5_INTERFACE_ACQUISITION_EVENTS.md`](022-V0_3_5_INTERFACE_ACQUISITION_EVENTS.md) — matrice finale de `0.3.5 — Interface acquisition events` : événements passifs slot/transaction, façade crate-root, bornes/debug et firewall Interface.
|
||||
- [`023-V0_3_6_JOB_API_BACKFILL.md`](023-V0_3_6_JOB_API_BACKFILL.md) — matrice candidate de `0.3.6 — Job API + RAW transaction backfill` : lifecycle/notifications runtime-neutral, scopes, provenance, RAW v1, Store/idempotence, concurrence/checkpoint, annulation/snapshots, hardening externe et gate workspace final.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/validation/023-V0_3_6_JOB_API_BACKFILL.md -->
|
||||
<!-- version: 25 -->
|
||||
<!-- version: 26 -->
|
||||
|
||||
# Validation v0.3.6 — Job API et premier backfill RAW
|
||||
|
||||
@@ -71,7 +71,8 @@ Aucune entrée absolue, traversée, avec séparateur inversé ou lien symbolique
|
||||
- [X] Les documents d'architecture courants sont réconciliés sur `ksp-job-backfill-lib`; les anciens plans historiques restent historiques et ne sont pas réécrits.
|
||||
- [X] `ksp-job-api` et `ksp-job-backfill-lib` sont obligatoires en parallèle dans la release finale.
|
||||
- [X] Worker API, application et pipeline RAW partagé sont explicitement hors v0.3.6.
|
||||
- [ ] Architecture, README, roadmap et contrats finaux réconciliés avant publication.
|
||||
- [X] Architecture, README, index et contrats de crate durables réconciliés sur la surface finale prouvée.
|
||||
- [ ] ROADMAP et CHANGELOG synchronisés uniquement dans la lane de publication `pre.013`.
|
||||
|
||||
## 5. Contrat `ksp-job-api`
|
||||
|
||||
@@ -261,20 +262,34 @@ Les arbres Cargo sont rejoués ici au titre de la clôture technique finale, mê
|
||||
|
||||
Le smoke PostgreSQL reste conditionnel à une URI dédiée explicitement disponible. En l'absence d'environnement live fourni, il reste non exécuté et non bloquant ; aucune réussite live n'est inventée.
|
||||
|
||||
**Statut : matérialisé ; gate opérateur final à exécuter.**
|
||||
**Statut : réalisé ; gate opérateur final intégralement vert.**
|
||||
|
||||
## 16. Preuves d'intégration et fermeture
|
||||
Preuve opérateur : `cargo fmt --all -- --check`, audits Rust/Markdown, `cargo check --workspace`, Clippy workspace/all-targets/all-features avec `-D warnings`, puis `cargo test --workspace --all-targets --all-features` passent. Le run agrège `1_404` tests passés, `0` échec et `15` tests ignorés explicitement opt-in/operator-only. Les graphes normal/features de `ksp-job-api` et `ksp-job-backfill-lib` sont cohérents ; `cargo tree --duplicates` a été exécuté et revu. Aucun smoke PostgreSQL dédié n'est revendiqué sans URI explicitement fournie.
|
||||
|
||||
## 16. Réconciliation documentaire finale `pre.012`
|
||||
|
||||
- [X] README racine réconcilié sans historique de prerelease.
|
||||
- [X] `ksp-job-api/README.md` et `USAGE.md` décrivent la façade runtime-neutral, le lifecycle, l'annulation et le contrat latest-value.
|
||||
- [X] `ksp-job-backfill-lib/README.md` et `USAGE.md` décrivent scopes, request bounds, runtime, provenance, Store, checkpoint, annulation et reprise sans note de version.
|
||||
- [X] Architectures Layers, Contracts, Inventory, Dependency Graph, Acquisition/Jobs et Apps/Control réconciliées sur le premier job concret.
|
||||
- [X] Index `docs/`, plans et validations synchronisés jusqu'aux documents `027` / `023`.
|
||||
- [X] Les documents durables distinguent checkpoint caller-owned et garantie de reprise crash-safe ; aucune persistence automatique du checkpoint n'est promise.
|
||||
- [X] CHANGELOG, ROADMAP et prompt suivant restent hors de cette tranche.
|
||||
|
||||
**Statut : matérialisé ; gate documentaire à exécuter.**
|
||||
|
||||
## 17. Preuves d'intégration et fermeture
|
||||
|
||||
- [X] Fake Transport et fake Store déterministes sans backend direct exécutés avec succès au gate `pre.007`; fake processor concurrent `pre.008-fix.001` exécuté avec succès.
|
||||
- [ ] Vertical découverte, hydratation, conversion, persistance et observation couvert.
|
||||
- [ ] Smoke Devnet plus PostgreSQL configuré exécuté si l'environnement explicite est disponible.
|
||||
- [ ] Aucun endpoint payant, credential ou donnée sensible requis par les tests normaux.
|
||||
- [ ] Gates technique, documentaire et de publication séparés.
|
||||
- [ ] CHANGELOG et ROADMAP alignés seulement après preuve technique.
|
||||
- [ ] Archives de release minimales et vérifiées.
|
||||
- [X] Vertical découverte, hydratation, conversion, persistance, observation, concurrence, checkpoint et runtime couvert par les gates déterministes.
|
||||
- [ ] Smoke Devnet plus PostgreSQL configuré exécuté si l'environnement explicite est disponible ; non bloquant sans environnement fourni.
|
||||
- [X] Aucun endpoint payant, credential ou donnée sensible requis par les tests normaux.
|
||||
- [X] Gates technique, documentaire et de publication séparés.
|
||||
- [ ] CHANGELOG et ROADMAP alignés seulement après preuve technique, dans `pre.013`.
|
||||
- [X] Archives de prerelease minimales et vérifiées jusqu'au gate technique final.
|
||||
- [ ] Version stable publiée uniquement après tous les critères obligatoires.
|
||||
|
||||
## 17. Règle de vérité
|
||||
## 18. Règle de vérité
|
||||
|
||||
Une case n'est cochée que par une preuve effectivement exécutée ou un audit effectivement réalisé. L'absence de `cargo`, de PostgreSQL configuré ou d'accès live est rapportée comme non exécutée ; elle n'est jamais convertie en succès implicite.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user