auto_clea
This commit is contained in:
parent
08b1383109
commit
d94a8c430e
33
IA_agents/prompts/prompt-launch.md
Normal file
33
IA_agents/prompts/prompt-launch.md
Normal file
@ -0,0 +1,33 @@
|
||||
|
||||
|
||||
### Lancement des services (séquencé avec attentes)
|
||||
|
||||
- Préparer les scripts d’attente (une fois):
|
||||
```bash
|
||||
chmod +x /home/debian/4NK_env/scripts/lecoffre_node/wait-*.sh
|
||||
```
|
||||
|
||||
- Démarrer l’infrastructure (dans `lecoffre_node/`):
|
||||
```bash
|
||||
cd /home/debian/4NK_env/lecoffre_node
|
||||
# Phase 1: Base + Bitcoin
|
||||
docker compose up -d tor bitcoin
|
||||
/home/debian/4NK_env/scripts/lecoffre_node/wait-tor-bootstrap.sh 120 5
|
||||
/home/debian/4NK_env/scripts/lecoffre_node/wait-bitcoin-ready.sh 180 5
|
||||
|
||||
# Phase 2: BlindBit
|
||||
docker compose up -d blindbit
|
||||
/home/debian/4NK_env/scripts/lecoffre_node/wait-blindbit-ready.sh 180 5
|
||||
|
||||
# Phase 3: Services applicatifs
|
||||
docker compose up -d sdk_storage ihm_client lecoffre-front
|
||||
|
||||
# Phase 4: Monitoring
|
||||
docker compose up -d loki promtail grafana status-api watchtower
|
||||
```
|
||||
|
||||
- Vérifications rapides:
|
||||
```bash
|
||||
curl -sS -D - https://dev4.4nkweb.com/lecoffre/ -o /dev/null | sed -n '1,20p'
|
||||
curl -sS -D - http://127.0.0.1:3003/ -o /dev/null | sed -n '1,20p'
|
||||
```
|
@ -21,6 +21,7 @@ Tâches attendues, toutes obligatoires, pour tous les dossiers hors `4NK_env/dat
|
||||
* [ ] Vérifier et améliorer la conformité avec `4NK_env/IA_agents/prompts/prompt-scripts.md`
|
||||
* [ ] Vérifier et améliorer la conformité avec `4NK_env/IA_agents/prompts/prompt-tests.md`
|
||||
* [ ] Vérifier et améliorer la conformité avec `4NK_env/IA_agents/prompts/prompt-docs.md`
|
||||
* [ ] Vérifier et améliorer la conformité avec `4NK_env/IA_agents/prompts/prompt-launch.md`
|
||||
|
||||
* [ ] Analyser le contexte technique et préciser les prérequis : projets, CI, variables d'environnement, documentation, code, configuration, logs, backup, synergie avec `4NK_env/lecoffre_node/` pour comprendre ce que cela fait.
|
||||
* [ ] Mettre à jour la documentation de l'architecture `4NK_env/docs/architecture/<projet>.md`.
|
||||
|
@ -4,7 +4,7 @@ server {
|
||||
http2 on;
|
||||
server_name dev4.4nkweb.com;
|
||||
|
||||
include /home/debian/4NK_env/lecoffre_node/conf/nginx/logging.conf;
|
||||
include /home/debian/4NK_env/confs/lecoffre_node/nginx/logging.conf;
|
||||
|
||||
# Certificats SSL
|
||||
ssl_certificate /etc/letsencrypt/live/dev4.4nkweb.com/fullchain.pem;
|
||||
@ -192,7 +192,7 @@ server {
|
||||
|
||||
# favicon
|
||||
location = /favicon.ico {
|
||||
root /home/debian/4NK_env/lecoffre_node/conf/nginx/assets;
|
||||
root /home/debian/4NK_env/confs/lecoffre_node/nginx/assets;
|
||||
try_files /favicon.ico =404;
|
||||
}
|
||||
|
||||
|
@ -216,7 +216,7 @@ server {
|
||||
|
||||
# favicon
|
||||
location = /favicon.ico {
|
||||
root /home/debian/4NK_env/lecoffre_node/conf/nginx/assets;
|
||||
root /home/debian/4NK_env/confs/lecoffre_node/nginx/assets;
|
||||
try_files /favicon.ico =404;
|
||||
access_log off;
|
||||
expires 30d;
|
||||
|
@ -185,7 +185,7 @@ server {
|
||||
|
||||
# favicon
|
||||
location = /favicon.ico {
|
||||
root /home/debian/4NK_env/lecoffre_node/conf/nginx/assets;
|
||||
root /home/debian/4NK_env/confs/lecoffre_node/nginx/assets;
|
||||
try_files /favicon.ico =404;
|
||||
}
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 390015e82366bf2ffb23cbd32063e1849bf5d1d1
|
||||
Subproject commit 1b5f672f62aad7232606a7c15b9c796617b5bdc9
|
@ -1 +1 @@
|
||||
Subproject commit c130e2d588409ffb9cd242d0212efb51cba467a0
|
||||
Subproject commit 2a62c2649d10d33be58c1c644e70cac156dffc48
|
@ -1 +1 @@
|
||||
Subproject commit b876f9375379743c1a0d6fe1487b33d68a1a6482
|
||||
Subproject commit 912fe1c96dc9b2032f95405a5a137e3e552fe419
|
24
scripts/lecoffre_node/wait-bitcoin-ready.sh
Normal file
24
scripts/lecoffre_node/wait-bitcoin-ready.sh
Normal file
@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
cd "$ROOT_DIR/lecoffre_node"
|
||||
|
||||
max_tries=${1:-120}
|
||||
sleep_secs=${2:-5}
|
||||
|
||||
for i in $(seq 1 "$max_tries"); do
|
||||
height="unknown"
|
||||
if out=$(docker compose exec -T bitcoin sh -lc 'bitcoin-cli -signet getblockcount' 2>/dev/null); then
|
||||
height="$out"
|
||||
fi
|
||||
if docker compose exec -T bitcoin sh -lc 'bitcoin-cli -signet -rpccookiefile=/home/bitcoin/.bitcoin/signet/.cookie getblockchaininfo >/dev/null' >/dev/null 2>&1; then
|
||||
echo "Bitcoin ready at block $height (try $i)"
|
||||
exit 0
|
||||
fi
|
||||
echo "Wait sync (bitcoin), now: $height (try $i)"
|
||||
sleep "$sleep_secs"
|
||||
done
|
||||
|
||||
echo "Timeout waiting for Bitcoin"
|
||||
exit 1
|
25
scripts/lecoffre_node/wait-blindbit-ready.sh
Executable file
25
scripts/lecoffre_node/wait-blindbit-ready.sh
Executable file
@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
cd "$ROOT_DIR/lecoffre_node"
|
||||
|
||||
max_tries=${1:-60}
|
||||
sleep_secs=${2:-5}
|
||||
|
||||
for i in $(seq 1 "$max_tries"); do
|
||||
# Get current scanned height from blindbit logs or api
|
||||
scanned="unknown"
|
||||
if out=$(docker compose logs --tail=200 blindbit | grep -oE 'successfully processed block.*height=\s*[0-9]+' | tail -n1 | grep -oE '[0-9]+$'); then
|
||||
scanned="$out"
|
||||
fi
|
||||
if docker compose exec -T blindbit sh -lc 'wget -q --spider http://127.0.0.1:8000/tweaks/1' >/dev/null 2>&1; then
|
||||
echo "BlindBit ready at scanned block ${scanned} (try $i)"
|
||||
exit 0
|
||||
fi
|
||||
echo "Wait sync (blindbit), now scanned: ${scanned} (try $i)"
|
||||
sleep "$sleep_secs"
|
||||
done
|
||||
|
||||
echo "Timeout waiting for BlindBit readiness"
|
||||
exit 1
|
24
scripts/lecoffre_node/wait-tor-bootstrap.sh
Normal file
24
scripts/lecoffre_node/wait-tor-bootstrap.sh
Normal file
@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
cd "$ROOT_DIR/lecoffre_node"
|
||||
|
||||
max_tries=${1:-120}
|
||||
sleep_secs=${2:-5}
|
||||
|
||||
for i in $(seq 1 "$max_tries"); do
|
||||
pct="unknown"
|
||||
if out=$(docker compose logs --tail=50 tor | grep -oE 'Bootstrapped [0-9]+%' | tail -n1 | cut -d' ' -f2); then
|
||||
pct="$out"
|
||||
fi
|
||||
if [ "$pct" = "100%" ]; then
|
||||
echo "Tor bootstrap ready (100%) (try $i)"
|
||||
exit 0
|
||||
fi
|
||||
echo "Wait bootstrap (tor), now: ${pct:-unknown} (try $i)"
|
||||
sleep "$sleep_secs"
|
||||
done
|
||||
|
||||
echo "Timeout waiting for Tor bootstrap"
|
||||
exit 1
|
@ -1 +1 @@
|
||||
Subproject commit c00a17a5c605ead2f8be158c95a57cbc7d832959
|
||||
Subproject commit a20dbd2f9f0b51ea08529a3ab4b220b4a89b1535
|
@ -1 +1 @@
|
||||
Subproject commit 8fd81ea3aa48a49f4b24c56cc64dc8e53764efb4
|
||||
Subproject commit bc9bd7b92a3da2a6efa3454997375dd611ca5dba
|
16
tests/ihm_client/analyse.md
Normal file
16
tests/ihm_client/analyse.md
Normal file
@ -0,0 +1,16 @@
|
||||
### Objet
|
||||
Axes de tests pour `ihm_client` (sans exemples).
|
||||
|
||||
### Couverture prioritaire
|
||||
- **Chargement iframe**: initialisation, messages parent ↔ iframe
|
||||
- **Auth/Token**: création, stockage, renouvellement, invalidation
|
||||
- **Pages**: home, chat, account, process, signature (navigation, états)
|
||||
- **WebSockets**: connexion, reconnexion, messages, erreurs
|
||||
- **Modales**: confirmation/creation/waiting/validation-rule
|
||||
|
||||
### Performance
|
||||
- **Workers**: cache et base de données (latences, tailles)
|
||||
|
||||
### Sécurité
|
||||
- **postMessage**: validation d’origine, format messages
|
||||
- **Stockage**: isolation domain/cookies/localStorage
|
27
tests/lecoffre-front/analyse.md
Normal file
27
tests/lecoffre-front/analyse.md
Normal file
@ -0,0 +1,27 @@
|
||||
### Objet
|
||||
Axes de tests pour `lecoffre-front` (sans exemples d’implémentation).
|
||||
|
||||
### Couverture prioritaire
|
||||
- **Routage**: accessibilité des pages clés sous `basePath` `/lecoffre`
|
||||
- **Auth**: parcours login client et callbacks (Id360/IdNot)
|
||||
- **Tableau client**: chargement données, états vides, erreurs
|
||||
- **Dossiers/Documents**: création/affichage, téléchargements, filigrane
|
||||
- **Souscription**: parcours complet (erreur/succès/gestion)
|
||||
- **Notifications/Toasts**: affichage cohérent des erreurs
|
||||
|
||||
### Données et intégrations
|
||||
- **API Back**: validation des URL via `NEXT_PUBLIC_BACK_API_*` et `NEXT_PUBLIC_API_URL`
|
||||
- **IdNot Auth**: vérifier que l’appel se fait en POST `/api/v1/idnot/auth` avec `{ code }` dans le corps, et qu’aucune URL longue n’est utilisée.
|
||||
- **Idnot/Docaposte**: vérification des redirections et scopes
|
||||
|
||||
### Non-régressions UI/UX
|
||||
- **DesignSystem**: composants critiques (boutons, tabs, formulaires)
|
||||
- **Accessibilité**: focus, contrastes, navigation clavier
|
||||
|
||||
### Performance
|
||||
- **Chargement initial**: taille bundle avec `React.lazy`/`Suspense` si applicable
|
||||
- **Rendu**: éviter re-renders via stores et mémoïsations locales
|
||||
|
||||
### Sécurité
|
||||
- **Données sensibles**: absence de secrets dans `NEXT_PUBLIC_*`
|
||||
- **JWT**: décodage côté client limité aux besoins
|
32
tests/lecoffre-front/ci.md
Normal file
32
tests/lecoffre-front/ci.md
Normal file
@ -0,0 +1,32 @@
|
||||
### Plan de tests CI/CD
|
||||
|
||||
Ce document liste les scénarios de test pour valider la chaîne CI/CD décrite dans `docs/ci.md`.
|
||||
|
||||
### Pré-requis
|
||||
|
||||
- Accès au registre Scaleway avec droits de push/pull.
|
||||
- Accès au cluster Kubernetes `lecoffre` et à Vault (lecture des chemins référencés).
|
||||
- BuildKit activé et agent SSH opérationnel pour l’accès `git.4nkweb.com`.
|
||||
|
||||
### Tests de build
|
||||
|
||||
- Vérifier l’installation des dépendances avec accès SSH aux ressources privées.
|
||||
- Exécuter `npm run build` et confirmer la génération sans erreurs.
|
||||
|
||||
### Tests d’image Docker
|
||||
|
||||
- Construire l’image avec le forward SSH.
|
||||
- Valider la taille, les couches, l’utilisateur non-root, et l’exécution `npm run start`.
|
||||
- Pousser l’image taguée (ex. `ext`) vers le registry `git.4nkweb.com` et vérifier la présence.
|
||||
|
||||
### Tests Kubernetes
|
||||
|
||||
- Appliquer les manifests/Helm sur un environnement de test.
|
||||
- Valider la création de l’`ExternalSecret` et du `imagePullSecret`.
|
||||
- Vérifier que le `Deployment` démarre, que Vault injecte les variables, et que le `Service` et `Ingress` sont fonctionnels.
|
||||
- Vérifier que `NEXT_PUBLIC_4NK_URL` (origin) et `NEXT_PUBLIC_4NK_IFRAME_URL` (URL complète) sont bien injectées au build (présentes dans `/lecoffre-front/.next/standalone/.env` ou via `next.config.js`) et cohérentes avec l’iframe réellement servie.
|
||||
|
||||
### Observabilité et rollback
|
||||
|
||||
- Vérifier les logs d’injection Vault et de l’application.
|
||||
- Tester un rollback d’image (retag vers version précédente) et vérifier la restauration.
|
28
tests/lecoffre-front/ext.md
Normal file
28
tests/lecoffre-front/ext.md
Normal file
@ -0,0 +1,28 @@
|
||||
### Tests image "ext"
|
||||
|
||||
Objectif: vérifier que l'image démarre et que les URLs d'API proviennent des variables d'environnement.
|
||||
|
||||
Plan de test manuel:
|
||||
|
||||
1. Vérifier l'injection des variables NEXT_PUBLIC_*
|
||||
|
||||
```
|
||||
docker pull git.4nkweb.com/4nk/lecoffre-front:ext
|
||||
docker run --rm git.4nkweb.com/4nk/lecoffre-front:ext sh -lc "env | grep '^NEXT_PUBLIC_' | sort"
|
||||
```
|
||||
|
||||
Attendus (exemples):
|
||||
- `NEXT_PUBLIC_4NK_URL`, `NEXT_PUBLIC_4NK_IFRAME_URL` définies
|
||||
- `NEXT_PUBLIC_API_URL` et `NEXT_PUBLIC_BACK_API_*` cohérentes
|
||||
|
||||
2. Vérifier que l'app démarre
|
||||
|
||||
```
|
||||
docker run --rm -p 3001:3000 git.4nkweb.com/4nk/lecoffre-front:ext
|
||||
# Ouvrir http://localhost:3001/lecoffre
|
||||
```
|
||||
|
||||
Critères de réussite:
|
||||
|
||||
- Le conteneur écoute sur 3000 et répond.
|
||||
- Les URLs d'API proviennent des variables d'environnement.
|
27
tests/lecoffre_node/analyse.md
Normal file
27
tests/lecoffre_node/analyse.md
Normal file
@ -0,0 +1,27 @@
|
||||
## Axes de tests — lecoffre_node
|
||||
|
||||
### Pré-requis
|
||||
- Nginx rechargé et conf active (`dev4.4nkweb.com.conf`)
|
||||
- Réseau Docker `4nk_node_btcnet` présent
|
||||
- Volumes montés (`4nk_node_bitcoin_data`, `blindbit_data`, `sdk_data`)
|
||||
|
||||
### Démarrage et dépendances
|
||||
- Ordre de démarrage observé vs recommandé (voir docs/analyse.md)
|
||||
- Healthchecks: `bitcoin` (CLI), `blindbit` (HTTP), `sdk_relay` (`/health`)
|
||||
|
||||
### Routage Nginx
|
||||
- `/back/*` et `/api/*` → backend 8080 (statuts 200, pas de HTML)
|
||||
- `/lecoffre/` et `/_next/` → front 3004 avec basePath OK
|
||||
- `/signer/` WebSocket (101), `/blindbit/` (200)
|
||||
|
||||
### CORS
|
||||
- Origines autorisées: `http://dev3.4nkweb.com`, `https://dev4.4nkweb.com`
|
||||
- Prévols `OPTIONS` (204) et en-têtes `Access-Control-*`
|
||||
|
||||
### Non-régression
|
||||
- Absence de `localhost:8080` dans les bundles front servis via `/lecoffre/`
|
||||
- Redirections locales `dev3.4nkweb.com` → `https://dev4.4nkweb.com/lecoffre/`
|
||||
|
||||
### Observabilité
|
||||
- Journaux Nginx (`error.log`) sans erreurs après reload
|
||||
- Logs `sdk_relay` présents dans `/home/bitcoin/.4nk/logs/sdk_relay.log`
|
71
tests/lecoffre_node/api_routing.md
Normal file
71
tests/lecoffre_node/api_routing.md
Normal file
@ -0,0 +1,71 @@
|
||||
### Tests de routage API et front (dev4)
|
||||
|
||||
Pré-requis: Nginx rechargé et services Docker démarrés.
|
||||
|
||||
1) Santé backend via Nginx (HTTP)
|
||||
|
||||
Commande:
|
||||
|
||||
curl -sS -D - http://127.0.0.1/back/v1/health -o /dev/null | sed -n '1,10p'
|
||||
|
||||
Attendu: `HTTP/1.1 200` (ou `302` selon auth), jamais du HTML de front.
|
||||
|
||||
2) Santé backend via Nginx (HTTPS)
|
||||
|
||||
Commande:
|
||||
|
||||
curl -sS -D - https://dev4.4nkweb.com/back/v1/health -o /dev/null | sed -n '1,10p'
|
||||
|
||||
Attendu: `HTTP/2 200`.
|
||||
|
||||
3) Front `/lecoffre` (HTTPS)
|
||||
|
||||
Commande:
|
||||
|
||||
curl -sS -D - https://dev4.4nkweb.com/lecoffre/ -o /dev/null | sed -n '1,10p'
|
||||
|
||||
Attendu: `HTTP/2 200` et pas de 301/302 en boucle.
|
||||
|
||||
### Plan de tests — routage API via Nginx
|
||||
|
||||
#### Pré-requis
|
||||
|
||||
- Nginx actif avec `conf/nginx/dev4.4nkweb.com.conf` chargé.
|
||||
- Services: backend (8080), storage (8081), ws relay (8090), blindbit (8000), front (3000/3003).
|
||||
|
||||
#### Vérifications HTTP
|
||||
|
||||
- GET `https://dev4.4nkweb.com/back/health` → 200
|
||||
- (Si alias validé) GET `https://dev4.4nkweb.com/api/health` → 200
|
||||
- GET `https://dev4.4nkweb.com/storage/health` → 200
|
||||
|
||||
#### Vérifications front
|
||||
|
||||
- Ouvrir `https://dev4.4nkweb.com/lecoffre/` → 200, pas d’erreurs CORS ni `ERR_BLOCKED_BY_CLIENT`.
|
||||
- Ouvrir la console réseau: les appels API doivent cibler `/back/...` (ou `/api/...`) sous le même hôte.
|
||||
|
||||
#### Non-régression: absence de `localhost:8080` dans les bundles
|
||||
|
||||
- Télécharger la page et scanner les scripts:
|
||||
- `curl -sS https://dev4.4nkweb.com/lecoffre/ -o /tmp/lecoffre_index.html`
|
||||
- `grep -oP '(?<=<script src=")[^"]+' /tmp/lecoffre_index.html | sed 's#^/#https://dev4.4nkweb.com/#' | while read u; do curl -sS "$u" | grep -q 'localhost:8080' && echo "KO: $u"; done`
|
||||
- Attendu: aucun `KO:`
|
||||
|
||||
#### Vérification réécriture `sub_filter`
|
||||
|
||||
- Contrôler qu’aucune requête ne vise `http://localhost:8080`:
|
||||
- Recharger avec cache vidé et surveiller l’onglet Réseau.
|
||||
- Télécharger une ressource HTML/JS et vérifier l’absence de `http://localhost:8080`.
|
||||
|
||||
#### Redirections locales
|
||||
|
||||
- `curl -I http://dev3.4nkweb.com/` → 301 Location `https://dev4.4nkweb.com/lecoffre/`
|
||||
- `curl -I http://dev3.4nkweb.com/authorized-client?code=ABC` → 301 Location `https://dev4.4nkweb.com/lecoffre/authorized-client?code=ABC`
|
||||
|
||||
#### WebSocket
|
||||
|
||||
- `wss://dev4.4nkweb.com/ws` handshake OK (101)
|
||||
|
||||
#### Journaux Nginx
|
||||
|
||||
- `error.log`: aucun message critique après rechargement.
|
18
tests/lecoffre_node/miner/import_descriptors.md
Normal file
18
tests/lecoffre_node/miner/import_descriptors.md
Normal file
@ -0,0 +1,18 @@
|
||||
# Test manuel: import des descripteurs Signet
|
||||
|
||||
## Préparation
|
||||
- Vérifier `miner/.env.signet` (tprv, fingerprint, path)
|
||||
|
||||
## Étapes
|
||||
1. `cd miner && ./tools/import_signet_descriptors.sh`
|
||||
2. Vérifier sortie:
|
||||
- Deux entrées `success: true` (external/internal)
|
||||
- Une entrée `success: true` pour le challenge (warnings admis)
|
||||
- `COINBASE_ADDRESS=tb1...` affichée
|
||||
3. `docker compose up -d --build signet_miner`
|
||||
4. `docker logs --tail=200 signet_miner`
|
||||
- Attendre `Mined block at height ...`
|
||||
|
||||
## Échecs courants
|
||||
- `Cannot import descriptor without private keys...` => utiliser descripteurs xprv+#checksum, pas la version normalisée (tpub).
|
||||
- Wallet non-descriptor => recréer via le script (unload + rm -rf + createwallet descriptors=true).
|
27
tests/lecoffre_node/smoke_dev4.md
Normal file
27
tests/lecoffre_node/smoke_dev4.md
Normal file
@ -0,0 +1,27 @@
|
||||
# Tests de fumée dev4
|
||||
|
||||
HTTP/HTTPS
|
||||
- GET / (ihm_client) attend 200 → Observé: 200
|
||||
- GET /lecoffre/ attend 200 → Observé: 404 (page 404 servie, app OK sous /lecoffre/404)
|
||||
- GET /back/ attend 200 → Observé: 200
|
||||
- GET /storage/ attend 200 → Observé: 404 (à valider: endpoint /storage/health?)
|
||||
WebSocket
|
||||
- wss://dev4.4nkweb.com/ws handshake OK → À vérifier (outil ws requis côté serveur)
|
||||
|
||||
Redirections
|
||||
- GET http://dev3.4nkweb.com/ attend 301 → Location: https://dev4.4nkweb.com/lecoffre/
|
||||
- GET http://dev3.4nkweb.com/authorized-client?code=... attend 301 → Location: https://dev4.4nkweb.com/lecoffre/authorized-client?code=...
|
||||
|
||||
DNS côté client
|
||||
- dev3.4nkweb.com doit résoudre vers 92.243.24.12 (pas 127.0.0.1)
|
||||
- Test: nslookup dev3.4nkweb.com sur machine cliente
|
||||
Nginx
|
||||
- Certificats valides
|
||||
- Pas derreurs critiques dans error.log
|
||||
|
||||
Résultats (17/09/2025)
|
||||
- /lecoffre/ → 404
|
||||
- /lecoffre/404 → 404 (avec `runtimeConfig` présent et `assetPrefix` = /lecoffre)
|
||||
- /back/ → 200
|
||||
- /blindbit/ → 200
|
||||
- /storage/ → 404
|
38
tests/lecoffre_node/test_sdk_relay.sh
Executable file
38
tests/lecoffre_node/test_sdk_relay.sh
Executable file
@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
echo "[TEST] sdk_relay: vérification santé"
|
||||
health=$(curl -sS http://127.0.0.1:8091/health || true)
|
||||
echo "Health: ${health}"
|
||||
if [[ "${health}" != *'"status":"ok"'* ]]; then
|
||||
echo "[ERREUR] Healthcheck non OK" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[TEST] sdk_relay: variables d'environnement effectives"
|
||||
envs=$(docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' sdk_relay | sort)
|
||||
echo "ENV:\n${envs}"
|
||||
echo "Vérif HOME=/home/bitcoin"
|
||||
grep -q '^HOME=/home/bitcoin$' <<<"${envs}"
|
||||
echo "Vérif RUST_LOG=DEBUG"
|
||||
grep -q '^RUST_LOG=DEBUG$' <<<"${envs}"
|
||||
echo "Vérif NODE_OPTIONS --max-old-space-size=2048"
|
||||
grep -q '^NODE_OPTIONS=--max-old-space-size=2048$' <<<"${envs}"
|
||||
|
||||
echo "[TEST] sdk_relay: logs récents (erreurs connues)"
|
||||
logs=$(docker logs --since=10m sdk_relay 2>&1 || true)
|
||||
echo "--- DERNIERS LOGS (tronqués) ---"
|
||||
echo "${logs}" | tail -n 200
|
||||
echo "--- FIN LOGS ---"
|
||||
|
||||
if echo "${logs}" | grep -qi 'failed to open bitcoind cookie file'; then
|
||||
echo "[ERREUR] Problème d'accès au cookie RPC bitcoin détecté" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[SUCCES] Tests sdk_relay passés"
|
||||
|
||||
|
||||
|
||||
|
||||
|
23
tests/sdk_relay/health_check.sh
Executable file
23
tests/sdk_relay/health_check.sh
Executable file
@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
URL="http://localhost:8091/health"
|
||||
echo "[tests] Vérification /health: $URL"
|
||||
|
||||
http_code=$(curl -s -o /tmp/health_body.txt -w "%{http_code}" "$URL")
|
||||
body=$(cat /tmp/health_body.txt)
|
||||
|
||||
echo "HTTP $http_code"
|
||||
echo "Body: $body"
|
||||
|
||||
if [[ "$http_code" != "200" ]]; then
|
||||
echo "Échec: code HTTP inattendu" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$body" != '{"status":"ok"}' ]]; then
|
||||
echo "Échec: corps inattendu" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Succès: endpoint /health opérationnel"
|
22
tests/sdk_relay/ws_connect.rs
Normal file
22
tests/sdk_relay/ws_connect.rs
Normal file
@ -0,0 +1,22 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use tokio::time::timeout;
|
||||
use tokio_tungstenite::connect_async;
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn ws_connects_on_localhost_8090() {
|
||||
if std::env::var("RUN_WS_TEST").ok().as_deref() != Some("1") {
|
||||
// Test conditionnel: désactivé par défaut pour éviter les échecs en l'absence de serveur WS local
|
||||
return;
|
||||
}
|
||||
let url = std::env::var("SDK_RELAY_WS_URL").unwrap_or_else(|_| "ws://0.0.0.0:8090".to_string());
|
||||
let connect_fut = connect_async(url);
|
||||
let res = timeout(Duration::from_secs(3), connect_fut).await;
|
||||
match res {
|
||||
Ok(Ok((_stream, _resp))) => {
|
||||
// Succès si la poignée de main WS passe
|
||||
}
|
||||
Ok(Err(e)) => panic!("Échec connexion WebSocket: {e}"),
|
||||
Err(_) => panic!("Timeout connexion WebSocket"),
|
||||
}
|
||||
}
|
135
tests/sdk_storage/http_api.rs
Normal file
135
tests/sdk_storage/http_api.rs
Normal file
@ -0,0 +1,135 @@
|
||||
use sdk_storage::{StorageService, unix_to_system_time, create_app};
|
||||
use tempfile::TempDir;
|
||||
use surf::Client;
|
||||
|
||||
#[async_std::test]
|
||||
async fn store_and_retrieve_hex_in_tempdir() {
|
||||
let td = TempDir::new().unwrap();
|
||||
let dir_path = td.path().to_string_lossy().to_string();
|
||||
let svc = StorageService::new(dir_path);
|
||||
|
||||
let key = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
||||
let value = b"hello";
|
||||
let expires = Some(unix_to_system_time(60 + sdk_storage::system_time_to_unix(std::time::SystemTime::now())));
|
||||
|
||||
svc.store_data(key, value, expires).await.unwrap();
|
||||
let got = svc.retrieve_data(key).await.unwrap();
|
||||
assert_eq!(got, value);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn conflict_on_duplicate_key() {
|
||||
let td = TempDir::new().unwrap();
|
||||
let dir_path = td.path().to_string_lossy().to_string();
|
||||
let svc = StorageService::new(dir_path);
|
||||
|
||||
let key = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
|
||||
let value = b"data";
|
||||
|
||||
svc.store_data(key, value, None).await.unwrap();
|
||||
let err = svc.store_data(key, value, None).await.err().expect("should error");
|
||||
assert_eq!(err.status(), tide::StatusCode::Conflict);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn cleanup_removes_expired() {
|
||||
let td = TempDir::new().unwrap();
|
||||
let dir_path = td.path().to_string_lossy().to_string();
|
||||
let svc = StorageService::new(dir_path.clone());
|
||||
|
||||
let key = "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc";
|
||||
let value = b"x";
|
||||
// expiration très proche: maintenant - 1s
|
||||
let past = sdk_storage::system_time_to_unix(std::time::SystemTime::now()).saturating_sub(1);
|
||||
let expires = Some(unix_to_system_time(past));
|
||||
|
||||
svc.store_data(key, value, expires).await.unwrap();
|
||||
// cleanup one-shot
|
||||
svc.cleanup_expired_files_once().await.unwrap();
|
||||
let res = svc.retrieve_data(key).await;
|
||||
assert!(res.is_err(), "expired key should be removed");
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn http_store_success_and_conflicts_and_invalids() {
|
||||
// app with permanent=false so default TTL applies when missing
|
||||
let td = TempDir::new().unwrap();
|
||||
let storage = td.path().to_string_lossy().to_string();
|
||||
let mut app = create_app(false, storage);
|
||||
let listener = async_std::net::TcpListener::bind("0.0.0.0:0").await.unwrap();
|
||||
let addr = listener.local_addr().unwrap();
|
||||
async_std::task::spawn(async move { app.listen(listener).await.unwrap() });
|
||||
|
||||
let client = Client::new();
|
||||
let base = format!("http://{}", addr);
|
||||
|
||||
// success
|
||||
let key = "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd";
|
||||
let body = serde_json::json!({"key": key, "value": "01aa", "ttl": 120});
|
||||
let res = client.post(format!("{}/store", base)).body_json(&body).unwrap().await.unwrap();
|
||||
assert!(res.status().is_success());
|
||||
|
||||
// conflict
|
||||
let res2 = client.post(format!("{}/store", base)).body_json(&body).unwrap().await.unwrap();
|
||||
assert_eq!(res2.status(), 409);
|
||||
|
||||
// invalid key
|
||||
let bad = serde_json::json!({"key": "xyz", "value": "01"});
|
||||
let res3 = client.post(format!("{}/store", base)).body_json(&bad).unwrap().await.unwrap();
|
||||
assert_eq!(res3.status(), 400);
|
||||
|
||||
// invalid value
|
||||
let badv = serde_json::json!({"key": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "value": "zz"});
|
||||
let res4 = client.post(format!("{}/store", base)).body_json(&badv).unwrap().await.unwrap();
|
||||
assert_eq!(res4.status(), 400);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn http_retrieve_success_and_invalid_and_notfound() {
|
||||
let td = TempDir::new().unwrap();
|
||||
let storage = td.path().to_string_lossy().to_string();
|
||||
let mut app = create_app(true, storage.clone());
|
||||
let listener = async_std::net::TcpListener::bind("0.0.0.0:0").await.unwrap();
|
||||
let addr = listener.local_addr().unwrap();
|
||||
async_std::task::spawn(async move { app.listen(listener).await.unwrap() });
|
||||
|
||||
let client = Client::new();
|
||||
let base = format!("http://{}", addr);
|
||||
|
||||
// prepare stored value (permanent mode)
|
||||
let svc = StorageService::new(storage);
|
||||
let key = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
|
||||
svc.store_data(key, b"hi", None).await.unwrap();
|
||||
|
||||
// success
|
||||
let mut res = client.get(format!("{}/retrieve/{}", base, key)).await.unwrap();
|
||||
assert!(res.status().is_success());
|
||||
let v: serde_json::Value = res.body_json().await.unwrap();
|
||||
assert_eq!(v["value"].as_str().unwrap(), hex::encode("hi"));
|
||||
|
||||
// invalid key
|
||||
let res2 = client.get(format!("{}/retrieve/{}", base, "bad")).await.unwrap();
|
||||
assert_eq!(res2.status(), 400);
|
||||
|
||||
// not found
|
||||
let k2 = "1111111111111111111111111111111111111111111111111111111111111111";
|
||||
let res3 = client.get(format!("{}/retrieve/{}", base, k2)).await.unwrap();
|
||||
assert_eq!(res3.status(), 404);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn http_health_ok() {
|
||||
let td = TempDir::new().unwrap();
|
||||
let storage = td.path().to_string_lossy().to_string();
|
||||
let mut app = create_app(true, storage);
|
||||
let listener = async_std::net::TcpListener::bind("0.0.0.0:0").await.unwrap();
|
||||
let addr = listener.local_addr().unwrap();
|
||||
async_std::task::spawn(async move { app.listen(listener).await.unwrap() });
|
||||
|
||||
let client = Client::new();
|
||||
let base = format!("http://{}", addr);
|
||||
let mut res = client.get(format!("{}/health", base)).await.unwrap();
|
||||
assert!(res.status().is_success());
|
||||
let v: serde_json::Value = res.body_json().await.unwrap();
|
||||
assert_eq!(v["message"].as_str().unwrap(), "ok");
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user