v0.3.9-pre.001
This commit is contained in:
567
docs/plans/030-V0_3_9_WORKER_API_RAW_TRANSACTION_AUDIT_PLAN.md
Normal file
567
docs/plans/030-V0_3_9_WORKER_API_RAW_TRANSACTION_AUDIT_PLAN.md
Normal file
@@ -0,0 +1,567 @@
|
||||
<!-- file: docs/plans/030-V0_3_9_WORKER_API_RAW_TRANSACTION_AUDIT_PLAN.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Plan v0.3.9 — Worker API générique + audit RAW Transaction
|
||||
|
||||
## 1. But de la version
|
||||
|
||||
La version `0.3.9` a deux responsabilités successives et volontairement séparées :
|
||||
|
||||
```text
|
||||
1. stabiliser ksp-worker-api comme lifecycle API générique de services continus ;
|
||||
2. seulement après sa freeze fonctionnelle, auditer exhaustivement les voies d’acquisition RawTransaction afin de préparer 0.3.10.
|
||||
```
|
||||
|
||||
Aucun besoin Solana, provider, Store, endpoint, replay ou backfill ne doit influencer le contrat générique de `ksp-worker-api` avant sa freeze.
|
||||
|
||||
## 2. Base autoritaire et vérification d’ouverture
|
||||
|
||||
Base fournie et vérifiée le 4 septembre 2026 :
|
||||
|
||||
```text
|
||||
archive KSP : khadhroony-solana-project-v0.3.8.zip
|
||||
workspace.package.version : 0.3.8
|
||||
delta stable : deltas/0.3.8/rel.001.md
|
||||
prompt : prompts/028-V0_3_9_START_PROMPT.md
|
||||
```
|
||||
|
||||
Preuves d’archive :
|
||||
|
||||
```text
|
||||
KSP SHA-256 = b3a34a3dfd56fac1eef3d23f13631ff001338b612834488038cf259112c63624
|
||||
KSP entries = 1809
|
||||
KSP raw bytes = 19667131
|
||||
KSP unzip -t = PASS
|
||||
|
||||
kbot3 SHA-256 = ee47643b9f8b582ee8db97b2381ec107e45aef8c009fee44757531514615d318
|
||||
kbot3 entries = 2501
|
||||
kbot3 raw bytes = 37467702
|
||||
kbot3 unzip -t = PASS
|
||||
```
|
||||
|
||||
Les deux ZIP ont été contrôlés sans entrée absolue, traversal, lien symbolique, `target/`, `node_modules/`, `.git/`, `Cargo.lock` ou `.env` livré.
|
||||
|
||||
Le ZIP stable ne contient volontairement pas les métadonnées Git ; le tag `v0.3.8` n’est donc pas réinspectable depuis `.git`. La base est néanmoins admissible selon le prompt car l’opérateur l’a fournie explicitement comme archive stable, sa version Cargo vaut `0.3.8` et son `rel.001` exige puis décrit le tag stable `v0.3.8`.
|
||||
|
||||
### 2.1 Membres structurants confirmés
|
||||
|
||||
```text
|
||||
ksp-app-store-desk
|
||||
ksp-job-api
|
||||
ksp-job-backfill-lib
|
||||
ksp-onchain-transport-lib
|
||||
ksp-config-lib
|
||||
ksp-store-api
|
||||
ksp-store-lib
|
||||
ksp-store-postgres-lib
|
||||
```
|
||||
|
||||
Le workspace stable comporte 18 membres et ne contient pas encore `ksp-worker-api`.
|
||||
|
||||
### 2.2 Baseline locale avant modification
|
||||
|
||||
Exécuté sur l’archive KSP inchangée :
|
||||
|
||||
```text
|
||||
python3 scripts/audit_rust_workspace_rules.py
|
||||
General Rust rule audit: clean
|
||||
Rust export completeness audit: 0 candidate(s)
|
||||
KSP workspace Rust rule audit: clean
|
||||
|
||||
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas
|
||||
Markdown table audit: clean (316 table(s), 725 file(s))
|
||||
```
|
||||
|
||||
Le binaire `cargo` n’est pas installé dans l’environnement d’assemblage. Les commandes Cargo de baseline, dont `cargo fmt --all -- --check`, `cargo check --workspace`, `cargo clippy --workspace --all-targets` et `cargo tree -p ksp-job-api`, sont donc **non exécutées ici et non déclarées PASS**. La preuve stable du delta `0.3.8-rel.001` rappelle qu’un gate opérateur complet avait été fermé en amont ; elle ne remplace pas une exécution locale de cette session.
|
||||
|
||||
## 3. Sources internes lues avant décision
|
||||
|
||||
Les règles et architectures demandées par le prompt ont été auditées avant la présente planification :
|
||||
|
||||
```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
|
||||
|
||||
docs/architecture/000-README.md
|
||||
docs/architecture/002-LAYERS_AND_DEPENDENCIES.md
|
||||
docs/architecture/003-COMPONENT_CONTRACTS.md
|
||||
docs/architecture/004-COMPONENT_INVENTORY.md
|
||||
docs/architecture/005-DEPENDENCY_GRAPH.md
|
||||
docs/architecture/009-ACQUISITION_WORKERS_AND_JOBS.md
|
||||
docs/architecture/010-APPS_SERVICES_SCENARIOS_AND_CONTROL.md
|
||||
|
||||
ksp-job-api manifest/README/USAGE/src/tests
|
||||
docs/plans/027-V0_3_6_JOB_API_BACKFILL_PLAN.md
|
||||
docs/validation/023-V0_3_6_JOB_API_BACKFILL.md
|
||||
|
||||
ksp-job-backfill-lib README/USAGE/src/tests
|
||||
ksp-app-backfill-desk README/USAGE
|
||||
docs/plans/028-V0_3_7_BACKFILL_DESK_PLAN.md
|
||||
docs/validation/024-V0_3_7_BACKFILL_DESK.md
|
||||
```
|
||||
|
||||
Les headers/version des fichiers normatifs et architecturaux exigés sont présents et cohérents. Aucun document stable antérieur n’est modifié dans `pre.001`.
|
||||
|
||||
## 4. Frontière Worker / Job décidée
|
||||
|
||||
Règle sémantique de base :
|
||||
|
||||
```text
|
||||
Job = traitement borné/terminable, fin normale et outcome attendus.
|
||||
Worker = service continu, Running peut durer indéfiniment, arrêt normal sans notion de completion.
|
||||
```
|
||||
|
||||
`ksp-job-api` est une référence de **propriétés déjà prouvées**, pas un parent nominal de Worker et pas une dépendance.
|
||||
|
||||
| Concept Job audité | Propriété générique | Décision Worker API | Motif |
|
||||
|---------------------------|-----------------------------------------|---------------------------------|--------------------------------------------------------|
|
||||
| JobId borné | oui | WorkerId propre | même propriété, identité sémantiquement distincte |
|
||||
| JobKindCode borné | oui | WorkerKindCode propre | famille stable utile au contrôle sans dépendre de Job |
|
||||
| Created | oui | WorkerState::Created | état passif avant démarrage |
|
||||
| Running | oui | WorkerState::Running | un Worker peut y rester indéfiniment |
|
||||
| Cancelling | non nominalement | WorkerState::Stopping | un service s’arrête, il ne termine pas un Job annulé |
|
||||
| Completed + JobCompletion | non | interdit | un Worker continu n’a pas de completion normale |
|
||||
| Cancelled | non | WorkerState::Stopped | arrêt normal distinct d’une annulation de traitement |
|
||||
| Failed | partiellement | WorkerState::Faulted(ErrorCode) | fault terminal avec diagnostic statique sûr |
|
||||
| Cancellation token | oui conceptuellement | WorkerStopToken | intention coopérative partagée et idempotente |
|
||||
| Notification générique S | latest-value oui, payload générique non | WorkerSnapshot fixe | évite payload arbitraire et simplifie le control plane |
|
||||
| Sequence monotone | oui | WorkerSnapshotSequence | resynchronisation sans queue |
|
||||
| SnapshotSource | oui | WorkerSnapshotSource | lecture current + wait_for_change runtime-neutral |
|
||||
| Terminal immuable | oui | retenu | ancien handle/source ne peut pas être réactivé |
|
||||
| Checkpoint / resume | non | interdit | spécifique aux Jobs/backfills |
|
||||
| Outcome / résultat | non | interdit | spécifique à un traitement terminable |
|
||||
| Core-only | oui | retenu | API passive et dependency firewall minimal |
|
||||
|
||||
Conséquence : une duplication limitée de petites primitives (`WorkerId`, séquence, token stop) est intentionnelle. Elle maintient deux vocabulaires de lifecycle indépendants et évite qu’une future évolution Job force Worker ou inversement.
|
||||
|
||||
## 5. Surface publique Worker API prévue
|
||||
|
||||
`pre.002` doit ouvrir uniquement le noyau suivant, sous réserve d’un défaut réel découvert lors de sa matérialisation :
|
||||
|
||||
```text
|
||||
WorkerId
|
||||
WorkerKindCode
|
||||
MAX_WORKER_ID_BYTES = 128
|
||||
MAX_WORKER_KIND_CODE_BYTES = 128
|
||||
|
||||
WorkerState
|
||||
WorkerHealth
|
||||
WorkerActivity
|
||||
WorkerLifecycle
|
||||
|
||||
WorkerStopToken
|
||||
|
||||
WorkerSnapshotSequence
|
||||
WorkerSnapshot
|
||||
WorkerSnapshotFuture<'a>
|
||||
WorkerSnapshotSource
|
||||
|
||||
ERROR_CODE_WORKER_ID_INVALID
|
||||
ERROR_CODE_WORKER_KIND_INVALID
|
||||
ERROR_CODE_WORKER_TRANSITION_INVALID
|
||||
ERROR_CODE_WORKER_SNAPSHOT_SEQUENCE_EXHAUSTED
|
||||
|
||||
reexports Core : Error, ErrorCode, ErrorContext, Result
|
||||
```
|
||||
|
||||
Modules de production prévus :
|
||||
|
||||
```text
|
||||
src/lib.rs
|
||||
src/error.rs
|
||||
src/identity.rs
|
||||
src/lifecycle.rs
|
||||
src/snapshot.rs
|
||||
src/stop.rs
|
||||
```
|
||||
|
||||
La façade reste crate-root ; aucun `pub mod`.
|
||||
|
||||
### 5.1 Identité
|
||||
|
||||
`WorkerId` et `WorkerKindCode` utilisent un contrat borné analogue dans ses propriétés à Job mais avec leurs propres types :
|
||||
|
||||
```text
|
||||
non vide
|
||||
maximum 128 octets
|
||||
alphabet ASCII sûr : A-Z a-z 0-9 _ - . :
|
||||
aucun slash, whitespace ou Unicode libre
|
||||
WorkerId Debug = redacted
|
||||
WorkerKindCode Debug = valeur validée sûre
|
||||
```
|
||||
|
||||
`WorkerId` identifie l’instance logique observée par un lifecycle/source donné. La V1 ne définit aucune notion de génération/restart et ne rebinde jamais un ancien handle/source terminal vers une nouvelle exécution.
|
||||
|
||||
## 6. Lifecycle exact retenu
|
||||
|
||||
États :
|
||||
|
||||
```text
|
||||
Created
|
||||
Starting
|
||||
Running
|
||||
Stopping
|
||||
Stopped
|
||||
Faulted(ErrorCode)
|
||||
```
|
||||
|
||||
| État source | Transitions autorisées | Transitions interdites notables |
|
||||
|---------------|----------------------------------|-----------------------------------|
|
||||
| Created | Starting, Stopped | Running direct, Stopping, Faulted |
|
||||
| Starting | Running, Stopping, Faulted(code) | Stopped direct, Created |
|
||||
| Running | Stopping, Faulted(code) | Starting, Stopped direct |
|
||||
| Stopping | Stopped, Faulted(code) | Running, Starting |
|
||||
| Stopped | aucune | toutes |
|
||||
| Faulted(code) | aucune | toutes |
|
||||
|
||||
Décisions :
|
||||
|
||||
- `Created -> Stopped` représente un arrêt demandé avant démarrage effectif ;
|
||||
- `Starting` et `Stopping` sont nécessaires parce que start/shutdown peuvent avoir une durée non nulle ;
|
||||
- `Running` n’a aucune notion de completion ;
|
||||
- `Faulted(ErrorCode)` ne conserve qu’un identifiant d’erreur KSP statique, jamais un message arbitraire ni un `Box<dyn Error>` ;
|
||||
- `Stopped` et `Faulted` sont terminaux et immuables ;
|
||||
- `WorkerLifecycle` est producteur-owned et non cloneable ; les clones éventuels concernent le token de stop et la source de snapshot, pas l’autorité de transition ;
|
||||
- une transition invalide retourne une erreur stable et laisse l’état inchangé ;
|
||||
- les appels lifecycle répétés ne sont pas silencieusement idempotents : l’idempotence appartient à l’intention de stop, pas à la state machine.
|
||||
|
||||
### 6.1 Race stop / fault
|
||||
|
||||
Le modèle ne crée pas de mutation concurrente de `WorkerLifecycle`. Le runtime concret possède une seule autorité de transition et arbitre les événements. Les ordres légaux sont explicitement testables :
|
||||
|
||||
```text
|
||||
Running -> Faulted => terminal Faulted, stop lifecycle ultérieur rejeté
|
||||
Running -> Stopping -> Faulted => terminal Faulted, Stopped ultérieur rejeté
|
||||
Running -> Stopping -> Stopped => terminal Stopped, Faulted ultérieur rejeté
|
||||
```
|
||||
|
||||
Le premier état terminal **validement enregistré** gagne. Un `WorkerStopToken` demandé après terminal peut conserver l’intention atomique mais ne réanime ni ne transforme l’état terminal.
|
||||
|
||||
## 7. Health et activity
|
||||
|
||||
`health` est distinct du lifecycle. Il décrit la qualité opérationnelle observée, pas la phase du service :
|
||||
|
||||
```text
|
||||
WorkerHealth::Unknown
|
||||
WorkerHealth::Healthy
|
||||
WorkerHealth::Degraded
|
||||
WorkerHealth::Unhealthy
|
||||
```
|
||||
|
||||
`activity` est volontairement plus faible qu’un progrès de Job :
|
||||
|
||||
```text
|
||||
WorkerActivity::Unknown
|
||||
WorkerActivity::Idle
|
||||
WorkerActivity::Active
|
||||
```
|
||||
|
||||
Aucun `current/total`, pourcentage, ETA, compteur métier, slot, signature, backlog ou débit n’entre dans Worker API. Un worker concret peut publier ses métriques métier via sa propre API/snapshot sans les injecter dans le snapshot commun.
|
||||
|
||||
Le lifecycle reste autoritaire pour savoir si le service est terminal ; health/activity ne doivent jamais être interprétés comme une seconde state machine.
|
||||
|
||||
## 8. Snapshot latest-value décidé
|
||||
|
||||
Contrairement à `JobNotification<S>`, Worker V1 retient un snapshot **fixe et non générique** afin que le control plane puisse lire la même forme pour tous les workers et afin d’empêcher un payload arbitraire dans le contrat commun.
|
||||
|
||||
`WorkerSnapshot` contient uniquement :
|
||||
|
||||
```text
|
||||
WorkerId
|
||||
WorkerKindCode
|
||||
WorkerSnapshotSequence
|
||||
WorkerState
|
||||
WorkerHealth
|
||||
WorkerActivity
|
||||
```
|
||||
|
||||
Aucune `String` diagnostique libre, aucun provider, endpoint, payload, transaction, slot, Store reference ou secret.
|
||||
|
||||
### 8.1 Séquence
|
||||
|
||||
`WorkerSnapshotSequence` :
|
||||
|
||||
```text
|
||||
initial = 0
|
||||
next = checked_add(1)
|
||||
aucun wrap silencieux
|
||||
is_after(observed) pour la resynchronisation
|
||||
```
|
||||
|
||||
Toute modification publiée du snapshot commun avance la séquence exactement une fois. Le détail de stockage/wakeup reste au runtime concret.
|
||||
|
||||
### 8.2 Source
|
||||
|
||||
Contrat prévu :
|
||||
|
||||
```text
|
||||
trait WorkerSnapshotSource: Send + Sync
|
||||
current() -> WorkerSnapshot
|
||||
wait_for_change(observed: WorkerSnapshotSequence) -> WorkerSnapshotFuture<'_>
|
||||
```
|
||||
|
||||
Le trait doit être object-safe pour permettre `&dyn WorkerSnapshotSource` ou une composition équivalente sans imposer Tokio.
|
||||
|
||||
Sémantique latest-value :
|
||||
|
||||
```text
|
||||
pas de queue d’événements
|
||||
pas de callback producteur
|
||||
les updates intermédiaires peuvent être coalescées
|
||||
un listener lent reçoit le snapshot courant le plus récent
|
||||
plusieurs listeners restent indépendants
|
||||
un listener tardif commence par current()
|
||||
le snapshot terminal reste lisible tant que la source existe
|
||||
```
|
||||
|
||||
Un appel `wait_for_change` n’est attendu qu’après inspection de `current()` et ne doit pas produire de boucle artificielle sur une séquence terminale déjà observée.
|
||||
|
||||
## 9. Stop coopératif
|
||||
|
||||
`WorkerStopToken` est une primitive runtime-neutral cloneable fondée sur une intention atomique :
|
||||
|
||||
```text
|
||||
request_stop() -> true uniquement pour la première demande partagée
|
||||
is_stop_requested() -> bool
|
||||
```
|
||||
|
||||
La demande est bornée au sens API : opération atomique locale, non bloquante, sans attente réseau/process/thread. Elle **ne garantit pas** que le worker concret s’arrête dans un délai donné. Timeout, drain, join, retry et politique de shutdown appartiennent au runtime/caller.
|
||||
|
||||
Le token ne modifie pas directement `WorkerLifecycle`; le producteur observe l’intention puis publie `Stopping`/terminal selon sa politique concrète.
|
||||
|
||||
## 10. Restart et supervision
|
||||
|
||||
La V1 ne contient pas :
|
||||
|
||||
```text
|
||||
restart()
|
||||
restart policy
|
||||
retry/backoff policy
|
||||
scheduler
|
||||
process manager
|
||||
remote protocol
|
||||
registry global
|
||||
WorkerHandle générique possédant le runtime
|
||||
```
|
||||
|
||||
Restart/recreate appartient au caller ou au futur `ksp-worker-control-lib`. Un lifecycle/source terminal ne redevient jamais Running et n’est jamais rebinding vers une nouvelle instance. Cette règle ferme la race « old handle observes a restarted worker » sans introduire prématurément une génération globale.
|
||||
|
||||
Un futur control plane peut composer les primitives `WorkerId`/kind/snapshot/stop avec ses propres factories et règles de remplacement.
|
||||
|
||||
## 11. Dépendances exactes
|
||||
|
||||
Cible décidée :
|
||||
|
||||
```text
|
||||
ksp-worker-api -> ksp-core-lib
|
||||
```
|
||||
|
||||
| Dépendance | Statut prévu | Justification |
|
||||
|-------------------------------|--------------|---------------------------------------------------------------|
|
||||
| ksp-core-lib | REQUISE | Error, ErrorCode, ErrorContext et Result communs |
|
||||
| ksp-job-api | INTERDITE | lifecycle Job distinct ; réutilisation seulement conceptuelle |
|
||||
| ksp-interface-lib | INTERDITE | aucun événement wire/domain requis |
|
||||
| ksp-config-lib | INTERDITE | Config/secrets hors API passive |
|
||||
| ksp-logging-lib | INTERDITE | aucun comportement runtime à instrumenter |
|
||||
| ksp-onchain-transport-lib | INTERDITE | aucun transport dans le contrat Worker |
|
||||
| ksp-store-api / ksp-store-lib | INTERDITES | aucune persistence dans le lifecycle commun |
|
||||
| tokio / futures | INTERDITES | std::future suffit au contrat d’attente abstrait |
|
||||
| serde | INTERDITE | aucun wire/serialization commun imposé |
|
||||
| Tauri / provider SDK | INTERDITS | contrôle UI/provider hors API |
|
||||
|
||||
Le manifeste prévu ne comporte ni feature, ni dev-dependency, ni build-dependency tant qu’un besoin réel n’est pas démontré. Les tests doivent fonctionner avec `std` + dépendance normale Core.
|
||||
|
||||
## 12. Error codes et Debug
|
||||
|
||||
Domaine prévu :
|
||||
|
||||
```text
|
||||
worker_api
|
||||
```
|
||||
|
||||
Codes prévus :
|
||||
|
||||
```text
|
||||
worker_id_invalid
|
||||
worker_kind_invalid
|
||||
worker_transition_invalid
|
||||
worker_snapshot_sequence_exhausted
|
||||
```
|
||||
|
||||
Les erreurs d’identité ne recopient pas la valeur hostile dans message/context ; elles indiquent uniquement le champ fautif. Les erreurs de transition exposent seulement les codes d’état source/cible. `Faulted(ErrorCode)` expose un code statique et non une chaîne externe.
|
||||
|
||||
Debug :
|
||||
|
||||
```text
|
||||
WorkerId -> valeur masquée
|
||||
WorkerKindCode -> code sûr borné autorisé
|
||||
WorkerLifecycle -> id masqué, kind/state sûrs
|
||||
WorkerStopToken -> bool stop_requested uniquement
|
||||
WorkerSnapshot -> id masqué, autres champs statiques/bornés
|
||||
```
|
||||
|
||||
## 13. Threat map
|
||||
|
||||
| Risque | Mesure décidée | Preuve prévue |
|
||||
|-------------------------------------|------------------------------------------------------------------------|-----------------------------------|
|
||||
| queue de notifications non bornée | latest-value unique, aucun backlog événementiel dans l’API | canarie source + audit production |
|
||||
| listener lent bloque producteur | coalescing ; listener se resynchronise sur current | listeners lents/indépendants |
|
||||
| snapshot périmé | sequence monotone attachée à toute valeur publiée | late listener + is_after |
|
||||
| wrap sequence | checked_add et erreur explicite | test exhaustion |
|
||||
| stop vs fault | lifecycle producteur unique ; premier terminal valide gagne | matrice et ordres adversariaux |
|
||||
| stop répété | WorkerStopToken atomique idempotent | multi-clone / cross-thread |
|
||||
| restart réanime ancien handle | terminal immutable ; nouvelle instance/source, aucun rebind | canarie terminal + documentation |
|
||||
| fuite identité | alphabet borné ; Debug WorkerId redacted | hostile marker |
|
||||
| payload/secret dans snapshot commun | snapshot fixe sans String/payload générique | inventaire de champs + Debug |
|
||||
| erreur externe dans état | Faulted ne retient qu’un ErrorCode statique | surface publique exacte |
|
||||
| confusion health/lifecycle | dimensions séparées ; lifecycle terminal reste autoritaire | tests indépendance |
|
||||
| fausse progression finie | aucun percent/total générique ; activité Unknown/Idle/Active seulement | inventaire API |
|
||||
| contamination Solana/Store/Config | Core-only + canaries lexicales/dependencies | dependency_boundary |
|
||||
| runtime implicite | aucun spawn/thread/channel Tokio possédé par API | manifest/source firewall |
|
||||
|
||||
## 14. Tests planifiés
|
||||
|
||||
### 14.1 Unit tests
|
||||
|
||||
```text
|
||||
identity exact bounds : 0, 1, 128, 129 octets
|
||||
alphabet hostile : whitespace, slash, backslash, Unicode, control chars
|
||||
lifecycle transition matrix exhaustive
|
||||
invalid transition leaves state unchanged
|
||||
Stopped/Faulted immutable sous tous les mutateurs
|
||||
Faulted conserve uniquement ErrorCode
|
||||
stop token first-wins/idempotent/shared
|
||||
stop token Send + Sync / cross-thread
|
||||
snapshot sequence initial/next/is_after/exhaustion
|
||||
health/activity stable safe codes si helpers exposés
|
||||
Debug hostile marker absent
|
||||
```
|
||||
|
||||
### 14.2 Integration/public API
|
||||
|
||||
```text
|
||||
construction exclusivement depuis crate root
|
||||
ErrorCode constants exacts
|
||||
bounds publics exacts
|
||||
WorkerSnapshotSource implémentable depuis une crate externe
|
||||
WorkerSnapshotSource object-safe
|
||||
source custom std-only sans Tokio
|
||||
slow + independent listeners resync vers latest value
|
||||
late listener current puis wait
|
||||
terminal current reste disponible
|
||||
Send/Sync des primitives promises
|
||||
```
|
||||
|
||||
### 14.3 Dependency/release completeness
|
||||
|
||||
```text
|
||||
manifest dependency exacte = ksp-core-lib uniquement
|
||||
aucune feature/dev/build dependency
|
||||
aucun tokio/futures/serde/tracing/Tauri
|
||||
aucun ksp-job-api/Config/Interface/Transport/Store
|
||||
aucun RawTransaction/slot/provider/endpoint/backfill/checkpoint
|
||||
modules de production exacts
|
||||
exports crate-root exacts
|
||||
aucun pub mod
|
||||
```
|
||||
|
||||
Les tests ne créent aucun runtime KSP fictif. Une implémentation de test peut utiliser `std::future::ready`, `Arc` et primitives `std` uniquement.
|
||||
|
||||
## 15. Questions explicitement différées
|
||||
|
||||
Les points suivants ne bloquent pas Worker API V1 et ne doivent pas être ouverts en `pre.002` par anticipation :
|
||||
|
||||
```text
|
||||
WorkerHandle générique de start/join
|
||||
registry/factory commune
|
||||
reconfiguration live
|
||||
generation/restart identity globale
|
||||
remote proxy/protocol/IPC
|
||||
serialization du snapshot commun
|
||||
metrics/rates/counters métier universels
|
||||
control-plane persistence
|
||||
process ownership
|
||||
```
|
||||
|
||||
Ils ne deviennent candidats que lorsqu’au moins plusieurs workers ou le futur control plane prouvent un besoin transverse.
|
||||
|
||||
## 16. Audit RAW Transaction : position et owner documentaire
|
||||
|
||||
Aucune analyse fonctionnelle de kbot3 ni réaudit provider courant n’est effectué dans `pre.001`, conformément au séquencement du prompt.
|
||||
|
||||
Après freeze fonctionnelle de `ksp-worker-api` en `pre.003`, l’audit RAW est scindé pour respecter le budget de tranche. Son owner durable prévu est :
|
||||
|
||||
```text
|
||||
docs/architecture/011-RAW_TRANSACTION_ACQUISITION.md
|
||||
```
|
||||
|
||||
Ce document séparera :
|
||||
|
||||
```text
|
||||
partie durable : taxonomy capabilities/roles/combinations/convergence
|
||||
partie audit daté : disponibilité provider, quotas, replay, tiers et liens sources primaires
|
||||
handoff : gaps Transport/Config 0.3.10 et applicability Backfill 0.3.12
|
||||
```
|
||||
|
||||
Ce choix évite de transformer le plan de release en registre provider tout en donnant à `0.3.10` et `0.3.12` une référence architecturale réauditable. L’index architecture ne sera synchronisé qu’au moment où ce document sera réellement créé, puis réconcilié dans le couloir documentaire final.
|
||||
|
||||
kbot3 ne sera alors utilisé que pour inventorier des comportements historiques. Aucun code, DTO, Config, URL, dependency ou version n’en sera repris.
|
||||
|
||||
## 17. Prévision souple recalibrée
|
||||
|
||||
Le `pre.004` unique imaginé par le prompt est scindé en trois tranches d’audit/synthèse : un audit Solana/KSP, un audit provider/kbot3, puis une synthèse. Un audit externe exhaustif Solana + Helius + Yellowstone + providers + KSP + mainnet naming dans une seule tranche dépasserait vraisemblablement le budget normatif de 15-20 minutes.
|
||||
|
||||
| Tranche | Objet | Budget de planification | Sortie |
|
||||
|---------|-----------------------------------------------------------------|-------------------------|--------------------------------------------------------|
|
||||
| pre.001 | audit, architecture, threat map, plan/tests | 15-20 min | présente livraison doc-only |
|
||||
| pre.002 | crate + contrats Worker API décidés | 15-20 min | noyau + tests unit/public/dependency |
|
||||
| pre.003 | hardening, races, object-safety, impl externe, freeze | 15-20 min | Worker API fonctionnellement fermée |
|
||||
| pre.004 | audit RAW A : Solana standard + KSP Transport/Store/Config | 15-20 min | capabilities/roles/gaps internes |
|
||||
| pre.005 | audit RAW B : Helius, Yellowstone/providers + kbot3 fonctionnel | 15-20 min | preuves primaires, quotas/replay/disponibilité |
|
||||
| pre.006 | synthèse RAW multi-source + handoff 0.3.10/0.3.12 | 15-20 min | matrice finale, combinaisons, gaps et stratégie réseau |
|
||||
| pre.007 | gate technique final | 10-15 min | workspace/worker-api/trees/duplicates verts |
|
||||
| pre.008 | réconciliation documentaire finale | 10-15 min | README/USAGE/plan/validation/architecture cohérents |
|
||||
| pre.009 | préparation de publication | 5-10 min | prompt 0.3.10 + CHANGELOG + ROADMAP + Cargo + delta |
|
||||
| rel.001 | publication mécanique stable | 5-10 min | v0.3.9 sans rattrapage |
|
||||
|
||||
Les numéros restent souples. Un défaut réel peut ouvrir `pre.NNN-fix.MMM` dans le même couloir ou forcer un split supplémentaire. Les responsabilités `gate technique -> réconciliation documentaire -> préparation de publication` restent séparées.
|
||||
|
||||
## 18. Versioning de `pre.001`
|
||||
|
||||
La présente tranche est strictement documentaire : nouveau plan, nouvelle validation et nouveau delta. Elle ne modifie aucun code/build/runtime/configuration et conserve donc explicitement :
|
||||
|
||||
```text
|
||||
workspace.package.version = 0.3.8
|
||||
```
|
||||
|
||||
Cette exception de démarrage est explicitement autorisée par le prompt 028 et cohérente avec `VER-ID-008`. Le premier changement Rust de `pre.002` portera la version technique correspondant à sa livraison selon le workflow KSP.
|
||||
|
||||
## 19. Gate de sortie `pre.001`
|
||||
|
||||
La tranche est fermée architecturalement lorsque les points suivants sont présents dans le plan/validation :
|
||||
|
||||
```text
|
||||
architecture Worker API décidée
|
||||
state/health/activity/snapshot/stop décidés
|
||||
surface publique prévue
|
||||
Core-only exact dependency map
|
||||
questions différées listées
|
||||
threat map
|
||||
plan de tests
|
||||
prévision souple recalibrée
|
||||
audit RAW positionné après freeze Worker API
|
||||
aucun code worker concret commencé
|
||||
```
|
||||
|
||||
Les gates Cargo restent à exécuter par l’opérateur dans un environnement Rust. Leur absence locale n’est pas masquée par les audits Python.
|
||||
204
docs/validation/026-V0_3_9_WORKER_API_RAW_TRANSACTION_AUDIT.md
Normal file
204
docs/validation/026-V0_3_9_WORKER_API_RAW_TRANSACTION_AUDIT.md
Normal file
@@ -0,0 +1,204 @@
|
||||
<!-- file: docs/validation/026-V0_3_9_WORKER_API_RAW_TRANSACTION_AUDIT.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Validation v0.3.9 — Worker API + audit RAW Transaction
|
||||
|
||||
## 1. Objet
|
||||
|
||||
Cette matrice suit les preuves de `0.3.9` sans remplacer les deltas. `pre.001` ferme seulement le cadrage architectural ; les preuves Rust et l’audit externe RAW restent ouverts jusqu’à leurs tranches dédiées.
|
||||
|
||||
## 2. Gate d’ouverture `pre.001`
|
||||
|
||||
- [X] Archive KSP fournie explicitement comme stable `v0.3.8`.
|
||||
- [X] SHA-256 KSP : `b3a34a3dfd56fac1eef3d23f13631ff001338b612834488038cf259112c63624`.
|
||||
- [X] `unzip -t` KSP intégral propre.
|
||||
- [X] 1 809 entrées KSP contrôlées sans traversal/absolu/symlink/artefact interdit.
|
||||
- [X] `workspace.package.version = 0.3.8`.
|
||||
- [X] `deltas/0.3.8/rel.001.md` présent.
|
||||
- [X] 18 membres workspace inventoriés ; Store Desk, Job, Transport, Config et Store requis présents.
|
||||
- [X] Archive kbot3 SHA-256 `ee47643b9f8b582ee8db97b2381ec107e45aef8c009fee44757531514615d318` et `unzip -t` propre.
|
||||
- [X] kbot3 **non inspecté fonctionnellement** pendant la conception Worker API ; usage réservé à l’audit RAW après freeze.
|
||||
- [X] Règles normatives et architectures obligatoires du prompt lues avant décision.
|
||||
- [X] Headers/version des documents obligatoires confirmés.
|
||||
- [X] `ksp-job-api` manifest/src/tests et plan/validation `0.3.6` audités comme référence de propriétés.
|
||||
- [X] `ksp-job-backfill-lib` et Backfill Desk audités comme contraste API générique / consumer concret.
|
||||
- [X] Audit Rust Python baseline : clean, export completeness 0, KSP workspace clean.
|
||||
- [X] Audit Markdown baseline : clean, 316 tables / 725 fichiers.
|
||||
- [ ] `cargo fmt --all -- --check` local : non exécuté, `cargo` absent.
|
||||
- [ ] `cargo check --workspace` local : non exécuté, `cargo` absent.
|
||||
- [ ] `cargo clippy --workspace --all-targets` local : non exécuté, `cargo` absent.
|
||||
- [ ] `cargo tree -p ksp-job-api --edges normal` local : non exécuté, `cargo` absent ; manifest statique Core-only confirmé séparément.
|
||||
|
||||
### Audit post-documentation `pre.001`
|
||||
|
||||
- [X] Audit Rust post-modification : General clean, export completeness 0, KSP workspace clean.
|
||||
- [X] Audit Markdown post-modification : clean, 321 tables / 728 fichiers.
|
||||
- [X] Diff byte-level contre le ZIP stable : trois ajouts, zéro modification, zéro suppression après retrait des artefacts ignorés.
|
||||
- [X] `Cargo.toml` reste byte-identique à la base et `workspace.package.version = 0.3.8`.
|
||||
|
||||
Le ZIP ne contient pas `.git`; l’existence du tag n’est pas inspectée directement. Le `rel.001` stable décrit l’opération `tag v0.3.8` et le prompt autorise l’archive stable explicitement fournie comme base.
|
||||
|
||||
## 3. Architecture Worker API décidée en `pre.001`
|
||||
|
||||
- [X] Job et Worker restent deux lifecycle APIs sémantiquement distinctes.
|
||||
- [X] Aucun edge `ksp-worker-api -> ksp-job-api`.
|
||||
- [X] Dependency cible exacte : `ksp-worker-api -> ksp-core-lib` uniquement.
|
||||
- [X] `WorkerId` et `WorkerKindCode` propres, 128 octets max, alphabet sûr.
|
||||
- [X] States retenus : Created, Starting, Running, Stopping, Stopped, Faulted(ErrorCode).
|
||||
- [X] Stopped et Faulted terminaux/immutables.
|
||||
- [X] Health distinct : Unknown, Healthy, Degraded, Unhealthy.
|
||||
- [X] Activity générique minimale : Unknown, Idle, Active.
|
||||
- [X] Aucun progress `current/total`, pourcentage, ETA ou métrique métier dans l’API commune.
|
||||
- [X] Snapshot commun fixe, non générique, sans payload arbitraire.
|
||||
- [X] Snapshot fields limités à identity/kind/sequence/state/health/activity.
|
||||
- [X] Latest-value retenu : current + wait_for_change + coalescing + resync.
|
||||
- [X] Sequence monotone checked, exhaustion explicite.
|
||||
- [X] `WorkerSnapshotSource` prévu `Send + Sync` et object-safe sans Tokio.
|
||||
- [X] `WorkerStopToken` coopératif, partagé, idempotent, non bloquant.
|
||||
- [X] Stop token ne possède ni timeout, ni join, ni runtime.
|
||||
- [X] Fault public ne conserve qu’un `ErrorCode` statique.
|
||||
- [X] Restart/retry/factory/control plane explicitement caller-owned et différés.
|
||||
- [X] Ancien lifecycle/source terminal jamais rebinding vers une nouvelle instance.
|
||||
- [X] Aucun WorkerHandle générique imposé en V1.
|
||||
- [X] Aucun type transaction/slot/provider/endpoint/Store/replay/backfill/checkpoint dans la surface prévue.
|
||||
|
||||
## 4. Surface et hardening à matérialiser
|
||||
|
||||
### `pre.002`
|
||||
|
||||
- [ ] `crates/ksp-worker-api` créée dans le workspace.
|
||||
- [ ] Manifest sans feature/dev/build dependency et avec Core uniquement.
|
||||
- [ ] `identity.rs`, `error.rs`, `lifecycle.rs`, `snapshot.rs`, `stop.rs`, `lib.rs` matérialisés.
|
||||
- [ ] Façade crate-root uniquement, aucun `pub mod`.
|
||||
- [ ] Quatre error codes stables `worker_api` matérialisés.
|
||||
- [ ] Bounds exacts identity testés.
|
||||
- [ ] Lifecycle transition matrix exacte testée.
|
||||
- [ ] Transition invalide conserve l’état source.
|
||||
- [ ] Stop token idempotent/shared testée.
|
||||
- [ ] Snapshot sequence/exhaustion testée.
|
||||
- [ ] Public API consumer depuis crate root testée.
|
||||
- [ ] Dependency firewall initial testée.
|
||||
|
||||
### `pre.003`
|
||||
|
||||
- [ ] Stop-vs-fault ordres adversariaux couverts.
|
||||
- [ ] Tous mutateurs refusent Stopped/Faulted.
|
||||
- [ ] Debug hostile identity redacted.
|
||||
- [ ] Snapshot ne contient aucun payload/string libre.
|
||||
- [ ] Stop token `Send + Sync` prouvé cross-thread.
|
||||
- [ ] `WorkerSnapshotSource: Send + Sync` prouvé.
|
||||
- [ ] `WorkerSnapshotSource` object-safe prouvé avec trait object.
|
||||
- [ ] Implémentation externe std-only compilée/testée.
|
||||
- [ ] Listeners lents indépendants resynchronisés vers latest value.
|
||||
- [ ] Late listener `current()` + séquence validés.
|
||||
- [ ] Snapshot terminal reste lisible.
|
||||
- [ ] Exact module inventory prouvé.
|
||||
- [ ] Exact crate-root export inventory prouvé.
|
||||
- [ ] Production sources sans Job/Config/Interface/Transport/Store/Tokio/futures/serde/Tauri/Solana.
|
||||
- [ ] Worker API déclarée fonctionnellement frozen avant tout audit RAW détaillé.
|
||||
|
||||
## 5. Threat model à fermer
|
||||
|
||||
- [X] Queue non bornée évitée architecturalement par latest-value.
|
||||
- [X] Slow-listener blocking évité architecturalement par coalescing/resync.
|
||||
- [X] Stale snapshot couvert par sequence monotone.
|
||||
- [X] Sequence wrap prévu comme erreur explicite.
|
||||
- [X] Stop répété couvert par token first-wins.
|
||||
- [X] Stop/fault terminal défini par first valid terminal transition.
|
||||
- [X] Old-handle/restart fermé par immutabilité + no rebind.
|
||||
- [X] Identity/log leakage réduit par bornes + Debug redaction.
|
||||
- [X] Arbitrary payload dans snapshot commun interdit par forme fixe.
|
||||
- [X] External error payload dans état interdit ; ErrorCode only.
|
||||
- [X] Health/lifecycle séparés.
|
||||
- [X] Fausse notion de completion/progress Worker interdite.
|
||||
- [X] Runtime ownership reste hors API.
|
||||
- [ ] Canaries Rust correspondantes exécutées après matérialisation.
|
||||
|
||||
## 6. Audit RAW Transaction post-freeze
|
||||
|
||||
Aucun item ci-dessous n’est déclaré exécuté en `pre.001`.
|
||||
|
||||
### `pre.004` — Solana standard + KSP
|
||||
|
||||
- [ ] Réaudit Solana JSON-RPC HTTP primaire.
|
||||
- [ ] Réaudit Solana WebSocket primaire.
|
||||
- [ ] Capabilities KSP Transport réellement publiques inventoriées.
|
||||
- [ ] Store RAW identity/content/provenance réconfirmés.
|
||||
- [ ] Config/secrets/network descriptors inventoriés pour handoff uniquement.
|
||||
- [ ] HTTP discovery/hydration roles classifiés.
|
||||
- [ ] WS logs/signature/block roles classifiés.
|
||||
- [ ] Live/catch-up/gap-repair/history applicability documentée.
|
||||
- [ ] `mainnet` / `mainnet-beta` audit interne commencé sans migration.
|
||||
|
||||
### `pre.005` — providers + kbot3 historique
|
||||
|
||||
- [ ] Helius HTTP standard Mainnet/Devnet réaudité sur sources officielles courantes.
|
||||
- [ ] Helius WS standard Mainnet/Devnet réaudité.
|
||||
- [ ] Helius transactionSubscribe/extensions réaudités séparément avec tier courant.
|
||||
- [ ] Yellowstone upstream transactions/transaction_status/blocks/block_meta réaudité.
|
||||
- [ ] Replay/from_slot réellement supporté classifié provider par provider.
|
||||
- [ ] Quotas/filter/subscription/reconnect limits sourcés.
|
||||
- [ ] Providers supplémentaires pertinents réaudités uniquement sur docs officielles.
|
||||
- [ ] kbot3 réaudité fonctionnellement : acquisition/live/history/recovery/fallback/provenance.
|
||||
- [ ] Aucun code/DTO/URL/Config/dependency kbot3 repris.
|
||||
|
||||
### `pre.006` — synthèse et handoff
|
||||
|
||||
- [ ] Matrice complète des dimensions imposées par le prompt 028.
|
||||
- [ ] Alternatives/complements/redundancy/specialization classifiés.
|
||||
- [ ] Discovery + hydration distingués des streams full transaction.
|
||||
- [ ] Dedup content vs observations de provenance explicitée.
|
||||
- [ ] Stratégie multi-source V1 `0.3.10` proposée sans enum protocole simpliste.
|
||||
- [ ] Gaps Transport `0.3.10` listés, non implémentés en `0.3.9`.
|
||||
- [ ] Gaps Config `0.3.10` listés, aucun nouvel endpoint ajouté en `0.3.9`.
|
||||
- [ ] Réutilisation unique `KSP_SECRET_HELIUS_API_KEY` confirmée.
|
||||
- [ ] Stratégie compatible `mainnet` / `mainnet-beta` conclue.
|
||||
- [ ] Applicability `0.3.12` Backfill indiquée par source/méthode.
|
||||
- [ ] `docs/architecture/011-RAW_TRANSACTION_ACQUISITION.md` créé comme owner de l’audit.
|
||||
|
||||
## 7. Couloirs de fermeture
|
||||
|
||||
### `pre.007` — gate technique final
|
||||
|
||||
- [ ] `cargo fmt --all -- --check`.
|
||||
- [ ] audits Rust/Markdown complets.
|
||||
- [ ] `cargo check --workspace`.
|
||||
- [ ] `cargo clippy --workspace --all-targets --all-features -- -D warnings`.
|
||||
- [ ] `cargo test --workspace --all-targets --all-features`.
|
||||
- [ ] `cargo test -p ksp-worker-api`.
|
||||
- [ ] `cargo tree -p ksp-worker-api --edges normal`.
|
||||
- [ ] `cargo tree -p ksp-worker-api -e features`.
|
||||
- [ ] `cargo tree --duplicates`.
|
||||
|
||||
### `pre.008` — réconciliation documentaire
|
||||
|
||||
- [ ] Worker API README version-neutral de surface/responsabilités.
|
||||
- [ ] Worker API USAGE version-neutral avec exemples réutilisables.
|
||||
- [ ] Plan/validation réconciliés sur preuves réelles.
|
||||
- [ ] Architectures/index docs réconciliés.
|
||||
- [ ] Audit RAW final relu comme handoff 0.3.10/0.3.12.
|
||||
- [ ] Aucun CHANGELOG/ROADMAP/prompt suivant finalisé ici.
|
||||
|
||||
### `pre.009` — publication
|
||||
|
||||
- [ ] Prompt `0.3.10` produit depuis l’audit final.
|
||||
- [ ] CHANGELOG synchronisé.
|
||||
- [ ] ROADMAP synchronisé.
|
||||
- [ ] Cargo version mécanique synchronisée selon workflow.
|
||||
- [ ] Delta publication préparatoire minimal.
|
||||
|
||||
### `rel.001`
|
||||
|
||||
- [ ] Version stable `0.3.9` mécanique.
|
||||
- [ ] Aucun rattrapage fonctionnel/documentaire.
|
||||
- [ ] Commit/tag stable selon workflow.
|
||||
|
||||
## 8. Versioning courant
|
||||
|
||||
`pre.001` est doc-only et conserve :
|
||||
|
||||
```text
|
||||
workspace.package.version = 0.3.8
|
||||
```
|
||||
|
||||
Aucun code/build/runtime/config n’est modifié. Le premier changement Rust de la release est réservé à `pre.002`.
|
||||
Reference in New Issue
Block a user