Files
khadhroony-solana-project/docs/validation/018-V0_3_1_STORE_RAW.md
2026-08-29 11:39:50 +02:00

538 lines
28 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- file: docs/validation/018-V0_3_1_STORE_RAW.md -->
<!-- version: 10 -->
# Validation `0.3.1` — Store API RAW foundation
## 1. Objet
Cette matrice est ouverte par `0.3.1-pre.001`, corrigée par `pre.001-fix.001` puis recalibrée par `pre.001-fix.002`. Elle valide **`ksp-store-api` uniquement**. La façade/runtime commune `ksp-store-lib` et l'implémentation PostgreSQL séparée `ksp-store-postgres-lib` seront développées de pair sur trois slices : fondation `0.3.2`, `RawTransaction` `0.3.3`, puis `RawAccountState` + complétude `0.3.4`.
Le scope concret N1 certain est :
```text
RawTransaction + observation
RawAccountState + observation
provenance/références/outcomes/queries communs
contrats/capabilities backend externes
cycle de rétention logique + tombstone
```
`pre.004` prouve la convergence de `RawAccountState`/observation entre HTTP/WS/gRPC sous admission stricte bytes complets + slot. `TransactionStatusObservation` reste différé : snapshot HTTP, transition WS et update Yellowstone ne sont pas encore un fait unique. Les notifications logs/slot/vote restent event-only candidates, avec ownership Interface préféré lorsqu'elles ne sont pas persistées.
## 2. Gate `pre.001`
| Critère | Statut | Preuve / décision |
|----------------------------------|---------|-----------------------------------------------------------------------------------|
| base stable `0.2.14` | PASS | Cargo `0.2.14`, `rel.001` et prompt 020 présents |
| baseline opérateur | PASS | audits/check/Clippy fournis verts ; validation tests déclarée OK |
| archive kbot3 + kbot2 historique | PASS | kbot3 extraite ; `olddocs/archivekbot2` audité pour lifecycle/replay |
| règles Store/API relues | PASS | règles KSP/Dependencies/Workflow prescrites relues |
| split version | PASS | `0.3.1 = Store API`, `0.3.2..0.3.4 = Store lib + PostgreSQL lib par slices` |
| dependency graph `0.3.1` | PASS | cible Core-only |
| modèle backend commun | PASS | API object/struct commune, rows backend privées |
| admission multi-source | PASS | même modèle seulement si HTTP/WS/gRPC satisfont intégralement la même sémantique |
| `RawTransaction` | PASS | premier modèle persistant certain |
| logs dans transaction | PASS | restent dans `RawTransaction`, extraction seulement en N2 STRUCTURAL |
| logsSubscribe | REPORTÉ | event-only candidat ; pas de `RawLog` Store persistant par défaut |
| account state | PASS | `pre.004` matérialise modèle/observation sous bytes complets + slot |
| transaction status | REPORTÉ | HTTP snapshot, WS transition et Yellowstone update restent distincts |
| slot/vote | TODO | event-only candidats ; ownership Interface à auditer |
| RawBlock | IDEA | non persisté par défaut ; `getBlock` sert de conteneur d'acquisition |
| Yellowstone Entry | REJETÉ | aucun replay/decomposition/event métier justifiant un modèle Store |
| frontière Interface/Store | PASS | persistent/replay -> Store API ; event-only partagé -> Interface préférentiel |
| N2 nomenclature | PASS | `CORE` remplacé par nom de travail `STRUCTURAL` |
| pipeline non linéaire | PASS | toutes les familles N1 ne sont pas forcées N1->N2->N3->N4 |
| processing proof | PASS | futur ledger stage+processor/version+input hash ; `processed: bool` insuffisant |
| retention lifecycle | PASS | `Full/Compacted/Archived/Purged` redessiné backend-agnostic |
| tombstone anti-rebackfill | PASS | identité/hash/slot minimal conservé après purge ; backfill forcé distinct |
| notification ownership runtime | PASS | Store ne possède aucun event bus/scheduler/DB notify |
| schema/migrations PostgreSQL | REPORTÉ | fondation `0.3.2`, schémas RAW complétés en `0.3.3`/`0.3.4` |
| D2/N3/N4 persistence | ABSENT | hors `0.3.1` |
| threat model | PASS | source mismatch, purge prématurée, stale processing, backend/event leaks couverts |
| sizing | PASS | dix prereleases courtes + lanes fermeture séparées |
## 3. Décisions structurelles à prouver par le code
| Contrat | Décision `pre.001-fix.002` | Gate futur |
|--------------------------------|------------------------------------------------------------------------------|------------------------------|
| crate `ksp-store-api` | seule crate Store créée en `0.3.1` | `pre.002` |
| dépendance normale | `ksp-core-lib` uniquement par défaut | `pre.002` |
| `RawPayload` | KSP-owned, source-independent, versionné, borné, Debug sans bytes | `pre.003` |
| `RawTransaction` | objet persistant commun uniquement depuis une source complète | `pre.003` |
| `RawTransactionObservation` | acquisition/provenance séparée du RAW | `pre.003` |
| transaction `logMessages` | partie du RAW transactionnel | `pre.003` |
| logs structuraux | extraction N2 STRUCTURAL future, jamais `RawLog` N1 distinct | canari négatif `pre.003/007` |
| `RawAccountState`/observation | modèle admis si HTTP/WS/gRPC convergent sans perte, matérialisé en `pre.004` | `pre.004` |
| `TransactionStatusObservation` | non matérialisé : surfaces status non équivalentes | report explicite `pre.004` |
| logs/slot/vote event-only | ne créent aucune capability Store par défaut | `pre.004/007` |
| Interface vs Store | event-only partagé -> Interface ; persistent/replay -> Store API | `pre.004/007` |
| model vs capability | un modèle API n'oblige pas tous les backends à le persister | `pre.005` |
| capabilities | read/write fines et object-safe | `pre.005` |
| transaction handle | aucun handle SQL/backend public | `pre.005` |
| atomic acquisition | méthode métier RAW + observation all-or-nothing | `pre.005/006` |
| write outcome | `Inserted / AlreadyPresent`; divergence = `Err Conflict` | `pre.006` |
| page/cursor | limit caller > 0 ; sans max KSP ; cursor opaque <= 4 KiB | `pre.006` |
| `RawRetentionState` | logique `Full/Compacted/Archived/Purged`, sans détail physique | `pre.006` |
| tombstone | identité/hash/slot minimal durable après purge | `pre.006` |
| backfill normal après purge | skip distinct | `pre.006` |
| force rehydrate | chemin explicite distinct, jamais fallback automatique | `pre.006` |
| processing evidence | futur ledger version-aware, jamais un bool unique | boundary `pre.006/007` |
| façade runtime `Store` | reportée à `ksp-store-lib`, hors `0.3.1` | fondation `0.3.2` |
## 4. Dependency firewall final attendu
Le graphe final `0.3.1` doit rester :
```text
ksp-store-api
└── ksp-core-lib
└── solana-pubkey
```
Interdits par défaut dans Store API :
```text
ksp-store-lib
ksp-onchain-transport-lib
ksp-offchain-transport-lib
ksp-interface-lib sans usage de type réel
ksp-program-api
ksp-program-lib
ksp-materializer-api
ksp-config-lib
ksp-logging-lib
ksp-wallet-lib
tokio-postgres
sqlx
serde / serde_json
chrono
tokio
async-trait
Tauri
```
Toute divergence exige un usage public réel et une révision du plan.
## 5. Matrice N1 initiale
| Famille / fait | Classification actuelle | Persistence Store | N2 attendu | Action `0.3.1` |
|--------------------------------|--------------------------|-------------------|----------------|--------------------------------------------------------------------|
| transaction complète | N1 RAW | oui | STRUCTURAL oui | implémenter modèle + observation |
| logs contenus dans transaction | partie de RawTransaction | via transaction | STRUCTURAL oui | préserver lossless, ne pas dupliquer en `RawLog` |
| account state complet | N1 RAW | oui à terme | pas démontré | modèle + observation matérialisés en `pre.004` |
| transaction status | familles distinctes | non figée | non | différer : snapshot HTTP != transition WS != update Yellowstone |
| `logsSubscribe` notification | event-only candidat | non par défaut | non | ownership Interface/worker à figer |
| slot/root/slotsUpdates | event-only candidat | non | non | TODO use-case + compatibilité |
| vote | event-only candidat | non | non | TODO seulement si forme commune utile |
| block complet | acquisition container | non par défaut | — | IDEA uniquement ; extraire transactions plutôt que stocker le bloc |
| Yellowstone Entry | transport-only | non | — | explicitement non retenu |
## 6. Frontière N1 -> N2 STRUCTURAL
`0.3.1` doit préserver sans implémenter :
```text
RawTransaction
-> StructuralTransaction/message
-> account keys
-> top-level instructions
-> CPI/inner instructions
-> logs/meta/balances/return data
-> traitement individuel ultérieur
```
N2 est nommé **STRUCTURAL** parce qu'il décrit une décomposition générique Solana, pas un domaine métier « Core ».
Canaris :
```text
ksp-store-api -X-> ksp-program-api
RawTransaction logMessages -X-> entité RawLog persistante séparée
une erreur/absence future de decoder -X-> blocage des autres instructions
```
Toutes les familles N1 ne sont pas obligées de posséder un N2. `RawAccountState` peut par exemple aller directement vers une future étape de decode si aucune décomposition structurelle utile n'est identifiée.
## 7. Extensibilité backend
Le canari externe doit démontrer :
```text
crate/test backend externe
-> dépend de ksp-store-api
-> définit son propre backend mémoire
-> implémente les contrats/capabilities publics
-X-> ksp-store-lib
-X-> PostgreSQL
```
`0.3.2` ajoutera ensuite la façade de consommation `ksp-store-lib` et la fondation `ksp-store-postgres-lib`. La conformance API du backend officiel sera matérialisée par famille : `RawTransaction` en `0.3.3`, puis `RawAccountState` et la complétude cross-family en `0.3.4`.
## 8. Threat/API gates futurs
| Gate | Attendu | Statut initial |
|---------------------------------------------|-------------------------------------------------|----------------|
| oversized RAW payload | rejet avant allocation pathologique | `pre.003` |
| payload Debug | aucun bytes brut | `pre.003` |
| partial source -> RawTransaction | interdit ; contrat complet exigé | `pre.003/004` |
| HTTP/WS/gRPC semantic mismatch | détecté par admission matrix | `pre.004` PASS |
| account bytes partiels/parsés | refusés avant `RawAccountState` | `pre.004` PASS |
| account sans slot durable | refusé comme état persistant | `pre.004` PASS |
| account data Debug | aucun bytes brut | `pre.004` PASS |
| status surfaces artificiellement fusionnées | aucun modèle commun prématuré | `pre.004` PASS |
| duplicate same content | `AlreadyPresent` | `pre.006` |
| duplicate divergent content | Conflict stable | `pre.006` |
| partial transaction+observation | interdit par atomic acquisition | `pre.005` PASS |
| event-only -> Store capability | absent par défaut | `pre.004/007` |
| Interface/Store duplicate model | absent | `pre.007` |
| page limit 0 | rejet ; aucun max KSP artificiel | `pre.006` |
| SQL/backend cursor leak | absent | `pre.006/007` |
| external backend | implémente API sans Store lib | `pre.005` PASS |
| processing `bool` comme vérité | absent ; future preuve version-aware documentée | `pre.006/007` |
| purge sans policy/evidence | impossible par contrat | `pre.006/007` |
| tombstone supprimé avec payload | interdit | `pre.006` |
| rebackfill normal après purge | skip | `pre.006` |
| force rehydrate implicite | interdit | `pre.006` |
| N2/N3/N4 creep | aucune surface | `pre.007` |
### 8.1 Matérialisation `pre.003`
La tranche implémente et couvre localement par canaris source/audit :
```text
RawNetworkId
RawTransactionSignature [u8; 64]
RawTransactionReference
RawFormatId
RawContentHash [u8; 32]
RawObservationKey [u8; 32]
RawTimestamp
RawAcquisitionOrigin
RawProvenanceCode
RawAcquisitionProvenance
RawPayload
RawTransaction
RawTransactionObservation
```
Gates matérialisés :
```text
Core-only dependency firewall conservé
payload KSP source-independent, non vide, version > 0
payload maximum Store = 16 MiB
source payload metadata maximum = 64 MiB
Debug RawPayload ne rend jamais les bytes
signature/observation key/hash ne dépendent d'aucune PK backend
provenance sans URL/source payload
observed_at <= received_at
logs transactionnels restent dans le payload RawTransaction
aucun RawLog/N2 STRUCTURAL/backend/runtime ajouté
```
La complétude sémantique d'une source HTTP/WS/gRPC vers le format canonique n'est pas simulée dans Store API : elle reste le gate d'admission/conversion de `pre.004`. `pre.003` exige seulement qu'un `RawTransaction` reçoive un `RawPayload` déjà canonique complet selon son format KSP déclaré.
### 8.2 Matérialisation `pre.004`
La tranche ajoute :
```text
MAX_RAW_ACCOUNT_DATA_BYTES
RawAccountStateReference
RawAccountState
RawAccountObservation
```
Invariants vérifiés par modèle/canaris :
```text
référence = network + pubkey + slot + canonical state hash
account data complet <= 16 MiB
empty account data autorisé
Debug RawAccountState ne rend jamais les bytes
write_version/transaction_signature/is_startup restent observation-only optionnels
HTTP/WS/gRPC source details n'entrent pas dans RawAccountState
aucun TransactionStatusObservation artificiel
aucun RawLogNotification/RawSlotEvent/RawVoteEvent/RawBlock/YellowstoneEntry public
```
Matrice d'admission validée architecturalement :
```text
getAccountInfo/getMultipleAccounts -> oui avec bytes complets
getProgramAccounts -> contexte obligatoire
accountSubscribe -> oui avec bytes complets
programSubscribe -> contexte obligatoire
Yellowstone Account -> aucun accounts_data_slice
jsonParsed/dataSlice/bare program -> non
```
La conversion source -> modèle reste hors `ksp-store-api`; la crate ne dépend toujours que de `ksp-core-lib`.
### 8.3 Matérialisation `pre.005`
La tranche ajoute uniquement des contracts de capability backend-agnostic :
```text
StoreApiFuture<'a, T>
RawTransactionRead
RawTransactionWrite
RawTransactionObservationRead
RawTransactionObservationWrite
RawAccountStateRead
RawAccountStateWrite
RawAccountObservationRead
RawAccountObservationWrite
```
Gates matérialisés :
```text
traits Send + Sync et dyn-compatible
aucune dépendance async-trait/tokio/futures-util ajoutée
backend externe implémentable avec std + ksp-store-api seulement
aucun trait StoreBackend monolithique
aucune façade runtime Store
aucun type Config/backend/SQL public
persist_raw_transaction_acquisition = transaction + observation atomiques
persist_raw_account_acquisition = account state + observation atomiques
record_*_observation = acquisition supplémentaire sans retransmettre le RAW
get_* = référence/observation key backend-independent
write success/failure seulement en pre.005
outcomes/idempotence/conflict détaillés réservés à pre.006
```
Le canari `tests/external_backend.rs` définit un backend mémoire externe qui implémente les huit traits sans dépendre de `ksp-store-lib`, PostgreSQL ou d'un runtime async. Il prouve également que chaque capability est utilisable derrière `dyn Trait`.
Aucune implémentation de persistence n'est fournie par `ksp-store-api`; les futures concrètes du canari ne servent qu'à vérifier le contrat d'extension.
### 8.4 Matérialisation `pre.006`
La tranche ajoute les contrats logiques suivants sans backend/runtime :
```text
RawPageCursor / RawPageLimit / RawPageRequest / RawPage<T>
RawSlotRange / RawSortDirection
RawTransactionQuery / RawAccountStateQuery
RawEntityWriteOutcome / RawObservationWriteOutcome / RawAcquisitionWriteOutcome
RawRetentionState
RawTransactionAcquisitionMode
RawTransactionTombstone
RawTransactionRetentionTransition / RawRetentionWriteOutcome
RawTransactionRetentionRead / RawTransactionRetentionWrite
```
Gates matérialisés :
```text
page limit 0 rejeté
u64::MAX admis comme demande représentable : aucun maximum métier KSP
cursor opaque borné à 4 KiB et Debug sans contenu
range de slots inversée rejetée
queries limitées aux critères de données, sans backlog/executor policy
Inserted / AlreadyPresent explicites
contenu divergent = ERROR_CODE_RAW_CONFLICT
RAW + observation gardent le contrat atomique
Full -> Compacted -> Archived -> Purged, avec Full -> Archived autorisé
aucun Full -> Purged direct
aucun Purged -> Full via transition générique
force rehydrate explicite via acquisition transactionnelle
tombstone minimal sans payload
retention policy choisie hors Store par worker/job/maintenance
```
### 8.5 Matérialisation `pre.007`
La tranche ferme le hardening de surface sans ajouter de nouvelle famille N1 :
```text
security_hardening.rs
release_completeness.rs
RawRetentionWriteOutcome::ExpectedStateMismatch
```
Gates matérialisés :
```text
erreurs model/query/provenance hostiles sans echo de valeur
Debug payload/hash/signature/account sans bytes sensibles
cursor exact 4 KiB accepté, dépassement rejeté
RawPageLimit u64::MAX reste représentable
compare-and-transition perdue distincte de Applied/AlreadyAtTarget
exports crate-root exacts
inventaire exact des modules production RAW
10 capabilities fines exactes, aucun StoreBackend/Store runtime
Interface ne réexporte pas les modèles persistants Store
Store API ne publie aucun event-only logs/slot/vote
aucune surface STRUCTURAL/DECODED/DOMAIN
aucune fuite PostgreSQL/MySQL/backend runtime
```
La course de rétention est un état normal de concurrence : si l'état durable ne correspond plus à `expected` et n'est pas déjà `target`, le backend doit retourner `ExpectedStateMismatch`. Cette sémantique évite d'utiliser une erreur de validation pour une course et impose une compare-and-transition atomique à l'implémentation future.
### 8.6 Gate technique `pre.008`
Le gate opérateur final a été exécuté après `cargo clean`, donc sans dépendre du cache incrémental précédent.
Résultat :
```text
audits Rust/Markdown PASS
cargo check --workspace PASS
cargo clippy --workspace --all-targets PASS
tests ciblés Core/Logging/Config/Transport/Off-chain/Wallet/Interface/Store/Desks PASS
cargo test --workspace PASS
cargo tauri build SOL Prices Desk PASS
cargo tauri build Wallet Desk PASS
cargo tauri build Config Desk PASS
cargo tree -p ksp-store-api --edges normal inspecté
cargo tree --duplicates inspecté
```
Le seul incident de commande était le nom inexistant `ksp-program-lib`; il ne correspond à aucune crate publiée. Le test ciblé correct `cargo test -p ksp-program-api` a ensuite été exécuté séparément et passe : 3 unit, 2 dependency-boundary, 2 external-implementation, 4 public-api, 4 release-completeness et 3 security-hardening, plus doc-tests.
Le graphe normal Store API reste strictement `ksp-store-api -> ksp-core-lib` et aucune dépendance backend/runtime n'entre dans la crate.
### 8.7 Réconciliation `pre.009`
**PASS opérateur ciblé.** Après application de `0.3.1-pre.009`, audits Rust/Markdown, `cargo check --workspace`, Clippy et `cargo test -p ksp-store-api` passent. Aucun re-gate Tauri/workspace complet n'était requis après le gate lourd propre de `pre.008`.
La surface finale réellement retenue pour `0.3.1` est :
```text
RawTransaction / RawTransactionObservation
RawAccountState / RawAccountObservation
primitives de provenance/format/hash/timestamps
queries cursorisées sans plafond métier KSP arbitraire
outcomes idempotence/conflit
RawRetentionState + tombstone transactionnel
normal skip après purge + force rehydrate explicite
10 capabilities backend fines/object-safe
```
Sont explicitement reportés plutôt que simulés dans la foundation :
```text
TransactionStatusObservation
logs/slot/vote event-only contracts
StoreHealth/readiness runtime
type canonique dédié de wake-up persisté-data
processing ledger / backlog métier / executor policy
compression/archive physique
backend PostgreSQL et std.store
N2 STRUCTURAL / N3 DECODED / N4 DOMAIN
```
`README.md` ne contient aucune surface Store détaillée devenue fausse et aucun document USAGE Store n'existe encore ; ils ne sont donc pas modifiés artificiellement par cette tranche.
## 9. Gates de fermeture
### Gate technique final `pre.008`
**PASS opérateur complet.** Voir §8.6. Le gate a été reconstruit après `cargo clean` et couvre audits, workspace check/Clippy/tests, builds Tauri des trois Desk et graphes Cargo. Le test ciblé `ksp-program-api` a également été rejoué avec le bon nom de package.
### Réconciliation documentaire `pre.009`
**PASS opérateur ciblé.** Voir §8.7. Le plan, la validation, les architectures Store réellement concernées et `IDEAS.md` sont réconciliés. Aucun README/USAGE Store n'existe à maintenir actuellement.
### Redécoupage documentaire `pre.010`
La décision opérateur postérieure à `pre.009` sépare l'ancien scope PostgreSQL unique en trois releases afin de préserver la qualité et la clôture par session, sans séparer `ksp-store-lib` de `ksp-store-postgres-lib`. Cette responsabilité documentaire doit être fermée avant la lane de publication.
### Préparation de publication `pre.011`
La préparation de publication finale est décalée à `pre.011` après le redécoupage documentaire `pre.010`. Elle doit rester limitée à :
```text
Cargo.toml
CHANGELOG.md
ROADMAP.md
prompts/021-V0_3_2_START_PROMPT.md
delta pre.011
```
`pre.011` ne doit plus réparer la taxonomie N1/N2 ni le découpage Store/PostgreSQL : ces décisions appartiennent aux tranches documentaires antérieures.
## 10. PostgreSQL reporté aux slices `0.3.2``0.3.4`
Aucun gate PostgreSQL live n'est demandé à `0.3.1`. Le développement de `ksp-store-lib` et `ksp-store-postgres-lib` reste conjoint, mais l'ancien scope unique `0.3.2` est redécoupé pour préserver la qualité et la clôture par session.
### `0.3.2` — fondation runtime/backend PostgreSQL
```text
ksp-store-lib
-> façade Store commune minimale
-> réexports utiles de ksp-store-api
-> feature postgres par défaut
-> dispatch backend selon Config
-> erreur backend connu mais non compilé
-> health/readiness runtime si justifié par le gate pre.001
ksp-store-postgres-lib
-> tokio-postgres
-> connexion/pool/TLS audités
-> bootstrap migrations KSP-owned
-> transaction primitive privée si nécessaire à la suite
Config
-> std.store
-> URI/DSN backend lorsque naturel
-> secrets ${KSP_SECRET_*} / .env owned par ksp-config-lib
-> aucun vrai secret versionné
```
Aucune capability `RawTransaction` ou `RawAccountState` n'est implémentée artificiellement dans cette fondation uniquement pour gonfler le scope.
### `0.3.3` — vertical slice PostgreSQL `RawTransaction`
```text
RawTransaction + observation
write/read/get/list cursorisé
atomic RAW + observation
idempotence / AlreadyPresent / conflict
retention / tombstone / force rehydrate
rollback et races réelles
conformance ksp-store-api
```
### `0.3.4` — vertical slice PostgreSQL `RawAccountState` + complétude
```text
RawAccountState + observation
write/read/get/list cursorisé
idempotence / conflict / atomic observation
conformance cross-family
migration/index hardening
backend dispatch/health final
gate PostgreSQL réel final
```
Règles communes aux trois slices :
```text
URI/DSN/credentials redacted
aucune lecture directe env/.env par Store ou backend
aucun plafond métier arbitraire de pagination imposé par Store
limitations physiques backend exposées sans devenir policy executor
PostgreSQL réel opt-in pendant développement puis gate final de la slice concernée
```
## 11. État des tranches
| Tranche | Objet | État |
|-----------|------------------------------------------|---------------------------------|
| `pre.001` | audit/design/taxonomie/split | PASS |
| `pre.002` | scaffold + taxonomie Store API | PASS |
| `pre.003` | primitives + RawTransaction | PASS après `fix.001` |
| `pre.004` | admission matrix + account/status models | PASS |
| `pre.005` | backend contracts/capabilities | PASS |
| `pre.006` | queries/outcomes/retention/tombstone | PASS après `fix.001` |
| `pre.007` | boundary/adversarial/completeness | PASS après `fix.001` |
| `pre.008` | gate technique final | PASS opérateur complet |
| `pre.009` | réconciliation documentaire | PASS opérateur ciblé |
| `pre.010` | redécoupage documentaire futures slices | PRÊT après audits documentaires |
| `pre.011` | préparation publication | À FAIRE |
| `rel.001` | stable | À FAIRE |