Compare commits
48 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f89921ecf3 | ||
|
|
9c81e2a1be | ||
|
|
811f2ee131 | ||
|
|
87d32653d9 | ||
|
|
3d6b7cc3d5 | ||
|
|
6420dea8c3 | ||
|
|
5127836232 | ||
|
|
6ec21b71d6 | ||
|
|
1ab24644bb | ||
|
|
2355aebf68 | ||
|
|
b190edbf72 | ||
|
|
ec527c765e | ||
|
|
3c4d62ea1c | ||
|
|
e4c63c35d6 | ||
|
|
dd4a449a10 | ||
|
|
447818ac1f | ||
|
|
9c6eef702b | ||
|
|
38dcac2724 | ||
|
|
0baa0792e6 | ||
|
|
6ce9ae1709 | ||
|
|
41dadc4b8e | ||
|
|
217883f606 | ||
|
|
c4a35ee864 | ||
|
|
fc14398f25 | ||
|
|
3f1d8b7d60 | ||
|
|
a330de126b | ||
|
|
4b84cf2a31 | ||
|
|
cf1ec31c1e | ||
|
|
e989e2780c | ||
|
|
02396f2dd4 | ||
|
|
fd592fab43 | ||
|
|
ed265264d1 | ||
|
|
5b0fa00aad | ||
|
|
9eb3255fdf | ||
|
|
36c14652bc | ||
|
|
0a543a186c | ||
|
|
e347a6e4de | ||
|
|
ebfb41ead5 | ||
|
|
09b2bb2cfe | ||
|
|
473b9b1c18 | ||
|
|
f51559e748 | ||
|
|
83b21cb815 | ||
|
|
8449083237 | ||
|
|
f4bf9791c0 | ||
|
|
95763806c8 | ||
|
|
fe60812c53 | ||
|
|
26f985195d | ||
|
|
34a65ec079 |
2
.ci-trigger
Normal file
2
.ci-trigger
Normal file
@ -0,0 +1,2 @@
|
||||
# CI Trigger
|
||||
# CI Trigger Sun Sep 21 19:57:52 UTC 2025
|
||||
@ -1,26 +1,8 @@
|
||||
# Ignorer les contenus volumineux pour le contexte IA
|
||||
# Cursor ignore file for sdk_signer
|
||||
node_modules/
|
||||
dist/
|
||||
build/
|
||||
*.log
|
||||
.env*
|
||||
.DS_Store
|
||||
coverage/
|
||||
.cache/
|
||||
.tmp/
|
||||
.parcel-cache/
|
||||
|
||||
# Rapports et logs de tests
|
||||
tests/logs/
|
||||
tests/reports/
|
||||
|
||||
# Fichiers lourds
|
||||
**/*.map
|
||||
**/*.min.*
|
||||
**/*.wasm
|
||||
**/*.{png,jpg,jpeg,svg,ico,pdf}
|
||||
|
||||
# Ne pas ignorer .cursor ni AGENTS.md
|
||||
!/.cursor
|
||||
!/AGENTS.md
|
||||
|
||||
!.cursor/
|
||||
|
||||
!AGENTS.md
|
||||
pkg/
|
||||
|
||||
166
.cursorrules
Normal file
166
.cursorrules
Normal file
@ -0,0 +1,166 @@
|
||||
# Règles globales Cursor pour les projets
|
||||
|
||||
## Principes généraux
|
||||
- Lire impérativement le fichier `.cursorrules` au démarrage de chaque session.
|
||||
- Lire tous les fichiers du dossier `docs/`, le code et les paramètres avant de commencer.
|
||||
- Poser des questions et proposer des améliorations si nécessaire.
|
||||
- Ajouter les leçons apprises à ce fichier `.cursorrules`.
|
||||
- Écrire des documents complets et exhaustifs.
|
||||
- Respecter strictement les règles de lint du Markdown.
|
||||
- Préférer toujours un shell **bash** à PowerShell.
|
||||
- Fermer et relancer le terminal avant chaque utilisation.
|
||||
- Si le terminal est interrompu, analyser la commande précédente (interruption probablement volontaire).
|
||||
- Exécuter automatiquement les étapes de résolution de problème.
|
||||
- Expliquer les commandes complexes avant de les lancer.
|
||||
- Compiler régulièrement et corriger toutes les erreurs avant de passer à l’étape suivante.
|
||||
- Tester, documenter, compiler, aligner tag git, changelog et version avant déploiement et push.
|
||||
- Utiliser `docx2txt` pour lire les fichiers `.docx`.
|
||||
- Ajouter automatiquement les dépendances et rechercher systématiquement les dernières versions.
|
||||
- Faire des commandes simples et claires en plusieurs étapes.
|
||||
- Vérifie toujours tes hypothèses avant de commencer.
|
||||
- N'oublie jamais qu'après la correction d'un problème, il faut corriger toutes les erreurs qui peuvent en découler.
|
||||
|
||||
## Organisation des fichiers et répertoires
|
||||
- Scripts regroupés dans `scripts/`
|
||||
- Configurations regroupées dans `confs/`
|
||||
- Journaux regroupés dans `logs/`
|
||||
- Répertoires obligatoires :
|
||||
- `docs/` : documentation de toute fonctionnalité ajoutée, modifiée, supprimée ou découverte.
|
||||
- `tests/` : tests liés à toute fonctionnalité ajoutée, modifiée, supprimée ou découverte.
|
||||
- Remplacer les résumés (`RESUME`) par des mises à jour dans `docs/`.
|
||||
|
||||
## Configuration critique des services
|
||||
- Mempool du réseau signet :
|
||||
`https://mempool2.4nkweb.com/fr/docs/api/rest`
|
||||
|
||||
## Développement et sécurité
|
||||
- Ne jamais committer de clés privées ou secrets.
|
||||
- Utiliser des variables d’environnement pour les données sensibles.
|
||||
- Définir correctement les dépendances Docker avec healthchecks.
|
||||
- Utiliser les URLs de service Docker Compose (`http://service_name:port`).
|
||||
- Documenter toutes les modifications importantes dans `docs/`.
|
||||
- Externaliser au maximum les variables d’environnement.
|
||||
- Toujours utiliser une clé SSH pour cloner les dépôts.
|
||||
- Monter en version les dépôts au début du travail.
|
||||
- Pousser les tags docker `int-dev` via la CI sur `git.4nkweb.com`.
|
||||
- Corriger systématiquement les problèmes, même mineurs, sans contournement.
|
||||
|
||||
## Scripts (règles critiques)
|
||||
- Vérifier l’existence d’un script dans `scripts/` avant toute action.
|
||||
- Utiliser les scripts existants plutôt que des commandes directes.
|
||||
- Ne jamais créer plusieurs versions ou noms de scripts.
|
||||
- Améliorer l’existant au lieu de créer des variantes (`startup-v2.sh`, etc.).
|
||||
|
||||
## Images Docker (règles critiques)
|
||||
- Ajouter systématiquement `apt update && apt upgrade` dans les Dockerfiles.
|
||||
- Installer en arrière-plan dans les images Docker :
|
||||
`curl, git, sed, awk, nc, wget, jq, telnet, tee, wscat, ping, npm (dernière version)`
|
||||
- Appliquer à tous les Dockerfiles et `docker-compose.yml`.
|
||||
- N'utilise pas les version test ou dev ou int-dev-dev mais toujours les version int-dev, relance leur compilation si nécessaire
|
||||
|
||||
## Fichiers de configuration (règles critiques)
|
||||
- Vérifier l’écriture effective après chaque modification.
|
||||
- Fichiers concernés : `nginx.conf`, `bitcoin.conf`, `package.json`, `Cargo.toml`.
|
||||
- Utiliser `cat`, `jq` ou vérificateurs de syntaxe.
|
||||
|
||||
## Connexion au réseau Bitcoin signet
|
||||
Commande unique et obligatoire :
|
||||
```bash
|
||||
docker exec bitcoin-signet bitcoin-cli -signet -rpccookiefile=/home/bitcoin/.bitcoin/signet/.cookie getblockchaininfo
|
||||
````
|
||||
|
||||
## Connexion au relay/faucet bootstrap
|
||||
|
||||
* Test via WSS : `wss://dev3.4nkweb.com/ws/`
|
||||
* Envoi Faucet, réponse attendue avec `NewTx` (tx hex et tweak\_data).
|
||||
|
||||
## Debug
|
||||
|
||||
* Automatiser dans le code toute solution validée.
|
||||
* Pérenniser les retours d’expérience dans code et paramètres.
|
||||
* Compléter les tests pour éviter les régressions.
|
||||
* Toujours tout corriger sans contournement, sans desactivation, sans simplification
|
||||
|
||||
## Nginx
|
||||
|
||||
* Tous les fichiers dans `conf/ngnix` doivent être mappés avec ceux du serveur.
|
||||
|
||||
## Minage (règles critiques)
|
||||
|
||||
* Toujours valider les adresses utilisées (adresses TSP non reconnues).
|
||||
* Utiliser uniquement des adresses Bitcoin valides (bech32m).
|
||||
* Vérifier que le minage génère des blocs avec transactions, pas uniquement coinbase.
|
||||
* Surveiller les logs du minage pour détecter les erreurs d’adresse.
|
||||
* Vérifier la propagation via le mempool externe.
|
||||
|
||||
## Mempool externe
|
||||
|
||||
* Utiliser `https://mempool2.4nkweb.com` pour vérifier les transactions.
|
||||
* Vérifier la synchronisation entre réseau local et externe.
|
||||
|
||||
## Données et modèles
|
||||
|
||||
* Utiliser les fichiers CSV comme base des modèles de données.
|
||||
* Être attentif aux en-têtes multi-lignes.
|
||||
* Confirmer la structure comprise et demander définition de toutes les colonnes.
|
||||
* Corriger automatiquement incohérences de type.
|
||||
|
||||
## Implémentation et architecture
|
||||
|
||||
* Code splitting avec `React.lazy` et `Suspense`.
|
||||
* Centraliser l’état avec Redux ou Context API.
|
||||
* Créer une couche d’abstraction pour les services de données.
|
||||
* Aller systématiquement au bout d’une implémentation.
|
||||
|
||||
## Préparation open source
|
||||
|
||||
Chaque projet doit être prêt pour un dépôt sur `git.4nkweb.com` :
|
||||
|
||||
* Inclure : `LICENSE` (MIT, Apache 2.0 ou GPL), `CONTRIBUTING.md`, `CHANGELOG.md`, `CODE_OF_CONDUCT.md`.
|
||||
* Aligner documentation et tests avec `4NK_node`.
|
||||
|
||||
## Versioning et documentation
|
||||
|
||||
* Mettre à jour documentation et tests systématiquement.
|
||||
* Gérer versioning avec changelog.
|
||||
* Demander validation avant tag.
|
||||
* Documenter les hypothèses testées dans un REX technique.
|
||||
* Tester avant tout commit.
|
||||
* Tester les buildsavant tout tag.
|
||||
|
||||
## Bonnes pratiques de confidentialité et sécurité
|
||||
|
||||
### Docker
|
||||
- Ne jamais stocker de secrets (clés, tokens, mots de passe) dans les Dockerfiles ou docker-compose.yml.
|
||||
- Utiliser des fichiers `.env` sécurisés (non commités avec copie en .env.example) pour toutes les variables sensibles.
|
||||
- Ne pas exécuter de conteneurs avec l’utilisateur root, privilégier un utilisateur dédié.
|
||||
- Limiter les capacités des conteneurs (option `--cap-drop`) pour réduire la surface d’attaque.
|
||||
- Scanner régulièrement les images Docker avec un outil de sécurité (ex : Trivy, Clair).
|
||||
- Mettre à jour en continu les images de base afin d’éliminer les vulnérabilités.
|
||||
- Ne jamais exposer de ports inutiles.
|
||||
- Restreindre les volumes montés au strict nécessaire.
|
||||
- Utiliser des réseaux Docker internes pour la communication inter-containers.
|
||||
- Vérifier et tenir à jour les .dockerignore.
|
||||
|
||||
### Git
|
||||
- Ne jamais committer de secrets, clés ou identifiants (même temporairement).
|
||||
- Configurer des hooks Git (pre-commit) pour détecter automatiquement les secrets et les failles.
|
||||
- Vérifier l’historique (`git log`, `git filter-repo`) pour s’assurer qu’aucune information sensible n’a été poussée.
|
||||
- Signer les commits avec GPG pour garantir l’authenticité.
|
||||
- Utiliser systématiquement SSH pour les connexions à distance.
|
||||
- Restreindre les accès aux dépôts (principes du moindre privilège).
|
||||
- Documenter les changements sensibles dans `CHANGELOG.md`.
|
||||
- Ne jamais pousser directement sur `main` ou `master`, toujours passer par des branches de feature ou PR.
|
||||
- Vérifier et tenir à jour les .gitignore.
|
||||
- Vérifier et tenir à jour les .gitkeep.
|
||||
- Vérifier et tenir à jour les .gitattributes.
|
||||
|
||||
### Cursor
|
||||
- Toujours ouvrir une session en commençant par relire le fichier `.cursorrules`.
|
||||
- Vérifier que Cursor ne propose pas de commit contenant des secrets ou fichiers sensibles.
|
||||
- Ne pas exécuter dans Cursor de commandes non comprises ou copiées sans vérification.
|
||||
- Préférer l’utilisation de scripts audités dans `scripts/` plutôt que des commandes directes dans Cursor.
|
||||
- Fermer et relancer Cursor régulièrement pour éviter des contextes persistants non désirés.
|
||||
- Ne jamais partager le contenu du terminal ou des fichiers sensibles via Cursor en dehors du périmètre du projet.
|
||||
- Vérifier et tenir à jour les .cursorrules.
|
||||
- Vérifier et tenir à jour les .cursorignore.
|
||||
2
.env.exemple
Normal file
2
.env.exemple
Normal file
@ -0,0 +1,2 @@
|
||||
|
||||
SIGNER_API_KEY=your-api-key-change-this
|
||||
@ -1,98 +0,0 @@
|
||||
---
|
||||
name: Bug Report
|
||||
about: Signaler un bug pour nous aider à améliorer sdk_signer
|
||||
title: '[BUG] '
|
||||
labels: ['bug', 'needs-triage']
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
## 🐛 Description du Bug
|
||||
|
||||
Description claire et concise du problème.
|
||||
|
||||
## 🔄 Étapes pour Reproduire
|
||||
|
||||
1. Aller à '...'
|
||||
2. Cliquer sur '...'
|
||||
3. Faire défiler jusqu'à '...'
|
||||
4. Voir l'erreur
|
||||
|
||||
## ✅ Comportement Attendu
|
||||
|
||||
Description de ce qui devrait se passer.
|
||||
|
||||
## ❌ Comportement Actuel
|
||||
|
||||
Description de ce qui se passe actuellement.
|
||||
|
||||
## 📸 Capture d'Écran
|
||||
|
||||
Si applicable, ajoutez une capture d'écran pour expliquer votre problème.
|
||||
|
||||
## 💻 Informations Système
|
||||
|
||||
- **OS** : [ex: Ubuntu 20.04, macOS 12.0, Windows 11]
|
||||
- **Docker** : [ex: 20.10.0]
|
||||
- **Docker Compose** : [ex: 2.0.0]
|
||||
- **Version sdk_signer** : [ex: v1.0.0]
|
||||
- **Architecture** : [ex: x86_64, ARM64]
|
||||
|
||||
## 📋 Configuration
|
||||
|
||||
### Services Actifs
|
||||
```bash
|
||||
docker ps
|
||||
```
|
||||
|
||||
### Variables d'Environnement
|
||||
```bash
|
||||
# Bitcoin Core
|
||||
BITCOIN_NETWORK=signet
|
||||
BITCOIN_RPC_PORT=18443
|
||||
|
||||
# Blindbit
|
||||
BLINDBIT_PORT=8000
|
||||
|
||||
# SDK Relay
|
||||
SDK_RELAY_PORTS=8090-8095
|
||||
```
|
||||
|
||||
## 📝 Logs
|
||||
|
||||
### Logs Pertinents
|
||||
```
|
||||
Logs pertinents ici
|
||||
```
|
||||
|
||||
### Logs d'Erreur
|
||||
```
|
||||
Logs d'erreur ici
|
||||
```
|
||||
|
||||
### Logs de Debug
|
||||
```
|
||||
Logs de debug ici (si RUST_LOG=debug)
|
||||
```
|
||||
|
||||
## 🔧 Tentatives de Résolution
|
||||
|
||||
- [ ] Redémarrage des services
|
||||
- [ ] Nettoyage des volumes Docker
|
||||
- [ ] Vérification de la connectivité réseau
|
||||
- [ ] Mise à jour des dépendances
|
||||
- [ ] Vérification de la configuration
|
||||
|
||||
## 📚 Contexte Supplémentaire
|
||||
|
||||
Toute autre information pertinente sur le problème.
|
||||
|
||||
## 🔗 Liens Utiles
|
||||
|
||||
- [Documentation](docs/)
|
||||
- [Guide de Dépannage](docs/TROUBLESHOOTING.md)
|
||||
- [Issues Similaires](https://git.4nkweb.com/4nk/4NK_node/issues?q=is%3Aissue+is%3Aopen+label%3Abug)
|
||||
|
||||
---
|
||||
|
||||
**Merci de votre contribution !** 🙏
|
||||
|
||||
@ -1,157 +0,0 @@
|
||||
---
|
||||
name: Feature Request
|
||||
about: Proposer une nouvelle fonctionnalité pour sdk_signer
|
||||
title: '[FEATURE] '
|
||||
labels: ['enhancement', 'needs-triage']
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
## 🚀 Résumé
|
||||
|
||||
Description claire et concise de la fonctionnalité souhaitée.
|
||||
|
||||
## 💡 Motivation
|
||||
|
||||
Pourquoi cette fonctionnalité est-elle nécessaire ? Quels problèmes résout-elle ?
|
||||
|
||||
### Problèmes Actuels
|
||||
- Problème 1
|
||||
- Problème 2
|
||||
- Problème 3
|
||||
|
||||
### Avantages de la Solution
|
||||
- Avantage 1
|
||||
- Avantage 2
|
||||
- Avantage 3
|
||||
|
||||
## 🎯 Proposition
|
||||
|
||||
Description détaillée de la fonctionnalité proposée.
|
||||
|
||||
### Fonctionnalités Principales
|
||||
- [ ] Fonctionnalité 1
|
||||
- [ ] Fonctionnalité 2
|
||||
- [ ] Fonctionnalité 3
|
||||
|
||||
### Interface Utilisateur
|
||||
Description de l'interface utilisateur si applicable.
|
||||
|
||||
### API Changes
|
||||
Description des changements d'API si applicable.
|
||||
|
||||
## 🔄 Alternatives Considérées
|
||||
|
||||
Autres solutions envisagées et pourquoi elles n'ont pas été choisies.
|
||||
|
||||
### Alternative 1
|
||||
- **Description** : ...
|
||||
- **Pourquoi rejetée** : ...
|
||||
|
||||
### Alternative 2
|
||||
- **Description** : ...
|
||||
- **Pourquoi rejetée** : ...
|
||||
|
||||
## 📊 Impact
|
||||
|
||||
### Impact sur les Utilisateurs
|
||||
- Impact positif 1
|
||||
- Impact positif 2
|
||||
- Impact négatif potentiel (si applicable)
|
||||
|
||||
### Impact sur l'Architecture
|
||||
- Changements nécessaires
|
||||
- Compatibilité avec l'existant
|
||||
- Performance
|
||||
|
||||
### Impact sur la Maintenance
|
||||
- Complexité ajoutée
|
||||
- Tests nécessaires
|
||||
- Documentation requise
|
||||
|
||||
## 💻 Exemples d'Utilisation
|
||||
|
||||
### Cas d'Usage 1
|
||||
```bash
|
||||
# Exemple de commande ou configuration
|
||||
```
|
||||
|
||||
### Cas d'Usage 2
|
||||
```python
|
||||
# Exemple de code Python
|
||||
```
|
||||
|
||||
### Cas d'Usage 3
|
||||
```javascript
|
||||
// Exemple de code JavaScript
|
||||
```
|
||||
|
||||
## 🧪 Tests
|
||||
|
||||
### Tests Nécessaires
|
||||
- [ ] Tests unitaires
|
||||
- [ ] Tests d'intégration
|
||||
- [ ] Tests de performance
|
||||
- [ ] Tests de sécurité
|
||||
- [ ] Tests de compatibilité
|
||||
|
||||
### Scénarios de Test
|
||||
- Scénario 1
|
||||
- Scénario 2
|
||||
- Scénario 3
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
### Documentation Requise
|
||||
- [ ] Guide d'utilisation
|
||||
- [ ] Documentation API
|
||||
- [ ] Exemples de code
|
||||
- [ ] Guide de migration
|
||||
- [ ] FAQ
|
||||
|
||||
## 🔧 Implémentation
|
||||
|
||||
### Étapes Proposées
|
||||
1. **Phase 1** : [Description]
|
||||
2. **Phase 2** : [Description]
|
||||
3. **Phase 3** : [Description]
|
||||
|
||||
### Estimation de Temps
|
||||
- **Développement** : X jours/semaines
|
||||
- **Tests** : X jours/semaines
|
||||
- **Documentation** : X jours/semaines
|
||||
- **Total** : X jours/semaines
|
||||
|
||||
### Ressources Nécessaires
|
||||
- Développeur(s)
|
||||
- Testeur(s)
|
||||
- Documentateur(s)
|
||||
- Infrastructure
|
||||
|
||||
## 🎯 Critères de Succès
|
||||
|
||||
Comment mesurer le succès de cette fonctionnalité ?
|
||||
|
||||
- [ ] Critère 1
|
||||
- [ ] Critère 2
|
||||
- [ ] Critère 3
|
||||
|
||||
## 🔗 Liens Utiles
|
||||
|
||||
- [Documentation existante](docs/)
|
||||
- [Issues similaires](https://git.4nkweb.com/4nk/4NK_node/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement)
|
||||
- [Roadmap](https://git.4nkweb.com/4nk/4NK_node/projects)
|
||||
- [Discussions](https://git.4nkweb.com/4nk/4NK_node/issues)
|
||||
|
||||
## 📋 Checklist
|
||||
|
||||
- [ ] J'ai vérifié que cette fonctionnalité n'existe pas déjà
|
||||
- [ ] J'ai lu la documentation existante
|
||||
- [ ] J'ai vérifié les issues similaires
|
||||
- [ ] J'ai fourni des exemples d'utilisation
|
||||
- [ ] J'ai considéré l'impact sur l'existant
|
||||
- [ ] J'ai proposé des tests
|
||||
|
||||
---
|
||||
|
||||
**Merci de votre contribution à l'amélioration de sdk_signer !** 🌟
|
||||
|
||||
@ -1,181 +0,0 @@
|
||||
# Pull Request - sdk_signer
|
||||
|
||||
## 📋 Description
|
||||
|
||||
Description claire et concise des changements apportés.
|
||||
|
||||
### Type de Changement
|
||||
- [ ] 🐛 Bug fix
|
||||
- [ ] ✨ Nouvelle fonctionnalité
|
||||
- [ ] 📚 Documentation
|
||||
- [ ] 🧪 Tests
|
||||
- [ ] 🔧 Refactoring
|
||||
- [ ] 🚀 Performance
|
||||
- [ ] 🔒 Sécurité
|
||||
- [ ] 🎨 Style/UI
|
||||
- [ ] 🏗️ Architecture
|
||||
- [ ] 📦 Build/CI
|
||||
|
||||
### Composants Affectés
|
||||
- [ ] Bitcoin Core
|
||||
- [ ] Blindbit
|
||||
- [ ] SDK Relay
|
||||
- [ ] Tor
|
||||
- [ ] Docker/Infrastructure
|
||||
- [ ] Tests
|
||||
- [ ] Documentation
|
||||
- [ ] Scripts
|
||||
|
||||
## 🔗 Issue(s) Liée(s)
|
||||
|
||||
Fixes #(issue)
|
||||
Relates to #(issue)
|
||||
|
||||
## 🧪 Tests
|
||||
|
||||
### Tests Exécutés
|
||||
- [ ] Tests unitaires
|
||||
- [ ] Tests d'intégration
|
||||
- [ ] Tests de connectivité
|
||||
- [ ] Tests externes
|
||||
- [ ] Tests de performance
|
||||
|
||||
### Commandes de Test
|
||||
```bash
|
||||
# Tests complets
|
||||
./tests/run_all_tests.sh
|
||||
|
||||
# Tests spécifiques
|
||||
./tests/run_unit_tests.sh
|
||||
./tests/run_integration_tests.sh
|
||||
```
|
||||
|
||||
### Résultats des Tests
|
||||
```
|
||||
Résultats des tests ici
|
||||
```
|
||||
|
||||
## 📸 Captures d'Écran
|
||||
|
||||
Si applicable, ajoutez des captures d'écran pour les changements visuels.
|
||||
|
||||
## 🔧 Changements Techniques
|
||||
|
||||
### Fichiers Modifiés
|
||||
- `fichier1.rs` - Description des changements
|
||||
- `fichier2.py` - Description des changements
|
||||
- `docker-compose.yml` - Description des changements
|
||||
|
||||
### Nouveaux Fichiers
|
||||
- `nouveau_fichier.rs` - Description
|
||||
- `nouveau_script.sh` - Description
|
||||
|
||||
### Fichiers Supprimés
|
||||
- `ancien_fichier.rs` - Raison de la suppression
|
||||
|
||||
### Changements de Configuration
|
||||
```yaml
|
||||
# Exemple de changement de configuration
|
||||
service:
|
||||
new_option: value
|
||||
```
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
### Documentation Mise à Jour
|
||||
- [ ] README.md
|
||||
- [ ] docs/INSTALLATION.md
|
||||
- [ ] docs/USAGE.md
|
||||
- [ ] docs/API.md
|
||||
- [ ] docs/ARCHITECTURE.md
|
||||
|
||||
### Nouvelle Documentation
|
||||
- [ ] Nouveau guide créé
|
||||
- [ ] Exemples ajoutés
|
||||
- [ ] API documentée
|
||||
|
||||
## 🔍 Code Review Checklist
|
||||
|
||||
### Code Quality
|
||||
- [ ] Le code suit les standards du projet
|
||||
- [ ] Les noms de variables/fonctions sont clairs
|
||||
- [ ] Les commentaires sont appropriés
|
||||
- [ ] Pas de code mort ou commenté
|
||||
- [ ] Gestion d'erreurs appropriée
|
||||
|
||||
### Performance
|
||||
- [ ] Pas de régression de performance
|
||||
- [ ] Optimisations appliquées si nécessaire
|
||||
- [ ] Tests de performance ajoutés
|
||||
|
||||
### Sécurité
|
||||
- [ ] Pas de vulnérabilités introduites
|
||||
- [ ] Validation des entrées utilisateur
|
||||
- [ ] Gestion sécurisée des secrets
|
||||
|
||||
### Tests
|
||||
- [ ] Couverture de tests suffisante
|
||||
- [ ] Tests pour les cas d'erreur
|
||||
- [ ] Tests d'intégration si nécessaire
|
||||
|
||||
### Documentation
|
||||
- [ ] Code auto-documenté
|
||||
- [ ] Documentation mise à jour
|
||||
- [ ] Exemples fournis
|
||||
|
||||
## 🚀 Déploiement
|
||||
|
||||
### Impact sur le Déploiement
|
||||
- [ ] Aucun impact
|
||||
- [ ] Migration de données requise
|
||||
- [ ] Changement de configuration
|
||||
- [ ] Redémarrage des services
|
||||
|
||||
### Étapes de Déploiement
|
||||
```bash
|
||||
# Étapes pour déployer les changements
|
||||
```
|
||||
|
||||
## 📊 Métriques
|
||||
|
||||
### Impact sur les Performances
|
||||
- Temps de réponse : +/- X%
|
||||
- Utilisation mémoire : +/- X%
|
||||
- Utilisation CPU : +/- X%
|
||||
|
||||
### Impact sur la Stabilité
|
||||
- Taux d'erreur : +/- X%
|
||||
- Disponibilité : +/- X%
|
||||
|
||||
## 🔄 Compatibilité
|
||||
|
||||
### Compatibilité Ascendante
|
||||
- [ ] Compatible avec les versions précédentes
|
||||
- [ ] Migration automatique
|
||||
- [ ] Migration manuelle requise
|
||||
|
||||
### Compatibilité Descendante
|
||||
- [ ] Compatible avec les futures versions
|
||||
- [ ] API stable
|
||||
- [ ] Configuration stable
|
||||
|
||||
## 🎯 Critères de Succès
|
||||
|
||||
- [ ] Critère 1
|
||||
- [ ] Critère 2
|
||||
- [ ] Critère 3
|
||||
|
||||
## 📝 Notes Supplémentaires
|
||||
|
||||
Informations supplémentaires importantes pour les reviewers.
|
||||
|
||||
## 🔗 Liens Utiles
|
||||
|
||||
- [Documentation](docs/)
|
||||
- [Tests](tests/)
|
||||
- [Issues liées](https://git.4nkweb.com/4nk/4NK_node/issues)
|
||||
|
||||
---
|
||||
|
||||
**Merci pour votre contribution !** 🙏
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
# .gitea
|
||||
|
||||
Fichiers de configuration Gitea (issues, templates, workflows) à ajouter au besoin.
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
# LOCAL_OVERRIDES.yml — dérogations locales contrôlées
|
||||
overrides:
|
||||
- path: ".gitea/workflows/ci.yml"
|
||||
reason: "spécificité d’environnement"
|
||||
owner: "@maintainer_handle"
|
||||
expires: "2025-12-31"
|
||||
- path: "scripts/auto-ssh-push.sh"
|
||||
reason: "flux particulier temporaire"
|
||||
owner: "@maintainer_handle"
|
||||
expires: "2025-10-01"
|
||||
policy:
|
||||
allow_only_listed_paths: true
|
||||
require_expiry: true
|
||||
audit_in_ci: true
|
||||
|
||||
86
.gitea/workflows/build-int-dev.yml
Normal file
86
.gitea/workflows/build-int-dev.yml
Normal file
@ -0,0 +1,86 @@
|
||||
name: build-and-push-int-dev
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- int-dev
|
||||
|
||||
jobs:
|
||||
build_push:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '19'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci --include=dev
|
||||
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y clang llvm-dev libclang-dev build-essential
|
||||
|
||||
- name: Setup Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y clang llvm-dev libclang-dev build-essential perl
|
||||
|
||||
- name: Install wasm-pack and wasm-bindgen
|
||||
run: |
|
||||
cargo install wasm-pack
|
||||
cargo install wasm-bindgen-cli --version 0.2.103
|
||||
|
||||
- name: Clone sdk_client
|
||||
run: |
|
||||
git clone -b dev https://git.4nkweb.com/4nk/sdk_client.git ./sdk_client
|
||||
|
||||
- name: Build WebAssembly
|
||||
run: |
|
||||
wasm-pack build --out-dir ./pkg ./sdk_client --target nodejs --dev
|
||||
mkdir -p ./pkg
|
||||
cp -r ./sdk_client/pkg/* ./pkg/
|
||||
|
||||
- name: Build project
|
||||
run: npm run build
|
||||
|
||||
- name: Run tests
|
||||
run: npx vitest run
|
||||
|
||||
- name: Docker login (git.4nkweb.com)
|
||||
shell: bash
|
||||
env:
|
||||
REG_USER: ${{ secrets.USER }}
|
||||
REG_TOKEN: ${{ secrets.TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
echo "$REG_TOKEN" | docker login git.4nkweb.com -u "$REG_USER" --password-stdin
|
||||
|
||||
- name: Build image (target int-dev)
|
||||
shell: bash
|
||||
env:
|
||||
DOCKER_BUILDKIT: "1"
|
||||
run: |
|
||||
set -euo pipefail
|
||||
docker build \
|
||||
-t git.4nkweb.com/4nk/sdk_signer:int-dev \
|
||||
-f Dockerfile .
|
||||
|
||||
- name: Push image
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
docker push git.4nkweb.com/4nk/sdk_signer:int-dev
|
||||
@ -1,486 +0,0 @@
|
||||
name: CI - 4NK Node
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
tags:
|
||||
- 'v*'
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
|
||||
env:
|
||||
RUST_VERSION: '1.70'
|
||||
DOCKER_COMPOSE_VERSION: '2.20.0'
|
||||
CI_SKIP: 'true'
|
||||
|
||||
jobs:
|
||||
# Job de vérification du code
|
||||
code-quality:
|
||||
name: Code Quality
|
||||
runs-on: [self-hosted, linux]
|
||||
if: ${{ env.CI_SKIP != 'true' }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
override: true
|
||||
|
||||
- name: Cache Rust dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
target
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cargo-
|
||||
|
||||
- name: Run clippy
|
||||
run: |
|
||||
cd sdk_relay
|
||||
cargo clippy --all-targets --all-features -- -D warnings
|
||||
|
||||
- name: Run rustfmt
|
||||
run: |
|
||||
cd sdk_relay
|
||||
cargo fmt --all -- --check
|
||||
|
||||
- name: Check documentation
|
||||
run: |
|
||||
cd sdk_relay
|
||||
cargo doc --no-deps
|
||||
|
||||
- name: Check for TODO/FIXME
|
||||
run: |
|
||||
if grep -r "TODO\|FIXME" . --exclude-dir=.git --exclude-dir=target; then
|
||||
echo "Found TODO/FIXME comments. Please address them."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Job de tests unitaires
|
||||
unit-tests:
|
||||
name: Unit Tests
|
||||
runs-on: [self-hosted, linux]
|
||||
if: ${{ env.CI_SKIP != 'true' }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
override: true
|
||||
|
||||
- name: Cache Rust dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
target
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cargo-
|
||||
|
||||
- name: Run unit tests
|
||||
run: |
|
||||
cd sdk_relay
|
||||
cargo test --lib --bins
|
||||
|
||||
- name: Run integration tests
|
||||
run: |
|
||||
cd sdk_relay
|
||||
cargo test --tests
|
||||
|
||||
# Job de tests d'intégration
|
||||
integration-tests:
|
||||
name: Integration Tests
|
||||
runs-on: [self-hosted, linux]
|
||||
if: ${{ env.CI_SKIP != 'true' }}
|
||||
|
||||
services:
|
||||
docker:
|
||||
image: docker:24.0.5
|
||||
options: >-
|
||||
--health-cmd "docker info"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 2375:2375
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Build Docker images
|
||||
run: |
|
||||
docker build -t 4nk-node-bitcoin ./bitcoin
|
||||
docker build -t 4nk-node-blindbit ./blindbit
|
||||
docker build -t 4nk-node-sdk-relay -f ./sdk_relay/Dockerfile ..
|
||||
|
||||
- name: Run integration tests
|
||||
run: |
|
||||
# Tests de connectivité de base
|
||||
./tests/run_connectivity_tests.sh || true
|
||||
|
||||
# Tests d'intégration
|
||||
./tests/run_integration_tests.sh || true
|
||||
|
||||
- name: Upload test results
|
||||
uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: test-results
|
||||
path: |
|
||||
tests/logs/
|
||||
tests/reports/
|
||||
retention-days: 7
|
||||
|
||||
# Job de tests de sécurité
|
||||
security-tests:
|
||||
name: Security Tests
|
||||
runs-on: [self-hosted, linux]
|
||||
if: ${{ env.CI_SKIP != 'true' }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
override: true
|
||||
|
||||
- name: Run cargo audit
|
||||
run: |
|
||||
cd sdk_relay
|
||||
cargo audit --deny warnings
|
||||
|
||||
- name: Check for secrets
|
||||
run: |
|
||||
# Vérifier les secrets potentiels
|
||||
if grep -r "password\|secret\|key\|token" . --exclude-dir=.git --exclude-dir=target --exclude=*.md; then
|
||||
echo "Potential secrets found. Please review."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Check file permissions
|
||||
run: |
|
||||
# Vérifier les permissions sensibles
|
||||
find . -type f -perm /0111 -name "*.conf" -o -name "*.key" -o -name "*.pem" | while read file; do
|
||||
if [[ $(stat -c %a "$file") != "600" ]]; then
|
||||
echo "Warning: $file has insecure permissions"
|
||||
fi
|
||||
done
|
||||
|
||||
# Job de build et test Docker
|
||||
docker-build:
|
||||
name: Docker Build & Test
|
||||
runs-on: [self-hosted, linux]
|
||||
if: ${{ env.CI_SKIP != 'true' }}
|
||||
|
||||
services:
|
||||
docker:
|
||||
image: docker:24.0.5
|
||||
options: >-
|
||||
--health-cmd "docker info"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 2375:2375
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Build and test Bitcoin Core
|
||||
run: |
|
||||
docker build -t 4nk-node-bitcoin:test ./bitcoin
|
||||
docker run --rm 4nk-node-bitcoin:test bitcoin-cli --version
|
||||
|
||||
- name: Build and test Blindbit
|
||||
run: |
|
||||
docker build -t 4nk-node-blindbit:test ./blindbit
|
||||
docker run --rm 4nk-node-blindbit:test --version || true
|
||||
|
||||
- name: Build and test SDK Relay
|
||||
run: |
|
||||
docker build -t 4nk-node-sdk-relay:test -f ./sdk_relay/Dockerfile ..
|
||||
docker run --rm 4nk-node-sdk-relay:test --version || true
|
||||
|
||||
- name: Test Docker Compose
|
||||
run: |
|
||||
docker-compose config
|
||||
docker-compose build --no-cache
|
||||
|
||||
# Job de tests de documentation
|
||||
documentation-tests:
|
||||
name: Documentation Tests
|
||||
runs-on: [self-hosted, linux]
|
||||
if: ${{ env.CI_SKIP != 'true' }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Check markdown links
|
||||
run: |
|
||||
# Vérification basique des liens markdown
|
||||
find . -name "*.md" -exec grep -l "\[.*\](" {} \; | while read file; do
|
||||
echo "Checking links in $file"
|
||||
done
|
||||
|
||||
markdownlint:
|
||||
name: Markdown Lint
|
||||
runs-on: [self-hosted, linux]
|
||||
if: ${{ env.CI_SKIP != 'true' }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
- name: Run markdownlint
|
||||
run: |
|
||||
npm --version || (curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt-get install -y nodejs)
|
||||
npx -y markdownlint-cli@0.42.0 "**/*.md" --ignore "archive/**"
|
||||
|
||||
- name: Check documentation structure
|
||||
run: |
|
||||
# Vérifier la présence des fichiers de documentation essentiels
|
||||
required_files=(
|
||||
"README.md"
|
||||
"LICENSE"
|
||||
"CONTRIBUTING.md"
|
||||
"CHANGELOG.md"
|
||||
"CODE_OF_CONDUCT.md"
|
||||
"SECURITY.md"
|
||||
)
|
||||
|
||||
for file in "${required_files[@]}"; do
|
||||
if [[ ! -f "$file" ]]; then
|
||||
echo "Missing required documentation file: $file"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
bash-required:
|
||||
name: Bash Requirement
|
||||
runs-on: [self-hosted, linux]
|
||||
if: ${{ env.CI_SKIP != 'true' }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
- name: Verify bash availability
|
||||
run: |
|
||||
if ! command -v bash >/dev/null 2>&1; then
|
||||
echo "bash is required for agents and scripts"; exit 1;
|
||||
fi
|
||||
- name: Verify agents runner exists
|
||||
run: |
|
||||
if [ ! -f scripts/agents/run.sh ]; then
|
||||
echo "scripts/agents/run.sh is missing"; exit 1;
|
||||
fi
|
||||
|
||||
agents-smoke:
|
||||
name: Agents Smoke (no AI)
|
||||
runs-on: [self-hosted, linux]
|
||||
if: ${{ env.CI_SKIP != 'true' }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
- name: Ensure agents scripts executable
|
||||
run: |
|
||||
chmod +x scripts/agents/*.sh || true
|
||||
- name: Run agents without AI
|
||||
env:
|
||||
OPENAI_API_KEY: ""
|
||||
run: |
|
||||
scripts/agents/run.sh
|
||||
- name: Upload agents reports
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: agents-reports
|
||||
path: tests/reports/agents
|
||||
|
||||
openia-agents:
|
||||
name: Agents with OpenIA
|
||||
runs-on: [self-hosted, linux]
|
||||
if: ${{ env.CI_SKIP != 'true' && secrets.OPENAI_API_KEY != '' }}
|
||||
env:
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
OPENAI_MODEL: ${{ vars.OPENAI_MODEL }}
|
||||
OPENAI_API_BASE: ${{ vars.OPENAI_API_BASE }}
|
||||
OPENAI_TEMPERATURE: ${{ vars.OPENAI_TEMPERATURE }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
- name: Ensure agents scripts executable
|
||||
run: |
|
||||
chmod +x scripts/agents/*.sh || true
|
||||
- name: Run agents with AI
|
||||
run: |
|
||||
scripts/agents/run.sh
|
||||
- name: Upload agents reports
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: agents-reports-ai
|
||||
path: tests/reports/agents
|
||||
|
||||
deployment-checks:
|
||||
name: Deployment Checks
|
||||
runs-on: [self-hosted, linux]
|
||||
if: ${{ env.CI_SKIP != 'true' }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
- name: Validate deployment documentation
|
||||
run: |
|
||||
if [ ! -f docs/DEPLOYMENT.md ]; then
|
||||
echo "Missing docs/DEPLOYMENT.md"; exit 1; fi
|
||||
if [ ! -f docs/SSH_UPDATE.md ]; then
|
||||
echo "Missing docs/SSH_UPDATE.md"; exit 1; fi
|
||||
- name: Ensure tests directories exist
|
||||
run: |
|
||||
mkdir -p tests/logs tests/reports || true
|
||||
echo "OK"
|
||||
|
||||
security-audit:
|
||||
name: Security Audit
|
||||
runs-on: [self-hosted, linux]
|
||||
if: ${{ env.CI_SKIP != 'true' }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
- name: Ensure scripts executable
|
||||
run: |
|
||||
chmod +x scripts/security/audit.sh || true
|
||||
- name: Run template security audit
|
||||
run: |
|
||||
if [ -f scripts/security/audit.sh ]; then
|
||||
./scripts/security/audit.sh
|
||||
else
|
||||
echo "No security audit script (ok)"
|
||||
fi
|
||||
|
||||
# Job de release guard (cohérence release)
|
||||
release-guard:
|
||||
name: Release Guard
|
||||
runs-on: [self-hosted, linux]
|
||||
needs: [code-quality, unit-tests, documentation-tests, markdownlint, security-audit, deployment-checks, bash-required]
|
||||
if: ${{ env.CI_SKIP != 'true' }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Ensure guard scripts are executable
|
||||
run: |
|
||||
chmod +x scripts/release/guard.sh || true
|
||||
chmod +x scripts/checks/version_alignment.sh || true
|
||||
|
||||
- name: Version alignment check
|
||||
run: |
|
||||
if [ -f scripts/checks/version_alignment.sh ]; then
|
||||
./scripts/checks/version_alignment.sh
|
||||
else
|
||||
echo "No version alignment script (ok)"
|
||||
fi
|
||||
|
||||
- name: Release guard (CI verify)
|
||||
env:
|
||||
RELEASE_TYPE: ci-verify
|
||||
run: |
|
||||
if [ -f scripts/release/guard.sh ]; then
|
||||
./scripts/release/guard.sh
|
||||
else
|
||||
echo "No guard script (ok)"
|
||||
fi
|
||||
|
||||
release-create:
|
||||
name: Create Release (Gitea API)
|
||||
runs-on: ubuntu-latest
|
||||
needs: [release-guard]
|
||||
if: ${{ env.CI_SKIP != 'true' && startsWith(github.ref, 'refs/tags/') }}
|
||||
env:
|
||||
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
BASE_URL: ${{ vars.BASE_URL }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
- name: Validate token and publish release
|
||||
run: |
|
||||
set -e
|
||||
if [ -z "${RELEASE_TOKEN}" ]; then
|
||||
echo "RELEASE_TOKEN secret is missing" >&2; exit 1; fi
|
||||
if [ -z "${BASE_URL}" ]; then
|
||||
BASE_URL="https://git.4nkweb.com"; fi
|
||||
TAG="${GITHUB_REF##*/}"
|
||||
REPO="${GITHUB_REPOSITORY}"
|
||||
OWNER="${REPO%%/*}"
|
||||
NAME="${REPO##*/}"
|
||||
echo "Publishing release ${TAG} to ${BASE_URL}/${OWNER}/${NAME}"
|
||||
curl -sSf -X POST \
|
||||
-H "Authorization: token ${RELEASE_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"tag_name\":\"${TAG}\",\"name\":\"${TAG}\",\"draft\":false,\"prerelease\":false}" \
|
||||
"${BASE_URL}/api/v1/repos/${OWNER}/${NAME}/releases" >/dev/null
|
||||
echo "Release created"
|
||||
|
||||
# Job de tests de performance
|
||||
performance-tests:
|
||||
name: Performance Tests
|
||||
runs-on: [self-hosted, linux]
|
||||
if: ${{ env.CI_SKIP != 'true' }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
override: true
|
||||
|
||||
- name: Run performance tests
|
||||
run: |
|
||||
cd sdk_relay
|
||||
cargo test --release --test performance_tests || true
|
||||
|
||||
- name: Check memory usage
|
||||
run: |
|
||||
# Tests de base de consommation mémoire
|
||||
echo "Performance tests completed"
|
||||
|
||||
# Job de notification
|
||||
notify:
|
||||
name: Notify
|
||||
runs-on: [self-hosted, linux]
|
||||
needs: [code-quality, unit-tests, integration-tests, security-tests, docker-build, documentation-tests]
|
||||
if: ${{ env.CI_SKIP != 'true' && always() }}
|
||||
|
||||
steps:
|
||||
- name: Notify success
|
||||
if: needs.code-quality.result == 'success' && needs.unit-tests.result == 'success' && needs.integration-tests.result == 'success' && needs.security-tests.result == 'success' && needs.docker-build.result == 'success' && needs.documentation-tests.result == 'success'
|
||||
run: |
|
||||
echo "✅ All tests passed successfully!"
|
||||
|
||||
- name: Notify failure
|
||||
if: needs.code-quality.result == 'failure' || needs.unit-tests.result == 'failure' || needs.integration-tests.result == 'failure' || needs.security-tests.result == 'failure' || needs.docker-build.result == 'failure' || needs.documentation-tests.result == 'failure'
|
||||
run: |
|
||||
echo "❌ Some tests failed!"
|
||||
exit 1
|
||||
@ -1,352 +0,0 @@
|
||||
name: CI - sdk_signer
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
|
||||
env:
|
||||
RUST_VERSION: '1.70'
|
||||
DOCKER_COMPOSE_VERSION: '2.20.0'
|
||||
|
||||
jobs:
|
||||
# Job de vérification du code
|
||||
code-quality:
|
||||
name: Code Quality
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
override: true
|
||||
|
||||
- name: Cache Rust dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
target
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cargo-
|
||||
|
||||
- name: Run clippy
|
||||
run: |
|
||||
cargo clippy --all-targets --all-features -- -D warnings
|
||||
|
||||
- name: Run rustfmt
|
||||
run: |
|
||||
cargo fmt --all -- --check
|
||||
|
||||
- name: Check documentation
|
||||
run: |
|
||||
cargo doc --no-deps
|
||||
|
||||
- name: Check for TODO/FIXME
|
||||
run: |
|
||||
if grep -r "TODO\|FIXME" . --exclude-dir=.git --exclude-dir=target; then
|
||||
echo "Found TODO/FIXME comments. Please address them."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Job de tests unitaires
|
||||
unit-tests:
|
||||
name: Unit Tests
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
override: true
|
||||
|
||||
- name: Cache Rust dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
target
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cargo-
|
||||
|
||||
- name: Run unit tests
|
||||
run: |
|
||||
cargo test --lib --bins
|
||||
|
||||
- name: Run integration tests
|
||||
run: |
|
||||
cargo test --tests
|
||||
|
||||
# Job de tests d'intégration
|
||||
integration-tests:
|
||||
name: Integration Tests
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
services:
|
||||
docker:
|
||||
image: docker:24.0.5
|
||||
options: >-
|
||||
--health-cmd "docker info"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 2375:2375
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Build Docker images
|
||||
run: |
|
||||
docker build -t 4nk-node-bitcoin ./bitcoin
|
||||
docker build -t 4nk-node-blindbit ./blindbit
|
||||
docker build -t 4nk-node-sdk-relay -f ./sdk_relay/Dockerfile ..
|
||||
|
||||
- name: Run integration tests
|
||||
run: |
|
||||
# Tests de connectivité de base
|
||||
./tests/run_connectivity_tests.sh || true
|
||||
|
||||
# Tests d'intégration
|
||||
./tests/run_integration_tests.sh || true
|
||||
|
||||
- name: Upload test results
|
||||
uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: test-results
|
||||
path: |
|
||||
tests/logs/
|
||||
tests/reports/
|
||||
retention-days: 7
|
||||
|
||||
# Job de tests de sécurité
|
||||
security-tests:
|
||||
name: Security Tests
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
override: true
|
||||
|
||||
- name: Run cargo audit
|
||||
run: |
|
||||
cargo audit --deny warnings
|
||||
|
||||
- name: Check for secrets
|
||||
run: |
|
||||
# Vérifier les secrets potentiels
|
||||
if grep -r "password\|secret\|key\|token" . --exclude-dir=.git --exclude-dir=target --exclude=*.md; then
|
||||
echo "Potential secrets found. Please review."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Check file permissions
|
||||
run: |
|
||||
# Vérifier les permissions sensibles
|
||||
find . -type f -perm /0111 -name "*.conf" -o -name "*.key" -o -name "*.pem" | while read file; do
|
||||
if [[ $(stat -c %a "$file") != "600" ]]; then
|
||||
echo "Warning: $file has insecure permissions"
|
||||
fi
|
||||
done
|
||||
|
||||
# Job de build et test Docker
|
||||
docker-build:
|
||||
name: Docker Build & Test
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
services:
|
||||
docker:
|
||||
image: docker:24.0.5
|
||||
options: >-
|
||||
--health-cmd "docker info"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 2375:2375
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Build and test Bitcoin Core
|
||||
run: |
|
||||
docker build -t 4nk-node-bitcoin:test ./bitcoin
|
||||
docker run --rm 4nk-node-bitcoin:test bitcoin-cli --version
|
||||
|
||||
- name: Build and test Blindbit
|
||||
run: |
|
||||
docker build -t 4nk-node-blindbit:test ./blindbit
|
||||
docker run --rm 4nk-node-blindbit:test --version || true
|
||||
|
||||
- name: Build and test SDK Relay
|
||||
run: |
|
||||
docker build -t 4nk-node-sdk-relay:test -f ./sdk_relay/Dockerfile ..
|
||||
docker run --rm 4nk-node-sdk-relay:test --version || true
|
||||
|
||||
- name: Test Docker Compose
|
||||
run: |
|
||||
docker-compose config
|
||||
docker-compose build --no-cache
|
||||
|
||||
# Job de tests de documentation
|
||||
documentation-tests:
|
||||
name: Documentation Tests
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Check markdown links
|
||||
run: |
|
||||
# Vérification basique des liens markdown
|
||||
find . -name "*.md" -exec grep -l "\[.*\](" {} \; | while read file; do
|
||||
echo "Checking links in $file"
|
||||
done
|
||||
|
||||
- name: Check documentation structure
|
||||
run: |
|
||||
# Vérifier la présence des fichiers de documentation essentiels
|
||||
required_files=(
|
||||
"README.md"
|
||||
"LICENSE"
|
||||
"CONTRIBUTING.md"
|
||||
"CHANGELOG.md"
|
||||
"CODE_OF_CONDUCT.md"
|
||||
"SECURITY.md"
|
||||
"docs/INDEX.md"
|
||||
"docs/INSTALLATION.md"
|
||||
"docs/USAGE.md"
|
||||
)
|
||||
|
||||
for file in "${required_files[@]}"; do
|
||||
if [[ ! -f "$file" ]]; then
|
||||
echo "Missing required documentation file: $file"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Validate documentation
|
||||
run: |
|
||||
echo "Documentation checks completed"
|
||||
|
||||
security-audit:
|
||||
name: Security Audit
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
- name: Ensure scripts executable
|
||||
run: |
|
||||
chmod +x scripts/security/audit.sh || true
|
||||
- name: Run template security audit
|
||||
run: |
|
||||
if [ -f scripts/security/audit.sh ]; then
|
||||
./scripts/security/audit.sh
|
||||
else
|
||||
echo "No security audit script (ok)"
|
||||
fi
|
||||
|
||||
# Job de release guard (cohérence release)
|
||||
release-guard:
|
||||
name: Release Guard
|
||||
runs-on: ubuntu-latest
|
||||
needs: [code-quality, unit-tests, documentation-tests, security-audit]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Ensure guard scripts are executable
|
||||
run: |
|
||||
chmod +x scripts/release/guard.sh || true
|
||||
chmod +x scripts/checks/version_alignment.sh || true
|
||||
|
||||
- name: Version alignment check
|
||||
run: |
|
||||
if [ -f scripts/checks/version_alignment.sh ]; then
|
||||
./scripts/checks/version_alignment.sh
|
||||
else
|
||||
echo "No version alignment script (ok)"
|
||||
fi
|
||||
|
||||
- name: Release guard (CI verify)
|
||||
env:
|
||||
RELEASE_TYPE: ci-verify
|
||||
run: |
|
||||
if [ -f scripts/release/guard.sh ]; then
|
||||
./scripts/release/guard.sh
|
||||
else
|
||||
echo "No guard script (ok)"
|
||||
fi
|
||||
|
||||
# Job de tests de performance
|
||||
performance-tests:
|
||||
name: Performance Tests
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ env.RUST_VERSION }}
|
||||
override: true
|
||||
|
||||
- name: Run performance tests
|
||||
run: |
|
||||
cd sdk_relay
|
||||
cargo test --release --test performance_tests || true
|
||||
|
||||
- name: Check memory usage
|
||||
run: |
|
||||
# Tests de base de consommation mémoire
|
||||
echo "Performance tests completed"
|
||||
|
||||
# Job de notification
|
||||
notify:
|
||||
name: Notify
|
||||
runs-on: ubuntu-latest
|
||||
needs: [code-quality, unit-tests, integration-tests, security-tests, docker-build, documentation-tests]
|
||||
if: always()
|
||||
|
||||
steps:
|
||||
- name: Notify success
|
||||
if: needs.code-quality.result == 'success' && needs.unit-tests.result == 'success' && needs.integration-tests.result == 'success' && needs.security-tests.result == 'success' && needs.docker-build.result == 'success' && needs.documentation-tests.result == 'success'
|
||||
run: |
|
||||
echo "✅ All tests passed successfully!"
|
||||
|
||||
- name: Notify failure
|
||||
if: needs.code-quality.result == 'failure' || needs.unit-tests.result == 'failure' || needs.integration-tests.result == 'failure' || needs.security-tests.result == 'failure' || needs.docker-build.result == 'failure' || needs.documentation-tests.result == 'failure'
|
||||
run: |
|
||||
echo "❌ Some tests failed!"
|
||||
exit 1
|
||||
@ -1,36 +0,0 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*.*.*'
|
||||
|
||||
jobs:
|
||||
docker-release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
- name: Login to DockerHub
|
||||
if: ${{ secrets.DOCKERHUB_USERNAME && secrets.DOCKERHUB_TOKEN }}
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Extract version
|
||||
id: vars
|
||||
run: echo "version=${GITHUB_REF##*/}" >> $GITHUB_OUTPUT
|
||||
- name: Build image
|
||||
run: docker build -t ${DOCKER_IMAGE:-sdk-signer}:${{ steps.vars.outputs.version }} .
|
||||
- name: Push image
|
||||
if: ${{ secrets.DOCKERHUB_USERNAME && secrets.DOCKERHUB_TOKEN }}
|
||||
run: |
|
||||
IMAGE=${DOCKER_IMAGE:-sdk-signer}
|
||||
docker tag $IMAGE:${{ steps.vars.outputs.version }} $IMAGE:latest
|
||||
docker push $IMAGE:${{ steps.vars.outputs.version }}
|
||||
docker push $IMAGE:latest
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
# .gitea/workflows/template-sync.yml — synchronisation et contrôles d’intégrité
|
||||
name: 4NK Template Sync
|
||||
on:
|
||||
schedule: # planification régulière
|
||||
- cron: "0 4 * * 1" # exécution hebdomadaire (UTC)
|
||||
workflow_dispatch: {} # déclenchement manuel
|
||||
|
||||
jobs:
|
||||
check-and-sync:
|
||||
runs-on: linux
|
||||
steps:
|
||||
- name: Lire TEMPLATE_VERSION et .4nk-sync.yml
|
||||
# Doit charger ref courant, source_repo et périmètre paths
|
||||
|
||||
- name: Récupérer la version publiée du template/4NK_rules
|
||||
# Doit comparer TEMPLATE_VERSION avec ref amont
|
||||
|
||||
- name: Créer branche de synchronisation si divergence
|
||||
# Doit créer chore/template-sync-<date> et préparer un commit
|
||||
|
||||
- name: Synchroniser les chemins autoritatifs
|
||||
# Doit mettre à jour .cursor/**, .gitea/**, AGENTS.md, scripts/**, docs/SSH_UPDATE.md
|
||||
|
||||
- name: Contrôles post-sync (bloquants)
|
||||
# 1) Vérifier présence et exécutable des scripts/*.sh
|
||||
# 2) Vérifier mise à jour CHANGELOG.md et docs/INDEX.md
|
||||
# 3) Vérifier docs/SSH_UPDATE.md si scripts/** a changé
|
||||
# 4) Vérifier absence de secrets en clair dans scripts/**
|
||||
# 5) Vérifier manifest_checksum si publié
|
||||
|
||||
- name: Tests, lint, sécurité statique
|
||||
# Doit exiger un état vert
|
||||
|
||||
- name: Ouvrir PR de synchronisation
|
||||
# Titre: "[template-sync] chore: aligner .cursor/.gitea/AGENTS.md/scripts"
|
||||
# Doit inclure résumé des fichiers modifiés et la version appliquée
|
||||
|
||||
- name: Mettre à jour TEMPLATE_VERSION (dans PR)
|
||||
# Doit remplacer la valeur par la ref appliquée
|
||||
|
||||
45
.gitignore
vendored
45
.gitignore
vendored
@ -1,7 +1,40 @@
|
||||
node_modules
|
||||
pkg
|
||||
dist
|
||||
data
|
||||
!.cursor/
|
||||
# Secrets et fichiers sensibles
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
!.env.exemple
|
||||
*.key
|
||||
*.pem
|
||||
secrets/
|
||||
|
||||
!AGENTS.md
|
||||
# Logs
|
||||
logs/
|
||||
*.log
|
||||
|
||||
# Node.js
|
||||
node_modules/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Build
|
||||
dist/
|
||||
build/
|
||||
pkg/
|
||||
|
||||
# WASM
|
||||
*.wasm
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Temporary files
|
||||
tmp/
|
||||
*.tmp
|
||||
18
CHANGELOG.md
18
CHANGELOG.md
@ -4,6 +4,24 @@ Toutes les modifications notables de ce projet seront documentées ici.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
- Service de Background Sync pour la détection automatique des données manquantes
|
||||
- Surveillance périodique des `pcd_commitment` (toutes les 30 secondes)
|
||||
- API WebSocket pour contrôler le background sync (`FORCE_DATA_SCAN`, `GET_BACKGROUND_SYNC_STATUS`)
|
||||
- Gestion automatique des entrées `diff` pour le tracking des données manquantes
|
||||
- Récupération en deux étapes des données manquantes :
|
||||
- Essai depuis les serveurs de stockage (retrieveData) en priorité
|
||||
- Fallback vers les pairs (requestDataFromPeers) si non trouvé
|
||||
- Extraction automatique des URLs de stockage depuis les rôles
|
||||
- Scripts de test et validation du service de background sync
|
||||
- Test spécifique pour la récupération depuis le storage
|
||||
- Documentation complète dans `docs/BACKGROUND_SYNC.md`
|
||||
|
||||
### Changed
|
||||
- Intégration du background sync dans le service principal
|
||||
- Démarrage automatique du background sync avec le serveur
|
||||
- Arrêt propre du background sync lors de l'arrêt du serveur
|
||||
|
||||
## [0.1.1] - 2025-08-26
|
||||
- Bump version package.json à 0.1.1
|
||||
- Documentation déploiement mise à jour (exemples tag)
|
||||
|
||||
82
Dockerfile
82
Dockerfile
@ -1,35 +1,65 @@
|
||||
FROM node:20-alpine AS base
|
||||
# syntax=docker/dockerfile:1.4
|
||||
FROM rust:1.85-alpine AS wasm-builder
|
||||
WORKDIR /build
|
||||
|
||||
# Install production dependencies only by default
|
||||
ENV NODE_ENV=production
|
||||
# Installation des dépendances nécessaires pour la compilation
|
||||
RUN apk update && apk add --no-cache \
|
||||
git \
|
||||
curl \
|
||||
nodejs \
|
||||
npm \
|
||||
build-base \
|
||||
pkgconfig \
|
||||
clang \
|
||||
llvm \
|
||||
musl-dev \
|
||||
perl
|
||||
|
||||
# Installation de wasm-pack et wasm-bindgen
|
||||
RUN cargo install wasm-pack
|
||||
RUN cargo install wasm-bindgen-cli --version 0.2.103
|
||||
|
||||
# Copie du projet sdk_signer
|
||||
COPY . sdk_signer/
|
||||
|
||||
# Clonage du sdk_client au même niveau que sdk_signer
|
||||
RUN git clone -b int-dev https://git.4nkweb.com/4nk/sdk_client.git
|
||||
|
||||
# Build du WebAssembly
|
||||
WORKDIR /build/sdk_client
|
||||
RUN wasm-pack build --out-dir ../sdk_signer/pkg --target nodejs --dev
|
||||
|
||||
FROM debian:bookworm-slim
|
||||
WORKDIR /app
|
||||
|
||||
# Install build dependencies
|
||||
FROM base AS deps
|
||||
ENV NODE_ENV=development
|
||||
RUN apk add --no-cache python3 make g++
|
||||
COPY package.json package-lock.json* ./
|
||||
RUN npm ci
|
||||
# Installation des dépendances minimales nécessaires
|
||||
RUN apt-get update && apt-get upgrade -y && \
|
||||
apt-get install -y --fix-missing \
|
||||
ca-certificates curl jq git \
|
||||
net-tools iputils-ping dnsutils \
|
||||
netcat-openbsd telnet procps && \
|
||||
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# Installation de Node.js
|
||||
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \
|
||||
apt-get install -y nodejs && \
|
||||
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# Création d'un utilisateur non-root
|
||||
RUN useradd -m -u 1000 appuser && \
|
||||
mkdir -p /app && chown -R appuser:appuser /app
|
||||
|
||||
# Copie des fichiers du projet
|
||||
COPY --from=wasm-builder /build/sdk_signer/pkg ./pkg
|
||||
COPY . .
|
||||
RUN chown -R appuser:appuser /app
|
||||
|
||||
# Installation des dépendances Node.js
|
||||
USER appuser
|
||||
RUN npm install
|
||||
|
||||
# Build TypeScript
|
||||
FROM deps AS build
|
||||
COPY tsconfig.json ./
|
||||
COPY src ./src
|
||||
COPY pkg ./pkg
|
||||
RUN npm run build
|
||||
|
||||
# Runtime image
|
||||
FROM base AS runner
|
||||
WORKDIR /app
|
||||
ENV NODE_ENV=production
|
||||
RUN addgroup -S nodejs && adduser -S nodejs -G nodejs
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY --from=build /app/dist ./dist
|
||||
COPY --from=build /app/pkg ./pkg
|
||||
EXPOSE 9090
|
||||
USER nodejs
|
||||
CMD ["node", "dist/index.js"]
|
||||
|
||||
|
||||
|
||||
CMD ["npm", "start"]
|
||||
317
package-lock.json
generated
317
package-lock.json
generated
@ -27,6 +27,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
|
||||
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/trace-mapping": "0.3.9"
|
||||
},
|
||||
@ -443,6 +444,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
||||
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
@ -459,15 +461,16 @@
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
|
||||
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/resolve-uri": "^3.0.3",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.10"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.48.1.tgz",
|
||||
"integrity": "sha512-rGmb8qoG/zdmKoYELCBwu7vt+9HxZ7Koos3pD0+sH5fR3u3Wb/jGcpnqxcnWsPEKDUyzeLSqksN8LJtgXjqBYw==",
|
||||
"version": "4.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.0.tgz",
|
||||
"integrity": "sha512-VxDYCDqOaR7NXzAtvRx7G1u54d2kEHopb28YH/pKzY6y0qmogP3gG7CSiWsq9WvDFxOQMpNEyjVAHZFXfH3o/A==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@ -479,9 +482,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.48.1.tgz",
|
||||
"integrity": "sha512-4e9WtTxrk3gu1DFE+imNJr4WsL13nWbD/Y6wQcyku5qadlKHY3OQ3LJ/INrrjngv2BJIHnIzbqMk1GTAC2P8yQ==",
|
||||
"version": "4.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.0.tgz",
|
||||
"integrity": "sha512-pqDirm8koABIKvzL59YI9W9DWbRlTX7RWhN+auR8HXJxo89m4mjqbah7nJZjeKNTNYopqL+yGg+0mhCpf3xZtQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -493,9 +496,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.48.1.tgz",
|
||||
"integrity": "sha512-+XjmyChHfc4TSs6WUQGmVf7Hkg8ferMAE2aNYYWjiLzAS/T62uOsdfnqv+GHRjq7rKRnYh4mwWb4Hz7h/alp8A==",
|
||||
"version": "4.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.0.tgz",
|
||||
"integrity": "sha512-YCdWlY/8ltN6H78HnMsRHYlPiKvqKagBP1r+D7SSylxX+HnsgXGCmLiV3Y4nSyY9hW8qr8U9LDUx/Lo7M6MfmQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -507,9 +510,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.48.1.tgz",
|
||||
"integrity": "sha512-upGEY7Ftw8M6BAJyGwnwMw91rSqXTcOKZnnveKrVWsMTF8/k5mleKSuh7D4v4IV1pLxKAk3Tbs0Lo9qYmii5mQ==",
|
||||
"version": "4.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.0.tgz",
|
||||
"integrity": "sha512-z4nw6y1j+OOSGzuVbSWdIp1IUks9qNw4dc7z7lWuWDKojY38VMWBlEN7F9jk5UXOkUcp97vA1N213DF+Lz8BRg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -521,9 +524,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||
"version": "4.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.48.1.tgz",
|
||||
"integrity": "sha512-P9ViWakdoynYFUOZhqq97vBrhuvRLAbN/p2tAVJvhLb8SvN7rbBnJQcBu8e/rQts42pXGLVhfsAP0k9KXWa3nQ==",
|
||||
"version": "4.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.0.tgz",
|
||||
"integrity": "sha512-Q/dv9Yvyr5rKlK8WQJZVrp5g2SOYeZUs9u/t2f9cQ2E0gJjYB/BWoedXfUT0EcDJefi2zzVfhcOj8drWCzTviw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -535,9 +538,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||
"version": "4.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.48.1.tgz",
|
||||
"integrity": "sha512-VLKIwIpnBya5/saccM8JshpbxfyJt0Dsli0PjXozHwbSVaHTvWXJH1bbCwPXxnMzU4zVEfgD1HpW3VQHomi2AQ==",
|
||||
"version": "4.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.0.tgz",
|
||||
"integrity": "sha512-kdBsLs4Uile/fbjZVvCRcKB4q64R+1mUq0Yd7oU1CMm1Av336ajIFqNFovByipciuUQjBCPMxwJhCgfG2re3rg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -549,9 +552,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.48.1.tgz",
|
||||
"integrity": "sha512-3zEuZsXfKaw8n/yF7t8N6NNdhyFw3s8xJTqjbTDXlipwrEHo4GtIKcMJr5Ed29leLpB9AugtAQpAHW0jvtKKaQ==",
|
||||
"version": "4.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.0.tgz",
|
||||
"integrity": "sha512-aL6hRwu0k7MTUESgkg7QHY6CoqPgr6gdQXRJI1/VbFlUMwsSzPGSR7sG5d+MCbYnJmJwThc2ol3nixj1fvI/zQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@ -563,9 +566,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||
"version": "4.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.48.1.tgz",
|
||||
"integrity": "sha512-leo9tOIlKrcBmmEypzunV/2w946JeLbTdDlwEZ7OnnsUyelZ72NMnT4B2vsikSgwQifjnJUbdXzuW4ToN1wV+Q==",
|
||||
"version": "4.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.0.tgz",
|
||||
"integrity": "sha512-BTs0M5s1EJejgIBJhCeiFo7GZZ2IXWkFGcyZhxX4+8usnIo5Mti57108vjXFIQmmJaRyDwmV59Tw64Ap1dkwMw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@ -577,9 +580,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.48.1.tgz",
|
||||
"integrity": "sha512-Vy/WS4z4jEyvnJm+CnPfExIv5sSKqZrUr98h03hpAMbE2aI0aD2wvK6GiSe8Gx2wGp3eD81cYDpLLBqNb2ydwQ==",
|
||||
"version": "4.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.0.tgz",
|
||||
"integrity": "sha512-uj672IVOU9m08DBGvoPKPi/J8jlVgjh12C9GmjjBxCTQc3XtVmRkRKyeHSmIKQpvJ7fIm1EJieBUcnGSzDVFyw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -591,9 +594,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.48.1.tgz",
|
||||
"integrity": "sha512-x5Kzn7XTwIssU9UYqWDB9VpLpfHYuXw5c6bJr4Mzv9kIv242vmJHbI5PJJEnmBYitUIfoMCODDhR7KoZLot2VQ==",
|
||||
"version": "4.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.0.tgz",
|
||||
"integrity": "sha512-/+IVbeDMDCtB/HP/wiWsSzduD10SEGzIZX2945KSgZRNi4TSkjHqRJtNTVtVb8IRwhJ65ssI56krlLik+zFWkw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -604,10 +607,10 @@
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
|
||||
"version": "4.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.48.1.tgz",
|
||||
"integrity": "sha512-yzCaBbwkkWt/EcgJOKDUdUpMHjhiZT/eDktOPWvSRpqrVE04p0Nd6EGV4/g7MARXXeOqstflqsKuXVM3H9wOIQ==",
|
||||
"node_modules/@rollup/rollup-linux-loong64-gnu": {
|
||||
"version": "4.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.0.tgz",
|
||||
"integrity": "sha512-U1vVzvSWtSMWKKrGoROPBXMh3Vwn93TA9V35PldokHGqiUbF6erSzox/5qrSMKp6SzakvyjcPiVF8yB1xKr9Pg==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
@ -619,9 +622,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
|
||||
"version": "4.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.48.1.tgz",
|
||||
"integrity": "sha512-UK0WzWUjMAJccHIeOpPhPcKBqax7QFg47hwZTp6kiMhQHeOYJeaMwzeRZe1q5IiTKsaLnHu9s6toSYVUlZ2QtQ==",
|
||||
"version": "4.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.0.tgz",
|
||||
"integrity": "sha512-X/4WfuBAdQRH8cK3DYl8zC00XEE6aM472W+QCycpQJeLWVnHfkv7RyBFVaTqNUMsTgIX8ihMjCvFF9OUgeABzw==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
@ -633,9 +636,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.48.1.tgz",
|
||||
"integrity": "sha512-3NADEIlt+aCdCbWVZ7D3tBjBX1lHpXxcvrLt/kdXTiBrOds8APTdtk2yRL2GgmnSVeX4YS1JIf0imFujg78vpw==",
|
||||
"version": "4.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.0.tgz",
|
||||
"integrity": "sha512-xIRYc58HfWDBZoLmWfWXg2Sq8VCa2iJ32B7mqfWnkx5mekekl0tMe7FHpY8I72RXEcUkaWawRvl3qA55og+cwQ==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
@ -647,9 +650,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-musl": {
|
||||
"version": "4.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.48.1.tgz",
|
||||
"integrity": "sha512-euuwm/QTXAMOcyiFCcrx0/S2jGvFlKJ2Iro8rsmYL53dlblp3LkUQVFzEidHhvIPPvcIsxDhl2wkBE+I6YVGzA==",
|
||||
"version": "4.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.0.tgz",
|
||||
"integrity": "sha512-mbsoUey05WJIOz8U1WzNdf+6UMYGwE3fZZnQqsM22FZ3wh1N887HT6jAOjXs6CNEK3Ntu2OBsyQDXfIjouI4dw==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
@ -661,9 +664,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||
"version": "4.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.48.1.tgz",
|
||||
"integrity": "sha512-w8mULUjmPdWLJgmTYJx/W6Qhln1a+yqvgwmGXcQl2vFBkWsKGUBRbtLRuKJUln8Uaimf07zgJNxOhHOvjSQmBQ==",
|
||||
"version": "4.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.0.tgz",
|
||||
"integrity": "sha512-qP6aP970bucEi5KKKR4AuPFd8aTx9EF6BvutvYxmZuWLJHmnq4LvBfp0U+yFDMGwJ+AIJEH5sIP+SNypauMWzg==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
@ -675,9 +678,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.48.1.tgz",
|
||||
"integrity": "sha512-90taWXCWxTbClWuMZD0DKYohY1EovA+W5iytpE89oUPmT5O1HFdf8cuuVIylE6vCbrGdIGv85lVRzTcpTRZ+kA==",
|
||||
"version": "4.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.0.tgz",
|
||||
"integrity": "sha512-nmSVN+F2i1yKZ7rJNKO3G7ZzmxJgoQBQZ/6c4MuS553Grmr7WqR7LLDcYG53Z2m9409z3JLt4sCOhLdbKQ3HmA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -689,9 +692,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.48.1.tgz",
|
||||
"integrity": "sha512-2Gu29SkFh1FfTRuN1GR1afMuND2GKzlORQUP3mNMJbqdndOg7gNsa81JnORctazHRokiDzQ5+MLE5XYmZW5VWg==",
|
||||
"version": "4.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.0.tgz",
|
||||
"integrity": "sha512-2d0qRo33G6TfQVjaMR71P+yJVGODrt5V6+T0BDYH4EMfGgdC/2HWDVjSSFw888GSzAZUwuska3+zxNUCDco6rQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -702,10 +705,24 @@
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-openharmony-arm64": {
|
||||
"version": "4.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.0.tgz",
|
||||
"integrity": "sha512-A1JalX4MOaFAAyGgpO7XP5khquv/7xKzLIyLmhNrbiCxWpMlnsTYr8dnsWM7sEeotNmxvSOEL7F65j0HXFcFsw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openharmony"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.48.1.tgz",
|
||||
"integrity": "sha512-6kQFR1WuAO50bxkIlAVeIYsz3RUx+xymwhTo9j94dJ+kmHe9ly7muH23sdfWduD0BA8pD9/yhonUvAjxGh34jQ==",
|
||||
"version": "4.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.0.tgz",
|
||||
"integrity": "sha512-YQugafP/rH0eOOHGjmNgDURrpYHrIX0yuojOI8bwCyXwxC9ZdTd3vYkmddPX0oHONLXu9Rb1dDmT0VNpjkzGGw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -717,9 +734,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.48.1.tgz",
|
||||
"integrity": "sha512-RUyZZ/mga88lMI3RlXFs4WQ7n3VyU07sPXmMG7/C1NOi8qisUg57Y7LRarqoGoAiopmGmChUhSwfpvQ3H5iGSQ==",
|
||||
"version": "4.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.0.tgz",
|
||||
"integrity": "sha512-zYdUYhi3Qe2fndujBqL5FjAFzvNeLxtIqfzNEVKD1I7C37/chv1VxhscWSQHTNfjPCrBFQMnynwA3kpZpZ8w4A==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@ -730,10 +747,24 @@
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-gnu": {
|
||||
"version": "4.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.0.tgz",
|
||||
"integrity": "sha512-fGk03kQylNaCOQ96HDMeT7E2n91EqvCDd3RwvT5k+xNdFCeMGnj5b5hEgTGrQuyidqSsD3zJDQ21QIaxXqTBJw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.48.1.tgz",
|
||||
"integrity": "sha512-8a/caCUN4vkTChxkaIJcMtwIVcBhi4X2PQRoT+yCK3qRYaZ7cURrmJFL5Ux9H9RaMIXj9RuihckdmkBX3zZsgg==",
|
||||
"version": "4.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.0.tgz",
|
||||
"integrity": "sha512-6iKDCVSIUQ8jPMoIV0OytRKniaYyy5EbY/RRydmLW8ZR3cEBhxbWl5ro0rkUNe0ef6sScvhbY79HrjRm8i3vDQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -755,25 +786,29 @@
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
|
||||
"integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@tsconfig/node12": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
|
||||
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@tsconfig/node14": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
|
||||
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@tsconfig/node16": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
|
||||
"integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.8",
|
||||
@ -783,9 +818,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.0.tgz",
|
||||
"integrity": "sha512-m5ObIqwsUp6BZzyiy4RdZpzWGub9bqLJMvZDD0QMXhxjqMHMENlj+SqF5QxoUwaQNFe+8kz8XM8ZQhqkQPTgMQ==",
|
||||
"version": "22.18.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.6.tgz",
|
||||
"integrity": "sha512-r8uszLPpeIWbNKtvWRt/DbVi5zbqZyj1PTmhRMqBMvDnaz1QpmSKujUtJLrqGZeoM8v72MfYggDceY4K1itzWQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
@ -795,6 +830,7 @@
|
||||
"version": "8.18.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
|
||||
"integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
@ -877,6 +913,7 @@
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/abstract-level/-/abstract-level-3.1.0.tgz",
|
||||
"integrity": "sha512-j2e+TsAxy7Ri+0h7dJqwasymgt0zHBWX4+nMk3XatyuqgHfdstBJ9wsMfbiGwE1O+QovRyPcVAqcViMYdyPaaw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"buffer": "^6.0.3",
|
||||
"is-buffer": "^2.0.5",
|
||||
@ -894,6 +931,7 @@
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@ -906,6 +944,7 @@
|
||||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
|
||||
"integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"acorn": "^8.11.0"
|
||||
},
|
||||
@ -930,7 +969,8 @@
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
|
||||
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/assertion-error": {
|
||||
"version": "1.1.0",
|
||||
@ -945,12 +985,14 @@
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.11.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz",
|
||||
"integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==",
|
||||
"version": "1.12.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz",
|
||||
"integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.4",
|
||||
@ -974,12 +1016,14 @@
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
]
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/browser-level": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/browser-level/-/browser-level-3.0.0.tgz",
|
||||
"integrity": "sha512-kGXtLh29jMwqKaskz5xeDLtCtN1KBz/DbQSqmvH7QdJiyGRC7RAM8PPg6gvUiNMa+wVnaxS9eSmEtP/f5ajOVw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"abstract-level": "^3.1.0"
|
||||
}
|
||||
@ -1002,6 +1046,7 @@
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"base64-js": "^1.3.1",
|
||||
"ieee754": "^1.2.1"
|
||||
@ -1021,6 +1066,7 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2"
|
||||
@ -1066,6 +1112,7 @@
|
||||
"resolved": "https://registry.npmjs.org/classic-level/-/classic-level-3.0.0.tgz",
|
||||
"integrity": "sha512-yGy8j8LjPbN0Bh3+ygmyYvrmskVita92pD/zCoalfcC9XxZj6iDtZTAnz+ot7GG8p9KLTG+MZ84tSA4AhkgVZQ==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"abstract-level": "^3.1.0",
|
||||
"module-error": "^1.0.1",
|
||||
@ -1080,6 +1127,7 @@
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
@ -1098,7 +1146,8 @@
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
|
||||
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.6",
|
||||
@ -1116,9 +1165,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
|
||||
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -1150,6 +1199,7 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
@ -1159,6 +1209,7 @@
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
|
||||
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
@ -1177,6 +1228,7 @@
|
||||
"version": "16.6.1",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
|
||||
"integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@ -1188,6 +1240,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
@ -1201,6 +1254,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
@ -1209,6 +1263,7 @@
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
@ -1217,6 +1272,7 @@
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0"
|
||||
},
|
||||
@ -1228,6 +1284,7 @@
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
||||
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"get-intrinsic": "^1.2.6",
|
||||
@ -1321,6 +1378,7 @@
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
@ -1334,6 +1392,7 @@
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
|
||||
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
@ -1364,6 +1423,7 @@
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
@ -1382,6 +1442,7 @@
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.2",
|
||||
"es-define-property": "^1.0.1",
|
||||
@ -1405,6 +1466,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dunder-proto": "^1.0.1",
|
||||
"es-object-atoms": "^1.0.0"
|
||||
@ -1430,6 +1492,7 @@
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
@ -1441,6 +1504,7 @@
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
@ -1452,6 +1516,7 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-symbols": "^1.0.3"
|
||||
},
|
||||
@ -1466,6 +1531,7 @@
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
@ -1500,7 +1566,8 @@
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
]
|
||||
],
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/is-buffer": {
|
||||
"version": "2.0.5",
|
||||
@ -1520,6 +1587,7 @@
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
@ -1555,6 +1623,7 @@
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/level/-/level-10.0.0.tgz",
|
||||
"integrity": "sha512-aZJvdfRr/f0VBbSRF5C81FHON47ZsC2TkGxbBezXpGGXAUEL/s6+GP73nnhAYRSCIqUNsmJjfeOF4lzRDKbUig==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"abstract-level": "^3.1.0",
|
||||
"browser-level": "^3.0.0",
|
||||
@ -1572,6 +1641,7 @@
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/level-supports/-/level-supports-6.2.0.tgz",
|
||||
"integrity": "sha512-QNxVXP0IRnBmMsJIh+sb2kwNCYcKciQZJEt+L1hPCHrKNELllXhvrlClVHXBYZVT+a7aTSM6StgNXdAldoab3w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
@ -1580,6 +1650,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/level-transcoder/-/level-transcoder-1.0.1.tgz",
|
||||
"integrity": "sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"buffer": "^6.0.3",
|
||||
"module-error": "^1.0.1"
|
||||
@ -1616,9 +1687,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/magic-string": {
|
||||
"version": "0.30.18",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.18.tgz",
|
||||
"integrity": "sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==",
|
||||
"version": "0.30.19",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz",
|
||||
"integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -1629,12 +1700,14 @@
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
|
||||
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/math-intrinsics": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
@ -1643,6 +1716,7 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/maybe-combine-errors/-/maybe-combine-errors-1.0.0.tgz",
|
||||
"integrity": "sha512-eefp6IduNPT6fVdwPp+1NgD0PML1NU5P6j1Mj5nz1nidX8/sWY7119WL8vTAHgqfsY74TzW0w1XPgdYEKkGZ5A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
@ -1658,6 +1732,7 @@
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
@ -1666,6 +1741,7 @@
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
@ -1710,6 +1786,7 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/module-error/-/module-error-1.0.2.tgz",
|
||||
"integrity": "sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
@ -1743,12 +1820,14 @@
|
||||
"node_modules/napi-macros": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.2.2.tgz",
|
||||
"integrity": "sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g=="
|
||||
"integrity": "sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-gyp-build": {
|
||||
"version": "4.8.4",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
|
||||
"integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"node-gyp-build": "bin.js",
|
||||
"node-gyp-build-optional": "optional.js",
|
||||
@ -1916,7 +1995,8 @@
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/react-is": {
|
||||
"version": "18.3.1",
|
||||
@ -1926,9 +2006,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.48.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.48.1.tgz",
|
||||
"integrity": "sha512-jVG20NvbhTYDkGAty2/Yh7HK6/q3DGSRH4o8ALKGArmMuaauM9kLfoMZ+WliPwA5+JHr2lTn3g557FxBV87ifg==",
|
||||
"version": "4.52.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.0.tgz",
|
||||
"integrity": "sha512-+IuescNkTJQgX7AkIDtITipZdIGcWF0pnVvZTWStiazUmcGA2ag8dfg0urest2XlXUi9kuhfQ+qmdc5Stc3z7g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -1942,26 +2022,28 @@
|
||||
"npm": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-android-arm-eabi": "4.48.1",
|
||||
"@rollup/rollup-android-arm64": "4.48.1",
|
||||
"@rollup/rollup-darwin-arm64": "4.48.1",
|
||||
"@rollup/rollup-darwin-x64": "4.48.1",
|
||||
"@rollup/rollup-freebsd-arm64": "4.48.1",
|
||||
"@rollup/rollup-freebsd-x64": "4.48.1",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.48.1",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.48.1",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.48.1",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.48.1",
|
||||
"@rollup/rollup-linux-loongarch64-gnu": "4.48.1",
|
||||
"@rollup/rollup-linux-ppc64-gnu": "4.48.1",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.48.1",
|
||||
"@rollup/rollup-linux-riscv64-musl": "4.48.1",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.48.1",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.48.1",
|
||||
"@rollup/rollup-linux-x64-musl": "4.48.1",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.48.1",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.48.1",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.48.1",
|
||||
"@rollup/rollup-android-arm-eabi": "4.52.0",
|
||||
"@rollup/rollup-android-arm64": "4.52.0",
|
||||
"@rollup/rollup-darwin-arm64": "4.52.0",
|
||||
"@rollup/rollup-darwin-x64": "4.52.0",
|
||||
"@rollup/rollup-freebsd-arm64": "4.52.0",
|
||||
"@rollup/rollup-freebsd-x64": "4.52.0",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.52.0",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.52.0",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.52.0",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.52.0",
|
||||
"@rollup/rollup-linux-loong64-gnu": "4.52.0",
|
||||
"@rollup/rollup-linux-ppc64-gnu": "4.52.0",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.52.0",
|
||||
"@rollup/rollup-linux-riscv64-musl": "4.52.0",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.52.0",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.52.0",
|
||||
"@rollup/rollup-linux-x64-musl": "4.52.0",
|
||||
"@rollup/rollup-openharmony-arm64": "4.52.0",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.52.0",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.52.0",
|
||||
"@rollup/rollup-win32-x64-gnu": "4.52.0",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.52.0",
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
@ -2090,6 +2172,7 @@
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
|
||||
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cspotcode/source-map-support": "^0.8.0",
|
||||
"@tsconfig/node10": "^1.0.7",
|
||||
@ -2139,10 +2222,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.8.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
|
||||
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
|
||||
"version": "5.9.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
|
||||
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@ -2168,12 +2252,13 @@
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
|
||||
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "5.4.19",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz",
|
||||
"integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==",
|
||||
"version": "5.4.20",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.20.tgz",
|
||||
"integrity": "sha512-j3lYzGC3P+B5Yfy/pfKNgVEg4+UtcIJcVRt2cDjIOmhLourAqPqf8P7acgxeiSgUB7E3p2P8/3gNIgDLpwzs4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -2356,6 +2441,7 @@
|
||||
"version": "8.18.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
|
||||
"integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
@ -2377,6 +2463,7 @@
|
||||
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
|
||||
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
|
||||
1
sdk_client
Submodule
1
sdk_client
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit c09135c4eb785fa5ef242cd106bb1e628d5f68fa
|
||||
352
src/background-sync.service.ts
Normal file
352
src/background-sync.service.ts
Normal file
@ -0,0 +1,352 @@
|
||||
// Service de surveillance en arrière-plan pour Node.js
|
||||
// Équivalent du service worker pour la détection des données manquantes
|
||||
|
||||
import { Service } from './service';
|
||||
import Database from './database.service';
|
||||
import { config } from './config';
|
||||
import { retrieveData } from './storage.service';
|
||||
|
||||
export class BackgroundSyncService {
|
||||
private static instance: BackgroundSyncService;
|
||||
private service: Service;
|
||||
private db: Database | null = null;
|
||||
private scanInterval: NodeJS.Timeout | null = null;
|
||||
private isRunning: boolean = false;
|
||||
private readonly SCAN_INTERVAL_MS = 30000; // 30 secondes
|
||||
private readonly EMPTY32BYTES = '0'.repeat(64);
|
||||
|
||||
private constructor() {
|
||||
this.service = Service.getInstance();
|
||||
console.log('🔧 BackgroundSyncService initialized');
|
||||
}
|
||||
|
||||
static async getInstance(): Promise<BackgroundSyncService> {
|
||||
if (!BackgroundSyncService.instance) {
|
||||
BackgroundSyncService.instance = new BackgroundSyncService();
|
||||
await BackgroundSyncService.instance.init();
|
||||
}
|
||||
return BackgroundSyncService.instance;
|
||||
}
|
||||
|
||||
private async init(): Promise<void> {
|
||||
this.db = await Database.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Démarre le service de surveillance en arrière-plan
|
||||
*/
|
||||
public async start(): Promise<void> {
|
||||
if (this.isRunning) {
|
||||
console.log('⚠️ BackgroundSyncService already running');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('🚀 Starting background sync service...');
|
||||
this.isRunning = true;
|
||||
|
||||
// Scan immédiat au démarrage
|
||||
await this.scanMissingData();
|
||||
|
||||
// Puis scan périodique
|
||||
this.scanInterval = setInterval(async () => {
|
||||
try {
|
||||
await this.scanMissingData();
|
||||
} catch (error) {
|
||||
console.error('❌ Error in background scan:', error);
|
||||
}
|
||||
}, this.SCAN_INTERVAL_MS);
|
||||
|
||||
console.log('✅ Background sync service started');
|
||||
}
|
||||
|
||||
/**
|
||||
* Arrête le service de surveillance
|
||||
*/
|
||||
public stop(): void {
|
||||
if (!this.isRunning) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('🛑 Stopping background sync service...');
|
||||
this.isRunning = false;
|
||||
|
||||
if (this.scanInterval) {
|
||||
clearInterval(this.scanInterval);
|
||||
this.scanInterval = null;
|
||||
}
|
||||
|
||||
console.log('✅ Background sync service stopped');
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan manuel des données manquantes (équivalent à scanMissingData du service worker)
|
||||
*/
|
||||
public async scanMissingData(): Promise<string[]> {
|
||||
console.log('🔍 Scanning for missing data...');
|
||||
|
||||
try {
|
||||
const myProcesses = await this.getMyProcesses();
|
||||
if (!myProcesses || myProcesses.length === 0) {
|
||||
console.log('No processes to scan');
|
||||
return [];
|
||||
}
|
||||
|
||||
const toDownload = new Set<string>();
|
||||
|
||||
for (const processId of myProcesses) {
|
||||
const process = await this.service.getProcess(processId);
|
||||
if (!process) continue;
|
||||
|
||||
for (const state of process.states) {
|
||||
if (state.state_id === this.EMPTY32BYTES) continue;
|
||||
|
||||
// Vérifier chaque pcd_commitment
|
||||
for (const [field, hash] of Object.entries(state.pcd_commitment)) {
|
||||
// Ignorer les champs publics
|
||||
if (state.public_data[field] !== undefined || field === 'roles') continue;
|
||||
|
||||
// Vérifier que hash est une string
|
||||
if (typeof hash !== 'string') continue;
|
||||
|
||||
// Vérifier si on a déjà les données
|
||||
const existingData = await this.getBlob(hash);
|
||||
if (!existingData) {
|
||||
toDownload.add(hash);
|
||||
// Ajouter une entrée diff si elle n'existe pas
|
||||
await this.addDiff(processId, state.state_id, hash, state.roles, field);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const missingHashes = Array.from(toDownload);
|
||||
|
||||
if (missingHashes.length > 0) {
|
||||
console.log(`📥 Found ${missingHashes.length} missing data hashes:`, missingHashes);
|
||||
await this.requestMissingData(missingHashes);
|
||||
} else {
|
||||
console.log('✅ No missing data found');
|
||||
}
|
||||
|
||||
return missingHashes;
|
||||
} catch (error) {
|
||||
console.error('❌ Error scanning missing data:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère les processus de l'utilisateur
|
||||
*/
|
||||
private async getMyProcesses(): Promise<string[]> {
|
||||
try {
|
||||
return await this.service.getMyProcesses() || [];
|
||||
} catch (error) {
|
||||
console.error('Error getting my processes:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si un blob existe en base
|
||||
*/
|
||||
private async getBlob(hash: string): Promise<Buffer | null> {
|
||||
try {
|
||||
return await this.service.getBufferFromDb(hash);
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajoute une entrée diff pour tracking
|
||||
*/
|
||||
private async addDiff(
|
||||
processId: string,
|
||||
stateId: string,
|
||||
hash: string,
|
||||
roles: any,
|
||||
field: string
|
||||
): Promise<void> {
|
||||
try {
|
||||
if (!this.db) {
|
||||
console.error('Database not initialized');
|
||||
return;
|
||||
}
|
||||
|
||||
const existingDiff = await this.db.getObject('diffs', hash);
|
||||
|
||||
if (!existingDiff) {
|
||||
const newDiff = {
|
||||
process_id: processId,
|
||||
state_id: stateId,
|
||||
value_commitment: hash,
|
||||
roles: roles,
|
||||
field: field,
|
||||
description: null,
|
||||
previous_value: null,
|
||||
new_value: null,
|
||||
notify_user: false,
|
||||
need_validation: false,
|
||||
validation_status: 'None'
|
||||
};
|
||||
|
||||
await this.db.addObject({
|
||||
storeName: 'diffs',
|
||||
object: newDiff,
|
||||
key: hash
|
||||
});
|
||||
|
||||
console.log(`📝 Added diff entry for hash: ${hash}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error adding diff:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Demande les données manquantes aux pairs
|
||||
*/
|
||||
private async requestMissingData(hashes: string[]): Promise<void> {
|
||||
try {
|
||||
console.log('🔄 Requesting missing data from peers...');
|
||||
|
||||
// Récupérer tous les processus pour déterminer les rôles
|
||||
const myProcesses = await this.getMyProcesses();
|
||||
const processesToRequest: Record<string, any> = {};
|
||||
|
||||
for (const processId of myProcesses) {
|
||||
const process = await this.service.getProcess(processId);
|
||||
if (process) {
|
||||
processesToRequest[processId] = process;
|
||||
}
|
||||
}
|
||||
|
||||
// Pour chaque hash manquant, essayer de le récupérer
|
||||
for (const hash of hashes) {
|
||||
try {
|
||||
// Trouver le diff correspondant
|
||||
const diffs = await this.service.getDiffsFromDb();
|
||||
const diff = Object.values(diffs).find((d: any) => d.value_commitment === hash);
|
||||
|
||||
if (diff) {
|
||||
const processId = diff.process_id;
|
||||
const stateId = diff.state_id;
|
||||
const roles = diff.roles;
|
||||
|
||||
if (processesToRequest[processId]) {
|
||||
// D'abord essayer de récupérer depuis les serveurs de stockage
|
||||
const retrievedFromStorage = await this.tryRetrieveFromStorage(hash, roles);
|
||||
|
||||
if (retrievedFromStorage) {
|
||||
console.log(`✅ Data retrieved from storage for hash ${hash}`);
|
||||
// Sauvegarder les données récupérées en base
|
||||
await this.service.saveBufferToDb(hash, Buffer.from(retrievedFromStorage));
|
||||
continue; // Passer au hash suivant
|
||||
}
|
||||
|
||||
// Si pas trouvé en storage, demander aux pairs
|
||||
console.log(`🔄 Requesting data for hash ${hash} from process ${processId}`);
|
||||
await this.service.requestDataFromPeers(processId, [stateId], [roles]);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error requesting data for hash ${hash}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error requesting missing data:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Essaie de récupérer les données depuis les serveurs de stockage
|
||||
*/
|
||||
private async tryRetrieveFromStorage(hash: string, roles: any): Promise<ArrayBuffer | null> {
|
||||
try {
|
||||
// Extraire les URLs de stockage depuis les rôles
|
||||
const storageUrls = this.extractStorageUrls(roles);
|
||||
|
||||
if (storageUrls.length === 0) {
|
||||
console.log(`No storage URLs found for hash ${hash}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
console.log(`🔍 Trying to retrieve hash ${hash} from storage servers:`, storageUrls);
|
||||
|
||||
// Essayer de récupérer depuis les serveurs de stockage
|
||||
const data = await retrieveData(storageUrls, hash);
|
||||
|
||||
if (data) {
|
||||
console.log(`✅ Successfully retrieved data for hash ${hash} from storage`);
|
||||
return data;
|
||||
} else {
|
||||
console.log(`❌ Data not found in storage for hash ${hash}`);
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error retrieving data from storage for hash ${hash}:`, error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extrait les URLs de stockage depuis les rôles
|
||||
*/
|
||||
private extractStorageUrls(roles: any): string[] {
|
||||
const storageUrls = new Set<string>();
|
||||
|
||||
try {
|
||||
if (roles && typeof roles === 'object') {
|
||||
for (const role of Object.values(roles)) {
|
||||
if (role && typeof role === 'object' && 'storages' in role && Array.isArray((role as any).storages)) {
|
||||
for (const storageUrl of (role as any).storages) {
|
||||
if (typeof storageUrl === 'string' && storageUrl.trim()) {
|
||||
storageUrls.add(storageUrl.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error extracting storage URLs from roles:', error);
|
||||
}
|
||||
|
||||
return Array.from(storageUrls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force un scan immédiat (pour tests ou usage manuel)
|
||||
*/
|
||||
public async forceScan(): Promise<string[]> {
|
||||
console.log('🔄 Forcing immediate scan...');
|
||||
return await this.scanMissingData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtient le statut du service
|
||||
*/
|
||||
public getStatus(): { isRunning: boolean; scanInterval: number } {
|
||||
return {
|
||||
isRunning: this.isRunning,
|
||||
scanInterval: this.SCAN_INTERVAL_MS
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour l'intervalle de scan
|
||||
*/
|
||||
public setScanInterval(intervalMs: number): void {
|
||||
if (this.isRunning && this.scanInterval) {
|
||||
clearInterval(this.scanInterval);
|
||||
this.scanInterval = setInterval(async () => {
|
||||
try {
|
||||
await this.scanMissingData();
|
||||
} catch (error) {
|
||||
console.error('❌ Error in background scan:', error);
|
||||
}
|
||||
}, intervalMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,4 @@
|
||||
import dotenv from 'dotenv';
|
||||
|
||||
// Load environment variables from .env file
|
||||
dotenv.config();
|
||||
// Configuration via variables d'environnement (centralisées dans lecoffre_node/.env.master)
|
||||
|
||||
export interface AppConfig {
|
||||
port: number;
|
||||
@ -30,4 +27,4 @@ export const config: AppConfig = loadConfig();
|
||||
// Validate required environment variables
|
||||
if (!config.apiKey || config.apiKey === 'your-api-key-change-this') {
|
||||
console.warn('⚠️ Warning: Using default API key. Set API_KEY environment variable for production.');
|
||||
}
|
||||
}
|
||||
@ -37,6 +37,11 @@ export enum MessageType {
|
||||
// Account management
|
||||
ADD_DEVICE = 'ADD_DEVICE',
|
||||
DEVICE_ADDED = 'DEVICE_ADDED',
|
||||
// Background sync
|
||||
FORCE_DATA_SCAN = 'FORCE_DATA_SCAN',
|
||||
DATA_SCAN_RESULT = 'DATA_SCAN_RESULT',
|
||||
GET_BACKGROUND_SYNC_STATUS = 'GET_BACKGROUND_SYNC_STATUS',
|
||||
BACKGROUND_SYNC_STATUS = 'BACKGROUND_SYNC_STATUS',
|
||||
}
|
||||
|
||||
// Re-export AnkFlag from WASM for relay message typing
|
||||
|
||||
@ -309,7 +309,7 @@ export class RelayManager {
|
||||
}
|
||||
|
||||
// Relay Message Handling
|
||||
private handleRelayMessage(relayId: string, message: any): void {
|
||||
private async handleRelayMessage(relayId: string, message: any): Promise<void> {
|
||||
console.log(`📨 Received message from relay ${relayId}:`);
|
||||
|
||||
if (message.flag === 'Handshake') {
|
||||
@ -321,7 +321,7 @@ export class RelayManager {
|
||||
// Handle different types of relay responses
|
||||
if (message.flag) {
|
||||
// Handle protocol-specific responses
|
||||
this.handleProtocolMessage(relayId, message);
|
||||
await this.handleProtocolMessage(relayId, message);
|
||||
} else if (message.type === 'heartbeat') {
|
||||
// Update heartbeat
|
||||
const relay = this.relays.get(relayId);
|
||||
@ -337,14 +337,16 @@ export class RelayManager {
|
||||
}
|
||||
}
|
||||
|
||||
private handleProtocolMessage(relayId: string, message: any): void {
|
||||
private async handleProtocolMessage(relayId: string, message: any): Promise<void> {
|
||||
// Handle different AnkFlag responses
|
||||
switch (message.flag) {
|
||||
case "NewTx":
|
||||
console.log(`📨 NewTx response from relay ${relayId}`);
|
||||
setImmediate(() => {
|
||||
Service.getInstance().parseNewTx(message.content);
|
||||
});
|
||||
try {
|
||||
await Service.getInstance().parseNewTx(message.content);
|
||||
} catch (error) {
|
||||
console.error(`❌ Error parsing NewTx from relay ${relayId}:`, error);
|
||||
}
|
||||
break;
|
||||
case "Commit":
|
||||
console.log(`📨 Commit response from relay ${relayId}`);
|
||||
@ -353,9 +355,11 @@ export class RelayManager {
|
||||
break;
|
||||
case "Cipher":
|
||||
console.log(`📨 Cipher response from relay ${relayId}`);
|
||||
setImmediate(() => {
|
||||
Service.getInstance().parseCipher(message.content);
|
||||
});
|
||||
try {
|
||||
await Service.getInstance().parseCipher(message.content);
|
||||
} catch (error) {
|
||||
console.error(`❌ Error parsing Cipher from relay ${relayId}:`, error);
|
||||
}
|
||||
break;
|
||||
case "Handshake":
|
||||
console.log(`📨 Handshake response from relay ${relayId}`);
|
||||
|
||||
@ -16,6 +16,7 @@ export class Service {
|
||||
private membersList: any = {};
|
||||
private relayManager: RelayManager;
|
||||
private storages: string[] = []; // storage urls
|
||||
private backgroundSync: any = null; // BackgroundSyncService
|
||||
|
||||
private constructor() {
|
||||
console.log('🔧 Service initialized');
|
||||
@ -1158,8 +1159,12 @@ export class Service {
|
||||
}
|
||||
|
||||
if (apiReturn.new_tx_to_send && apiReturn.new_tx_to_send.transaction.length != 0) {
|
||||
await this.sendNewTxMessage(JSON.stringify(apiReturn.new_tx_to_send));
|
||||
await new Promise(r => setTimeout(r, 500));
|
||||
try {
|
||||
await this.sendNewTxMessage(JSON.stringify(apiReturn.new_tx_to_send));
|
||||
await new Promise(r => setTimeout(r, 500));
|
||||
} catch (error) {
|
||||
console.error('❌ Error sending NewTx message:', error);
|
||||
}
|
||||
}
|
||||
|
||||
if (apiReturn.secrets) {
|
||||
@ -1244,11 +1249,19 @@ export class Service {
|
||||
|
||||
if (apiReturn.commit_to_send) {
|
||||
const commit = apiReturn.commit_to_send;
|
||||
await this.sendCommitMessage(JSON.stringify(commit));
|
||||
try {
|
||||
await this.sendCommitMessage(JSON.stringify(commit));
|
||||
} catch (error) {
|
||||
console.error('❌ Error sending Commit message:', error);
|
||||
}
|
||||
}
|
||||
|
||||
if (apiReturn.ciphers_to_send && apiReturn.ciphers_to_send.length != 0) {
|
||||
await this.sendCipherMessages(apiReturn.ciphers_to_send);
|
||||
try {
|
||||
await this.sendCipherMessages(apiReturn.ciphers_to_send);
|
||||
} catch (error) {
|
||||
console.error('❌ Error sending Cipher messages:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1448,4 +1461,54 @@ export class Service {
|
||||
throw new Error(`Failed to dump device: ${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Démarre le service de surveillance en arrière-plan
|
||||
*/
|
||||
public async startBackgroundSync(): Promise<void> {
|
||||
if (!this.backgroundSync) {
|
||||
const { BackgroundSyncService } = await import('./background-sync.service');
|
||||
this.backgroundSync = await BackgroundSyncService.getInstance();
|
||||
}
|
||||
await this.backgroundSync.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Arrête le service de surveillance
|
||||
*/
|
||||
public stopBackgroundSync(): void {
|
||||
if (this.backgroundSync) {
|
||||
this.backgroundSync.stop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Force un scan manuel des données manquantes
|
||||
*/
|
||||
public async forceDataScan(): Promise<string[]> {
|
||||
if (!this.backgroundSync) {
|
||||
const { BackgroundSyncService } = await import('./background-sync.service');
|
||||
this.backgroundSync = await BackgroundSyncService.getInstance();
|
||||
}
|
||||
return await this.backgroundSync.forceScan();
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtient le statut du service de background sync
|
||||
*/
|
||||
public getBackgroundSyncStatus(): { isRunning: boolean; scanInterval: number } | null {
|
||||
if (!this.backgroundSync) {
|
||||
return null;
|
||||
}
|
||||
return this.backgroundSync.getStatus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure l'intervalle de scan du background sync
|
||||
*/
|
||||
public setBackgroundSyncInterval(intervalMs: number): void {
|
||||
if (this.backgroundSync) {
|
||||
this.backgroundSync.setScanInterval(intervalMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -321,6 +321,57 @@ class SimpleProcessHandlers {
|
||||
}
|
||||
}
|
||||
|
||||
async handleForceDataScan(event: ServerMessageEvent): Promise<ServerResponse> {
|
||||
if (event.data.type !== MessageType.FORCE_DATA_SCAN) {
|
||||
throw new Error('Invalid message type');
|
||||
}
|
||||
|
||||
try {
|
||||
const { apiKey } = event.data;
|
||||
|
||||
if (!apiKey || !this.validateApiKey(apiKey)) {
|
||||
throw new Error('Invalid API key');
|
||||
}
|
||||
|
||||
const missingHashes = await this.service.forceDataScan();
|
||||
|
||||
return {
|
||||
type: MessageType.DATA_SCAN_RESULT,
|
||||
missingHashes,
|
||||
count: missingHashes.length,
|
||||
messageId: event.data.messageId
|
||||
};
|
||||
} catch (e) {
|
||||
const errorMessage = e instanceof Error ? e.message : String(e || 'Unknown error');
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
async handleGetBackgroundSyncStatus(event: ServerMessageEvent): Promise<ServerResponse> {
|
||||
if (event.data.type !== MessageType.GET_BACKGROUND_SYNC_STATUS) {
|
||||
throw new Error('Invalid message type');
|
||||
}
|
||||
|
||||
try {
|
||||
const { apiKey } = event.data;
|
||||
|
||||
if (!apiKey || !this.validateApiKey(apiKey)) {
|
||||
throw new Error('Invalid API key');
|
||||
}
|
||||
|
||||
const status = this.service.getBackgroundSyncStatus();
|
||||
|
||||
return {
|
||||
type: MessageType.BACKGROUND_SYNC_STATUS,
|
||||
status,
|
||||
messageId: event.data.messageId
|
||||
};
|
||||
} catch (e) {
|
||||
const errorMessage = e instanceof Error ? e.message : String(e || 'Unknown error');
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
async handleMessage(event: ServerMessageEvent): Promise<ServerResponse> {
|
||||
try {
|
||||
switch (event.data.type) {
|
||||
@ -336,6 +387,10 @@ class SimpleProcessHandlers {
|
||||
return await this.handleGetMyProcesses(event);
|
||||
case MessageType.GET_PAIRING_ID:
|
||||
return await this.handleGetPairingId(event);
|
||||
case MessageType.FORCE_DATA_SCAN:
|
||||
return await this.handleForceDataScan(event);
|
||||
case MessageType.GET_BACKGROUND_SYNC_STATUS:
|
||||
return await this.handleGetBackgroundSyncStatus(event);
|
||||
default:
|
||||
throw new Error(`Unhandled message type: ${event.data.type}`);
|
||||
}
|
||||
@ -433,10 +488,20 @@ export class Server {
|
||||
// Connect to relays
|
||||
await service.connectToRelaysAndWaitForHandshake();
|
||||
|
||||
// Start background sync service for missing data detection
|
||||
try {
|
||||
await service.startBackgroundSync();
|
||||
console.log('🔄 Background sync service started');
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to start background sync service:', error);
|
||||
// Don't exit, continue without background sync
|
||||
}
|
||||
|
||||
console.log(`✅ Simple server running on port ${this.wss.options.port}`);
|
||||
console.log('📋 Supported operations: UPDATE_PROCESS, NOTIFY_UPDATE, VALIDATE_STATE');
|
||||
console.log('🔑 Authentication: API key required for all operations');
|
||||
console.log('🔧 Services: Integrated with SimpleService protocol logic');
|
||||
console.log('🔄 Background sync: Automatic missing data detection enabled');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to initialize server:', error);
|
||||
@ -509,6 +574,15 @@ export class Server {
|
||||
public shutdown() {
|
||||
console.log('🛑 Shutting down server...');
|
||||
|
||||
// Stop background sync service
|
||||
try {
|
||||
const service = Service.getInstance();
|
||||
service.stopBackgroundSync();
|
||||
console.log('🔄 Background sync service stopped');
|
||||
} catch (error) {
|
||||
console.error('❌ Error stopping background sync service:', error);
|
||||
}
|
||||
|
||||
// Close all active client connections first
|
||||
for (const [ws, clientId] of this.clients.entries()) {
|
||||
console.log(`🔌 Closing connection to ${clientId}...`);
|
||||
|
||||
@ -50,11 +50,24 @@ export async function retrieveData(servers: string[], key: string): Promise<Arra
|
||||
});
|
||||
|
||||
if (response.status === 200) {
|
||||
// Validate that we received an ArrayBuffer
|
||||
// Handle both ArrayBuffer and Buffer (Node.js)
|
||||
if (response.data instanceof ArrayBuffer) {
|
||||
return response.data;
|
||||
} else if (Buffer.isBuffer(response.data)) {
|
||||
// Convert Buffer to ArrayBuffer
|
||||
return (response.data.buffer as ArrayBuffer).slice(
|
||||
response.data.byteOffset,
|
||||
response.data.byteOffset + response.data.byteLength
|
||||
);
|
||||
} else if (response.data && typeof response.data === 'object' && 'buffer' in response.data) {
|
||||
// Handle Uint8Array or similar typed arrays
|
||||
const buffer = response.data.buffer;
|
||||
return (buffer as ArrayBuffer).slice(
|
||||
response.data.byteOffset,
|
||||
response.data.byteOffset + response.data.byteLength
|
||||
);
|
||||
} else {
|
||||
console.error('Server returned non-ArrayBuffer data:', typeof response.data);
|
||||
console.error('Server returned unsupported data type:', typeof response.data, response.data?.constructor?.name);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user