v0.3.6-pre.010

This commit is contained in:
2026-09-01 16:55:14 +02:00
parent 8dbd86c297
commit 7f8ce987a5
6 changed files with 613 additions and 25 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/027-V0_3_6_JOB_API_BACKFILL_PLAN.md -->
<!-- version: 20 -->
<!-- version: 23 -->
# Plan v0.3.6 — Job API et premier backfill RAW
@@ -504,7 +504,7 @@ Budget cible : **15-20 min**. Entrée : frontière prouvée et gate `pre.008-fix
L'annulation réutilise `JobCancellationToken` et ajoute un signal réveillable privé. Les attentes de découverte et d'hydratation pré-Store sont abandonnables ; une vérification supplémentaire intervient après hydratation et avant soumission Store. Dès que `persist_backfill_hydration` est appelée, l'écriture atomique n'est plus sélectionnée contre l'annulation : toute opération Store déjà soumise est drainée jusqu'à un résultat connu. L'exécuteur arrête ensuite les nouvelles admissions, draine l'in-flight et publie frontier/checkpoint sûrs. Une arbitration atomique sépare `ACTIVE`, demande d'annulation et états terminaux : une annulation acceptée avant la décision terminale gagne sur une complétion normale, une complétion déjà réclamée refuse l'annulation tardive, et une erreur fatale peut remplacer une annulation pendante afin de ne pas masquer un échec Transport/Store.
Le snapshot complet reste sûr : phase, catégorie de scope, borne de découverte, compteurs d'admission/fin, dispositions entité/observation, missing/conflits/annulations/trous, maximum in-flight, préfixe contigu, checkpoint et éventuel code d'erreur stable ; aucune URL, endpoint/provider, payload RAW ou message fournisseur n'y entre. La tranche matérialise 47 tests unitaires et 10 canaries d'intégration au total, dont listener lent/multi-listeners, rétention terminale, courses terminales, attente pré-Store longue, attente de page RPC pendante et drainage après annulation. Le gate opérateur exécute ces 47 + 10 tests avec succès, mais Clippy révèle deux réexports `pub(crate)` non consommés via la façade crate-root et une canarie générique à type non utilisé ; l'audit manuel montre en outre que plusieurs usages intra-module des items partagés `pub`/`pub(crate)` de la nouvelle crate contournent `crate::`, en contradiction avec `RUST-IMPORT-009`, `RUST-IMPORT-012` et `RUST-API-007`. `pre.010` reste fermé jusqu'au gate vert du fix.
Le snapshot complet reste sûr : phase, catégorie de scope, borne de découverte, compteurs d'admission/fin, dispositions entité/observation, missing/conflits/annulations/trous, maximum in-flight, préfixe contigu, checkpoint et éventuel code d'erreur stable ; aucune URL, endpoint/provider, payload RAW ou message fournisseur n'y entre. La tranche matérialise 47 tests unitaires et 10 canaries d'intégration au total, dont listener lent/multi-listeners, rétention terminale, courses terminales, attente pré-Store longue, attente de page RPC pendante et drainage après annulation. Le gate opérateur exécute ces 47 + 10 tests avec succès, mais Clippy révèle deux réexports `pub(crate)` non consommés via la façade crate-root et une canarie générique à type non utilisé ; l'audit manuel montre en outre que plusieurs usages intra-module des items partagés `pub`/`pub(crate)` de la nouvelle crate contournent `crate::`, en contradiction avec `RUST-IMPORT-009`, `RUST-IMPORT-012` et `RUST-API-007`. `pre.009-fix.002` est désormais validé par le gate opérateur : audits, `cargo check`, Clippy et 47 unitaires + 10 canaries sont verts. `pre.010` peut donc ouvrir le hardening externe.
#### `pre.009-fix.001` — Normalisation crate-root des items partagés et visibilité runtime
@@ -514,16 +514,18 @@ Le fix réconcilie l'intégralité de `ksp-job-backfill-lib` avec les règles de
#### `pre.009-fix.002` — Construction privée du fingerprint via façade crate-root
**Statut : matérialisé ; gate opérateur à rejouer.**
**Statut : alisé ; gate opérateur intégralement vert.**
Le gate de `pre.009-fix.001` révèle une erreur `E0423` : le type public `BackfillScopeFingerprint` est correctement référencé via `crate::BackfillScopeFingerprint`, mais son constructeur de tuple struct n'est pas visible à travers le réexport crate-root puisque son champ `[u8; 32]` reste privé. Le correctif conserve le champ privé et la discipline crate-root : l'initialisation des octets est confinée dans un constructeur associé privé `from_bytes` défini dans `impl crate::BackfillScopeFingerprint`, puis le calcul de fingerprint appelle `crate::BackfillScopeFingerprint::from_bytes(bytes)`. Aucun contrat public, fingerprint, hash, dépendance ou feature ne change.
### `pre.010` — Hardening et canaries externes
**Statut : planifié.**
**Statut : réalisé ; gate opérateur à rejouer.**
Budget cible : **15-20 min**. Entrée : vertical déterministe complet. Fermer scénarios adversariaux, API externe, dépendances et sécurité ; exécuter la preuve live si justifiée et disponible. Sortie : aucun défaut fonctionnel ou firewall ouvert.
La tranche n'élargit aucune API de production et ne modifie aucune dépendance : elle ajoute une suite d'intégration externe `tests/hardening.rs` et renforce la canarie de complétude. Les preuves couvrent les neuf codes d'erreur publics et leur unicité, les bornes/adversaires de requête, l'identité sémantique du fingerprint `(réseau + scope)` indépendante du JobId/rôle Transport, les redactions `Debug`, l'état initial et l'idempotence de l'annulation via le handle public, la surface exacte des dépendances normales/dev, l'absence de backend Store direct et de retour des couches basses vers Job, les chemins crate-root exigés par RUST-IMPORT-009/010/012 et l'absence de types Tokio/Store backend/HTTP dans la façade publique. Le gate matérialisé attendu reste à 47 unitaires et passe de 10 à 20 canaries d'intégration. Le smoke live reste conditionnel et n'est pas requis par cette tranche faute d'environnement PostgreSQL explicitement fourni.
### `pre.011` — Gate technique final
**Statut : planifié.**