Files
khadhroony-solana-project/deltas/0.3.14/pre.009.md
2026-09-12 11:22:53 +02:00

8.7 KiB

Delta 0.3.14-pre.009 — health policy multi-source

Base requise

0.3.14-pre.008-fix.002
workspace.package.version = 0.3.14-pre.8.fix.2
deltas/0.3.14/pre.008-fix.002.md présent

Gate de la base

Le gate opérateur de 0.3.14-pre.008-fix.002 est validé avant ouverture de cette tranche :

cargo fmt --all : PASS
cargo fmt --all -- --check : PASS
audit Rust workspace rules : PASS
audit Markdown tables : PASS
cargo check --workspace : PASS
cargo clippy --workspace --all-targets --all-features -- -D warnings : PASS
cargo test -p ksp-worker-raw-transaction-ingest-lib --all-targets --all-features : PASS

Le gate Worker comprend notamment :

139 unit tests : PASS
cross_layer_completeness : 8 PASS
dependency_boundary : 19 PASS
hardening : 33 PASS
public_api : 20 PASS
release_completeness : 10 PASS

Objectif

Implémenter strictement la tranche pre.009 du plan 035 :

projeter Healthy / Degraded / Unhealthy depuis des preuves de coverage présentes et futures
conserver Faulted comme état lifecycle terminal du Worker
ne jamais rendre Healthy sur le seul fait qu'un Transport ait reconnecté
rendre Healthy uniquement lorsque toutes les sources attendues sont Active et que les gaps sont fermés
rendre Degraded lorsqu'une source reste perdue mais que le présent est réconcilié et TargetCoverage reste couvert pour la suite
rendre Unhealthy pendant une réconciliation non prouvée, avec gap ouvert ou coverage future insuffisante
ne créer aucune health source/provider spécifique publique

Projection de health fondée sur la continuité

Le ledger de pre.008 expose maintenant une projection privée et source-neutral :

continuity_frontier
has_open_gaps
future_target_coverage
failed_source_losses_reconciled

Pour chaque source projetée Failed, failed_source_losses_reconciled exige un gap SourceFailure effectivement enregistré puis fermé par une preuve run-local. Une source simplement marquée Failed dans l'inventaire ne suffit donc jamais à autoriser Degraded.

future_target_coverage est calculé uniquement depuis les sources réellement Active et les relations Exact / Superset déjà validées par TargetCoverage.

La configuration d'une source ne constitue toujours pas une preuve historique. Le présent reste gouverné par :

aucun gap ouvert
continuity frontier == processing frontier

Les deux dimensions sont volontairement distinctes :

coverage future disponible != gap historique réparé
gap historique réparé != coverage future encore disponible

Pont Inventory -> Continuity -> Snapshot

Chaque publication agrégée de l'inventaire multi-source calcule désormais, après libération du lock Inventory :

ensemble exact des sources Active
processing frontier agrégé
projection continuity/TargetCoverage sous le lock continuity séparé
projection health privée ajoutée au message latest-value

Aucun MutexGuard n'est conservé à travers un await et aucun client Transport/Store n'est exposé dans la snapshot publique.

La source HTTP full-ledger republie sa projection après l'enregistrement d'un coverage epoch afin qu'une fermeture de gap puisse mettre à jour la health sans attendre une transaction ou un slot produit supplémentaire.

Politique Running

Lorsque la projection de continuité est disponible, la health suit la politique conservative suivante :

source Reconnecting
    -> Unhealthy tant que la continuité de l'incident n'est pas explicitement réconciliée

gap ouvert
ou continuity frontier != processing frontier
ou TargetCoverage future non couverte par les sources Active
    -> Unhealthy

toutes les sources attendues Active
+ aucun gap ouvert
+ continuity frontier rattrapé
+ TargetCoverage future couverte
    -> Healthy

une source reste perdue/Failed
+ son gap SourceFailure a été enregistré et réconcilié
+ aucune source Reconnecting
+ aucun gap ouvert
+ continuity frontier rattrapé
+ TargetCoverage future couverte
    -> Degraded

Une source perdue n'est donc jamais transformée en source optionnelle. Degraded indique uniquement que le service du run reste couvert malgré son absence ; les observations spécifiques que cette source aurait produites ne sont pas inventées.

Faulted reste un état lifecycle

ksp-worker-api::WorkerHealth reste inchangé et conserve :

Unknown
Healthy
Degraded
Unhealthy

La quatrième politique terminale du plan est représentée par :

WorkerState::Faulted(error_code)
WorkerHealth::Unhealthy

Aucune nouvelle variante WorkerHealth::Faulted ni extension de l'API générique Worker n'est introduite.

Retour à Healthy

Le retour à Healthy exige simultanément :

toutes les sources attendues projetées Active
aucune source projetée Reconnecting
aucun gap run-local ouvert
continuity frontier == processing frontier
TargetCoverage future couverte par les sources Active

Le simple passage Transport Reconnecting -> Active ne constitue pas une preuve suffisante si le continuity ledger n'est pas réconcilié.

Tests ajoutés

Les unit tests couvrent notamment :

projection health séparant future TargetCoverage et gap historique ouvert
rejet des ensembles Active dupliqués ou inconnus
pont Inventory -> continuity health avec gap puis coverage epoch de réconciliation
Reconnecting -> Unhealthy tant que la preuve de continuité manque
sources Active + gap ouvert -> Unhealthy
sources Active + gaps fermés + coverage future -> Healthy
source Failed sans gap SourceFailure réconcilié -> Unhealthy
source Failed avec gap SourceFailure réconcilié et présent/futur couverts -> Degraded
publication supervisor immédiate après réconciliation réussie de la perte de source
coverage future insuffisante -> Unhealthy
WorkerState::Faulted -> WorkerHealth::Unhealthy

Les canaris hardening et release_completeness vérifient en plus :

health fondée sur continuity frontier + gaps + TargetCoverage
aucune health provider/source-key spécifique publique
aucune variante WorkerHealth::Faulted ajoutée
aucune croissance de la surface publique TargetCoverage

Hors périmètre inchangé

aucune fairness spécifique nominal/repair de pre.010
aucune observabilité publique détaillée des gaps/repair de pre.011
aucun nouveau mécanisme de replay/reconnect Worker
aucun respawn de source
aucun EARLY/shred
aucun Job Backfill depuis Worker
aucun nouveau provider ou SDK

Fichiers ajoutés

deltas/0.3.14/pre.009.md

Fichiers modifiés

Cargo.toml
crates/ksp-worker-raw-transaction-ingest-lib/src/continuity.rs
crates/ksp-worker-raw-transaction-ingest-lib/src/runtime_resources.rs
crates/ksp-worker-raw-transaction-ingest-lib/src/snapshot.rs
crates/ksp-worker-raw-transaction-ingest-lib/tests/hardening.rs
crates/ksp-worker-raw-transaction-ingest-lib/tests/release_completeness.rs
crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/continuity.rs
crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime_resources.rs
crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/snapshot.rs

Fichiers supprimés

aucun

Version Cargo

Conformément à VER-ID-009 :

header Cargo.toml : 578 -> 579
workspace.package.version : 0.3.14-pre.8.fix.2 -> 0.3.14-pre.9

Versions des fichiers modifiés :

continuity.rs : 8 -> 9
runtime_resources.rs : 36 -> 37
snapshot.rs : 5 -> 6
unit_tests/continuity.rs : 6 -> 7
unit_tests/runtime_resources.rs : 30 -> 31
unit_tests/snapshot.rs : 5 -> 6
tests/hardening.rs : 32 -> 33
tests/release_completeness.rs : 27 -> 28

Validation exécutée dans l'environnement de préparation

python3 scripts/audit_rust_workspace_rules.py : PASS
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas : PASS
scan des frontières Worker/Transport/Backfill/Store : PASS
scan de la crate-root historique : PASS
comparaison exacte pre.008-fix.002 -> pre.009 : PASS

Les gates Cargo ne sont pas déclarés PASS dans l'environnement de préparation lorsqu'ils ne peuvent pas y être exécutés. Ils restent obligatoires côté opérateur avant pre.010.

Décisions prises

la health est une projection de preuves run-local, pas un statut provider
le futur est prouvé par TargetCoverage sur les sources Active
le présent est prouvé par continuity frontier + absence de gap ouvert
Reconnecting reste Unhealthy tant que l'incident n'est pas réconcilié
Failed ne devient Degraded qu'après enregistrement et fermeture effective de son gap SourceFailure
une source perdue mais réellement redondante maintient Degraded, jamais Healthy
Faulted reste un WorkerState terminal avec WorkerHealth::Unhealthy