v0.3.15-pre.001
This commit is contained in:
424
docs/validation/032-V0_3_15_RAW_TRANSACTION_INGEST_DESK.md
Normal file
424
docs/validation/032-V0_3_15_RAW_TRANSACTION_INGEST_DESK.md
Normal file
@@ -0,0 +1,424 @@
|
||||
<!-- file: docs/validation/032-V0_3_15_RAW_TRANSACTION_INGEST_DESK.md -->
|
||||
<!-- version: 2 -->
|
||||
|
||||
# Validation v0.3.15 — Raw Transaction Ingest Desk
|
||||
|
||||
## 1. Rôle
|
||||
|
||||
Ce document enregistre les preuves et non-claims de `0.3.15`. En `pre.001`, aucune crate Desk, aucun Start/Stop Worker et aucune extension lower-layer ne sont encore implémentés : la tranche est exclusivement le gate de lecture, audit, brainstorming, external re-audit, sizing et planification imposé par `prompts/034-V0_3_15_START_PROMPT.md`.
|
||||
|
||||
## 2. Archive stable contrôlée
|
||||
|
||||
```text
|
||||
archive : khadhroony-solana-project-v0.3.14.zip
|
||||
SHA-256 : 897bd30b0d06c00abc120a7459250b78c11629e84825ac29adbe151d60a668ed
|
||||
bytes : 8591925
|
||||
entries : 2046
|
||||
files : 1851
|
||||
absolute entries : 0
|
||||
parent traversal entries : 0
|
||||
duplicate entries : 0
|
||||
symlink entries : 0
|
||||
workspace members : 21
|
||||
crate manifests : 21
|
||||
workspace.package.version : 0.3.14
|
||||
edition : 2024
|
||||
stable delta : deltas/0.3.14/rel.001.md
|
||||
```
|
||||
|
||||
Artefacts interdits recherchés :
|
||||
|
||||
```text
|
||||
Cargo.lock : absent
|
||||
package-lock.json : absent
|
||||
pnpm-lock.yaml : absent
|
||||
yarn.lock : absent
|
||||
rust-toolchain.toml : absent
|
||||
.env : absent
|
||||
target/ : absent
|
||||
node_modules/ : absent
|
||||
dist/ : absent
|
||||
.git/ : absent
|
||||
```
|
||||
|
||||
Résultat archive : PASS.
|
||||
|
||||
L'absence de `.git` empêche de comparer l'objet du tag `v0.3.14`; aucune équivalence cryptographique au tag n'est revendiquée.
|
||||
|
||||
## 3. Preuve opérateur stable fournie
|
||||
|
||||
Le journal opérateur joint à la demande contient notamment l'exécution stable `0.3.14` de :
|
||||
|
||||
```text
|
||||
cargo clean
|
||||
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-worker-raw-transaction-ingest-lib --all-targets --all-features
|
||||
cargo test --workspace --all-targets --all-features
|
||||
cargo tree -p ksp-worker-raw-transaction-ingest-lib --edges normal
|
||||
cargo tree -p ksp-worker-raw-transaction-ingest-lib -e features
|
||||
cargo tree --duplicates
|
||||
```
|
||||
|
||||
Les sorties fournies montrent notamment :
|
||||
|
||||
```text
|
||||
General Rust rule audit: clean
|
||||
Rust export completeness audit: 0 candidate(s)
|
||||
KSP workspace Rust rule audit: clean
|
||||
Markdown table audit: clean (340 table(s), 886 file(s))
|
||||
Worker unit tests: 152 passed / 0 failed
|
||||
Worker cross-layer completeness: 12 passed / 0 failed
|
||||
Worker dependency boundary: 21 passed / 0 failed
|
||||
Worker hardening: 38 passed / 0 failed
|
||||
Worker public API: 22 passed / 0 failed
|
||||
Worker release completeness: 15 passed / 0 failed
|
||||
```
|
||||
|
||||
Le journal continue avec le gate workspace stable et ses tests. Cette preuve qualifie l'entrée `0.3.14`; elle n'est pas réutilisée comme prétendue exécution post-bump `0.3.15-pre.1`.
|
||||
|
||||
## 4. Audits locaux de la base avant modification
|
||||
|
||||
Exécuté localement :
|
||||
|
||||
```bash
|
||||
python3 scripts/audit_rust_workspace_rules.py
|
||||
```
|
||||
|
||||
Résultat :
|
||||
|
||||
```text
|
||||
General Rust rule audit: clean
|
||||
Rust export completeness audit: 0 candidate(s)
|
||||
KSP workspace Rust rule audit: clean
|
||||
```
|
||||
|
||||
Exécuté localement :
|
||||
|
||||
```bash
|
||||
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas
|
||||
```
|
||||
|
||||
Résultat :
|
||||
|
||||
```text
|
||||
Markdown table audit: clean (340 table(s), 886 file(s))
|
||||
```
|
||||
|
||||
`cargo`/`rustfmt` ne sont pas présents dans l'environnement d'assemblage courant. Aucune commande Cargo locale n'est déclarée PASS.
|
||||
|
||||
## 5. Audit des règles
|
||||
|
||||
Documents relus :
|
||||
|
||||
```text
|
||||
RULES.md
|
||||
ROADMAP.md
|
||||
CHANGELOG.md
|
||||
docs/000-README.md
|
||||
docs/rules/RULES_GENERAL.md
|
||||
docs/rules/RULES_KSP.md
|
||||
docs/rules/RULES_RUST.md
|
||||
docs/rules/RULES_DEPENDENCIES.md
|
||||
docs/rules/RULES_DOCUMENTATION.md
|
||||
docs/rules/FILE_CONTRACTS.md
|
||||
docs/rules/VERSION_WORKFLOW.md
|
||||
docs/rules/PROMPT_STRUCTURE.md
|
||||
```
|
||||
|
||||
Scan des définitions normatives :
|
||||
|
||||
```text
|
||||
489 définitions
|
||||
489 IDs uniques
|
||||
0 doublon
|
||||
```
|
||||
|
||||
Les deltas publiés antérieurs ne sont pas réécrits. Le gate `pre.001` modifie uniquement `Cargo.toml` et ajoute les trois livrables exigés.
|
||||
|
||||
## 6. Handoff stable et Worker audités
|
||||
|
||||
Les documents `0.3.14`, README/USAGE Worker et les sources/tests Worker ont été audités.
|
||||
|
||||
API publique pertinente confirmée :
|
||||
|
||||
```text
|
||||
RawTransactionIngestRuntimeResources
|
||||
RawTransactionIngestYellowstoneSource
|
||||
RawTransactionIngestStandardLogsSource
|
||||
RawTransactionIngestStandardBlockSource
|
||||
RawTransactionIngestHeliusTransactionSource
|
||||
RawTransactionIngestHttpBlockPollingSource
|
||||
RawTransactionIngestWorker::start_with_runtime_resources
|
||||
RawTransactionIngestHandle
|
||||
RawTransactionIngestSnapshotSource
|
||||
```
|
||||
|
||||
Frontières confirmées :
|
||||
|
||||
```text
|
||||
Worker -X-> Config
|
||||
Worker -X-> Job Backfill
|
||||
Worker -X-> ksp-store-postgres-lib
|
||||
Worker -> ksp-store-lib
|
||||
Worker -> ksp-onchain-transport-lib
|
||||
```
|
||||
|
||||
Plusieurs Workers peuvent recevoir le même `Arc<Store>` ; leurs lifecycle/gaps/TargetCoverage restent indépendants.
|
||||
|
||||
## 7. Requirements exacts des cinq familles Worker
|
||||
|
||||
| Route V1 | Network | Required capability | Optional capability | Config evidence | Worker resource | Composable aujourd’hui ? | Missing contract | Live-testable ? |
|
||||
|-------------------------------|------------------|----------------------------------------------------------------|-------------------------------------------------|-----------------------|-----------------------------------------------|---------------------------------------------------------|--------------------------------------------------|-----------------------------------------------|
|
||||
| `yellowstone-hydrated` | réseau du profil | Yellowstone gRPC Subscribe + HTTP `getTransaction` même réseau | scan HTTP repair si rôle compatible | gRPC + HTTP role | `RawTransactionIngestYellowstoneSource` | oui sur profil complet et secrets résolus | aucun contrat essentiel | provider-gated selon profil |
|
||||
| `standard-logs-hydrated` | réseau du profil | WS Solana standard `logsSubscribe` + HTTP `getTransaction` | scan HTTP repair si rôle compatible | WS + HTTP role | `RawTransactionIngestStandardLogsSource` | non prouvable strictement avant capability WS explicite | Transport + Config + enforcement Worker minimaux | oui, notamment Devnet keyless après extension |
|
||||
| `standard-block-direct` | réseau du profil | WS Solana standard `blockSubscribe` explicitement déclaré | aucune hydration obligatoire | WS capability Block | `RawTransactionIngestStandardBlockSource` | non prouvable aujourd’hui | Transport + Config + enforcement Worker minimaux | seulement endpoint prouvé compatible |
|
||||
| `helius-transaction-hydrated` | réseau du profil | WS Helius `transactionSubscribe` + HTTP `getTransaction` | scan HTTP repair si rôle compatible | Helius WS + HTTP role | `RawTransactionIngestHeliusTransactionSource` | non dans les profils committed actuels | Config data/composite + capability WS explicite | provider-gated Helius |
|
||||
| `http-block-polling` | réseau du profil | HTTP `getSlot` + `getBlocksWithLimit` + `getBlock` | `getTransaction` pour known-reference hydration | HTTP role | `RawTransactionIngestHttpBlockPollingSource` | oui lorsque le rôle résolu annonce les trois méthodes | aucun contrat essentiel | oui sur endpoint public compatible |
|
||||
|
||||
Qualification importante : `Composable aujourd'hui ?` signifie « prouvable à partir de la Config stable telle qu'elle est structurée », pas « le provider distant répond actuellement ».
|
||||
|
||||
## 8. Audit Config
|
||||
|
||||
`ResolvedTransportConfig` fournit des settings typed HTTP/WS/gRPC et `ResolvedStoreConfig` fournit les settings Store sans exiger une lecture JSON frontend.
|
||||
|
||||
HTTP : rôles et `request_kinds` sont déjà projetables côté Rust.
|
||||
|
||||
WS : le protocol kind est projetable, mais `WsEndpointSettings` ne porte pas de liste de `WsSubscriptionKind`. C'est le gap déterminant de `pre.001`.
|
||||
|
||||
Profils committed vs exemple :
|
||||
|
||||
| Profil/config | Réseau | Surfaces | Secret requis | Committed ? | Observation |
|
||||
|-------------------------|------------------------------|---------------------------------------|-----------------------|----------------------|-------------------------------------------|
|
||||
| `devnet_public` | devnet | HTTP + WS Solana standard | non | oui | pas de capability WS fine aujourd’hui |
|
||||
| `orbitflare_devnet` | devnet | HTTP + WS standard + Yellowstone gRPC | token gRPC secret | conditionnel | profil complet seulement si secret résolu |
|
||||
| `mainnet_public` | mainnet | HTTP + WS Solana standard | non | oui | pas de capability WS fine aujourd’hui |
|
||||
| `mainnet_backfill_pool` | mainnet | plusieurs HTTP + WS standard | selon endpoint/config | oui si profil résolu | priorités/rôles restent Transport-owned |
|
||||
| `publicnode_mainnet` | mainnet | HTTP + WS standard + Yellowstone gRPC | x-token secret | conditionnel | gRPC provider-gated |
|
||||
| `publicnode_testnet` | testnet | HTTP + WS standard + Yellowstone gRPC | x-token secret | conditionnel | gRPC provider-gated |
|
||||
| Helius exemple | mainnet/devnet selon exemple | WS `helius_laserstream` | API key secret | non committed | exemple != profil actif |
|
||||
|
||||
Aucun profil Helius WS n'est committed dans `config/std.transport.json`; sa présence dans un exemple ne constitue pas une availability V1.
|
||||
|
||||
## 9. Audit Store
|
||||
|
||||
Chemin validé :
|
||||
|
||||
```text
|
||||
ResolvedStoreConfig -> StoreSettings -> ksp-store-lib::Store::open
|
||||
```
|
||||
|
||||
Aucun besoin de nouvelle API Store n'est identifié pour inventaire, Start/Stop ou partage du Store entre Workers du même réseau.
|
||||
|
||||
## 10. Audit gabarit Desk
|
||||
|
||||
Les cinq Desk KSP existantes ont été utilisées comme références de structure et non comme code à copier pendant `pre.001`.
|
||||
|
||||
Socle confirmé :
|
||||
|
||||
```text
|
||||
splash KSP commun
|
||||
fonts/style KSP
|
||||
backend Tauri Rust propriétaire des ressources
|
||||
frontend sans accès direct réseau/Store/secrets
|
||||
@fltsci/tauri-plugin-tracing
|
||||
@fortawesome/fontawesome-free
|
||||
@tauri-apps/api
|
||||
bootstrap
|
||||
resize-observer-polyfill
|
||||
simplebar
|
||||
```
|
||||
|
||||
Aucun upgrade npm opportuniste n'est retenu.
|
||||
|
||||
## 11. External re-audit `pre.001`
|
||||
|
||||
Sources primaires/courantes consultées pour qualifier les capabilities :
|
||||
|
||||
```text
|
||||
Solana JSON-RPC WebSocket blockSubscribe
|
||||
Solana JSON-RPC WebSocket logsSubscribe
|
||||
Yellowstone gRPC upstream Subscribe/proto/changelog
|
||||
Helius WebSocket standard + transactionSubscribe + unsupported methods
|
||||
PublicNode Solana RPC/WS/Yellowstone offre actuelle
|
||||
OrbitFlare Yellowstone gRPC offre actuelle
|
||||
```
|
||||
|
||||
Constats utilisés :
|
||||
|
||||
```text
|
||||
blockSubscribe est unstable et dépend de l'activation côté validator/provider
|
||||
logsSubscribe est standard
|
||||
Helius distingue les méthodes Solana standard de son extension transactionSubscribe
|
||||
Helius indique blockSubscribe non supporté
|
||||
Yellowstone expose les filtres Subscribe et le replay/from_slot lower-layer
|
||||
```
|
||||
|
||||
Aucune de ces informations Web n'est convertie directement en route sélectionnable : Config locale reste l'autorité de composabilité.
|
||||
|
||||
## 12. Gap classification
|
||||
|
||||
| Sujet | Classification | Owner | Décision |
|
||||
|--------------------------------------------------|------------------------------|--------------------|----------------------------------------------------------------|
|
||||
| Catalogue de cinq routes et IDs applicatifs | adaptation app seulement | Desk | catalogue borné, pas de nouvelle crate |
|
||||
| Projection HTTP `request_kinds` / rôles / réseau | aucun gap | Config + Transport | déjà exploitable côté Rust |
|
||||
| Projection gRPC Yellowstone / metadata sûre | aucun gap | Config + Transport | secrets restent Rust-only |
|
||||
| Capability WS exacte par subscription | extension Transport minimale | Transport | ajouter une déclaration typed réutilisant `WsSubscriptionKind` |
|
||||
| Mapping schema/config des capabilities WS | extension Config minimale | Config | Config reste propriétaire de la déclaration |
|
||||
| Refus Worker si capability WS requise absente | extension Worker minimale | Worker | enforcement avant I/O, pas de logique provider dans Desk |
|
||||
| Composite dédié Raw Ingest Desk | extension Config minimale | Config | profils app dédiés et cohérents Store/Transport |
|
||||
| Store open / network / partage `Arc<Store>` | aucun gap | Store + app | `ksp-store-lib` suffit |
|
||||
| Lifecycle / stop / snapshots Worker | aucun gap | Worker + app | handles publics existants |
|
||||
| Backfill / historical repair | hors scope | Job Backfill | aucune orchestration automatique |
|
||||
| Taille release | pas de split de release | plan | forecast étendu jusqu’à `pre.016` |
|
||||
|
||||
Résultat : `0.3.15` reste une release cohérente. Aucun split vers `0.3.16` n'est nécessaire avant implémentation, mais le forecast interne est élargi.
|
||||
|
||||
## 13. Décisions UX / architecture validées au gate
|
||||
|
||||
```text
|
||||
catalogue de routes V1 app-owned
|
||||
cinq route IDs bornés
|
||||
réseau dérivé d'un composite/profil app cohérent Store+Transport
|
||||
changement de profil interdit pendant Workers actifs
|
||||
inventaire Config sans I/O réseau
|
||||
Start revalide toute la Config
|
||||
multiple endpoints satisfaisant une route : sélection Transport selon rôles/priorités
|
||||
1 Worker par route
|
||||
fault d'une route n'arrête pas les autres
|
||||
Store partagé seulement si réseau strictement identique
|
||||
fermeture app : stop/join de tous les Workers détenus
|
||||
frontend sans endpoints/secrets/handles/source keys/payloads bruts
|
||||
```
|
||||
|
||||
États UI retenus :
|
||||
|
||||
| État UI | Sémantique | Action principale |
|
||||
|-------------|----------------------------------------------------------------|-------------------------------------|
|
||||
| Unavailable | requirements incomplets ou incohérents | non |
|
||||
| Configured | requirements Config complètes, aucune preuve runtime | oui |
|
||||
| Starting | revalidation + reconstruction + ouverture Store + start Worker | non |
|
||||
| Running | Worker actif, snapshots reçus | Stop |
|
||||
| Stopping | stop demandé, attente terminale bornée | non |
|
||||
| Stopped | Worker terminal propre, handle retiré | Start après nouvelle revalidation |
|
||||
| Faulted | échec Start/runtime avec code sûr | Start après correction/revalidation |
|
||||
|
||||
## 14. IPC et tracing planifiés
|
||||
|
||||
| DTO candidat | Sens | Contenu autorisé | Exclusions |
|
||||
|---------------------------------|---------------------|------------------------------------------------------------------------------|------------------------------------------|
|
||||
| `RawIngestDeskOptionsDto` | backend -> frontend | profils logiques sûrs, réseaux, commitments supportés, génération inventaire | URL, secret, Store URI |
|
||||
| `RawIngestRouteDto` | backend -> frontend | route_id, family, label, network, state, selectable, reason code | endpoint name/URL/token/source key |
|
||||
| `RawIngestRouteStartRequestDto` | frontend -> backend | route_id, inventory_generation, commitment | endpoint/credential/client |
|
||||
| `RawIngestRouteStopRequestDto` | frontend -> backend | route_id | Worker handle |
|
||||
| `RawIngestRouteRuntimeDto` | backend -> frontend | route_id, lifecycle/health/activity, compteurs source-neutral | payload brut, erreur provider arbitraire |
|
||||
| `CommandErrorDto` | backend -> frontend | code stable + contexte whiteliste | texte remote arbitraire |
|
||||
| `FrontendLogPayloadDto` | frontend -> backend | target/level/action IDs bornés | valeurs config/route sensibles |
|
||||
|
||||
| Interaction | Trace autorisée | Interdit |
|
||||
|--------------------------|---------------------------------------------|----------------------------------|
|
||||
| Navigation/tab | control_id + action | aucun profil, endpoint ou secret |
|
||||
| Sélection profil/réseau | action + résultat code + counts | pas de valeur de secret ni URL |
|
||||
| Sélection route | route family/route_id sûr + booléen | pas de source key |
|
||||
| Start/Stop | route_id sûr + lifecycle outcome code | pas de payload Worker |
|
||||
| Refresh/resync snapshots | action + sequence/count | pas de transactions |
|
||||
| IPC success/failure | command id + stable code + durée éventuelle | pas d’erreur remote brute |
|
||||
|
||||
Ces tables décrivent le contrat de sécurité à implémenter ; elles ne revendiquent aucune commande Tauri existante en `pre.001`.
|
||||
|
||||
## 15. Sizing / forecast
|
||||
|
||||
| Tranche | Objectif borné |
|
||||
|-----------|------------------------------------------------------------------------------------------------------|
|
||||
| `pre.001` | audit, route model, external re-audit, sizing, plan/validation |
|
||||
| `pre.002` | Transport : capability WS typed par subscription + tests, sans app |
|
||||
| `pre.003` | Config : schema/mapping capabilities WS + composite/profils Raw Ingest Desk |
|
||||
| `pre.004` | Worker : enforcement des capabilities WS déclarées + canaris route constructors |
|
||||
| `pre.005` | scaffold `ksp-app-raw-transaction-ingest-desk`, gabarit KSP, DTO/route IDs/states, sans Start Worker |
|
||||
| `pre.006` | Config -> inventaire de routes composables/non composables + raisons sûres |
|
||||
| `pre.007` | reconstruction/revalidation Start des ressources Transport pour les cinq routes, sans launch Worker |
|
||||
| `pre.008` | Store lifecycle + Start/Stop mono-route réel |
|
||||
| `pre.009` | multi-route : un Worker par route, même Store, isolation des faults |
|
||||
| `pre.010` | snapshots/events/monitoring lifecycle-health-activity-backpressure-reconnect-replay-gaps-repair |
|
||||
| `pre.011` | frontend fonctionnel complet + tracing TypeScript sûr |
|
||||
| `pre.012` | races, shutdown app, sécurité IPC, hardening hostile/stale inventory |
|
||||
| `pre.013` | cross-layer completeness + canaris système sans expansion de frontières |
|
||||
| `pre.014` | gate technique/live accessible + frontend/Tauri + build final de validation technique |
|
||||
| `pre.015` | réconciliation documentaire finale : plan/validation/README/USAGE |
|
||||
| `pre.016` | préparation publication minimale : prompt suivant + CHANGELOG + ROADMAP |
|
||||
| `rel.001` | mécanique stable uniquement, aucun rattrapage fonctionnel |
|
||||
|
||||
Le forecast initial du prompt n'est pas recopié : trois tranches lower-layer précèdent volontairement le scaffold UI.
|
||||
|
||||
## 16. Modifications `pre.001`
|
||||
|
||||
Ajouts :
|
||||
|
||||
```text
|
||||
docs/plans/036-V0_3_15_RAW_TRANSACTION_INGEST_DESK_PLAN.md
|
||||
docs/validation/032-V0_3_15_RAW_TRANSACTION_INGEST_DESK.md
|
||||
deltas/0.3.15/pre.001.md
|
||||
```
|
||||
|
||||
Modification :
|
||||
|
||||
```text
|
||||
Cargo.toml
|
||||
header 593 -> 594
|
||||
workspace.package.version 0.3.14 -> 0.3.15-pre.1
|
||||
```
|
||||
|
||||
Aucun fichier de production Rust, Config, frontend ou Tauri n'est modifié par le gate.
|
||||
|
||||
## 17. Validations post-modification
|
||||
|
||||
Exécuté localement après le bump et l’ajout des trois livrables :
|
||||
|
||||
```bash
|
||||
python3 scripts/audit_rust_workspace_rules.py
|
||||
```
|
||||
|
||||
Résultat :
|
||||
|
||||
```text
|
||||
General Rust rule audit: clean
|
||||
Rust export completeness audit: 0 candidate(s)
|
||||
KSP workspace Rust rule audit: clean
|
||||
```
|
||||
|
||||
Exécuté localement :
|
||||
|
||||
```bash
|
||||
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas
|
||||
```
|
||||
|
||||
Résultat :
|
||||
|
||||
```text
|
||||
Markdown table audit: clean (354 table(s), 889 file(s))
|
||||
```
|
||||
|
||||
Contrôles complémentaires :
|
||||
|
||||
```text
|
||||
rule definitions : 489
|
||||
unique rule IDs : 489
|
||||
duplicates : 0
|
||||
stable -> worktree : 3 additions / 1 modification / 0 deletion
|
||||
modified stable file : Cargo.toml seulement
|
||||
```
|
||||
|
||||
Non exécuté localement :
|
||||
|
||||
```text
|
||||
cargo fmt --all -- --check : NON EXÉCUTÉ — cargo absent du sandbox
|
||||
cargo check --workspace : NON EXÉCUTÉ — cargo absent du sandbox
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings : NON EXÉCUTÉ — cargo absent du sandbox
|
||||
cargo test : NON EXÉCUTÉ — cargo absent du sandbox
|
||||
```
|
||||
|
||||
Aucun de ces gates Cargo n’est déclaré PASS. Ils restent dans le gate opérateur après application du delta.
|
||||
Reference in New Issue
Block a user