9.0 KiB
Delta 0.3.17-pre.002 — contrats Store API conflict lifecycle et classification d'erreur
Base requise
0.3.17-pre.001 appliquée
workspace.package.version = 0.3.17-pre.1
Le gate opérateur reçu le 24 septembre 2026 est propre :
cargo fmt --all -- --check PASS
General Rust rule audit clean
Rust export completeness audit 0 candidate(s)
KSP workspace Rust rule audit clean
Markdown table audit clean (352 table(s), 965 file(s))
cargo check --workspace PASS, 6.11 s
cargo clippy --workspace --all-targets --all-features -- -D warnings
PASS, 25.28 s
Objet
Figer la surface backend-neutral requise par le cycle de vie complet des variantes/conflits avant toute migration PostgreSQL V004.
Cette tranche reste strictement dans ksp-store-api et ajoute :
inspection des variantes
inspection des conflict cases
participant ledger DTO
historique append-only DTO/query
actions compare-and-set à double revision
outcomes stale/idempotent explicites
StoreErrorClass Transient/Terminal
StoreErrorClassifier backend-neutral
Elle ne modifie encore :
aucune migration SQL
aucun backend PostgreSQL
aucun ksp-store-lib
aucun Worker
aucun Transport/Config
aucun Job Backfill
aucune application Desk
Version workspace
Cargo.toml :
header version : 652 -> 653
workspace : 0.3.17-pre.1 -> 0.3.17-pre.2
Fichiers ajoutés
crates/ksp-store-api/src/capability/raw_conflict.rs
crates/ksp-store-api/src/model/raw_conflict.rs
crates/ksp-store-api/unit_tests/model/raw_conflict.rs
deltas/0.3.17/pre.002.md
Fichiers modifiés
Cargo.toml
crates/ksp-store-api/src/capability.rs
crates/ksp-store-api/src/error.rs
crates/ksp-store-api/src/lib.rs
crates/ksp-store-api/src/model.rs
crates/ksp-store-api/tests/dependency_boundary.rs
crates/ksp-store-api/tests/external_backend.rs
crates/ksp-store-api/tests/public_api.rs
crates/ksp-store-api/tests/release_completeness.rs
crates/ksp-store-api/tests/security_hardening.rs
docs/validation/034-V0_3_17_RAW_OPERATIONAL_RESILIENCE.md
Contrats variantes
La lecture opérateur des variantes est portée par :
RawTransactionVariantInspectionQuery
RawTransactionVariantSummary
RawTransactionVariantDetail
RawTransactionVariantInspectionRead
La query est random-access bornée via RawInspectionPageRequest, exige un network et accepte seulement un filtre transaction exact cohérent avec ce network.
Le summary reste payload-free et expose uniquement les métadonnées nécessaires :
variant reference
origin
slot / block_time
format id/version
retention state
payload size si disponible
is_current_canonical
observation_count
created_at
RawTransactionVariantDetail peut porter la transaction RAW complète uniquement dans la lecture explicite d'un variant. Le constructeur vérifie transaction identity, slot, block time, format et taille déclarée ; un variant Purged ne peut pas prétendre contenir encore le payload.
Contrats conflict case
Identité :
RawTransactionConflictReference
-> RawTransactionReference
Inspection :
RawTransactionConflictInspectionQuery
RawTransactionConflictSummary
RawTransactionConflictParticipantSummary
RawTransactionConflictDetail
RawTransactionConflictInspectionRead
La projection courante conserve explicitement :
status Open/Resolved
conflict revision > 0
canonical variant
canonical selector revision > 0
latest incoming variant
latest Conflict/Incomparable relation + reason
resolved canonical variant si Resolved
latest resolution action si Resolved
participant_count >= 2
created_at / updated_at
Les références canonical/incoming/resolved doivent appartenir à la même transaction que le conflict case.
Le detail valide que le participant ledger :
contient exactement participant_count entrées
n'a aucun variant_id dupliqué
reste dans le même scope transaction
n'annonce aucun first_seen_revision > current conflict revision
contient canonical/latest incoming/resolved target requis
Historique append-only
Types ajoutés :
RawTransactionConflictEventKind
RawTransactionConflictEventOrigin
RawTransactionConflictEventSummary
RawTransactionConflictHistoryQuery
RawTransactionConflictHistoryRead
Event kinds figés :
Opened
ParticipantAdded
ResolvedKeepCanonical
ResolvedPromoteVariant
ResolvedRestoreVariant
Reopened
Origins sûres :
Automatic
Operator
Aucun acteur libre, texte backend, SQL ou payload RAW n'entre dans le DTO d'historique.
Une transition de résolution exige exactement le RawTransactionConflictResolutionAction correspondant. Opened et ParticipantAdded exigent une comparaison durable Conflict ou Incomparable.
Actions compare-and-set
Types :
RawTransactionConflictResolutionAction
RawTransactionConflictResolution
RawTransactionConflictAction
RawTransactionConflictActionRequest
RawTransactionConflictActionOutcome
RawTransactionConflictActionWrite
Actions disponibles :
KeepCurrentCanonical
PromoteVariant(target)
RestoreVariant(target)
Resolve(explicit canonical resolution)
Reopen
Chaque request transporte obligatoirement :
conflict reference
expected_conflict_revision > 0
expected_canonical_revision > 0
action
Tout target variant doit appartenir à la transaction du conflict case.
Outcomes backend-neutral :
Applied
AlreadyAtTarget
StaleRevision
ConflictNotOpen
ConflictNotResolved
VariantNotParticipant
VariantPayloadUnavailable
AlreadyAtTarget et StaleRevision restent volontairement distincts : une répétition idempotente n'est pas une perte de compare-and-set concurrente.
Classification Store error
ksp-store-api expose désormais :
StoreErrorClass::Transient
StoreErrorClass::Terminal
StoreErrorClassifier
Le classifier reçoit une ksp_core_lib::Error déjà projetée/redacted. Le Worker futur consommera ce contrat au lieu de comparer des codes PostgreSQL ou des chaînes libres.
Cette tranche ne classe encore aucun SQLSTATE concret : le raffinement physique reste réservé à pre.006. La politique fail-closed définie par le plan reste inchangée : tout code non explicitement reconnu par l'implémentation future sera Terminal.
Frontières préservées
Le manifest ksp-store-api reste inchangé :
runtime dependency exacte = ksp-core-lib uniquement
Aucun nouveau crate externe n'est introduit.
Tous les nouveaux items publics sont réexportés depuis la racine ksp-store-api; aucun pub mod n'est ajouté. Les enums évolutifs sont #[non_exhaustive].
Les capabilities restent object-safe et implémentables par un backend externe sans dépendre de ksp-store-lib ou PostgreSQL.
Tests/canaris ajoutés ou étendus
La tranche couvre statiquement et par tests Rust :
network coherence des queries variant/conflict
double revision strictement positive
scope transaction des targets d'action
status Open/Resolved et projection resolution cohérente
relation conflict/incomparable requise pour le conflict current
participant ledger complet, unique et revision-safe
history event/action consistency
outcomes Applied/AlreadyAtTarget/StaleRevision distincts
codes event/origin/resolution stables
variant detail payload debug redacted
object safety des quatre nouvelles capabilities + classifier
inventaire exact crate-root/module/capability
frontière dépendances backend-neutral
#[non_exhaustive] des nouveaux enums
Validation locale de l'assemblage
L'environnement d'assemblage ne fournit toujours pas cargo, rustc ou rustfmt. Aucun PASS Cargo n'est inventé pour pre.002.
Audits réellement exécutés après les changements Rust :
General Rust rule audit clean
Rust export completeness audit 0 candidate(s)
KSP workspace Rust rule audit clean
Markdown table audit clean (352 table(s), 966 file(s))
Le gate Cargo utilisateur reste autoritaire pour confirmer compilation, rustfmt, Clippy et tests.
Gate requis après application
cargo fmt --all
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
cargo check --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test -p ksp-store-api --all-targets --all-features
Ne pas lancer de test PostgreSQL live pour cette tranche : aucune migration ni implémentation backend n'est encore modifiée.
Prochaine tranche
Après gate propre :
0.3.17-pre.003
Objet prévu : migration PostgreSQL V004 additive pour participants, historique append-only, projection de résolution et bootstrap legacy, avec canaris garantissant l'immuabilité byte/checksum de V000/V001/V002/V003.