0.3.17-pre.002

This commit is contained in:
2026-09-24 10:55:34 +02:00
parent a60397f08e
commit c56ae68834
15 changed files with 1995 additions and 17 deletions

334
deltas/0.3.17/pre.002.md Normal file
View File

@@ -0,0 +1,334 @@
<!-- file: deltas/0.3.17/pre.002.md -->
<!-- version: 1 -->
# Delta `0.3.17-pre.002` — contrats Store API conflict lifecycle et classification d'erreur
## Base requise
```text
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 :
```text
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 :
```text
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 :
```text
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` :
```text
header version : 652 -> 653
workspace : 0.3.17-pre.1 -> 0.3.17-pre.2
```
## Fichiers ajoutés
```text
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
```text
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 :
```text
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 :
```text
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é :
```text
RawTransactionConflictReference
-> RawTransactionReference
```
Inspection :
```text
RawTransactionConflictInspectionQuery
RawTransactionConflictSummary
RawTransactionConflictParticipantSummary
RawTransactionConflictDetail
RawTransactionConflictInspectionRead
```
La projection courante conserve explicitement :
```text
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 :
```text
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 :
```text
RawTransactionConflictEventKind
RawTransactionConflictEventOrigin
RawTransactionConflictEventSummary
RawTransactionConflictHistoryQuery
RawTransactionConflictHistoryRead
```
Event kinds figés :
```text
Opened
ParticipantAdded
ResolvedKeepCanonical
ResolvedPromoteVariant
ResolvedRestoreVariant
Reopened
```
Origins sûres :
```text
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 :
```text
RawTransactionConflictResolutionAction
RawTransactionConflictResolution
RawTransactionConflictAction
RawTransactionConflictActionRequest
RawTransactionConflictActionOutcome
RawTransactionConflictActionWrite
```
Actions disponibles :
```text
KeepCurrentCanonical
PromoteVariant(target)
RestoreVariant(target)
Resolve(explicit canonical resolution)
Reopen
```
Chaque request transporte obligatoirement :
```text
conflict reference
expected_conflict_revision > 0
expected_canonical_revision > 0
action
```
Tout target variant doit appartenir à la transaction du conflict case.
Outcomes backend-neutral :
```text
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 :
```text
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é :
```text
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 :
```text
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 :
```text
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
```bash
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 :
```text
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.