Compare commits

..

No commits in common. "v1.1.0" and "create-account" have entirely different histories.

140 changed files with 7380 additions and 19398 deletions

View File

@ -1,11 +0,0 @@
# Ignorer les sorties volumineuses ou non pertinentes pour le contexte IA
archive/**
tests/logs/**
tests/reports/**
node_modules/**
dist/**
build/**
.tmp/**
.cache/**#
.env
.env.*

View File

@ -1,59 +0,0 @@
---
alwaysApply: true
---
# Fondations de rédaction et de comportement
[portée]
Sapplique à tout le dépôt 4NK/4NK_node pour toute génération, refactorisation, édition inline ou discussion dans Cursor.
[objectifs]
- Garantir lusage exclusif du français.
- Proscrire linjection dexemples de code applicatif dans la base de code.
- Assurer une cohérence stricte de terminologie et de ton.
- Exiger une introduction et/ou une conclusion dans toute proposition de texte.
[directives]
- Toujours répondre et documenter en français.
- Ne pas inclure dexemples exécutables ou de quickstarts dans la base ; préférer des descriptions prescriptives.
- Tout contenu produit doit mentionner explicitement les artefacts à mettre à jour lorsquil impacte docs/ et tests/.
- Préserver la typographie française (capitaliser uniquement le premier mot dun titre et les noms propres).
[validations]
- Relecture linguistique et technique systématique.
- Refuser toute sortie avec exemples de code applicatif.
- Vérifier que lissue traitée se conclut par un rappel des fichiers à mettre à jour.
[artefacts concernés]
- README.md, docs/**, tests/**, CHANGELOG.md, .gitea/**.# Fondations de rédaction et de comportement
[portée]
Sapplique à tout le dépôt 4NK/4NK_node pour toute génération, refactorisation, édition inline ou discussion dans Cursor.
[objectifs]
- Garantir lusage exclusif du français.
- Proscrire linjection dexemples de code applicatif dans la base de code.
- Assurer une cohérence stricte de terminologie et de ton.
- Exiger une introduction et/ou une conclusion dans toute proposition de texte.
[directives]
- Toujours répondre et documenter en français.
- Ne pas inclure dexemples exécutables ou de quickstarts dans la base ; préférer des descriptions prescriptives.
- Tout contenu produit doit mentionner explicitement les artefacts à mettre à jour lorsquil impacte docs/ et tests/.
- Préserver la typographie française (capitaliser uniquement le premier mot dun titre et les noms propres).
[validations]
- Relecture linguistique et technique systématique.
- Refuser toute sortie avec exemples de code applicatif.
- Vérifier que lissue traitée se conclut par un rappel des fichiers à mettre à jour.
[artefacts concernés]
- README.md, docs/**, tests/**, CHANGELOG.md, .gitea/**.

View File

@ -1,139 +0,0 @@
---
alwaysApply: true
---
# Structure projet 4NK_node
[portée]
Maintenance de larborescence canonique, création/mise à jour/suppression de fichiers et répertoires.
[objectifs]
- Garantir lalignement strict avec larborescence 4NK_node.
- Prévenir toute dérive structurelle.
[directives]
- Sassurer que larborescence suivante existe et reste conforme :
4NK/4NK_node
├── archive
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── docker-compose.yml
├── docs
│ ├── API.md
│ ├── ARCHITECTURE.md
│ ├── COMMUNITY_GUIDE.md
│ ├── CONFIGURATION.md
│ ├── GITEA_SETUP.md
│ ├── INDEX.md
│ ├── INSTALLATION.md
│ ├── MIGRATION.md
│ ├── OPEN_SOURCE_CHECKLIST.md
│ ├── QUICK_REFERENCE.md
│ ├── RELEASE_PLAN.md
│ ├── ROADMAP.md
│ ├── SECURITY_AUDIT.md
│ ├── TESTING.md
│ └── USAGE.md
├── LICENSE
├── README.md
├── tests
│ ├── cleanup.sh
│ ├── connectivity
│ ├── external
│ ├── integration
│ ├── logs
│ ├── performance
│ ├── README.md
│ ├── reports
│ └── unit
└── .gitea
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── PULL_REQUEST_TEMPLATE.md
└── workflows
└── ci.yml
- Tout document obsolète est déplacé vers archive/ avec métadonnées (date, raison).
- Interdire la suppression brute de fichiers sans archivage et note dans CHANGELOG.md.
[validations]
- Diff structurel comparé à cette référence.
- Erreur bloquante si un fichier « requis » manque.
[artefacts concernés]
- archive/**, docs/**, tests/**, .gitea/**, CHANGELOG.md.
# Structure projet 4NK_node
[portée]
Maintenance de larborescence canonique, création/mise à jour/suppression de fichiers et répertoires.
[objectifs]
- Garantir lalignement strict avec larborescence 4NK_node.
- Prévenir toute dérive structurelle.
[directives]
- Sassurer que larborescence suivante existe et reste conforme :
4NK/4NK_node
├── archive
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── docker-compose.yml
├── docs
│ ├── API.md
│ ├── ARCHITECTURE.md
│ ├── COMMUNITY_GUIDE.md
│ ├── CONFIGURATION.md
│ ├── GITEA_SETUP.md
│ ├── INDEX.md
│ ├── INSTALLATION.md
│ ├── MIGRATION.md
│ ├── OPEN_SOURCE_CHECKLIST.md
│ ├── QUICK_REFERENCE.md
│ ├── RELEASE_PLAN.md
│ ├── ROADMAP.md
│ ├── SECURITY_AUDIT.md
│ ├── TESTING.md
│ └── USAGE.md
├── LICENSE
├── README.md
├── tests
│ ├── cleanup.sh
│ ├── connectivity
│ ├── external
│ ├── integration
│ ├── logs
│ ├── performance
│ ├── README.md
│ ├── reports
│ └── unit
└── .gitea
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── PULL_REQUEST_TEMPLATE.md
└── workflows
└── ci.yml
- Tout document obsolète est déplacé vers archive/ avec métadonnées (date, raison).
- Interdire la suppression brute de fichiers sans archivage et note dans CHANGELOG.md.
[validations]
- Diff structurel comparé à cette référence.
- Erreur bloquante si un fichier « requis » manque.
[artefacts concernés]
- archive/**, docs/**, tests/**, .gitea/**, CHANGELOG.md.

View File

@ -1,62 +0,0 @@
---
alwaysApply: true
---
# Documentation continue
[portée]
Mises à jour de docs/** corrélées à tout changement de code, configuration, dépendance, données ou CI.
[objectifs]
- Remplacer toute section générique « RESUME » par des mises à jour ciblées dans les fichiers appropriés.
- Tenir INDEX.md comme table des matières de référence.
[directives]
- À chaque changement, mettre à jour :
- API.md (spécifications, contrats, schémas, invariants).
- ARCHITECTURE.md (décisions, diagrammes, couplages, performances).
- CONFIGURATION.md (paramètres, formats, valeurs par défaut).
- INSTALLATION.md (pré-requis, étapes, vérifications).
- MIGRATION.md (chemins de migration, scripts, compatibilités).
- USAGE.md (parcours fonctionnels, contraintes).
- TESTING.md (pyramide, critères dacceptation).
- SECURITY_AUDIT.md (menaces, contrôles, dettes résiduelles).
- RELEASE_PLAN.md, ROADMAP.md (planification), OPEN_SOURCE_CHECKLIST.md, COMMUNITY_GUIDE.md, GITEA_SETUP.md.
- Maintenir QUICK_REFERENCE.md pour les référentiels synthétiques utilisés par léquipe.
- Ajouter un REX technique en cas dhypothèses multiples avant résolution dans archive/.
[validations]
- Cohérence croisée entre README.md et INDEX.md.
- Refus si une modification de code na pas de trace dans docs/** correspondants.
[artefacts concernés]
- docs/**, README.md, archive/**.
# Documentation continue
[portée]
Mises à jour de docs/** corrélées à tout changement de code, configuration, dépendance, données ou CI.
[objectifs]
- Remplacer toute section générique « RESUME » par des mises à jour ciblées dans les fichiers appropriés.
- Tenir INDEX.md comme table des matières de référence.
[directives]
- À chaque changement, mettre à jour :
- API.md (spécifications, contrats, schémas, invariants).
- ARCHITECTURE.md (décisions, diagrammes, couplages, performances).
- CONFIGURATION.md (paramètres, formats, valeurs par défaut).
- INSTALLATION.md (pré-requis, étapes, vérifications).
- MIGRATION.md (chemins de migration, scripts, compatibilités).
- USAGE.md (parcours fonctionnels, contraintes).
- TESTING.md (pyramide, critères dacceptation).
- SECURITY_AUDIT.md (menaces, contrôles, dettes résiduelles).
- RELEASE_PLAN.md, ROADMAP.md (planification), OPEN_SOURCE_CHECKLIST.md, COMMUNITY_GUIDE.md, GITEA_SETUP.md.
- Maintenir QUICK_REFERENCE.md pour les référentiels synthétiques utilisés par léquipe.
- Ajouter un REX technique en cas dhypothèses multiples avant résolution dans archive/.
[validations]
- Cohérence croisée entre README.md et INDEX.md.
- Refus si une modification de code na pas de trace dans docs/** correspondants.
[artefacts concernés]
- docs/**, README.md, archive/**.

View File

@ -1,57 +0,0 @@
---
alwaysApply: true
---
# Tests et qualité
[portée]
Stratégie de tests, exécution locale, stabilité, non-régression.
[objectifs]
- Exiger des tests verts avant tout commit.
- Couvrir les axes unit, integration, connectivity, performance, external.
[directives]
- Ajouter/mettre à jour des tests dans tests/unit, tests/integration, tests/connectivity, tests/performance, tests/external selon limpact.
- Consigner les journaux dans tests/logs et les rapports dans tests/reports.
- Maintenir tests/README.md (stratégie, outillage, seuils).
- Fournir un nettoyage reproductible via tests/cleanup.sh.
- Bloquer lédition si des tests échouent tant que la correction nest pas appliquée.
[validations]
- Refus dun commit si tests en échec.
- Exiger justification et plan de test dans docs/TESTING.md pour toute refonte majeure.
[artefacts concernés]
- tests/**, docs/TESTING.md, CHANGELOG.md.
# Tests et qualité
[portée]
Stratégie de tests, exécution locale, stabilité, non-régression.
[objectifs]
- Exiger des tests verts avant tout commit.
- Couvrir les axes unit, integration, connectivity, performance, external.
[directives]
- Ajouter/mettre à jour des tests dans tests/unit, tests/integration, tests/connectivity, tests/performance, tests/external selon limpact.
- Consigner les journaux dans tests/logs et les rapports dans tests/reports.
- Maintenir tests/README.md (stratégie, outillage, seuils).
- Fournir un nettoyage reproductible via tests/cleanup.sh.
- Bloquer lédition si des tests échouent tant que la correction nest pas appliquée.
[validations]
- Refus dun commit si tests en échec.
- Exiger justification et plan de test dans docs/TESTING.md pour toute refonte majeure.
[artefacts concernés]
- tests/**, docs/TESTING.md, CHANGELOG.md.

View File

@ -1,55 +0,0 @@
---
alwaysApply: true
---
# Dépendances, compilation et build
[portée]
Gestion des dépendances, compilation fréquente, politique de versions.
[objectifs]
- Ajouter automatiquement les dépendances manquantes si justifié.
- Rechercher systématiquement les dernières versions stables.
[directives]
- Lorsquune fonctionnalité nécessite une dépendance, lajouter et la documenter (nom, version, portée, impact) dans docs/ARCHITECTURE.md et docs/CONFIGURATION.md si nécessaire.
- Compiler très régulièrement et « quand nécessaire » (avant refactor, avant push, après mise à jour de dépendances).
- Corriger toute erreur de compilation/exécution avant de poursuivre.
- Documenter tout changement de dépendances (raison, risques, rollback).
[validations]
- Interdire la progression si la compilation échoue.
- Vérifier la présence dune note de changement dans CHANGELOG.md en cas de dépendance ajoutée/retirée.
[artefacts concernés]
- docs/ARCHITECTURE.md, docs/CONFIGURATION.md, CHANGELOG.md.
# Dépendances, compilation et build
[portée]
Gestion des dépendances, compilation fréquente, politique de versions.
[objectifs]
- Ajouter automatiquement les dépendances manquantes si justifié.
- Rechercher systématiquement les dernières versions stables.
[directives]
- Lorsquune fonctionnalité nécessite une dépendance, lajouter et la documenter (nom, version, portée, impact) dans docs/ARCHITECTURE.md et docs/CONFIGURATION.md si nécessaire.
- Compiler très régulièrement et « quand nécessaire » (avant refactor, avant push, après mise à jour de dépendances).
- Corriger toute erreur de compilation/exécution avant de poursuivre.
- Documenter tout changement de dépendances (raison, risques, rollback).
[validations]
- Interdire la progression si la compilation échoue.
- Vérifier la présence dune note de changement dans CHANGELOG.md en cas de dépendance ajoutée/retirée.
[artefacts concernés]
- docs/ARCHITECTURE.md, docs/CONFIGURATION.md, CHANGELOG.md.

View File

@ -1,54 +0,0 @@
---
alwaysApply: false
---
# Modélisation des données à partir de CSV
[portée]
Utilisation des CSV comme base des modèles de données, y compris en-têtes multi-lignes.
[objectifs]
- Confirmer la structure inférée pour chaque CSV.
- Demander une définition formelle de toutes les colonnes.
[directives]
- Gérer explicitement les en-têtes multi-lignes (titre principal + sous-colonnes).
- Confirmer par écrit dans docs/API.md ou docs/ARCHITECTURE.md : nombre de lignes den-tête, mapping colonnes→types, unités, domaines de valeurs, nullabilité, contraintes.
- Poser des questions si ambiguïtés ; proposer une normalisation temporaire documentée.
- Corriger automatiquement les incohérences de types si une règle de mapping est établie ailleurs et documenter la transformation.
[validations]
- Aucune ingestion sans spécification de colonnes validée.
- Traçabilité des corrections de types (avant/après) dans docs/ARCHITECTURE.md.
[artefacts concernés]
- docs/API.md, docs/ARCHITECTURE.md, docs/USAGE.md.
# Modélisation des données à partir de CSV
[portée]
Utilisation des CSV comme base des modèles de données, y compris en-têtes multi-lignes.
[objectifs]
- Confirmer la structure inférée pour chaque CSV.
- Demander une définition formelle de toutes les colonnes.
[directives]
- Gérer explicitement les en-têtes multi-lignes (titre principal + sous-colonnes).
- Confirmer par écrit dans docs/API.md ou docs/ARCHITECTURE.md : nombre de lignes den-tête, mapping colonnes→types, unités, domaines de valeurs, nullabilité, contraintes.
- Poser des questions si ambiguïtés ; proposer une normalisation temporaire documentée.
- Corriger automatiquement les incohérences de types si une règle de mapping est établie ailleurs et documenter la transformation.
[validations]
- Aucune ingestion sans spécification de colonnes validée.
- Traçabilité des corrections de types (avant/après) dans docs/ARCHITECTURE.md.
[artefacts concernés]
- docs/API.md, docs/ARCHITECTURE.md, docs/USAGE.md.

View File

@ -1,41 +0,0 @@
---
alwaysApply: false
---
# Lecture des documents bureautiques
[portée]
Lecture des fichiers .docx et alternatives.
[objectifs]
- Utiliser docx2txt par défaut.
- Proposer des solutions de repli si lecture impossible.
[directives]
- Lire les .docx avec docx2txt.
- En cas déchec, proposer : conversion via pandoc, demande dune source alternative, ou extraction textuelle.
- Documenter dans docs/INDEX.md la provenance et le statut des documents importés.
[validations]
- Vérification que les contenus extraits sont intégrés aux fichiers docs/ concernés.
[artefacts concernés]
- docs/**, archive/**.
# Lecture des documents bureautiques
[portée]
Lecture des fichiers .docx et alternatives.
[objectifs]
- Utiliser docx2txt par défaut.
- Proposer des solutions de repli si lecture impossible.
[directives]
- Lire les .docx avec docx2txt.
- En cas déchec, proposer : conversion via pandoc, demande dune source alternative, ou extraction textuelle.
- Documenter dans docs/INDEX.md la provenance et le statut des documents importés.
[validations]
- Vérification que les contenus extraits sont intégrés aux fichiers docs/ concernés.
[artefacts concernés]
- docs/**, archive/**.

View File

@ -1,56 +0,0 @@
---
alwaysApply: false
---
# Architecture frontend
[portée]
Qualité du bundle, découpage, état global et couche de services.
[objectifs]
- Réduire la taille du bundle initial via code splitting.
- Éviter le prop drilling via Redux ou Context API.
- Abstraire les services de données pour testabilité et maintenance.
[directives]
- Mettre en place React.lazy et Suspense pour le chargement différé des vues/segments.
- Centraliser létat global via Redux ou Context API.
- Isoler les appels « data » derrière une couche dabstraction à interface stable.
- Interdire lajout dexemples front dans la base de code.
[validations]
- Vérifier que les points dentrée sont minimes et que les segments non critiques sont chargés à la demande.
- Sassurer que docs/ARCHITECTURE.md décrit les décisions et les points dextension.
[artefacts concernés]
- docs/ARCHITECTURE.md, docs/TESTING.md.
# Architecture frontend
[portée]
Qualité du bundle, découpage, état global et couche de services.
[objectifs]
- Réduire la taille du bundle initial via code splitting.
- Éviter le prop drilling via Redux ou Context API.
- Abstraire les services de données pour testabilité et maintenance.
[directives]
- Mettre en place React.lazy et Suspense pour le chargement différé des vues/segments.
- Centraliser létat global via Redux ou Context API.
- Isoler les appels « data » derrière une couche dabstraction à interface stable.
- Interdire lajout dexemples front dans la base de code.
[validations]
- Vérifier que les points dentrée sont minimes et que les segments non critiques sont chargés à la demande.
- Sassurer que docs/ARCHITECTURE.md décrit les décisions et les points dextension.
[artefacts concernés]
- docs/ARCHITECTURE.md, docs/TESTING.md.

View File

@ -1,53 +0,0 @@
---
alwaysApply: false
---
# Versionnage et publication
[portée]
Gestion sémantique des versions, CHANGELOG, confirmation push/tag.
[objectifs]
- Tenir CHANGELOG.md comme source unique de vérité.
- Demander confirmation avant push et tag.
[directives]
- À chaque changement significatif, mettre à jour CHANGELOG.md (ajouts, changements, corrections, ruptures).
- Proposer un bump semver (major/minor/patch) motivé par limpact.
- Avant tout push ou tag, demander confirmation explicite.
[validations]
- Refus si modification sans entrée correspondante dans CHANGELOG.md.
- Cohérence entre CHANGELOG.md, docs/RELEASE_PLAN.md et docs/ROADMAP.md.
[artefacts concernés]
- CHANGELOG.md, docs/RELEASE_PLAN.md, docs/ROADMAP.md.
# Versionnage et publication
[portée]
Gestion sémantique des versions, CHANGELOG, confirmation push/tag.
[objectifs]
- Tenir CHANGELOG.md comme source unique de vérité.
- Demander confirmation avant push et tag.
[directives]
- À chaque changement significatif, mettre à jour CHANGELOG.md (ajouts, changements, corrections, ruptures).
- Proposer un bump semver (major/minor/patch) motivé par limpact.
- Avant tout push ou tag, demander confirmation explicite.
[validations]
- Refus si modification sans entrée correspondante dans CHANGELOG.md.
- Cohérence entre CHANGELOG.md, docs/RELEASE_PLAN.md et docs/ROADMAP.md.
[artefacts concernés]
- CHANGELOG.md, docs/RELEASE_PLAN.md, docs/ROADMAP.md.

View File

@ -1,59 +0,0 @@
---
alwaysApply: true
---
# Open source et Gitea
[portée]
Conformité open source, templates Gitea, CI.
[objectifs]
- Préparer chaque projet pour un dépôt Gitea (git.4nkweb.com).
- Maintenir les fichiers de gouvernance et la CI.
[directives]
- Vérifier la présence et lactualité de : LICENSE, CONTRIBUTING.md, CODE_OF_CONDUCT.md, OPEN_SOURCE_CHECKLIST.md.
- Maintenir .gitea/ :
- ISSUE_TEMPLATE/bug_report.md, feature_request.md
- PULL_REQUEST_TEMPLATE.md
- workflows/ci.yml
- Documenter dans docs/GITEA_SETUP.md la configuration distante et les permissions.
[validations]
- Refus si un des fichiers « gouvernance/CI » manque.
- Cohérence entre docs/OPEN_SOURCE_CHECKLIST.md et létat du repo.
[artefacts concernés]
- .gitea/**, docs/GITEA_SETUP.md, docs/OPEN_SOURCE_CHECKLIST.md.
# Open source et Gitea
[portée]
Conformité open source, templates Gitea, CI.
[objectifs]
- Préparer chaque projet pour un dépôt Gitea (git.4nkweb.com).
- Maintenir les fichiers de gouvernance et la CI.
[directives]
- Vérifier la présence et lactualité de : LICENSE, CONTRIBUTING.md, CODE_OF_CONDUCT.md, OPEN_SOURCE_CHECKLIST.md.
- Maintenir .gitea/ :
- ISSUE_TEMPLATE/bug_report.md, feature_request.md
- PULL_REQUEST_TEMPLATE.md
- workflows/ci.yml
- Documenter dans docs/GITEA_SETUP.md la configuration distante et les permissions.
[validations]
- Refus si un des fichiers « gouvernance/CI » manque.
- Cohérence entre docs/OPEN_SOURCE_CHECKLIST.md et létat du repo.
[artefacts concernés]
- .gitea/**, docs/GITEA_SETUP.md, docs/OPEN_SOURCE_CHECKLIST.md.

View File

@ -1,53 +0,0 @@
---
alwaysApply: true
---
# Tri, diagnostic et résolution de problèmes
[portée]
Boucle de triage : reproduction, diagnostic, correctif, non-régression.
[objectifs]
- Exécuter automatiquement les étapes de résolution.
- Bloquer lavancement tant que les erreurs ne sont pas corrigées.
[directives]
- Étapes obligatoires : reproduction minimale, inspection des logs, bissection des changements, formulation dhypothèses, tests ciblés, correctif, test de non-régression.
- Lorsque plusieurs hypothèses ont été testées, produire un REX dans archive/ avec liens vers les commits.
- Poser des questions de cohérence fonctionnelle si des ambiguïtés subsistent (contrats dAPI, invariants, SLA).
[validations]
- Interdiction de clore une tâche si un test échoue ou si une alerte critique subsiste.
- Traçabilité du REX si investigations multiples.
[artefacts concernés]
- tests/**, archive/**, docs/TESTING.md, docs/ARCHITECTURE.md.
# Tri, diagnostic et résolution de problèmes
[portée]
Boucle de triage : reproduction, diagnostic, correctif, non-régression.
[objectifs]
- Exécuter automatiquement les étapes de résolution.
- Bloquer lavancement tant que les erreurs ne sont pas corrigées.
[directives]
- Étapes obligatoires : reproduction minimale, inspection des logs, bissection des changements, formulation dhypothèses, tests ciblés, correctif, test de non-régression.
- Lorsque plusieurs hypothèses ont été testées, produire un REX dans archive/ avec liens vers les commits.
- Poser des questions de cohérence fonctionnelle si des ambiguïtés subsistent (contrats dAPI, invariants, SLA).
[validations]
- Interdiction de clore une tâche si un test échoue ou si une alerte critique subsiste.
- Traçabilité du REX si investigations multiples.
[artefacts concernés]
- tests/**, archive/**, docs/TESTING.md, docs/ARCHITECTURE.md.

View File

@ -1,15 +0,0 @@
# Index des règles .cursor/rules
- 00-foundations.mdc : règles linguistiques et éditoriales (français, pas dexemples en base, introduction/conclusion).
- 10-project-structure.mdc : arborescence canonique 4NK_node et garde-fous.
- 20-documentation.mdc : documentation continue, remplacement de « RESUME », INDEX.md.
- 30-testing.mdc : tests (unit, integration, connectivity, performance, external), logs/reports.
- 40-dependencies-and-build.mdc : dépendances, compilation, corrections bloquantes.
- 50-data-csv-models.mdc : CSV avec en-têtes multi-lignes, définition des colonnes.
- 60-office-docs.mdc : lecture .docx via docx2txt + repli.
- 70-frontend-architecture.mdc : React.lazy/Suspense, état global, couche de services.
- 80-versioning-and-release.mdc : CHANGELOG, semver, confirmation push/tag.
- 90-gitea-and-oss.mdc : fichiers open source, .gitea, CI, Gitea remote.
- 95-triage-and-problem-solving.mdc : boucle de diagnostic, REX, non-régression.
Ces règles sont conçues pour être ajoutées au contexte de Cursor depuis linterface (@Cursor Rules) et sappuient sur le mécanisme de règles projet stockées dans `.cursor/rules/`. :contentReference[oaicite:3]{index=3}

View File

@ -1,102 +0,0 @@
# Fichiers et répertoires à ignorer pour lindexation Cursor
# Dépendances frontend / JS
node_modules/
**/node_modules/**
# Artefacts de build et caches courants
dist/
build/
out/
.next/
coverage/
.cache/
.turbo/
.parcel-cache/
.eslintcache
# Logs et temporaires
*.log
*.tmp
*.swp
*.swo
npm-debug.log*
yarn-debug.log*
pnpm-debug.log*
# Environnements et secrets (ne pas indexer)
.env
.env.*
*.pem
*.key
*.crt
# Artefacts tests
tests/logs/
tests/reports/
tests/**/tmp/
# Répertoires développeur
.nvm/
.venv/
.idea/
.vscode/
# Système
.DS_Store
Thumbs.db
# Rust (si présent localement)
target/
# Docker (artefacts locaux éventuels)
docker-compose.override.yml
docker-compose.*.yml.local
*.docker.tar
docker-image-*.tar
docker-save-*.tar
.docker/
.docker-compose/
docker-data/
docker-volumes/
docker-logs/
# ihm_client spécifiques
ihm_client/.vercel/
ihm_client/.pnpm-store/
ihm_client/.yarn/**
# Archives et sauvegardes (ne pas indexer)
*.zip
*.tar
*.tar.gz
*.tgz
*.gz
*.bz2
*.xz
*.zst
*.7z
*.rar
*.iso
*.bak
*.backup
*.old
*.orig
# Répertoire darchives du projet
archive/
# Dumps SQL et exports de bases de données
*.sql
*.sql.gz
*.dump
*.dmp
*.sqlite
*.sqlite3
*.db
*.db3
*.bak.sql
sql_dumps/
db_dumps/
database_dumps/
backups/sql/

3
.env
View File

@ -1,4 +1,3 @@
# .env # .env
VITE_API_URL=https://api.example.com VITE_API_URL=https://api.example.com
VITE_API_KEY=your_api_key VITE_API_KEY=your_api_key
VITE_JWT_SECRET_KEY="your_secret_key"

View File

@ -1,39 +0,0 @@
---
name: Rapport de bug
about: Créer un rapport pour nous aider à améliorer l'interface utilisateur 4NK
title: '[BUG] '
labels: ['bug', 'needs-triage']
assignees: ''
---
## Description du bug
Une description claire et concise du bug.
## Étapes pour reproduire
1. Aller à '...'
2. Cliquer sur '...'
3. Faire défiler jusqu'à '...'
4. Voir l'erreur
## Comportement attendu
Une description claire et concise de ce que vous attendiez.
## Captures d'écran
Si applicable, ajoutez des captures d'écran pour expliquer votre problème.
## Environnement
- OS: [ex. iOS]
- Navigateur: [ex. chrome, safari]
- Version: [ex. 22]
- Version de l'application: [ex. 1.0.0]
## Contexte supplémentaire
Ajoutez tout autre contexte concernant le problème ici.
## Logs
Si applicable, ajoutez les logs d'erreur du navigateur ou de l'application.
## Checklist
- [ ] J'ai vérifié que le bug n'a pas déjà été signalé
- [ ] J'ai fourni toutes les informations nécessaires pour reproduire le bug
- [ ] J'ai testé sur différents navigateurs/environnements

View File

@ -1,46 +0,0 @@
---
name: Demande de fonctionnalité
about: Suggérer une idée pour l'interface utilisateur 4NK
title: '[FEATURE] '
labels: ['enhancement', 'needs-triage']
assignees: ''
---
## Problème lié
Une description claire et concise du problème que cette fonctionnalité résoudrait.
Exemple: Handshake iframe fragile (courses à l'init) entre parent et `ihm_client`.
## Solution proposée
Une description claire et concise de ce que vous voulez qu'il se passe.
Proposition: protocole READY → LISTENING → REQUEST_LINK avec ACKs, timeouts et retries exponentiels; validation stricte de `origin` et corrélation `messageId`.
## Alternatives considérées
Une description claire et concise de toutes les solutions ou fonctionnalités alternatives que vous avez considérées.
## Contexte supplémentaire
Ajoutez tout autre contexte ou captures d'écran concernant la demande de fonctionnalité ici.
Critères dacceptation:
- Pas de course observée (100 itérations CI)
- Compatibilité ascendante des intégrations existantes
## Impact utilisateur
- [ ] Améliore l'expérience utilisateur
- [ ] Corrige un problème de performance
- [ ] Ajoute une fonctionnalité manquante
- [ ] Améliore l'accessibilité
- [ ] Autre (précisez)
## Priorité
- [ ] Critique
- [ ] Haute
- [ ] Moyenne
- [ ] Basse
## Checklist
- [ ] J'ai vérifié que cette fonctionnalité n'a pas déjà été demandée
- [ ] J'ai fourni une description claire du besoin
- [ ] J'ai considéré les alternatives
- [ ] J'ai évalué l'impact sur les utilisateurs existants

View File

@ -1,30 +0,0 @@
## Description
Une description claire et concise des changements apportés.
## Type de changement
- [ ] Correction de bug (changement non-breaking qui corrige un problème)
- [ ] Nouvelle fonctionnalité (changement non-breaking qui ajoute une fonctionnalité)
- [ ] Breaking change (correction ou fonctionnalité qui causerait un comportement existant à ne pas fonctionner comme prévu)
- [ ] Documentation (mise à jour de la documentation)
## Tests
- [ ] J'ai exécuté les tests unitaires
- [ ] J'ai exécuté les tests d'intégration
- [ ] J'ai testé manuellement les changements
- [ ] J'ai vérifié la compatibilité avec les navigateurs cibles
## Checklist
- [ ] Mon code suit les conventions de style du projet
- [ ] J'ai effectué un auto-review de mon propre code
- [ ] J'ai commenté mon code, particulièrement dans les zones difficiles à comprendre
- [ ] J'ai apporté les changements correspondants à la documentation
- [ ] Mes changements ne génèrent pas de nouveaux warnings
- [ ] J'ai ajouté des tests qui prouvent que ma correction fonctionne ou que ma fonctionnalité fonctionne
- [ ] Les tests unitaires et d'intégration passent avec mes changements
- [ ] J'ai vérifié que mes changements n'affectent pas négativement les performances
## Captures d'écran (si applicable)
Ajoutez des captures d'écran pour montrer les changements visuels.
## Informations supplémentaires
Toute autre information ou contexte que vous souhaitez ajouter.

View File

@ -1,116 +0,0 @@
name: CI/CD Pipeline
on:
push:
branches: [ docker-support ]
pull_request:
branches: [ docker-support ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Setup SSH for Gitea
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H git.4nkweb.com >> ~/.ssh/known_hosts
git config --global url."git@git.4nkweb.com:".insteadOf "https://git.4nkweb.com/"
- name: Checkout code
uses: actions/checkout@v3
with:
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
submodules: recursive
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run linting
run: npm run lint
- name: Run type checking
run: npm run type-check
- name: Run tests
run: npm run test
- name: Build application
run: npm run build
- name: Install Playwright browsers
run: npm run e2e:install
- name: Run E2E tests
run: npm run test:e2e
- name: Test Docker build (artefacts)
run: |
docker build -t ihm-client:dist .
docker image rm ihm-client:dist
security:
runs-on: ubuntu-latest
needs: test
steps:
- name: Setup SSH for Gitea
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H git.4nkweb.com >> ~/.ssh/known_hosts
git config --global url."git@git.4nkweb.com:".insteadOf "https://git.4nkweb.com/"
- name: Checkout code
uses: actions/checkout@v3
with:
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Run security audit
run: npm audit --audit-level=moderate
- name: Check for known vulnerabilities
run: npm audit --audit-level=high
integration-test:
runs-on: ubuntu-latest
needs: test
steps:
- name: Setup SSH for Gitea
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H git.4nkweb.com >> ~/.ssh/known_hosts
git config --global url."git@git.4nkweb.com:".insteadOf "https://git.4nkweb.com/"
- name: Checkout code
uses: actions/checkout@v3
with:
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Build Docker artefacts
run: |
docker build -t ihm-client:dist .
docker image rm ihm-client:dist

32
.gitignore vendored
View File

@ -1,35 +1,7 @@
target/ target/
pkg/
Cargo.lock Cargo.lock
node_modules/ node_modules/
dist/ dist/
.vscode .vscode
public/ssl/ public/ssl/
# Temporary dependencies
temp-deps/
# Test coverage
coverage/
# Environment files
.env
.env.local
.env.production
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
# Editor directories and files
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@ -1,18 +0,0 @@
# Configuration SSH automatique pour ihm_client
# Généré le lun. 25 août 2025 16:59:11 CEST
# Configuration Git
git config --global url."git@git.4nkweb.com:".insteadOf "https://git.4nkweb.com/"
# Alias Git
git config --global alias.ssh-push '!f() { git add . && git commit -m "${1:-Auto-commit $(date)}" && git push origin $(git branch --show-current); }; f'
git config --global alias.quick-push '!f() { git add . && git commit -m "Update $(date)" && git push origin $(git branch --show-current); }; f'
# Test SSH
ssh -T git@git.4nkweb.com
# Scripts disponibles
./scripts/auto-ssh-push.sh quick
./scripts/auto-ssh-push.sh message "Mon message"
git ssh-push "Mon message"
git quick-push

357
AGENTS.md
View File

@ -1,357 +0,0 @@
# AGENTS.md - ihm_client
## Table des matières
- [Introduction](#introduction)
- [Agents fondamentaux](#agents-fondamentaux)
- [Agents spécialisés frontend](#agents-spécialisés-frontend)
- [Agents spécialisés WASM](#agents-spécialisés-wasm)
- [Agents spécialisés tests](#agents-spécialisés-tests)
- [Agents documentation](#agents-documentation)
- [Agents open source et CI](#agents-open-source-et-ci)
- [Agents complémentaires](#agents-complémentaires)
- [Matrice de coordination](#matrice-de-coordination)
- [Conclusion](#conclusion)
---
## Introduction
Ce document définit les agents, leurs rôles et leurs responsabilités dans le projet `ihm_client`.
Chaque agent est assigné à un périmètre clair (frontend, WASM, tests, documentation, CI, gouvernance open source).
L'objectif est d'assurer une maintenance cohérente de l'interface utilisateur, une traçabilité complète et une exécution fiable des bonnes pratiques.
Les règles détaillées de réalisation et de contrôle sont précisées dans `.cursor/rules/`.
---
## Agents fondamentaux
### Agent Fondation
**Rôle (Responsable)** :
- Garantir que toute production est en français.
- Vérifier l'absence d'exemples de code applicatif dans la base de code.
- Imposer l'introduction et/ou conclusion dans chaque contenu.
**Artefacts :**
- Tous fichiers.
---
### Agent Structure
**Rôle (Responsable)** :
- Maintenir l'arborescence canonique du projet.
- Déplacer les documents obsolètes vers `archive/`.
- Bloquer toute suppression non documentée.
**Artefacts :**
- `archive/`, `docs/`, `tests/`, `.gitea/`, `CHANGELOG.md`.
---
## Agents spécialisés frontend
### Agent Vue.js
**Rôle (Responsable)** :
- Maintenir la qualité du code Vue.js.
- Assurer la cohérence des composants.
- Optimiser les performances de l'interface.
**Artefacts :**
- `src/components/`, `src/pages/`, `src/services/`.
---
### Agent TypeScript
**Rôle (Responsable)** :
- Maintenir la qualité du code TypeScript.
- Assurer la cohérence des types.
- Optimiser la compilation TypeScript.
**Artefacts :**
- `src/types/`, `tsconfig.json`, `vite.config.ts`.
---
### Agent UI/UX
**Rôle (Responsable)** :
- Maintenir la cohérence de l'interface utilisateur.
- Assurer l'accessibilité.
- Optimiser l'expérience utilisateur.
**Artefacts :**
- `src/components/`, `src/pages/`, `src/assets/`.
---
## Agents spécialisés WASM
### Agent Rust
**Rôle (Responsable)** :
- Maintenir la qualité du code Rust.
- Assurer la sécurité de la mémoire.
- Optimiser les performances WASM.
**Artefacts :**
- `temp-deps/sdk_client/`, `temp-deps/sdk_common/`.
---
### Agent WASM
**Rôle (Responsable)** :
- Maintenir la compilation WASM.
- Assurer l'intégration avec le frontend.
- Optimiser la taille du bundle WASM.
**Artefacts :**
- `pkg/`, `scripts/setup-remote-deps.sh`.
---
### Agent Silent Payments
**Rôle (Responsable)** :
- Maintenir l'intégration des Silent Payments.
- Assurer la sécurité des transactions.
- Optimiser les performances de paiement.
**Artefacts :**
- `src/services/`, `src/types/sdk_client.d.ts`.
---
## Agents spécialisés tests
### Agent Tests Frontend
**Rôle (Responsable)** :
- Maintenir la couverture des tests frontend.
- Assurer la qualité des tests Vue.js.
- Optimiser l'exécution des tests.
**Artefacts :**
- `tests/unit/`, `tests/integration/`.
---
### Agent Tests WASM
**Rôle (Responsable)** :
- Maintenir la couverture des tests WASM.
- Assurer la qualité des tests Rust.
- Optimiser l'exécution des tests WASM.
**Artefacts :**
- `temp-deps/sdk_client/tests/`.
---
### Agent Tests E2E
**Rôle (Responsable)** :
- Maintenir la couverture des tests end-to-end.
- Assurer la qualité des tests d'intégration.
- Optimiser l'exécution des tests E2E.
**Artefacts :**
- `tests/e2e/`, `tests/performance/`.
---
## Agents documentation
### Agent Documentation
**Rôle (Responsable)** :
- Mettre à jour les fichiers de `docs/` selon l'impact des changements.
- Maintenir `README.md` comme documentation principale.
- Produire des REX techniques dans `archive/`.
**Artefacts :**
- `docs/`, `README.md`, `CHANGELOG.md`.
---
### Agent API Documentation
**Rôle (Responsable)** :
- Maintenir la documentation des APIs.
- Assurer la cohérence des types TypeScript.
- Optimiser la documentation des interfaces.
**Artefacts :**
- `docs/API.md`, `src/types/`.
---
### Agent User Documentation
**Rôle (Responsable)** :
- Maintenir la documentation utilisateur.
- Assurer la clarté des guides.
- Optimiser l'expérience de lecture.
**Artefacts :**
- `docs/USAGE.md`, `docs/INSTALLATION.md`.
---
## Agents open source et CI
### Agent Open Source
**Rôle (Responsable)** :
- Maintenir la conformité open source.
- Assurer la qualité des licences.
- Optimiser la gouvernance open source.
**Artefacts :**
- `LICENSE`, `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`.
---
### Agent CI/CD
**Rôle (Responsable)** :
- Maintenir la pipeline CI/CD.
- Assurer la qualité des builds.
- Optimiser l'automatisation.
**Artefacts :**
- `.gitea/workflows/`, `scripts/`.
---
### Agent Security
**Rôle (Responsable)** :
- Maintenir la sécurité du code.
- Assurer la qualité des audits de sécurité.
- Optimiser la gestion des vulnérabilités.
**Artefacts :**
- `SECURITY.md`, `docs/SECURITY_AUDIT.md`.
---
## Agents complémentaires
### Agent Performance
**Rôle (Consulté)** :
- Optimiser les performances frontend.
- Assurer la qualité des métriques.
- Optimiser l'expérience utilisateur.
**Artefacts :**
- `src/`, `dist/`.
---
### Agent Accessibility
**Rôle (Consulté)** :
- Maintenir l'accessibilité de l'interface.
- Assurer la conformité WCAG.
- Optimiser l'expérience pour tous les utilisateurs.
**Artefacts :**
- `src/components/`, `src/pages/`.
---
### Agent Internationalization
**Rôle (Consulté)** :
- Maintenir l'internationalisation.
- Assurer la qualité des traductions.
- Optimiser l'expérience multilingue.
**Artefacts :**
- `src/locales/`, `src/i18n/`.
---
## Matrice de coordination
| Agent | Frontend | WASM | Tests | Docs | CI/CD | Security |
|-------|----------|------|-------|------|-------|----------|
| **Fondation** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| **Structure** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| **Vue.js** | 🔴 | ⚪ | ⚪ | ⚪ | ⚪ | ⚪ |
| **TypeScript** | 🔴 | ⚪ | 🔴 | ⚪ | ⚪ | ⚪ |
| **UI/UX** | 🔴 | ⚪ | ⚪ | ⚪ | ⚪ | ⚪ |
| **Rust** | ⚪ | 🔴 | ⚪ | ⚪ | ⚪ | 🔴 |
| **WASM** | 🔴 | 🔴 | ⚪ | ⚪ | ⚪ | ⚪ |
| **Silent Payments** | 🔴 | 🔴 | 🔴 | ⚪ | ⚪ | 🔴 |
| **Tests Frontend** | 🔴 | ⚪ | 🔴 | ⚪ | ⚪ | ⚪ |
| **Tests WASM** | ⚪ | 🔴 | 🔴 | ⚪ | ⚪ | ⚪ |
| **Tests E2E** | 🔴 | 🔴 | 🔴 | ⚪ | ⚪ | ⚪ |
| **Documentation** | ⚪ | ⚪ | ⚪ | 🔴 | ⚪ | ⚪ |
| **API Documentation** | 🔴 | 🔴 | ⚪ | 🔴 | ⚪ | ⚪ |
| **User Documentation** | 🔴 | ⚪ | ⚪ | 🔴 | ⚪ | ⚪ |
| **Open Source** | ⚪ | ⚪ | ⚪ | ⚪ | 🔴 | ⚪ |
| **CI/CD** | 🔴 | 🔴 | 🔴 | ⚪ | 🔴 | ⚪ |
| **Security** | 🔴 | 🔴 | 🔴 | ⚪ | ⚪ | 🔴 |
| **Performance** | 🔴 | 🔴 | ⚪ | ⚪ | ⚪ | ⚪ |
| **Accessibility** | 🔴 | ⚪ | ⚪ | ⚪ | ⚪ | ⚪ |
| **Internationalization** | 🔴 | ⚪ | ⚪ | ⚪ | ⚪ | ⚪ |
**Légende :**
- 🔴 **Responsable** - Agent principal pour ce domaine
- ⚪ **Consulté** - Agent consulté si nécessaire
- ✅ **Tous** - Applicable à tous les domaines
## Conclusion
Cette organisation des agents assure une couverture complète du projet `ihm_client` avec des responsabilités claires et une coordination efficace. Chaque agent contribue à maintenir la qualité, la sécurité et la performance de l'interface utilisateur pour les Silent Payments.
---
**Objectif** : Maintenir `ihm_client` comme une interface utilisateur moderne, sécurisée et performante pour les Silent Payments. 🚀

View File

@ -1,179 +0,0 @@
# Changelog - ihm_client
Tous les changements notables de ce projet seront documentés dans ce fichier.
Le format est basé sur [Keep a Changelog](https://keepachangelog.com/fr/1.0.0/),
et ce projet adhère au [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
### Changed
### Fixed
## [1.1.0] - 2025-08-26
### Added
- Intégration complète avec l'infrastructure 4NK_node
- Compilation WASM réussie avec sdk_client et sdk_common
- Interface utilisateur moderne avec Vue.js et TypeScript
- Système de notifications en temps réel
- Gestion des Silent Payments via WASM
- Scanner QR Code intégré
- Système de pairing entre utilisateurs
- Gestion des documents et signatures
- Tests unitaires pour les fonctions de conversion hex
- Documentation d'intégration avec 4NK_node
- Tests unitaires pour `sp-address.utils` et `html.utils`
- Documentation: `docs/API.md`, `docs/TESTING.md`, `docs/CONFIGURATION.md`
- Documentation fonctionnelle: `docs/FONCTIONNEL.md` et index mis à jour
- Spécification dintégration iframe: `docs/INTEGRATION_IFRAME.md` et index mis à jour
- Tests pour `TokenService` et fallback denvironnement pour tests
### Changed
- Suppression des vues `chat`, `process`, `process-element`, `signature`; routeur limité à `home` et `account`
- Nettoyage de `src/main.ts` et `src/utils/notification.store.ts` pour retirer les dépendances aux vues supprimées
- Stabilisation des tests unitaires de canal en conditionnant l'émission `LISTENING` au mode E2E en iframe
- Documentation mise à jour: `docs/USAGE.md`, `docs/INDEX.md`
- Migration vers la branche `docker-support`
- Optimisation du build Docker multi-stage
- Amélioration des performances de compilation
- Modernisation de l'interface utilisateur
- Amélioration du script de démarrage pour une meilleure robustesse
- Suppression des dépendances critiques pour permettre le démarrage même si certains services ne sont pas prêts
- Ajout de vérifications WebSocket pour les relays
- `tsconfig.build.json` en module `ES2022` pour supporter `import.meta` et top-level `await`
- Import dynamique des services dans `sp-address.utils` pour alléger les tests
### Fixed
- Correction de la configuration Vite pour générer correctement index.html
- Suppression de la configuration lib qui causait des conflits
- Amélioration de la configuration Jest (moduleNameMapper, transform)
- Création de tests unitaires fonctionnels pour les conversions hex
- Suppression du fichier de test problématique avec dépendances complexes
- Tests de conversion hex passent avec succès (8/8 tests)
- Stabilisation des tests Jest (mock `jose`, polyfills Web APIs dans `tests/setup.ts`)
- Correction de lindex de documentation (liens API et SSH)
## [1.0.1] - 2025-08-25
### Fixed
- Correction de la configuration Vite pour générer correctement index.html
- Suppression de la configuration lib qui causait des conflits
- Amélioration de la configuration Jest (moduleNameMapper, transform)
- Création de tests unitaires fonctionnels pour les conversions hex
- Suppression du fichier de test problématique avec dépendances complexes
- Tests de conversion hex passent avec succès (8/8 tests)
### Technical
- Correction de la configuration build pour éviter les conflits entre lib et application
- Amélioration de la configuration Jest pour une meilleure compatibilité
- Tests unitaires robustes pour les fonctions de conversion hex
- Suppression des dépendances complexes dans les tests
### Changed
- Migration vers la branche `docker-support`
- Optimisation du build Docker multi-stage
- Amélioration des performances de compilation
- Modernisation de l'interface utilisateur
- Amélioration du script de démarrage pour une meilleure robustesse
- Suppression des dépendances critiques pour permettre le démarrage même si certains services ne sont pas prêts
- Ajout de vérifications WebSocket pour les relays
### Fixed
- Correction des erreurs de compilation WASM
- Résolution des problèmes de dépendances TypeScript
- Correction des imports manquants dans sdk_client
- Amélioration de la gestion des erreurs
- Correction de la fonction `hexToBlob` pour gérer correctement les types ArrayBuffer
- Amélioration de la gestion des erreurs de connexion
- Correction des timeouts de démarrage
### Technical
- Ajout de tests pour les fonctions de conversion hex
- Mise à jour de la documentation d'intégration
- Amélioration des logs de démarrage
## [1.0.0] - 2025-08-25
### Added
- Interface utilisateur complète pour les Silent Payments
- Intégration WASM avec sdk_client et sdk_common
- Architecture Vue.js + TypeScript + Vite
- Système de routing et navigation
- Gestion des profils utilisateurs
- Système de pairing avec QR codes
- Gestion des processus et documents
- Système de signatures électroniques
- Chat en temps réel
- Notifications push
- Gestion des wallets Silent Payments
- Interface responsive et moderne
### Features
- **Interface utilisateur** : Vue.js avec TypeScript
- **WASM** : Intégration complète avec sdk_client
- **Pairing** : Connexion avec QR codes
- **Documents** : Gestion et signature
- **Chat** : Communication temps réel
- **Notifications** : Système de notifications
- **Wallet** : Gestion des Silent Payments
### Technical
- Architecture frontend moderne avec Vue.js
- Compilation WASM avec Rust et wasm-pack
- Build optimisé avec Vite
- Docker multi-stage pour la production
- Intégration complète avec 4NK_node
- Variables d'environnement configurées
- Scripts d'automatisation
## [0.9.0] - 2025-08-20
### Added
- Version initiale de l'interface utilisateur
- Configuration de base Vue.js + TypeScript
- Premiers composants d'interface
- Tests de compilation WASM
### Changed
- Configuration initiale du projet
- Premiers tests d'intégration WASM
### Fixed
- Problèmes de compilation TypeScript
- Configuration des dépendances
## [0.8.0] - 2025-08-15
### Added
- Support de l'intégration WASM
- Configuration des dépendances distantes
- Scripts d'automatisation
- Documentation technique
### Changed
- Amélioration de l'architecture WASM
- Optimisation des performances
### Fixed
- Correction des problèmes de compilation
- Amélioration de la stabilité
## [0.7.0] - 2025-08-10
### Added
- Support des Silent Payments
- Intégration avec sdk_client
- Tests de fonctionnalités
- Documentation des APIs
### Changed
- Amélioration de l'architecture
- Optimisation des performances
### Fixed
- Correction des bugs d'intégration
- Amélioration de la stabilité

View File

@ -1,93 +0,0 @@
# Code de Conduite - ihm_client
## Notre Engagement
Dans l'intérêt de favoriser un environnement ouvert et accueillant, nous, en tant que contributeurs et mainteneurs, nous engageons à faire de la participation à notre projet et à notre communauté une expérience sans harcèlement pour tous, peu importe l'âge, la taille, le handicap, l'ethnicité, les caractéristiques sexuelles, l'identité et l'expression de genre, le niveau d'expérience, l'éducation, le statut socio-économique, la nationalité, l'apparence personnelle, la race, la religion ou l'identité et l'orientation sexuelles.
## Nos Standards
Exemples de comportements qui contribuent à créer un environnement positif :
* Utiliser un langage accueillant et inclusif
* Respecter les différents points de vue et expériences
* Accepter gracieusement les critiques constructives
* Se concentrer sur ce qui est le mieux pour la communauté
* Faire preuve d'empathie envers les autres membres de la communauté
Exemples de comportements inacceptables :
* L'utilisation de langage ou d'imagerie sexualisés et d'attention ou d'avances sexuelles non désirées
* Le trolling, les commentaires insultants/désobligeants et les attaques personnelles ou politiques
* Le harcèlement public ou privé
* Publier les informations privées d'autres personnes, telles que des adresses physiques ou électroniques, sans permission explicite
* Autres comportements qui pourraient raisonnablement être considérés comme inappropriés dans un contexte professionnel
## Nos Responsabilités
Les mainteneurs du projet sont responsables de clarifier les standards de comportement acceptable et sont censés prendre des mesures correctives appropriées et équitables en réponse à tout cas de comportement inacceptable.
Les mainteneurs du projet ont le droit et la responsabilité de supprimer, modifier ou rejeter les commentaires, commits, code, modifications de wiki, questions et autres contributions qui ne sont pas alignés avec ce Code de Conduite, et de bannir temporairement ou définitivement tout contributeur pour d'autres comportements qu'ils jugent inappropriés, menaçants, offensants ou nuisibles.
## Portée
Ce Code de Conduite s'applique à la fois dans les espaces du projet et dans les espaces publics lorsqu'un individu représente le projet ou sa communauté. Des exemples de représentation du projet ou de la communauté incluent l'utilisation d'une adresse email officielle du projet, la publication via un compte de média social officiel, ou l'action en tant que représentant désigné lors d'un événement en ligne ou hors ligne. La représentation du projet peut être davantage définie et clarifiée par les mainteneurs du projet.
## Application
Les cas de comportement abusif, harcelant ou autrement inacceptable peuvent être signalés en contactant l'équipe du projet à contact@4nkweb5.com. Toutes les plaintes seront examinées et enquêtées et se traduiront par une réponse jugée nécessaire et appropriée aux circonstances. L'équipe du projet est obligée de maintenir la confidentialité concernant le rapporteur d'un incident. Plus de détails sur les politiques d'application spécifiques peuvent être publiés séparément.
Les mainteneurs du projet qui ne suivent pas ou n'appliquent pas le Code de Conduite de bonne foi peuvent faire face à des répercussions temporaires ou permanentes déterminées par d'autres membres de la direction du projet.
## Attribution
Ce Code de Conduite est adapté du [Contributor Covenant](https://www.contributor-covenant.org), version 2.0, disponible à https://www.contributor-covenant.org/fr/version/2/0/code_of_conduct.html.
## Contact
Pour signaler un problème ou poser des questions concernant ce Code de Conduite, vous pouvez :
* Créer une issue privée sur le repository
* Contacter l'équipe de maintenance via les canaux officiels
* Utiliser les canaux de discussion du projet
## Équipe de Modération
L'équipe de modération est composée des mainteneurs principaux du projet qui s'engagent à :
* Traiter tous les signalements avec impartialité
* Maintenir la confidentialité des rapports
* Prendre des mesures appropriées et équitables
* Documenter les décisions prises
* Améliorer continuellement le processus
## Processus de Signalement
1. **Signalement** : Contactez l'équipe via les canaux appropriés
2. **Accusé de réception** : Vous recevrez une confirmation dans les 48h
3. **Enquête** : L'équipe examinera le signalement
4. **Décision** : Une décision sera prise et communiquée
5. **Appel** : Possibilité de faire appel de la décision
## Mesures Correctives
Les mesures correctives peuvent inclure :
* Avertissement privé
* Avertissement public
* Suspension temporaire
* Bannissement permanent
* Suppression de contenu inapproprié
## Engagement envers l'Amélioration
Nous nous engageons à :
* Réviser régulièrement ce Code de Conduite
* Solliciter les retours de la communauté
* Améliorer les processus de modération
* Former l'équipe de modération
* Maintenir un environnement sain et inclusif
---
**Merci de contribuer à maintenir ihm_client comme un projet accueillant et inclusif !** 🌟

View File

@ -1,311 +0,0 @@
# Guide de Contribution - ihm_client
Merci de votre intérêt pour contribuer au projet ihm_client ! Ce guide vous aidera à comprendre comment participer au développement de cette interface utilisateur pour les Silent Payments.
## 📋 Table des Matières
- [🎯 Comment Contribuer](#-comment-contribuer)
- [🚀 Premiers Pas](#-premiers-pas)
- [🔧 Environnement de Développement](#-environnement-de-développement)
- [📝 Processus de Contribution](#-processus-de-contribution)
- [🧪 Tests](#-tests)
- [📚 Documentation](#-documentation)
- [🐛 Signaler un Bug](#-signaler-un-bug)
- [💡 Proposer une Fonctionnalité](#-proposer-une-fonctionnalité)
- [🔍 Code Review](#-code-review)
- [📦 Release](#-release)
## 🎯 Comment Contribuer
### Types de Contributions
Nous accueillons différents types de contributions :
- **🐛 Bug fixes** - Correction de bugs et problèmes
- **✨ Nouvelles fonctionnalités** - Ajout de nouvelles capacités
- **📚 Documentation** - Amélioration de la documentation
- **🧪 Tests** - Ajout ou amélioration des tests
- **🔧 Outils** - Amélioration des scripts et outils
- **🌐 Traductions** - Traduction de la documentation
- **📊 Performance** - Optimisations de performance
- **🔒 Sécurité** - Améliorations de sécurité
### Niveaux de Contribution
- **Débutant** - Documentation, tests, petits bugs
- **Intermédiaire** - Nouvelles fonctionnalités, améliorations UI
- **Avancé** - Architecture WASM, optimisations majeures
## 🚀 Premiers Pas
### Prérequis
- **Node.js 18+** et **npm**
- **Git** configuré
- **Rust** (pour le développement WASM)
- **Docker** (pour l'intégration 4NK_node)
- **Connexion Internet** stable
### Fork et Clone
```bash
# 1. Fork le repository sur Gitea
# 2. Clone votre fork
git clone https://git.4nkweb.com/votre-username/ihm_client.git
cd ihm_client
# 3. Ajouter le repository original comme upstream
git remote add upstream https://git.4nkweb.com/4nk/ihm_client.git
```
### Branches
```bash
# Créer une branche pour votre contribution
git checkout -b feature/nom-de-votre-feature
# ou
git checkout -b fix/nom-du-bug
```
## 🔧 Environnement de Développement
### Installation Locale
```bash
# 1. Cloner le repository
git clone https://git.4nkweb.com/4nk/ihm_client.git
cd ihm_client
# 2. Installer les dépendances
npm install
# 3. Configurer les dépendances WASM
./scripts/setup-remote-deps.sh
# 4. Démarrer le serveur de développement
npm run dev
```
### Configuration de Développement
```bash
# Variables d'environnement pour le développement
export NODE_ENV=development
export VITE_DEV_SERVER_PORT=3000
export VITE_API_URL=http://localhost:8091
```
### Outils de Développement
```bash
# Tests
npm run test
# Build de production
npm run build
# Linting
npm run lint
# Type checking
npm run type-check
```
## 📝 Processus de Contribution
### 1. Préparation
```bash
# Mettre à jour votre branche
git checkout main
git pull upstream main
# Créer votre branche de feature
git checkout -b feature/votre-feature
```
### 2. Développement
- Suivez les conventions de code
- Écrivez des tests pour les nouvelles fonctionnalités
- Mettez à jour la documentation si nécessaire
- Vérifiez que les tests passent
### 3. Commit
```bash
# Ajouter vos changements
git add .
# Créer un commit descriptif
git commit -m "feat: ajout de la fonctionnalité X
- Description détaillée des changements
- Impact sur l'interface utilisateur
- Tests ajoutés"
```
### 4. Push et Pull Request
```bash
# Pousser votre branche
git push origin feature/votre-feature
# Créer une Pull Request sur Gitea
```
## 🧪 Tests
### Types de Tests
- **Unit Tests** - Tests des composants individuels
- **Integration Tests** - Tests d'intégration WASM
- **E2E Tests** - Tests end-to-end de l'interface
- **Performance Tests** - Tests de performance
### Exécution des Tests
```bash
# Tous les tests
npm run test
# Tests unitaires uniquement
npm run test:unit
# Tests d'intégration
npm run test:integration
# Tests avec couverture
npm run test:coverage
```
## 📚 Documentation
### Mise à Jour de la Documentation
- **README.md** - Documentation principale
- **docs/** - Documentation technique détaillée
- **CHANGELOG.md** - Historique des changements
- **API.md** - Documentation des APIs
### Standards de Documentation
- Écrire en français
- Utiliser des exemples concrets
- Inclure des captures d'écran pour l'UI
- Maintenir la cohérence du style
## 🐛 Signaler un Bug
### Template de Bug Report
```markdown
**Description du bug**
Description claire et concise du problème.
**Étapes pour reproduire**
1. Aller à '...'
2. Cliquer sur '...'
3. Voir l'erreur
**Comportement attendu**
Description de ce qui devrait se passer.
**Captures d'écran**
Si applicable, ajouter des captures d'écran.
**Environnement**
- OS: [ex: Windows 10, macOS, Linux]
- Navigateur: [ex: Chrome, Firefox, Safari]
- Version: [ex: 1.0.0]
**Informations supplémentaires**
Contexte supplémentaire sur le problème.
```
## 💡 Proposer une Fonctionnalité
### Template de Feature Request
```markdown
**Problème à résoudre**
Description claire du problème que cette fonctionnalité résoudrait.
**Solution proposée**
Description de la solution souhaitée.
**Alternatives considérées**
Autres solutions envisagées.
**Contexte supplémentaire**
Informations supplémentaires, captures d'écran, etc.
```
## 🔍 Code Review
### Critères de Review
- **Fonctionnalité** - Le code fait-il ce qu'il doit faire ?
- **Qualité** - Le code est-il propre et maintenable ?
- **Tests** - Y a-t-il des tests appropriés ?
- **Documentation** - La documentation est-elle mise à jour ?
- **Performance** - L'impact sur les performances est-il acceptable ?
### Processus de Review
1. **Automatique** - Tests et linting
2. **Review** - Review par un mainteneur
3. **Approbation** - Approbation requise pour merge
4. **Merge** - Intégration dans la branche principale
## 📦 Release
### Processus de Release
1. **Préparation** - Mise à jour du CHANGELOG
2. **Versioning** - Incrémentation de la version
3. **Build** - Build de production
4. **Tests** - Tests de validation
5. **Tag** - Création du tag de release
6. **Déploiement** - Déploiement en production
### Versioning
Nous suivons le [Semantic Versioning](https://semver.org/) :
- **MAJOR** - Changements incompatibles
- **MINOR** - Nouvelles fonctionnalités compatibles
- **PATCH** - Corrections de bugs compatibles
## 🤝 Code de Conduite
### Nos Standards
- Être respectueux et inclusif
- Utiliser un langage accueillant
- Accepter les critiques constructives
- Se concentrer sur ce qui est le mieux pour la communauté
### Nos Responsabilités
- Clarifier les standards de comportement acceptable
- Prendre des mesures correctives appropriées
- Supprimer, éditer ou rejeter les commentaires inappropriés
## 📞 Support
### Obtenir de l'Aide
- **Issues** - [Git.4nkweb.com](https://git.4nkweb.com/4nk/ihm_client/issues)
- **Documentation** - [docs/](docs/)
- **Discussions** - [Git.4nkweb.com](https://git.4nkweb.com/4nk/ihm_client)
### Ressources
- [Documentation Vue.js](https://vuejs.org/guide/)
- [Documentation TypeScript](https://www.typescriptlang.org/docs/)
- [Documentation WASM](https://webassembly.org/docs/)
---
Merci de contribuer à ihm_client ! 🚀

View File

@ -1,44 +1,13 @@
# Dockerfile: construction des artefacts (dist/) sans serveur — Nginx géré par 4NK_node FROM node:20
FROM node:20-alpine AS builder
ENV TZ=Europe/Paris
WORKDIR /app RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# Installation des dépendances système # use this user because he have uid et gid 1000 like theradia
RUN apk update && apk add --no-cache \ USER node
git \
build-base \ WORKDIR /app
python3 \
make \ CMD ["npm", "start"]
g++ \ # "--disable-host-check", "--host", "0.0.0.0", "--ssl", "--ssl-cert", "/ssl/certs/site.crt", "--ssl-key", "/ssl/private/site.dec.key"]
curl \
ca-certificates
# Copie des fichiers de dépendances
COPY package*.json ./
# Installation des dépendances (inclut les devDependencies nécessaires au build)
RUN npm install
# Copie du code source
COPY . .
# Préparation des dépendances wasm (pkg/sdk_client)
ARG SDK_CLIENT_PKG_URL=""
ARG SDK_CLIENT_PKG_TARBALL=""
ARG SDK_CLIENT_PKG_BASE="https://git.4nkweb.com/4nk/ihm_client/raw/branch/docker-support/pkg"
ENV SDK_CLIENT_PKG_URL=${SDK_CLIENT_PKG_URL}
ENV SDK_CLIENT_PKG_TARBALL=${SDK_CLIENT_PKG_TARBALL}
ENV SDK_CLIENT_PKG_BASE=${SDK_CLIENT_PKG_BASE}
RUN chmod +x ./scripts/setup-remote-deps.sh && npm run build_wasm
# Build de l'application
RUN npm run build
# Stage artefacts uniquement (pas de serveur ici)
FROM alpine:3.19 AS dist
WORKDIR /opt/ihm_client
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package*.json ./
# Conteneur neutre (aucun port exposé, artefacts montables dans 4NK_node)
CMD ["sh", "-c", "echo 'dist prêt dans /opt/ihm_client/dist'; tail -f /dev/null"]

View File

@ -1,53 +0,0 @@
# Dockerfile optimisé pour l'intégration dans 4NK_node
FROM node:20-alpine AS builder
WORKDIR /app
# Installation des dépendances système
RUN apk update && apk add --no-cache \
git \
build-base \
python3 \
make \
g++
# Copie des fichiers de dépendances
COPY package*.json ./
# Installation des dépendances
RUN npm ci --only=production
# Copie du code source
COPY . .
# Build de l'application
RUN npm run build
# Image de production
FROM nginx:alpine
# Installation de Node.js pour les scripts de démarrage
RUN apk update && apk add --no-cache nodejs npm
# Copie des fichiers buildés
COPY --from=builder /app/dist /usr/share/nginx/html
COPY --from=builder /app/package*.json /app/
# Copie de la configuration nginx optimisée pour 4NK_node
COPY nginx.4nk-node.conf /etc/nginx/conf.d/default.conf
# Script de démarrage
COPY start-4nk-node.sh /start-4nk-node.sh
RUN chmod +x /start-4nk-node.sh
# Exposition des ports
EXPOSE 80 3003
# Variables d'environnement pour 4NK_node
ENV SDK_RELAY_WS_URL=ws://sdk_relay_1:8090
ENV SDK_RELAY_HTTP_URL=http://sdk_relay_1:8091
ENV BITCOIN_RPC_URL=http://bitcoin:18443
ENV BLINDBIT_URL=http://blindbit:8000
# Point d'entrée
CMD ["/start-4nk-node.sh"]

21
LICENSE
View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2024 4NK Team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

122
README.md
View File

@ -1,86 +1,52 @@
# ihm_client # ihm_client
Interface utilisateur moderne pour les Silent Payments - Intégrée dans l'infrastructure 4NK_node
## 🚀 Statut actuel
**✅ OPÉRATIONNEL ET PRÊT POUR LA PRODUCTION** ## HOW TO START
- **Branche** : `docker-support` 1 - clone sdk_common, commit name "doc pcd" from 28.10.2024
- **Compilation WASM** : ✅ Réussie 2 - clone sdk_client, commit name "Ignore messages" from 17.10.2024
- **Compilation TypeScript** : ✅ Réussie 3 - clone ihm_client_test3
- **Intégration 4NK_node** : ✅ Configurée 4 - cargo build in sdk_common
5 - cargo run in sdk_client
6 - npm run build_wasm in ihm_client_test3
7 - npm run start in ihm_client_test3
## 📋 Fonctionnalités ## USER STORIES
### Interface utilisateur 1 - I can login with my adress device
- 🌐 **Accueil** - Vue d'ensemble et navigation 2 - I can login with QR code
- 👤 **Compte** - Gestion du profil utilisateur 3 - J'accède à la page Process après ma connexion
- 📄 **Processus** - Création et gestion des processus 4 - Dans l'interface Process, je peux sélectionner un processus avec sa zone
- ✍️ **Signature** - Signatures de documents 5 - Je reçois des notifications dans la page Process
- 💬 **Chat** - Communication entre membres 6 - Dans le menu, je peux importer mes données au format JSON
7 - Dans le menu, je peux accèder à la page Account
8 - Dans la page Account, je peux cliquer sur mon profil via la bulle de profil en haut à gauche et une popup de profil s'ouvre
9 - Dans la popup de profil, je peux voir mes informations personnelles et modifier certaines d'entre elles dont le nom, le prénom
10 - Dans la popup de profil, je peux changer ma photo de profil
11 - Dans la popup de profil, je peux fermer la popup en cliquant sur le bouton "X" en haut à droite de la popup
12 - Dans la popup de profil, je peux cliquer sur le bouton "Export User Data", ce qui me génère un fichier JSON
13 - Dans la popup de profil, je peux cliquer sur le bouton "Delete Account", ce qui me demande à valider mon choix
14 - Dans la popup de profil, je peux cliquer sur le bouton "Logout", ce qui me déconnecte
15 - Dans la popup de profil, je peux cliquer sur le bouton "Export Recovery", ce qui me demandera de confirmer mon choix ou d'annuler, si je confirme, je dois retenir et écrire les 4 mots de récupération, le bouton ne sera plus accessible après cela
16 - Dans l'onglet Pairing de la page Account, je peux ajouter un nouveau "device" en cliquant sur le bouton "Add Device"
17 - Dans l'onglet Pairing de la page Account, je peux supprimer un "device" en cliquant sur l'emoji de la poubelle à côté du device que je souhaite supprimer
18 - Dans l'onglet Pairing de la page Account, je peux cliquer sur le bouton "Scan QR Code" pour scanner le QR Code d'un nouveau device
19 - Dans l'onglet Pairing de la page Account, je peux renommer un "Device" en cliquant sur son nom et en modifiant le nom
20 - Dans l'onglet Wallet de la page Account, je peux ajouter un nouveau "wallet" en cliquant sur le bouton "Add a line"
21 - Dans l'onglet Process de la page Account, je peux voir les Process disponibles et voir leur notifications en cliquant sur sur la sonnette à côté du processus
22 - Dans l'onglet Data de la page Account, je peux voir les données importées
23 - Je peux voir le contrat associé à une Data en cliquant sur le contrat dans la ligne de la Data
24 - Dans le menu je peux accèder à la page Chat
25 - Dans la page Chat, je peux voir les Processus
26 - Dans les Processus, je peux voir utilisateurs assignés à un rôle
27 - Dans les Processus, je peux envoyer des messages et des documents en cliquant sur le nom d'un utilisateur en en envoyant "send"
28 - Dans le menu je peux accèder à la page "Signatures"
29 - Je peux voir les documents à signer et vierge en cliquand sur l'emoji ⚙️ à côté du processus
30 - En cliquand sur l'onglet d'un processus, je peux voir les rôles assignés à un utilisateur en cliquant dessus
31 - En cliquand sur l'emoji 📁 à côté d'un rôle, je peux voir les documents associés à ce rôle
32 - Dans la vue des documents associés à un rôle, je peux créer un évènement de nouvelle signature pour tous les rôles associés à ce Processus, avec le bouton "New Request"
33 - En cliquant sur le bouton "New Request", une nouvelle fenêtre s'ouvre pour me permettre de rentrer la description, la visibilité, la date d'échéance, importer des documents, voir les signataires et "Request"
34 - Dans le menu, je peux me déconnecter avec le bouton "Disconnect"
### Fonctionnalités techniques ## TO DO
- 🔗 **Pairing** - Connexion avec d'autres utilisateurs
- 💰 **Wallet** - Gestion des Silent Payments
- 📋 **Documents** - Validation et signature
- 🔔 **Notifications** - Système temps réel
- 📱 **QR Code** - Scanner et génération
- ⚡ **WASM** - Intégration complète avec sdk_client
## 🏗️ Architecture
- **Frontend** : TypeScript + Vite + Vue.js
- **WASM** : Rust + wasm-pack
- **Build** : Vite + TypeScript Compiler
- **Docker** : Build artefacts dist/ (Nginx géré par 4NK_node)
## 🔗 Intégration 4NK_node
L'interface est intégrée dans l'infrastructure 4NK_node et accessible sur :
- **URL** : http://localhost:8080
- **Service** : `ihm_client` dans docker-compose.yml
## 📚 Documentation
- [Référence rapide](docs/QUICK_REFERENCE.md) - Points dentrée et commandes
- [Intégration iframe](docs/INTEGRATION_IFRAME.md) - Messagerie dintégration
- [Configuration SSH](docs/SSH_USAGE.md) - SSH automatisé
- [Architecture](docs/ARCHITECTURE.md) - Architecture technique
- [API](docs/API.md) - Documentation des APIs
- [Tests E2E](docs/TESTING.md) - Playwright (smoke tests)
## 🛠️ Développement
```bash
# Installation
npm install
# Développement local
npm run dev
# Build de production
npm run build
# Configuration des dépendances distantes
./scripts/setup-remote-deps.sh
```
## 📊 Métriques
- **WASM** : 3.3 MB
- **CSS** : 711 KB (gzippé)
- **JavaScript** : 4.5 MB (gzippé)
- **Temps de compilation** : ~25s
## 🎯 Prochaines étapes
1. Test complet de l'infrastructure 4NK_node
2. Validation des fonctionnalités en production
3. Optimisation des performances
---
**État** : ✅ **PRÊT POUR LA PRODUCTION**
**Version** : docker-support
**Dernière mise à jour** : 25 août 2025

View File

@ -1,217 +0,0 @@
# Politique de Sécurité - ihm_client
## 🛡️ Signalement de Vulnérabilités
Nous prenons la sécurité très au sérieux. Si vous découvrez une vulnérabilité de sécurité, nous vous demandons de la signaler de manière responsable.
### Comment Signaler une Vulnérabilité
**NE PAS** créer d'issue publique pour les vulnérabilités de sécurité.
**À la place :**
1. Envoyez un email à [security@4nkweb.com](mailto:security@4nkweb.com)
2. Incluez "SECURITY VULNERABILITY" dans l'objet
3. Décrivez la vulnérabilité de manière détaillée
4. Incluez les étapes pour reproduire le problème
5. Proposez une solution si possible
### Ce que nous attendons
- **Confidentialité** : Ne divulguez pas la vulnérabilité publiquement
- **Détails** : Fournissez suffisamment d'informations pour reproduire le problème
- **Patience** : Nous examinerons et répondrons dans les 48h
- **Coopération** : Nous pouvons avoir besoin de clarifications
### Ce que vous pouvez attendre
- **Réponse rapide** : Accusé de réception dans les 48h
- **Évaluation** : Analyse de la vulnérabilité
- **Mise à jour** : Statut de la correction
- **Reconnaissance** : Mention dans les remerciements (si souhaité)
## 🔒 Bonnes Pratiques de Sécurité
### Pour les Contributeurs
#### Code Frontend
- Validez toutes les entrées utilisateur côté client et serveur
- Utilisez des requêtes préparées pour les APIs
- Évitez les injections XSS et CSRF
- Implémentez l'authentification appropriée
- Utilisez HTTPS pour toutes les communications
#### WASM et Rust
- Validez les entrées dans le code Rust
- Évitez les vulnérabilités de mémoire
- Utilisez des types sûrs
- Testez les cas limites
- Maintenez les dépendances à jour
#### Configuration
- Ne committez jamais de secrets
- Utilisez des variables d'environnement pour les données sensibles
- Vérifiez les permissions des fichiers
- Maintenez les dépendances à jour
#### Tests
- Incluez des tests de sécurité
- Testez les cas limites
- Validez les entrées malveillantes
- Vérifiez les fuites de mémoire
### Pour les Utilisateurs
#### Installation
- Utilisez des sources officielles
- Vérifiez les checksums
- Maintenez le système à jour
- Utilisez un pare-feu
#### Configuration
- Changez les mots de passe par défaut
- Utilisez des clés SSH fortes
- Limitez l'accès réseau
- Surveillez les logs
#### Opération
- Surveillez les connexions
- Sauvegardez régulièrement
- Testez les sauvegardes
- Documentez les incidents
## 🔍 Audit de Sécurité
### Composants Principaux
#### Interface Utilisateur (Vue.js)
- **Validation** : Validation côté client et serveur
- **Authentification** : Gestion sécurisée des sessions
- **XSS Protection** : Échappement des données
- **CSRF Protection** : Tokens de sécurité
#### WASM (sdk_client)
- **Mémoire** : Gestion sûre de la mémoire
- **Entrées** : Validation des paramètres
- **Cryptographie** : Utilisation de bibliothèques sûres
- **Silent Payments** : Protection des clés privées
#### Communication
- **WebSocket** : Validation des messages
- **HTTPS** : Chiffrement des communications
- **APIs** : Authentification et autorisation
- **CORS** : Configuration sécurisée
#### Stockage
- **Local Storage** : Pas de données sensibles
- **Session Storage** : Données temporaires sécurisées
- **Cookies** : Configuration sécurisée
- **Cache** : Pas d'informations sensibles
## 🚨 Vulnérabilités Connues
### Vulnérabilités Résolues
#### [CVE-2024-XXXX] - Injection XSS
- **Statut** : Résolu
- **Version** : 1.0.0
- **Description** : Vulnérabilité d'injection XSS dans les champs de saisie
- **Solution** : Validation et échappement des entrées utilisateur
#### [CVE-2024-XXXX] - Fuite de Mémoire WASM
- **Statut** : Résolu
- **Version** : 1.0.0
- **Description** : Fuite de mémoire dans le module WASM
- **Solution** : Gestion correcte de la mémoire Rust
### Vulnérabilités Actives
Aucune vulnérabilité active connue.
## 🔧 Mesures de Sécurité
### Authentification
- **JWT** : Tokens sécurisés avec expiration
- **Refresh Tokens** : Rotation automatique
- **Multi-Factor** : Support pour l'authentification à deux facteurs
- **Session Management** : Gestion sécurisée des sessions
### Autorisation
- **RBAC** : Contrôle d'accès basé sur les rôles
- **Permissions** : Permissions granulaires
- **Audit** : Logs d'audit complets
- **Validation** : Validation des permissions côté serveur
### Chiffrement
- **HTTPS** : Chiffrement en transit
- **WASM** : Chiffrement des données sensibles
- **Local Storage** : Chiffrement des données locales
- **APIs** : Chiffrement des communications
### Monitoring
- **Logs** : Logs de sécurité complets
- **Alertes** : Alertes automatiques
- **Audit** : Audit de sécurité régulier
- **Incidents** : Gestion des incidents de sécurité
## 📋 Checklist de Sécurité
### Développement
- [ ] Validation des entrées utilisateur
- [ ] Protection contre XSS
- [ ] Protection contre CSRF
- [ ] Authentification sécurisée
- [ ] Autorisation appropriée
- [ ] Chiffrement des données sensibles
- [ ] Gestion sûre des erreurs
- [ ] Tests de sécurité
### Déploiement
- [ ] Configuration HTTPS
- [ ] Headers de sécurité
- [ ] Variables d'environnement sécurisées
- [ ] Permissions de fichiers appropriées
- [ ] Monitoring de sécurité
- [ ] Sauvegarde sécurisée
- [ ] Documentation de sécurité
### Maintenance
- [ ] Mise à jour des dépendances
- [ ] Audit de sécurité régulier
- [ ] Monitoring des vulnérabilités
- [ ] Tests de pénétration
- [ ] Formation à la sécurité
- [ ] Plan de réponse aux incidents
## 📞 Contact Sécurité
### Équipe de Sécurité
- **Email** : [security@4nkweb.com](mailto:security@4nkweb.com)
- **PGP** : [Clé publique PGP](https://4nkweb.com/security.asc)
- **Signalement** : [Formulaire de signalement](https://4nkweb.com/security)
### Réponse aux Incidents
1. **Détection** : Identification de l'incident
2. **Containment** : Limitation de l'impact
3. **Éradication** : Suppression de la cause
4. **Récupération** : Retour à la normale
5. **Post-mortem** : Analyse et amélioration
### Communication
- **Interne** : Communication avec l'équipe
- **Utilisateurs** : Notification des utilisateurs
- **Public** : Communication publique si nécessaire
- **Autorités** : Notification des autorités si requis
---
**La sécurité est une responsabilité partagée. Merci de contribuer à maintenir ihm_client sécurisé !** 🔒

BIN
dist.zip

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 1.9 MiB

After

Width:  |  Height:  |  Size: 1.9 MiB

View File

@ -1,43 +0,0 @@
version: '3.8'
services:
ihm_client:
build:
context: .
dockerfile: Dockerfile.4nk-node
container_name: 4nk-ihm-client
ports:
- "8080:80"
- "3003:3003"
environment:
- SDK_RELAY_WS_URL=ws://sdk_relay_1:8090
- SDK_RELAY_HTTP_URL=http://sdk_relay_1:8091
- BITCOIN_RPC_URL=http://bitcoin:18443
- BLINDBIT_URL=http://blindbit:8000
- NODE_ENV=production
volumes:
- ihm_client_logs:/var/log/nginx
- ihm_client_data:/usr/share/nginx/html/data
networks:
- btcnet
depends_on:
- sdk_relay_1
- sdk_relay_2
- sdk_relay_3
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--timeout=5", "--spider", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
volumes:
ihm_client_logs:
driver: local
ihm_client_data:
driver: local
networks:
btcnet:
external: true

View File

@ -1,49 +0,0 @@
# API - ihm_client
Ce document décrit les interfaces publiques significatives exposées par linterface `ihm_client`. Il ne contient aucun exemple dusage exécutable et sert de référence de contrat.
## Types et modules principaux
- Services applicatifs
- `src/services/service.ts` (classe `Services`) : opérations dapp, gestion des relays, pairing, processus, stockage, conversions hex/blob.
- `src/services/token.ts` (classe `TokenService`) : génération/validation/refresh de jetons de session.
- Utilitaires
- `src/utils/sp-address.utils.ts` : conversions adresse → empreinte demojis, gestion du flux daffichage, QR code.
- `src/utils/html.utils.ts` : résolution du DOM racine ou `shadowRoot`.
## Contrats clés
- `Services.getInstance(): Promise<Services>`: retour singleton initialisé.
- Pairing et processus
- `createPairingProcess(userName: string, pairWith: string[]): Promise<ApiReturn>`
- `confirmPairing(): Promise<void>`
- `createProcess(...)`, `updateProcess(...)` : gestion des états/processus.
- Données chiffrées
- `getHashForFile(commitedIn: string, label: string, fileBlob: { type: string; data: Uint8Array }): string`
- `getMerkleProofForFile(processState, attributeName): MerkleProofResult`
- `validateMerkleProof(proof, hash): boolean`
- Conversion binaire
- `hexToBlob(hex: string): Blob`
- `hexToUInt8Array(hex: string): Uint8Array`
- `blobToHex(blob: Blob): Promise<string>`
- Tokens
- `TokenService.getInstance(): Promise<TokenService>`
- `generateSessionToken(origin: string): Promise<{ accessToken: string; refreshToken: string }>`
- `validateToken(token: string, origin: string): Promise<boolean>`
- `refreshAccessToken(refreshToken: string, origin: string): Promise<string | null>`
## Invariants
- Les méthodes de `Services` supposent linitialisation du module WASM (`pkg/sdk_client`) lors du `init()`.
- `TokenService` requiert une clé de signature via `VITE_JWT_SECRET_KEY` (Vite ou environnement Node en test).
- Les conversions hex/binaire doivent préserver lintégrité des octets (longueur paire pour lhex).
## Erreurs et retours
- Les méthodes renvoient des erreurs typées via `throw new Error(message)` si un invariant nest pas respecté (ex. adresse manquante, état introuvable).
- Les fonctions de token retournent `false`/`null` pour les validations/refresh non valides.
## Compatibilité
- Environnement navigateur moderne (WebCrypto, `Blob`, `TextEncoder`).
- Tests sous Jest avec polyfills contrôlés dans `tests/setup.ts`.

View File

@ -1,570 +0,0 @@
# 🏗️ Architecture Technique - ihm_client
Documentation technique détaillée de l'architecture de l'interface utilisateur ihm_client.
## 📋 Vue d'Ensemble
### Architecture Générale
```
┌─────────────────────────────────────────────────────────────┐
│ ihm_client │
├─────────────────────────────────────────────────────────────┤
│ Frontend (Vue.js + TypeScript) │
│ ├── Components Vue.js │
│ ├── Services TypeScript │
│ ├── Types et Interfaces │
│ └── Utilitaires │
├─────────────────────────────────────────────────────────────┤
│ WASM (Rust + sdk_client) │
│ ├── Module WebAssembly │
│ ├── Fonctions Silent Payments │
│ └── Interface JavaScript │
├─────────────────────────────────────────────────────────────┤
│ Build System (Vite) │
│ ├── Compilation TypeScript │
│ ├── Bundling et Optimisation │
│ └── Hot Module Replacement │
└─────────────────────────────────────────────────────────────┘
```
### Stack Technologique
| Couche | Technologie | Version | Rôle |
|--------|-------------|---------|------|
| **Frontend** | Vue.js | 3.x | Framework UI |
| **Language** | TypeScript | 5.x | Typage statique |
| **Build** | Vite | 5.x | Build tool |
| **WASM** | Rust | 1.70+ | Logique métier |
| **WASM Build** | wasm-pack | 0.12+ | Compilation WASM |
| **Styling** | CSS3 | - | Styles |
| **Package Manager** | npm | 8.x+ | Gestion dépendances |
## 🏛️ Architecture Frontend
### Structure des Composants
```
src/
├── components/ # Composants réutilisables
│ ├── header/ # En-tête de l'application
│ ├── modal/ # Modales et popups
│ ├── qrcode-scanner/ # Scanner QR code
│ └── validation-modal/ # Modales de validation
├── pages/ # Pages de l'application
│ ├── home/ # Page d'accueil
│ ├── account/ # Gestion du compte
│ ├── signature/ # Signatures de documents
│ └── process-element/ # Gestion des processus
├── services/ # Services et APIs
│ ├── service.ts # Service principal
│ ├── modal.service.ts # Gestion des modales
│ ├── storage.service.ts # Gestion du stockage
│ └── token.ts # Gestion des tokens
├── types/ # Types TypeScript
│ ├── sdk_client.d.ts # Types WASM
│ └── raw-imports.d.ts # Types d'imports
└── utils/ # Utilitaires
├── document.utils.ts # Utilitaires documents
├── html.utils.ts # Utilitaires HTML
└── sp-address.utils.ts # Utilitaires Silent Payments
```
### Architecture Vue.js
#### Composants Principaux
##### Header Component
```typescript
interface HeaderProps {
user: User;
notifications: Notification[];
onLogout: () => void;
}
```
**Responsabilités :**
- Navigation principale
- Affichage du profil utilisateur
- Gestion des notifications
- Menu de déconnexion
##### Modal Components
```typescript
interface ModalProps {
isOpen: boolean;
title: string;
content: string;
onConfirm: () => void;
onCancel: () => void;
}
```
**Types de modales :**
- **Confirmation** : Actions critiques
- **Validation** : Validation de données
- **QR Scanner** : Scanner de codes QR
- **Profile** : Édition du profil
##### QR Code Scanner
```typescript
interface QRScannerProps {
onScan: (data: string) => void;
onError: (error: Error) => void;
onClose: () => void;
}
```
**Fonctionnalités :**
- Accès à la caméra
- Détection de QR codes
- Validation des données
- Gestion des erreurs
### Services et Communication
#### Service Principal
```typescript
class Service {
// Communication avec sdk_client WASM
async generateWallet(): Promise<Wallet>;
async lockUTXOs(wallet: Wallet, utxos: UTXO[]): Promise<boolean>;
// Communication avec les APIs
async sendMessage(message: Message): Promise<void>;
async uploadDocument(file: File): Promise<Document>;
// Gestion des données
async saveData(key: string, data: any): Promise<void>;
async loadData(key: string): Promise<any>;
}
```
#### Gestion des États
```typescript
// Store global (Vuex/Pinia)
interface AppState {
user: User | null;
wallet: Wallet | null;
processes: Process[];
notifications: Notification[];
settings: Settings;
}
```
## ⚡ Architecture WASM
### Module sdk_client
#### Structure du Module
```
pkg/
├── sdk_client_bg.wasm # Module WASM principal (3.3 MB)
├── sdk_client.d.ts # Types TypeScript (12.6 KB)
├── sdk_client.js # Wrapper JavaScript (182 B)
├── sdk_client_bg.js # Code JavaScript généré (38 KB)
└── package.json # Métadonnées du package
```
#### Fonctions Principales
##### Gestion des Wallets
```rust
// Rust (sdk_client)
pub fn generate_sp_wallet() -> Wallet {
// Génération d'un nouveau wallet Silent Payment
}
pub fn lock_freezed_utxos(wallet: Wallet, utxos: Vec<UTXO>) -> bool {
// Verrouillage des UTXOs gelés
}
```
##### Interface JavaScript
```typescript
// TypeScript (ihm_client)
import { generate_sp_wallet, lock_freezed_utxos } from 'pkg/sdk_client';
const wallet = generate_sp_wallet();
const success = lock_freezed_utxos(wallet, utxos);
```
### Intégration WASM-Frontend
#### Initialisation
```typescript
// Initialisation du module WASM
import init from 'pkg/sdk_client';
async function initializeWASM() {
try {
await init();
console.log('WASM module initialized');
} catch (error) {
console.error('Failed to initialize WASM:', error);
}
}
```
#### Communication
```typescript
// Appel de fonctions WASM
async function createWallet() {
try {
const wallet = generate_sp_wallet();
return wallet;
} catch (error) {
console.error('WASM error:', error);
throw error;
}
}
```
## 🔧 Architecture Build
### Configuration Vite
```typescript
// vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import wasm from 'vite-plugin-wasm';
export default defineConfig({
plugins: [
vue(),
wasm(),
],
optimizeDeps: {
exclude: ['pkg/sdk_client']
},
build: {
target: 'es2020',
rollupOptions: {
output: {
manualChunks: {
'sdk-client': ['pkg/sdk_client']
}
}
}
}
});
```
### Processus de Build
#### Développement
```bash
# Serveur de développement
npm run dev
# Hot Module Replacement activé
# Compilation TypeScript en temps réel
# Chargement WASM à la demande
```
#### Production
```bash
# Build optimisé
npm run build
# Optimisations :
# - Tree shaking
# - Code splitting
# - Minification
# - Compression gzip
```
### Optimisations
#### Code Splitting
```typescript
// Chargement à la demande des composants
const SignatureComponent = () => import('./pages/signature/signature-component.vue');
const AccountComponent = () => import('./pages/account/account-component.vue');
```
#### Lazy Loading WASM
```typescript
// Chargement différé du module WASM
const loadWASM = async () => {
if (!wasmModule) {
wasmModule = await import('pkg/sdk_client');
await wasmModule.default();
}
return wasmModule;
};
```
## 🔄 Flux de Données
### Flux Principal
```
1. Utilisateur → Interface Vue.js
2. Interface → Services TypeScript
3. Services → Module WASM (sdk_client)
4. WASM → APIs externes (si nécessaire)
5. Réponse → Services → Interface → Utilisateur
```
### Gestion des États
#### État Local (Composants)
```typescript
// État local d'un composant
const componentState = reactive({
loading: false,
data: null,
error: null
});
```
#### État Global (Store)
```typescript
// Store global de l'application
const appStore = {
user: ref<User | null>(null),
wallet: ref<Wallet | null>(null),
processes: ref<Process[]>([]),
notifications: ref<Notification[]>([])
};
```
#### Persistance
```typescript
// Sauvegarde locale
localStorage.setItem('user-data', JSON.stringify(userData));
// Synchronisation avec le serveur
await service.syncData(userData);
```
## 🔒 Architecture de Sécurité
### Sécurité Frontend
#### Validation des Entrées
```typescript
// Validation côté client
function validateUserInput(input: string): boolean {
return input.length > 0 && input.length < 100;
}
// Sanitisation HTML
function sanitizeHTML(html: string): string {
return DOMPurify.sanitize(html);
}
```
#### Protection XSS
```typescript
// Échappement des données
function escapeHTML(text: string): string {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
```
### Sécurité WASM
#### Gestion de la Mémoire
```rust
// Rust - Gestion sûre de la mémoire
pub fn process_data(data: Vec<u8>) -> Result<Vec<u8>, Error> {
// Validation des données d'entrée
if data.len() > MAX_SIZE {
return Err(Error::DataTooLarge);
}
// Traitement sécurisé
let result = process_secure(data)?;
Ok(result)
}
```
#### Protection des Clés
```rust
// Protection des clés privées
pub struct SecureWallet {
private_key: SecureString,
public_key: String,
}
impl SecureWallet {
pub fn new() -> Self {
let private_key = generate_secure_key();
let public_key = derive_public_key(&private_key);
Self {
private_key: SecureString::new(private_key),
public_key,
}
}
}
```
## 📊 Architecture de Performance
### Métriques de Performance
#### Temps de Chargement
- **Premier rendu** : < 2s
- **Interactivité** : < 3s
- **Chargement complet** : < 5s
#### Optimisations
##### Bundle Size
```bash
# Taille des bundles
dist/
├── index.js # ~300 KB (gzippé)
├── sdk_client.wasm # ~3.3 MB (gzippé)
└── vendor.js # ~200 KB (gzippé)
```
##### Lazy Loading
```typescript
// Chargement à la demande
const routes = [
{
path: '/signature',
component: () => import('./pages/signature.vue')
}
];
```
##### Caching
```typescript
// Cache du module WASM
const wasmCache = new Map();
async function getWASMModule() {
if (wasmCache.has('sdk_client')) {
return wasmCache.get('sdk_client');
}
const module = await loadWASMModule();
wasmCache.set('sdk_client', module);
return module;
}
```
## 🔍 Monitoring et Observabilité
### Logs et Debugging
#### Logs Frontend
```typescript
// Logging structuré
const logger = {
info: (message: string, data?: any) => {
console.log(`[INFO] ${message}`, data);
},
error: (message: string, error?: Error) => {
console.error(`[ERROR] ${message}`, error);
}
};
```
#### Logs WASM
```rust
// Logging Rust
use log::{info, error};
pub fn process_wallet() -> Result<Wallet, Error> {
info!("Starting wallet processing");
match process_secure() {
Ok(wallet) => {
info!("Wallet processed successfully");
Ok(wallet)
},
Err(e) => {
error!("Wallet processing failed: {}", e);
Err(e)
}
}
}
```
### Métriques
#### Métriques Frontend
- **Temps de rendu** : Performance des composants
- **Temps de réponse** : Réactivité de l'interface
- **Utilisation mémoire** : Consommation RAM
- **Erreurs JavaScript** : Stabilité de l'application
#### Métriques WASM
- **Temps d'initialisation** : Chargement du module
- **Temps d'exécution** : Performance des fonctions
- **Utilisation mémoire** : Gestion de la mémoire
- **Erreurs Rust** : Stabilité du module
## 🚀 Déploiement
### Environnements
#### Développement
```bash
# Serveur de développement
npm run dev
# Variables d'environnement
NODE_ENV=development
VITE_API_URL=http://localhost:8091
VITE_WS_URL=ws://localhost:8090
```
#### Production
```bash
# Build de production
npm run build
# Variables d'environnement
NODE_ENV=production
VITE_API_URL=https://api.4nkweb.com
VITE_WS_URL=wss://ws.4nkweb.com
```
### Intégration 4NK_node
#### Artefacts et serveur
- Le Dockerfile de `ihm_client` produit uniquement les artefacts `dist/`.
- Le serveur (Nginx) est géré par `4NK_node` qui consomme `dist/`.
#### Variables d'Environnement
```bash
# Configuration pour 4NK_node
SDK_RELAY_WS_URL=ws://sdk_relay_1:8090
SDK_RELAY_HTTP_URL=http://sdk_relay_1:8091
BITCOIN_RPC_URL=http://bitcoin:18443
BLINDBIT_URL=http://blindbit:8000
```
## 🔮 Évolutions Futures
### Améliorations Planifiées
#### Performance
- **Web Workers** : Traitement en arrière-plan
- **Service Workers** : Cache et offline
- **WebAssembly SIMD** : Optimisations vectorielles
#### Fonctionnalités
- **PWA** : Application web progressive
- **Offline Mode** : Fonctionnement hors ligne
- **Real-time Sync** : Synchronisation temps réel
#### Sécurité
- **Hardware Security** : Intégration TPM/SE
- **Multi-factor Auth** : Authentification à deux facteurs
- **Audit Trail** : Traçabilité complète
---
**🏗️ Architecture ihm_client - Conçue pour la performance et la sécurité** 🚀

View File

@ -1,5 +0,0 @@
# Guide de la communauté - ihm_client
- Comment contribuer (issues, PR, revues)
- Standards de code et de documentation
- Processus de release et de support

View File

@ -1,34 +0,0 @@
# Configuration - ihm_client
Ce document synthétise la configuration de lapplication et des outils. Il complète `INSTALLATION.md`.
## Variables denvironnement
- Variables Vite (navigateur)
- `VITE_API_URL`: URL HTTP du relais/API.
- `VITE_WS_URL`: URL WS du relais.
- `VITE_WASM_PATH`: chemin vers `pkg/sdk_client_bg.wasm`.
- `VITE_JWT_SECRET_KEY`: clé de signature des JWT (utilisée par `TokenService`).
- Intégration 4NK_node (serveur géré côté 4NK_node, artefacts `dist/` produits ici)
- `SDK_RELAY_WS_URL`, `SDK_RELAY_HTTP_URL`, `BITCOIN_RPC_URL`, `BLINDBIT_URL`.
## Build
- Outil: Vite 5 + TypeScript 5.
- Ciblage: `es2020`+.
- WASM: `vite-plugin-wasm`, bundle différé conseillé.
## Tests
- Jest 29 + `ts-jest`.
- `tests/setup.ts` injecte polyfills et mocks.
## Résolution des modules
- Aliases: `~/*``src/*` (cf. `tsconfig.json`).
- Mapper: `jest.config.js` mappe `pkg/` vers `pkg/` local.
## CI/CD
- Étapes minimales: install, tests, build, artefacts.
- Audit dépendances à intégrer selon politique sécurité.

View File

@ -1,99 +0,0 @@
# Documentation fonctionnelle - ihm_client
Cette documentation décrit ce que fait fonctionnellement linterface `ihm_client`, les parcours utilisateurs, les règles de gestion et les contraintes associées. Aucun exemple de code applicatif nest inclus.
## Objectif produit
- Proposer une interface moderne pour la gestion de processus collaboratifs autour des Silent Payments.
- Faciliter le pairing sécurisé entre appareils/utilisateurs et la gestion des transactions associées.
- Offrir un espace unifié pour la gestion des membres, documents, signatures et échanges (chat/notifications).
## Personas et rôles
- Utilisateur standard: initie/participe à des processus, signe des documents, échange des messages.
- Administrateur de processus: configure les rôles, vérifie les validations, déclenche des mises à jour.
- Observateur (lecture seule): consulte les informations publiques/partagées sans intervenir.
## Parcours principaux
### Accueil
- Accès rapide aux sections clés (Compte, Processus, Signature, Chat, Pairing).
- Indicateurs dactivité: processus actifs, notifications récentes, métriques succinctes.
### Pairing (mise en relation)
- Objectif: établir une relation de confiance entre appareils via adresse Silent Payment.
- Étapes:
1. Saisir ou scanner ladresse SP distante (ou URL contenant `sp_address`).
2. Vérifier lempreinte visuelle (emojis) dérivée de ladresse pour confirmer lidentité.
3. Créer et confirmer le processus de pairing (flux guidé, confirmation finale).
- Résultat: lappareil local est appairé; les échanges sécurisés sont possibles.
### Wallet et relays
- Visualiser létat du wallet (montant disponible, synchro via relays).
- Interagir avec le réseau via relays (mise à jour des membres/états, échange de messages techniques).
- Disposer dun mécanisme de “faucet” en environnement de test pour provisionner le wallet.
### Processus
- Créer un nouveau processus (données publiques et privées, rôles, règles de validation).
- Mettre à jour un processus existant (évolution des états, validations, preuves).
- Consulter lhistorique (états validés, états en attente/non committés).
### Membres et rôles
- Gérer les membres impliqués (par adresse SP).
- Définir des rôles et règles de validation (quorum, champs soumis à contrôle, seuils).
- Vérifier lappartenance de lutilisateur à un rôle (autorisation implicite des actions).
### Documents et signatures
- Associer des documents aux processus (hashés et stockés via mécanismes dédiés).
- Déclencher des demandes de signature, suivre leur statut (en attente, signé, expiré).
- Vérifier/valider les preuves (ex. Merkle) liées aux documents échangés.
### Chat et notifications
- Échanger des messages dans le contexte des processus.
- Recevoir des notifications liées aux événements (nouvelle transaction, demande de signature, mise à jour de processus).
## Règles de gestion clés
- Pairing
- Une empreinte visuelle (emojis) dérivée de ladresse SP aide à la confirmation utilisateur.
- Un processus de pairing doit inclure ladresse de lappareil local.
- Validation
- Les règles de validation (quorum, seuils) sappliquent aux champs déclarés.
- Une mise à jour de processus peut être refusée si les preuves/validations sont insuffisantes.
- Données
- Les données volumineuses (blobs) sont stockées séparément et référencées par hash.
- Les attributs chiffrés nécessitent clés/permissions pour être déchiffrés.
- Sécurité
- Les échanges sont consolidés via relays; lappairage conditionne laccès aux données privées.
- Les tokens de session sont temporaires et régénérables (Access/Refresh).
## Contraintes et limites
- Dépendance au module WASM pour les opérations de bas niveau (Silent Payments, encodages, preuves).
- Nécessité dun ou plusieurs relays disponibles pour la synchronisation et léchange dinformations.
- Performance dépendant du contexte (navigateur, réseau, taille des données).
## Indicateurs et métriques
- Disponibilité des relays et latence observée.
- État de synchronisation (hauteur de bloc, mises à jour reçues).
- Taille et temps de manipulation des documents.
- Taux de succès des signatures et validations.
## Gestion des erreurs et non-régression
- Messages derreur explicites pour états manquants, adresses invalides, clés indisponibles, connexions relays.
- Tests unitaires couvrant conversions (hex/blob), DOM utilitaire et tokens.
- Stratégie de test documentée (voir `docs/TESTING.md`).
## Confidentialité et conformité
- Pas de stockage permanent de secrets en clair côté client.
- Utilisation stricte de variables denvironnement pour les secrets runtime.
- Revue régulière des dépendances et audits sécurité (voir `docs/SECURITY_AUDIT.md`).
## Support et usage
- Guides dinstallation et dutilisation (voir `docs/INSTALLATION.md`, `docs/USAGE.md`).
- Référentiel contractuel des API (voir `docs/API.md`).
- Intégration dans un site via iframe (voir `docs/INTEGRATION_IFRAME.md`).

View File

@ -1,17 +0,0 @@
# Configuration Gitea - ihm_client
## Repository
- Création du dépôt sur `git.4nkweb.com`
- Droits décriture/lecture selon rôle
## SSH
- Ajout de la clé dans Settings > SSH Keys
- Scripts: `scripts/init-ssh-env.sh`, `scripts/auto-ssh-push.sh`
## CI/CD
- Workflows dans `.gitea/workflows/` (à définir selon pipeline)
- Politique de branche: protection de `main`/`docker-support`
## Permissions
- Maintainers: merge + tags
- Contributeurs: PRs avec validation

View File

@ -1,219 +0,0 @@
# 📚 Index de Documentation - ihm_client
Index complet de la documentation de l'interface utilisateur ihm_client pour les Silent Payments.
## 📖 Guides Principaux
### 🚀 [Guide d'Installation](INSTALLATION.md)
Guide complet pour installer et configurer l'interface utilisateur ihm_client.
- **Prérequis système et logiciels**
- **Installation de Node.js et dépendances**
- **Configuration Rust et WASM**
- **Configuration des dépendances distantes**
- **Tests post-installation**
- **Dépannage et monitoring**
### 📖 [Guide d'Utilisation](USAGE.md)
### 🧭 [Documentation fonctionnelle](FONCTIONNEL.md)
Description fonctionnelle complète (parcours, règles de gestion, contraintes).
Guide complet pour utiliser l'interface utilisateur ihm_client au quotidien.
- **Démarrage du serveur de développement**
- **Utilisation de l'interface utilisateur**
- **Navigation Accueil et Compte**
- **Opérations de pairing et wallet**
- **Tests et validation**
### ⚙️ [Guide de Configuration](CONFIGURATION.md)
Guide complet pour configurer l'interface selon vos besoins.
- **Configuration générale et variables d'environnement**
- **Configuration Vue.js et TypeScript**
- **Configuration WASM et sdk_client**
- **Configuration de l'intégration 4NK_node**
- **Configuration Docker et production**
- **Configuration SSL/TLS**
- **Configuration de monitoring et sauvegarde**
## 🔧 Guides Techniques
### 🏗️ [Architecture Technique](ARCHITECTURE.md)
Documentation technique détaillée de l'architecture.
- **Architecture générale du frontend**
- **Composants principaux (Vue.js, TypeScript, WASM)**
- **Intégration avec sdk_client et sdk_common**
- **Flux de données entre composants**
- **Architecture des Silent Payments**
- **Sécurité et isolation**
- **Performance et optimisations**
- **Monitoring et observabilité**
### 📡 [API](API.md)
Documentation contractuelle des APIs disponibles.
- **API sdk_client WASM** : Interface WebAssembly pour les Silent Payments
- **API Vue.js Components** : Composants réutilisables
- **API Services** : Services de communication et gestion
- **API Types TypeScript** : Types et interfaces
- **Format des données et payloads**
- **Gestion des erreurs**
- **Exemples d'utilisation**
- **Limites et quotas**
### 🔒 [Sécurité](SECURITY.md)
Guide de sécurité et bonnes pratiques.
- **Authentification et autorisation**
- **Protection XSS et CSRF**
- **Sécurité WASM et mémoire**
- **Chiffrement et certificats**
- **Audit et monitoring de sécurité**
- **Bonnes pratiques frontend**
### 🐙 [Configuration Gitea](GITEA_SETUP.md)
Guide de configuration spécifique pour Gitea.
- **Configuration du repository Gitea**
- **Templates d'issues et pull requests**
- **Configuration CI/CD avec Gitea Actions**
- **Intégrations et webhooks**
- **Workflow de contribution**
- **Sécurité et permissions**
### 🚀 [Plan de Release](RELEASE_PLAN.md)
Plan de lancement open source complet.
- **Phases de préparation**
- **Communication et marketing**
- **Checklist de lancement**
- **Support communautaire**
- **Gestion des risques**
### 🌟 [Guide de la Communauté](COMMUNITY_GUIDE.md)
Guide complet pour la communauté.
- **Comment contribuer**
- **Ressources d'apprentissage**
- **Environnement de développement**
- **Processus de contribution**
- **Support et reconnaissance**
### 🗺️ [Roadmap](ROADMAP.md)
Roadmap de développement détaillée.
- **Timeline de développement**
- **Fonctionnalités planifiées**
- **Évolution de l'architecture**
- **Métriques de succès**
## 🧪 Guides de Test
### 🧪 [Guide des Tests](TESTING.md)
Guide complet pour les tests de l'interface utilisateur.
- **Tests unitaires Vue.js**
- **Tests d'intégration WASM**
- **Tests end-to-end (Playwright)**
- **Tests de performance**
- **Tests de sécurité**
- **Tests d'accessibilité**
- **Tests de compatibilité navigateur**
### 🔍 [Audit de Sécurité](SECURITY_AUDIT.md)
Audit de sécurité détaillé.
- **Vulnérabilités connues**
- **Tests de pénétration**
- **Audit de code**
- **Recommandations de sécurité**
- **Plan de remédiation**
## 🔧 Guides de Développement
### 🔧 [Guide de Développement](DEVELOPMENT.md)
Guide complet pour le développement.
- **Environnement de développement**
- **Workflow de développement**
- **Standards de code**
- **Debugging et profiling**
- **Optimisation des performances**
- **Déploiement et CI/CD**
### 📋 [Référence Rapide](QUICK_REFERENCE.md)
Référence rapide pour les développeurs.
- **Commandes essentielles**
- **Structure du projet**
- **APIs principales**
- **Configuration rapide**
- **Dépannage rapide**
### 🔄 [Guide de Migration](MIGRATION.md)
Guide pour les migrations et mises à jour.
- **Migration des versions**
- **Breaking changes**
- **Mise à jour des dépendances**
- **Migration des données**
- **Tests de migration**
## 🌐 Guides d'Intégration
### 🧩 [Intégration iframe](INTEGRATION_IFRAME.md)
Spécification de messagerie postMessage (requêtes/réponses, erreurs, prérequis).
### 🔑 [Configuration SSH](SSH_USAGE.md)
Guide de configuration SSH pour le développement.
- **Génération des clés SSH**
- **Configuration Git**
- **Intégration avec Gitea**
- **Automatisation des déploiements**
### 🤖 [Push SSH Automatisé](AUTO_SSH_PUSH.md)
Guide pour l'automatisation des pushes SSH.
- **Configuration des scripts**
- **Intégration CI/CD**
- **Gestion des clés**
- **Sécurité et bonnes pratiques**
## 📊 État et Monitoring
### 📊 [Référence rapide](QUICK_REFERENCE.md)
Raccourcis daccès (commandes, dossiers, URLs) pour démarrer vite.
## 🔧 Guides d'Open Source
### ✅ [Checklist Open Source](OPEN_SOURCE_CHECKLIST.md)
Checklist complète pour l'ouverture en open source.
- **Préparation du code**
- **Documentation**
- **Licences et légal**
- **Infrastructure**
- **Communication**
## 📞 Support et Contact
### 📞 [Support](SUPPORT.md)
Guide de support et contact.
- **Comment obtenir de l'aide**
- **Création d'issues**
- **Canal de communication**
- **FAQ**
- **Ressources additionnelles**
---
## 🎯 Navigation Rapide
### 🚀 Démarrage Rapide
1. [Installation](INSTALLATION.md) - Installer ihm_client
2. [Configuration](CONFIGURATION.md) - Configurer l'environnement
3. [Utilisation](USAGE.md) - Utiliser l'interface
### 🔧 Développement
1. [Architecture](ARCHITECTURE.md) - Comprendre l'architecture
2. [API](API.md) - Consulter les APIs
3. [Tests](TESTING.md) - Exécuter les tests
### 📚 Documentation
1. [Index](INDEX.md) - Cet index
2. [Quick Reference](QUICK_REFERENCE.md) - Référence rapide
3. [Roadmap](ROADMAP.md) - Évolution du projet
### 🤝 Communauté
1. [Guide Communauté](COMMUNITY_GUIDE.md) - Contribuer
2. [Code de Conduite](../CODE_OF_CONDUCT.md) - Règles de conduite
3. [Support](SUPPORT.md) - Obtenir de l'aide
---
**📚 Documentation complète pour ihm_client - Interface utilisateur moderne pour les Silent Payments** 🚀

View File

@ -1,374 +0,0 @@
# 📦 Guide d'Installation - ihm_client
Guide complet pour installer et configurer l'interface utilisateur ihm_client pour les Silent Payments.
## 📋 Prérequis
### Système
- **OS** : Linux (Ubuntu 20.04+, Debian 11+, CentOS 8+), macOS 10.15+, Windows 10+
- **Architecture** : x86_64, ARM64 (Apple Silicon)
- **RAM** : 4 Go minimum, 8 Go recommandés
- **Stockage** : 5 Go minimum, 10 Go recommandés
- **Réseau** : Connexion Internet stable
### Logiciels
- **Node.js** : Version 18.0+ (LTS recommandé)
- **npm** : Version 8.0+
- **Git** : Version 2.25+
- **Rust** : Version 1.70+ (pour la compilation WASM)
- **Docker** : Version 20.10+ (optionnel, pour l'intégration 4NK_node)
## 🚀 Installation
### 1. Installation de Node.js
#### Ubuntu/Debian
```bash
# Mettre à jour les paquets
sudo apt update
# Installer Node.js via NodeSource
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
# Vérifier l'installation
node --version
npm --version
```
#### CentOS/RHEL
```bash
# Installer Node.js via NodeSource
curl -fsSL https://rpm.nodesource.com/setup_18.x | sudo bash -
sudo yum install -y nodejs
# Vérifier l'installation
node --version
npm --version
```
#### macOS
```bash
# Installer via Homebrew
brew install node@18
# Ou télécharger depuis nodejs.org
# https://nodejs.org/en/download/
```
#### Windows
```bash
# Télécharger et installer depuis
# https://nodejs.org/en/download/
```
### 2. Installation de Rust
#### Linux/macOS
```bash
# Installer Rust via rustup
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Recharger l'environnement
source ~/.cargo/env
# Vérifier l'installation
rustc --version
cargo --version
```
#### Windows
```bash
# Télécharger et installer rustup depuis
# https://rustup.rs/
```
### 3. Installation de wasm-pack
```bash
# Installer wasm-pack
cargo install wasm-pack
# Vérifier l'installation
wasm-pack --version
```
### 4. Configuration SSH (Recommandé)
```bash
# Générer une clé SSH
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_ihm -C "ihm-client-automation"
# Ajouter à l'agent SSH
ssh-add ~/.ssh/id_ed25519_ihm
# Configurer Git pour utiliser la clé
git config --global core.sshCommand "ssh -i ~/.ssh/id_ed25519_ihm"
# Afficher la clé publique pour Gitea
cat ~/.ssh/id_ed25519_ihm.pub
```
**Ajouter la clé publique à Gitea :**
1. Aller sur Gitea > Settings > SSH Keys
2. Coller la clé publique
3. Cliquer sur "Add key"
### 5. Clonage du Repository
```bash
# Cloner avec SSH (recommandé)
git clone git@git.4nkweb.com:4nk/ihm_client.git
cd ihm_client
# Ou cloner avec HTTPS
git clone https://git.4nkweb.com/4nk/ihm_client.git
cd ihm_client
```
### 6. Installation des Dépendances
```bash
# Installer les dépendances Node.js
npm install
# Vérifier l'installation
npm list --depth=0
```
### 7. Configuration des Dépendances WASM
```bash
# Configurer les dépendances distantes (sdk_client, sdk_common)
./scripts/setup-remote-deps.sh
# Vérifier la compilation WASM
ls -la pkg/
```
## 🔧 Configuration
### Variables d'Environnement
Créer un fichier `.env` à la racine du projet :
```bash
# Configuration de développement
NODE_ENV=development
VITE_DEV_SERVER_PORT=3000
VITE_API_URL=http://localhost:8091
VITE_WS_URL=ws://localhost:8090
# Configuration WASM
VITE_WASM_PATH=./pkg/sdk_client_bg.wasm
# Configuration pour l'intégration 4NK_node
SDK_RELAY_WS_URL=ws://sdk_relay_1:8090
SDK_RELAY_HTTP_URL=http://sdk_relay_1:8091
BITCOIN_RPC_URL=http://bitcoin:18443
BLINDBIT_URL=http://blindbit:8000
```
### Configuration TypeScript
Le fichier `tsconfig.json` est déjà configuré pour :
- Vue.js 3
- TypeScript strict
- Support WASM
- Path mapping
### Configuration Vite
Le fichier `vite.config.ts` est configuré pour :
- Support WASM
- Hot module replacement
- Build optimisé
- Support des types TypeScript
## 🧪 Tests Post-Installation
### 1. Test de Compilation
```bash
# Test de compilation TypeScript
npm run build
# Vérifier le build
ls -la dist/
```
### 2. Test de Développement
```bash
# Démarrer le serveur de développement
npm run dev
# Ouvrir http://localhost:3000 dans le navigateur
```
### 3. Test WASM
```bash
# Vérifier que le module WASM fonctionne
npm run test:wasm
```
### 4. Test Complet
```bash
# Exécuter tous les tests
npm run test
# Vérifier la couverture
npm run test:coverage
```
## 🚨 Dépannage
### Problèmes Courants
#### Node.js non trouvé
```bash
# Vérifier l'installation
which node
node --version
# Réinstaller si nécessaire
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
```
#### Rust non trouvé
```bash
# Vérifier l'installation
which rustc
rustc --version
# Réinstaller si nécessaire
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source ~/.cargo/env
```
#### Erreurs de compilation WASM
```bash
# Nettoyer et recompiler
rm -rf pkg/
./scripts/setup-remote-deps.sh
# Vérifier les dépendances Rust
cd temp-deps/sdk_client
cargo check
```
#### Erreurs de dépendances npm
```bash
# Nettoyer et réinstaller
rm -rf node_modules/ package-lock.json
npm install
# Vérifier les vulnérabilités
npm audit
npm audit fix
```
#### Problèmes de permissions
```bash
# Corriger les permissions
sudo chown -R $USER:$USER .
chmod +x scripts/*.sh
```
### Logs Détaillés
```bash
# Logs de compilation TypeScript
npm run build --verbose
# Logs de compilation WASM
cd temp-deps/sdk_client
wasm-pack build --target web --out-dir ../../pkg --verbose
# Logs du serveur de développement
npm run dev --verbose
```
## 🔒 Sécurité
### Vérifications de Sécurité
```bash
# Audit des dépendances npm
npm audit
# Audit des dépendances Rust
cargo audit
# Vérification des vulnérabilités WASM
wasm-pack build --target web --out-dir ../../pkg
```
### Bonnes Pratiques
- Utiliser HTTPS en production
- Valider toutes les entrées utilisateur
- Maintenir les dépendances à jour
- Utiliser des variables d'environnement pour les secrets
- Tester régulièrement la sécurité
## 📊 Monitoring
### Métriques d'Installation
```bash
# Taille du projet
du -sh .
# Nombre de fichiers
find . -type f | wc -l
# Dépendances installées
npm list --depth=0 | wc -l
# Taille du module WASM
ls -lh pkg/sdk_client_bg.wasm
```
### Vérification de l'Installation
```bash
# Script de vérification
./scripts/verify-installation.sh
# Tests automatisés
npm run test:installation
```
## 🎯 Prochaines Étapes
Après l'installation réussie :
1. **Lire le [Guide d'Utilisation](USAGE.md)** - Utiliser l'interface
2. **Consulter l'[Architecture](ARCHITECTURE.md)** - Comprendre le système
3. **Explorer les [APIs](API.md)** - Utiliser les fonctionnalités
4. **Consulter l'[Intégration iframe](INTEGRATION_IFRAME.md)** - Intégrer dans un site hôte
## 📞 Support
En cas de problème :
1. Consulter la [documentation](INDEX.md)
2. Vérifier les [issues existantes](https://git.4nkweb.com/4nk/ihm_client/issues)
3. Créer une nouvelle issue avec les détails du problème
4. Inclure les logs et la configuration utilisée
---
**🚀 Installation terminée ! ihm_client est prêt à être utilisé.** ✨

View File

@ -1,156 +0,0 @@
# Intégration iframe Spécification de messagerie
Ce document définit les échanges entre un site hôte et `ihm_client` intégré en iframe, via `window.postMessage`. Aucun exemple de code exécutable nest inclus.
## Principes
- Canal: postMessage entre la page parente et liframe `ihm_client`.
- Découverte: `ihm_client` émet `LISTENING` pour signaler la disponibilité des listeners (côté iframe). En mode E2E (`?e2e=1`) et seulement lorsque lapp tourne en iframe, `LISTENING` est émis périodiquement (jusquà 100 fois) pour éviter les courses de tests. Hors E2E, pas démission périodique.
- Sécurité:
- Utiliser la cible `event.origin` pour les réponses.
- De nombreuses opérations exigent un `accessToken` valide (lié à `origin`).
- `messageId` recommandé pour corréler requêtes/réponses.
- Pré-requis: pour la plupart des actions de processus, lappareil doit être appairé.
## Types de message
Référence: `src/models/process.model.ts` (enum `MessageType`).
### LISTENING
- Émis par `ihm_client` au parent pour signaler la disponibilité des listeners.
- Réception côté parent (aucune requête attendue). Pas de payload spécifique.
---
### REQUEST_LINK (Requête)
- Objet: ouverture dun consentement utilisateur pour lier lhôte à lappareil.
- Requête (parent → iframe):
- `type`: `REQUEST_LINK`
- `messageId`: string (optionnel mais recommandé)
- Réponses (iframe → parent):
- Succès: `type`: `LINK_ACCEPTED`, `accessToken`: string, `refreshToken`: string, `messageId`
- Erreur: `type`: `ERROR`, `error`: string, `messageId`
### VALIDATE_TOKEN (Requête)
- Objet: vérifier la validité du couple `{accessToken, refreshToken}`.
- Requête: `type`, `accessToken`, `refreshToken`, `messageId`
- Réponse: `type`: `VALIDATE_TOKEN`, `isValid`: boolean, `accessToken`, `refreshToken`, `messageId`
### RENEW_TOKEN (Requête)
- Objet: obtenir un nouveau `accessToken` depuis un `refreshToken`.
- Requête: `type`, `refreshToken`, `messageId`
- Réponses:
- Succès: `type`: `RENEW_TOKEN`, `accessToken`, `refreshToken`, `messageId`
- Erreur: `ERROR`
---
### CREATE_PAIRING (Requête)
- Objet: initier lappairage de lappareil.
- Pré-requis: `accessToken` valide; appareil non appairé.
- Requête: `type`, `accessToken`, `messageId`
- Réponses:
- Succès: `type`: `PAIRING_CREATED`, `pairingId`: string, `messageId`
- Erreur: `ERROR`
### GET_PAIRING_ID (Requête)
- Objet: récupérer lidentifiant dappairage utilisateur.
- Pré-requis: appairé + `accessToken` valide.
- Requête: `type`, `accessToken`, `messageId`
- Réponse: `type`: `GET_PAIRING_ID`, `userPairingId`: string, `messageId`
---
### GET_MY_PROCESSES (Requête)
- Objet: lister les processus auxquels lutilisateur participe.
- Pré-requis: appairé + `accessToken` valide.
- Requête: `type`, `accessToken`, `messageId`
- Réponse: `type`: `GET_MY_PROCESSES`, `myProcesses`: string[] | null, `messageId`
### GET_PROCESSES (Requête)
- Objet: récupérer tous les processus connus localement.
- Pré-requis: appairé + `accessToken` valide.
- Requête: `type`, `accessToken`, `messageId`
- Réponse: `type`: `PROCESSES_RETRIEVED`, `processes`: Record<string, Process>, `messageId`
---
### RETRIEVE_DATA (Requête)
- Objet: déchiffrer et retourner les attributs autorisés dun état de processus.
- Pré-requis: appairé + `accessToken` valide.
- Requête: `type`, `processId`: string, `stateId`: string (32 bytes hex), `accessToken`, `messageId`
- Réponse: `type`: `DATA_RETRIEVED`, `data`: Record<string, any>, `messageId`
### DECODE_PUBLIC_DATA (Requête)
- Objet: décoder des données publiques encodées.
- Pré-requis: appairé + `accessToken` valide.
- Requête: `type`, `accessToken`, `encodedData`: number[], `messageId`
- Réponse: `type`: `PUBLIC_DATA_DECODED`, `decodedData`: any, `messageId`
---
### CREATE_PROCESS (Requête)
- Objet: créer un nouveau processus.
- Pré-requis: appairé + `accessToken` valide.
- Requête:
- `type`
- `processData`: Record<string, any> (données brutes à répartir en public/privé)
- `privateFields`: string[] (liste des nouveaux champs à forcer en privé)
- `roles`: Record<string, RoleDefinition>
- `accessToken`, `messageId`
- Réponse succès: `type`: `PROCESS_CREATED`, `processCreated`: { `processId`: string, `process`: Process, `processData`: Record<string, any> }, `messageId`
- Réponse erreur: `ERROR`
### UPDATE_PROCESS (Requête)
- Objet: créer un nouvel état avec des mises à jour (champs publics/privés déterminés automatiquement, `privateFields` pour les nouveaux champs privés).
- Pré-requis: appairé + `accessToken` valide + processus existant avec état committé.
- Requête: `type`, `processId`, `newData`: Record<string, any>, `privateFields`: string[], `roles` (ou null pour conserver), `accessToken`, `messageId`
- Réponse: `type`: `PROCESS_UPDATED`, `updatedProcess`: Process, `messageId`
---
### NOTIFY_UPDATE (Requête)
- Objet: demander lémission dun PRD Update pour un état précis.
- Pré-requis: appairé + `accessToken` valide.
- Requête: `type`, `processId`, `stateId` (32 bytes hex), `accessToken`, `messageId`
- Réponse: `type`: `UPDATE_NOTIFIED`, `messageId`
### VALIDATE_STATE (Requête)
- Objet: valider un état (selon règles/permissions WASM).
- Pré-requis: appairé + `accessToken` valide.
- Requête: `type`, `processId`, `stateId` (32 bytes hex), `accessToken`, `messageId`
- Réponse: `type`: `STATE_VALIDATED`, `validatedProcess`: Process, `messageId`
---
### HASH_VALUE (Requête)
- Objet: obtenir le hash dun blob (document) pour un engagement donné.
- Requête: `type`, `accessToken`, `commitedIn`: string, `label`: string, `fileBlob`: { type: string; data: Uint8Array }, `messageId`
- Réponse: `type`: `VALUE_HASHED`, `hash`: string, `messageId`
### GET_MERKLE_PROOF (Requête)
- Objet: récupérer la preuve Merkle dun attribut dans un état.
- Requête: `type`, `accessToken`, `processState`: ProcessState, `attributeName`: string, `messageId`
- Réponse: `type`: `MERKLE_PROOF_RETRIEVED`, `proof`: MerkleProofResult, `messageId`
### VALIDATE_MERKLE_PROOF (Requête)
- Objet: valider une preuve Merkle pour un document donné.
- Requête: `type`, `accessToken`, `merkleProof`: string (JSON sérialisé), `documentHash`: string, `messageId`
- Réponse: `type`: `MERKLE_PROOF_VALIDATED`, `isValid`: boolean, `messageId`
---
## Erreurs communes (`ERROR`)
- Conditions typiques:
- `Device not paired` (opération nécessitant appairage)
- `Invalid or expired session token`
- `Failed to ...` (création/lecture/validation)
- `Invalid state id` / `Process not found`
- Payload générique: `{ type: 'ERROR', error: string, messageId?: string }`
## Bonnes pratiques dintégration
- Toujours préciser et propager `messageId` pour tracer les échanges.
- Conserver `origin` côté parent et utiliser la même valeur dans les requêtes suivantes.
- Renouveler régulièrement le `accessToken` via `RENEW_TOKEN`.
- Séparer données publiques/privées dès la création dun processus.
- Valider les formats (ids hex 32 bytes, structures de rôles) avant envoi.

View File

@ -1,8 +0,0 @@
# Checklist open source - ihm_client
- Licence présente et valide (LICENSE)
- Code de conduite (CODE_OF_CONDUCT.md)
- Guide de contribution (CONTRIBUTING.md)
- CI/CD documentée
- Documentation technique et utilisateur à jour
- Aucune donnée sensible dans le dépôt

View File

@ -1,5 +0,0 @@
# Référence rapide - ihm_client
- Commandes: install, dev, build, test, test:e2e
- Dossiers clés: src/, pkg/, docs/
- URLs: dev 3003, app servi par 4NK_node (artefacts dist/)

View File

@ -1,5 +0,0 @@
# Plan de release - ihm_client
- Phases: préparation, RC, GA
- Critères: tests verts, docs à jour, audit dépendances
- Communication: notes de version, changelog, guide de migration

View File

@ -1,8 +0,0 @@
- [ ] Handshake iframe robuste (READY → LISTENING → REQUEST_LINK) avec ACKs
- Objectif: éliminer les conditions de course à linitialisation
- Détails: séquence explicite, timeouts, retry backoff
# Roadmap - ihm_client
- Court terme: stabilisation iframe, optimisation WASM
- Moyen terme: E2E tests, PWA, performances
- Long terme: analytics, nouvelles intégrations

View File

@ -1,25 +0,0 @@
# Audit de sécurité - ihm_client
Ce document synthétise la posture de sécurité, les contrôles, et les axes daudit pour `ihm_client`.
## Portée
- Surface frontend (TypeScript, Vite, dépendances npm)
- Intégration WASM (sdk_client)
- Messagerie iframe (`postMessage`) avec sites hôtes
## Contrôles actuels
- Validation et renouvellement de tokens de session liés à lorigine appelante
- Isolation des données privées (déchiffrement conditionné, clés requises)
- Aucune exposition de secrets runtime dans le code
## Axes daudit
- Dépendances: revue `npm audit`, vérification des transitive deps
- WASM: taille, init sécurisé, absence dAPIs dangereuses
- Iframe: vérification stricte des `origin`, absence délévation via messages
## Vulnérabilités connues
- Aucune critique ouverte à date
## Plan de remédiation
- Mise à jour régulière des dépendances
- Tests de sécurité ciblés côté messagerie et décodage de données

View File

@ -1,322 +0,0 @@
# Documentation SSH complète - ihm_client
## Vue d'ensemble
Ce document consolide toute la documentation SSH pour le projet `ihm_client`, couvrant l'automatisation des push, la configuration CI/CD, et les bonnes pratiques de sécurité.
## Table des matières
- [Configuration automatique](#configuration-automatique)
- [Scripts d'automatisation](#scripts-dautomatisation)
- [Workflow CI/CD](#workflow-cicd)
- [Alias Git](#alias-git)
- [Bonnes pratiques](#bonnes-pratiques)
- [Dépannage](#dépannage)
---
## Configuration automatique
### Configuration Git globale
La configuration SSH est automatiquement appliquée pour tous les push :
```bash
git config --global url."git@git.4nkweb.com:".insteadOf "https://git.4nkweb.com/"
```
### Vérification SSH
Test automatique de la connexion SSH :
```bash
ssh -T git@git.4nkweb.com
```
---
## Scripts d'automatisation
### 1. Script principal : `auto-ssh-push.sh`
Le script `scripts/auto-ssh-push.sh` offre plusieurs modes de push automatique :
#### Options disponibles
```bash
# Push rapide (message automatique)
./scripts/auto-ssh-push.sh quick
# Push avec message personnalisé
./scripts/auto-ssh-push.sh message "feat: nouvelle fonctionnalité"
# Push sur une branche spécifique
./scripts/auto-ssh-push.sh branch feature/nouvelle-fonctionnalite
# Push et merge (avec confirmation)
./scripts/auto-ssh-push.sh merge
# Vérification du statut
./scripts/auto-ssh-push.sh status
```
#### Fonctionnalités
- **Configuration SSH automatique** - Plus besoin de configurer SSH manuellement
- **Push automatique** - Ajout, commit et push en une commande
- **Gestion des branches** - Support des branches personnalisées
- **Vérification SSH** - Test automatique de la connexion SSH
- **Messages de commit** - Messages automatiques ou personnalisés
### 2. Script d'initialisation : `init-ssh-env.sh`
Le script `scripts/init-ssh-env.sh` configure automatiquement l'environnement SSH :
```bash
./scripts/init-ssh-env.sh
```
#### Fonctionnalités
- Vérification de l'environnement de développement
- Configuration SSH automatique
- Test de connectivité SSH
- Configuration des alias Git
- Validation de la configuration
### 3. Script CI/CD : `setup-ssh-ci.sh`
Le script `scripts/setup-ssh-ci.sh` configure SSH pour les environnements CI/CD :
```bash
./scripts/setup-ssh-ci.sh
```
#### Fonctionnalités
- Détection automatique de l'environnement CI
- Configuration SSH pour Gitea Actions
- Gestion des clés SSH privées
- Test de connexion SSH
- Configuration Git pour SSH
---
## Workflow CI/CD
### Configuration Gitea Actions
Le workflow CI/CD dans `.gitea/workflows/ci.yml` inclut une étape de configuration SSH :
```yaml
- name: Setup SSH for Gitea
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H git.4nkweb.com >> ~/.ssh/known_hosts
git config --global url."git@git.4nkweb.com:".insteadOf "https://git.4nkweb.com/"
```
### Variables d'environnement requises
- `SSH_PRIVATE_KEY` : Clé SSH privée pour l'authentification
- `SSH_PUBLIC_KEY` : Clé SSH publique (optionnelle)
### Jobs configurés
- **test** : Tests unitaires et d'intégration
- **security** : Tests de sécurité et audit
- **integration-test** : Tests d'intégration complets
---
## Alias Git
### Alias configurés
```bash
# Push rapide avec message automatique
git quick-push
# Push avec message personnalisé
git ssh-push "Mon message de commit"
```
### Configuration des alias
```bash
# Alias pour push rapide
git config --global alias.quick-push '!f() { git add . && git commit -m "Update $(date)" && git push origin $(git branch --show-current); }; f'
# Alias pour push avec message
git config --global alias.ssh-push '!f() { git add . && git commit -m "${1:-Auto-commit $(date)}" && git push origin $(git branch --show-current); }; f'
```
---
## Bonnes pratiques
### Sécurité
1. **Permissions des clés SSH**
```bash
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
chmod 600 ~/.ssh/config
```
2. **Configuration SSH sécurisée**
```bash
Host git.4nkweb.com
HostName git.4nkweb.com
User git
IdentityFile ~/.ssh/id_rsa
StrictHostKeyChecking no
UserKnownHostsFile=/dev/null
```
3. **Gestion des secrets**
- Ne jamais commiter de clés SSH dans le code
- Utiliser les secrets Gitea pour les clés privées
- Rotation régulière des clés SSH
### Workflow recommandé
1. **Initialisation**
```bash
./scripts/init-ssh-env.sh
```
2. **Développement quotidien**
```bash
# Push rapide
./scripts/auto-ssh-push.sh quick
# Ou avec alias Git
git quick-push
```
3. **Push avec message**
```bash
./scripts/auto-ssh-push.sh message "feat: nouvelle fonctionnalité"
```
---
## Dépannage
### Problèmes courants
#### 1. Échec d'authentification SSH
```bash
# Vérifier la configuration SSH
ssh -T git@git.4nkweb.com
# Vérifier les permissions
ls -la ~/.ssh/
# Régénérer la clé SSH si nécessaire
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_4nk
```
#### 2. Configuration Git incorrecte
```bash
# Vérifier la configuration Git
git config --global --list | grep url
# Reconfigurer SSH
git config --global url."git@git.4nkweb.com:".insteadOf "https://git.4nkweb.com/"
```
#### 3. Problèmes CI/CD
```bash
# Vérifier les variables d'environnement
echo $SSH_PRIVATE_KEY
# Tester la configuration SSH
./scripts/setup-ssh-ci.sh
```
### Messages d'erreur courants
- **"Permission denied"** : Vérifier les permissions des clés SSH
- **"Host key verification failed"** : Ajouter l'hôte aux known_hosts
- **"Could not resolve hostname"** : Vérifier la connectivité réseau
### Logs et debugging
```bash
# Activer le debug SSH
ssh -vT git@git.4nkweb.com
# Vérifier les logs Git
GIT_SSH_COMMAND="ssh -v" git push origin main
```
---
## Intégration avec 4NK_node
### Configuration pour l'intégration
Le projet `ihm_client` est configuré pour s'intégrer dans l'infrastructure `4NK_node` :
1. **Script d'intégration** : `scripts/integrate-4nk-node.sh`
2. **Configuration Docker** : `Dockerfile.4nk-node`
3. **Configuration Nginx** : gérée dans `4NK_node` (consommation de `dist/`)
4. **Script de démarrage** : `start-4nk-node.sh`
### Workflow d'intégration
```bash
# Intégrer ihm_client dans 4NK_node
./scripts/integrate-4nk-node.sh
# Vérifier l'intégration
docker-compose -f docker-compose.4nk-node.yml up -d
```
---
## Évolution future
### Améliorations prévues
1. **Support multi-environnements**
- Configuration automatique pour différents environnements
- Gestion des clés SSH multiples
2. **Intégration avancée**
- Support des hooks Git
- Intégration avec d'autres outils CI/CD
3. **Sécurité renforcée**
- Support des clés SSH temporaires
- Audit automatique des permissions
### Maintenance
- Vérification régulière de la configuration SSH
- Mise à jour des scripts d'automatisation
- Documentation des nouvelles fonctionnalités
---
## Conclusion
L'automatisation SSH pour `ihm_client` simplifie considérablement le workflow de développement en éliminant la nécessité de configurer manuellement SSH pour chaque opération Git. Les scripts et alias fournis offrent une interface simple et sécurisée pour tous les push vers le repository.
### Ressources
- [Documentation SSH officielle](https://git-scm.com/book/fr/v2/Git-sur-le-serveur-Génération-d-une-clé-SSH)
- [Guide Gitea SSH](https://docs.gitea.com/usage/ssh-setup)
- [Bonnes pratiques SSH](https://www.ssh.com/academy/ssh/key)
---
**Dernière mise à jour** : $(date '+%Y-%m-%d')
**Version** : 1.0.0

View File

@ -1,51 +0,0 @@
# Tests - ihm_client
Cette page décrit la stratégie de test, loutillage et les conventions. Aucun exemple exécutable nest inclus.
## Périmètre et objectifs
- Couverture des utilitaires (hex/binaire, DOM, adresses → emojis).
- Couverture des services isolables (`TokenService`).
- Non-régression des conversions et des invariants dAPI.
## Outils
- Test runner: Jest 29 (environnement `jsdom`).
- TypeScript: `ts-jest` (transform TS).
- Setup global: `tests/setup.ts` (polyfills Web, mocks réseau et stockage).
- E2E: Playwright (Chromium headless) avec `playwright.config.ts`.
## Organisation
- `tests/unit/` : tests unitaires ciblés, rapides.
- `tests/integration/` : réservé aux interactions WASM/services (à compléter si besoin).
- `tests/e2e/` : tests de bout en bout (smoke tests).
## Exécution
- Lancer tous les tests: `npm run test`
- Couverture: `npm run test:coverage`
- Veille interactive: `npm run test:watch`
- E2E: `npm run e2e:install` puis `npm run test:e2e`
## Conventions
- Un test = un invariant métier/technique.
- Mocks minimaux, privilégier lisolation des dépendances (ex. `jose` mocké).
- Aucun exemple de code applicatif dans la documentation.
## Polyfills et mocks de test
- `TextEncoder`/`TextDecoder` via `util`.
- `crypto.subtle.digest` faux pour hashing déterministe en test demojis.
- `fetch`, `WebSocket`, `localStorage`, `sessionStorage` mockés.
## Critères dacceptation
- 100% vert sur la suite unitaire.
- Build TypeScript OK (`npm run build:dist`) avant commit.
## Rapports
- Rapport couverture: `coverage/` (text, lcov, html).
- Logs de tests: sortie Jest standard.

View File

@ -1,423 +0,0 @@
# 📖 Guide d'Utilisation - ihm_client
Guide complet pour utiliser l'interface utilisateur ihm_client au quotidien.
## 🚀 Démarrage Rapide
### Démarrage du Serveur de Développement
```bash
# Démarrer le serveur de développement
npm run dev
# Le serveur démarre sur http://localhost:3000
# Hot reload activé pour le développement
```
### Accès à l'Interface
1. **Ouvrir le navigateur** : http://localhost:3000
2. **Page d'accueil** : Vue d'ensemble et navigation
3. **Connexion** : Via adresse device ou QR code
## 🏠 Page d'Accueil
### Navigation Principale
- **🏠 Accueil** - Vue d'ensemble et navigation
- **👤 Compte** - Gestion du profil utilisateur
### Tableau de Bord
- **Statistiques personnelles** : Processus actifs, documents signés
- **Notifications récentes** : Alertes et mises à jour
- **Actions rapides** : Créer un processus, scanner QR code
- **État du wallet** : Solde et transactions récentes
## 👤 Gestion du Compte
### Profil Utilisateur
#### Accès au Profil
1. Cliquer sur la bulle de profil en haut à gauche
2. Popup de profil s'ouvre avec les informations personnelles
#### Informations Modifiables
- **Nom et prénom** : Éditer directement dans les champs
- **Photo de profil** : Cliquer pour changer l'image
- **Email** : Adresse de contact (lecture seule)
- **Adresse device** : Identifiant unique (lecture seule)
#### Actions du Profil
##### Export User Data
```bash
# Génère un fichier JSON avec toutes les données utilisateur
# Inclut : profil, processus, documents, wallet
```
##### Export Recovery
```bash
# Génère les 4 mots de récupération
# IMPORTANT : Noter et conserver en lieu sûr
# Le bouton devient inaccessible après utilisation
```
##### Delete Account
```bash
# Supprime définitivement le compte
# Demande de confirmation obligatoire
# Action irréversible
```
##### Logout
```bash
# Déconnexion de l'interface
# Retour à la page de connexion
```
### Onglet Pairing
#### Ajouter un Device
1. Cliquer sur "Add Device"
2. Choisir la méthode :
- **Scanner QR Code** : Scanner le code d'un autre device
- **Saisir manuellement** : Entrer l'adresse device
#### Gérer les Devices
- **Renommer** : Cliquer sur le nom pour l'éditer
- **Supprimer** : Cliquer sur l'icône poubelle
- **Statut** : En ligne/hors ligne
#### Scanner QR Code
1. Cliquer sur "Scan QR Code"
2. Autoriser l'accès à la caméra
3. Pointer vers le QR code
4. Confirmation automatique
### Onglet Wallet
#### Gestion des Wallets
- **Voir le solde** : Affichage en temps réel
- **Ajouter une ligne** : Nouveau wallet Silent Payment
- **Historique** : Transactions récentes
- **Détails** : Cliquer pour plus d'informations
#### Opérations Wallet
```bash
# Générer un nouveau wallet
generate_sp_wallet()
# Verrouiller des UTXOs
lock_freezed_utxos(wallet, utxos)
# Scanner des blocs
scan_blocks(wallet, blocks)
```
### Onglet Process
#### Processus Disponibles
- **Liste des processus** : Tous les processus accessibles
- **Notifications** : Cliquer sur la sonnette pour voir les alertes
- **Statut** : Actif, en attente, terminé
- **Actions** : Voir, modifier, supprimer
#### Créer un Processus
1. Cliquer sur "Nouveau Processus"
2. Remplir les informations :
- **Nom** : Nom du processus
- **Description** : Détails du processus
- **Membres** : Ajouter des participants
- **Rôles** : Définir les responsabilités
3. Valider la création
### Onglet Data
#### Données Importées
- **Liste des données** : Fichiers JSON importés
- **Contrats associés** : Cliquer pour voir le contrat
- **Statut** : Validé, en cours, rejeté
- **Actions** : Voir, modifier, supprimer
## 📄 Gestion des Processus
### Vue d'Ensemble
#### Onglets du Processus
- **📋 Informations** : Détails du processus
- **👥 Membres** : Participants et rôles
- **📁 Documents** : Fichiers associés
- **✍️ Signatures** : Demandes de signature
- **💬 Chat** : Communication interne
### Gestion des Membres
#### Ajouter un Membre
1. Cliquer sur "Ajouter Membre"
2. Choisir la méthode :
- **Scanner QR Code** : Invitation directe
- **Envoyer un lien** : Lien d'invitation
- **Saisir l'adresse** : Adresse device manuelle
#### Assigner des Rôles
1. Sélectionner un membre
2. Cliquer sur "Assigner Rôle"
3. Choisir le rôle :
- **Admin** : Gestion complète
- **Signataire** : Peut signer des documents
- **Lecteur** : Lecture seule
- **Custom** : Rôle personnalisé
### Gestion des Documents
#### Importer un Document
1. Cliquer sur "Importer Document"
2. Choisir le fichier (PDF, DOC, etc.)
3. Remplir les métadonnées :
- **Nom** : Nom du document
- **Description** : Détails du document
- **Rôles requis** : Qui doit signer
4. Valider l'import
#### Organiser les Documents
- **Dossiers** : Créer des dossiers pour organiser
- **Tags** : Ajouter des étiquettes
- **Recherche** : Filtrer par nom, type, statut
- **Tri** : Par date, nom, taille
## ✍️ Système de Signatures
### Demandes de Signature
#### Créer une Demande
1. Aller dans l'onglet "Signatures"
2. Cliquer sur "Nouvelle Demande"
3. Remplir les informations :
- **Document** : Sélectionner le document
- **Signataires** : Choisir les participants
- **Description** : Détails de la demande
- **Date limite** : Échéance de signature
- **Visibilité** : Publique ou privée
4. Valider la création
#### Gérer les Demandes
- **En attente** : Demandes non signées
- **Signées** : Demandes complétées
- **Expirées** : Demandes dépassées
- **Actions** : Voir, modifier, annuler
### Signer un Document
#### Processus de Signature
1. Recevoir une notification de demande
2. Cliquer sur "Voir la demande"
3. Prévisualiser le document
4. Cliquer sur "Signer"
5. Confirmer la signature
#### Types de Signature
- **Signature électronique** : Signature numérique
- **Signature biométrique** : Empreinte digitale
- **Signature par mot de passe** : Code secret
## 💬 Système de Chat
### Communication Interne
#### Accès au Chat
1. Aller dans l'onglet "Chat"
2. Sélectionner le processus
3. Voir les conversations
#### Envoyer un Message
1. Sélectionner un utilisateur ou groupe
2. Taper le message
3. Cliquer sur "Envoyer"
#### Types de Messages
- **Texte** : Messages simples
- **Documents** : Fichiers partagés
- **Images** : Captures d'écran
- **Liens** : URLs partagées
### Notifications
#### Types de Notifications
- **Messages** : Nouveaux messages reçus
- **Signatures** : Demandes de signature
- **Processus** : Mises à jour de processus
- **Système** : Alertes système
#### Gestion des Notifications
- **Marquer comme lu** : Cliquer sur la notification
- **Répondre** : Répondre directement
- **Ignorer** : Masquer la notification
- **Paramètres** : Configurer les alertes
## 🔗 Système de Pairing
### Connexion avec d'Autres Utilisateurs
#### Méthodes de Pairing
1. **QR Code** : Scanner le code d'un autre device
2. **Lien d'invitation** : Envoyer un lien
3. **Adresse manuelle** : Saisir l'adresse device
#### Processus de Pairing
1. **Initiative** : Un utilisateur initie la connexion
2. **Confirmation** : L'autre utilisateur confirme
3. **Établissement** : La connexion est établie
4. **Vérification** : Test de communication
#### Gestion des Connexions
- **Connexions actives** : Devices connectés
- **Demandes en attente** : Invitations non acceptées
- **Historique** : Connexions passées
- **Actions** : Déconnecter, renommer, supprimer
## 🔔 Notifications et Alertes
### Centre de Notifications
#### Accès aux Notifications
- **Icône cloche** : En haut à droite
- **Compteur** : Nombre de notifications non lues
- **Liste** : Toutes les notifications
#### Types d'Alertes
- **Urgentes** : Rouge, action immédiate requise
- **Importantes** : Orange, attention requise
- **Informatives** : Bleu, information générale
- **Succès** : Vert, confirmation d'action
### Configuration des Notifications
#### Paramètres
1. Aller dans "Paramètres" > "Notifications"
2. Configurer par type :
- **Messages** : Notifications de chat
- **Signatures** : Demandes de signature
- **Processus** : Mises à jour
- **Système** : Alertes système
#### Préférences
- **Son** : Activer/désactiver les sons
- **Pop-up** : Notifications en pop-up
- **Email** : Notifications par email
- **Push** : Notifications push (si supporté)
## 🛠️ Fonctionnalités Avancées
### Recherche Globale
#### Utilisation
1. Cliquer sur l'icône de recherche
2. Taper le terme recherché
3. Voir les résultats :
- **Processus** : Processus correspondants
- **Documents** : Documents correspondants
- **Messages** : Messages correspondants
- **Utilisateurs** : Utilisateurs correspondants
### Filtres et Tri
#### Filtres Disponibles
- **Date** : Filtrer par période
- **Type** : Filtrer par type de contenu
- **Statut** : Filtrer par statut
- **Utilisateur** : Filtrer par utilisateur
#### Options de Tri
- **Date** : Plus récent/ancien
- **Nom** : Alphabétique
- **Taille** : Plus grand/petit
- **Statut** : Priorité des statuts
### Export et Sauvegarde
#### Exporter des Données
```bash
# Export complet du profil
Export User Data > JSON
# Export des processus
Processus > Exporter > CSV
# Export des documents
Documents > Exporter > ZIP
```
#### Sauvegarde Automatique
- **Sauvegarde locale** : Données stockées localement
- **Synchronisation** : Synchronisation avec le serveur
- **Récupération** : Restauration des données
## 🚨 Dépannage
### Problèmes Courants
#### Interface ne se charge pas
```bash
# Vérifier le serveur
npm run dev
# Vérifier les logs
npm run dev --verbose
# Nettoyer le cache
npm run clean
```
#### Module WASM non trouvé
```bash
# Recompiler le module WASM
./scripts/setup-remote-deps.sh
# Vérifier le fichier
ls -la pkg/sdk_client_bg.wasm
```
#### Erreurs de connexion
```bash
# Vérifier les variables d'environnement
cat .env
# Tester la connectivité
npm run test:connectivity
```
### Support Utilisateur
#### Obtenir de l'Aide
1. **Documentation** : Consulter ce guide
2. **FAQ** : Questions fréquentes
3. **Support** : Contacter l'équipe
4. **Issues** : Signaler un problème
#### Signaler un Bug
1. Aller sur [Issues](https://git.4nkweb.com/4nk/ihm_client/issues)
2. Créer une nouvelle issue
3. Décrire le problème :
- **Étapes** : Comment reproduire
- **Comportement** : Ce qui se passe
- **Attendu** : Ce qui devrait se passer
- **Environnement** : OS, navigateur, version
## 📊 Métriques d'Utilisation
### Statistiques Personnelles
- **Processus créés** : Nombre de processus
- **Documents signés** : Nombre de signatures
- **Messages envoyés** : Communication
- **Temps d'utilisation** : Temps passé
### Performance
- **Temps de chargement** : Vitesse de l'interface
- **Temps de réponse** : Réactivité
- **Utilisation mémoire** : Consommation RAM
- **Taille des données** : Stockage utilisé
---
**🎯 Interface utilisateur ihm_client - Prête pour une utilisation quotidienne !** ✨

View File

@ -6,7 +6,7 @@
<meta name="description" content="4NK Web5 Platform"> <meta name="description" content="4NK Web5 Platform">
<meta name="keywords" content="4NK web5 bitcoin blockchain decentralize dapps relay contract"> <meta name="keywords" content="4NK web5 bitcoin blockchain decentralize dapps relay contract">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/style/4nk.css"> <link rel="stylesheet" href="./style/4nk.css">
<script src="https://unpkg.com/html5-qrcode"></script> <script src="https://unpkg.com/html5-qrcode"></script>
<title>4NK Application</title> <title>4NK Application</title>
</head> </head>

View File

@ -1,34 +0,0 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
roots: ['<rootDir>/src', '<rootDir>/tests'],
testMatch: [
'**/__tests__/**/*.ts',
'**/?(*.)+(spec|test).ts'
],
transform: {
'^.+\\.ts$': 'ts-jest',
},
collectCoverageFrom: [
'src/**/*.ts',
'!src/**/*.d.ts',
'!src/main.ts',
'!src/vite-env.d.ts'
],
coverageDirectory: 'coverage',
coverageReporters: ['text', 'lcov', 'html'],
setupFilesAfterEnv: ['<rootDir>/tests/setup.ts'],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
'^~/(.*)$': '<rootDir>/src/$1',
'^pkg/(.*)$': '<rootDir>/pkg/$1',
'^(.*)\\?raw$': '<rootDir>/tests/rawFileMock.js',
'\\.(css|less|sass|scss)$': '<rootDir>/tests/styleMock.js'
},
testTimeout: 10000,
transform: {
'^.+\\.ts$': ['ts-jest', {
tsconfig: 'tsconfig.json'
}],
}
};

View File

@ -1,16 +0,0 @@
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|webp|wasm)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}

5348
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,64 +1,43 @@
{ {
"name": "sdk_client", "name": "sdk_client",
"version": "1.1.0", "version": "1.0.0",
"description": "", "description": "",
"main": "dist/index.js", "main": "dist/index.js",
"scripts": { "scripts": {
"test": "jest", "test": "echo \"Error: no test specified\" && exit 1",
"test:watch": "jest --watch", "build_wasm": "wasm-pack build --out-dir ../ihm_client_dev1/pkg ../sdk_client --target bundler --dev",
"test:coverage": "jest --coverage",
"test:unit": "jest --testPathPattern=tests/unit",
"test:integration": "jest --testPathPattern=tests/integration",
"build_wasm": "./scripts/setup-remote-deps.sh",
"cleanup_deps": "./scripts/cleanup-deps.sh",
"start": "vite --host 0.0.0.0", "start": "vite --host 0.0.0.0",
"build": "tsc && vite build", "build": "tsc && vite build",
"deploy": "sudo cp -r dist/* /var/www/html/", "deploy": "sudo cp -r dist/* /var/www/html/",
"prettify": "prettier --config ./.prettierrc --write \"src/**/*{.ts,.html,.css,.js}\"", "prettify": "prettier --config ./.prettierrc --write \"src/**/*{.ts,.html,.css,.js}\""
"build:dist": "tsc -p tsconfig.build.json",
"lint": "prettier -c \"src/**/*{.ts,.html,.css,.js}\"",
"type-check": "tsc -p tsconfig.json --noEmit",
"e2e:install": "npx playwright install --with-deps",
"test:e2e": "playwright test"
}, },
"keywords": [], "keywords": [],
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"@rollup/plugin-typescript": "^12.1.1", "@rollup/plugin-typescript": "^12.1.1",
"@types/jest": "^29.5.12",
"@types/node": "^20.11.24",
"@vitejs/plugin-vue": "^5.0.5",
"copy-webpack-plugin": "^12.0.2", "copy-webpack-plugin": "^12.0.2",
"html-webpack-plugin": "^5.6.0", "html-webpack-plugin": "^5.6.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"prettier": "^3.3.3", "prettier": "^3.3.3",
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"ts-jest": "^29.1.2",
"ts-loader": "^9.5.1", "ts-loader": "^9.5.1",
"typescript": "^5.3.3", "typescript": "^5.3.3",
"vite": "^5.4.11", "vite": "^5.4.11",
"vite-plugin-static-copy": "^1.0.6", "vite-plugin-static-copy": "^1.0.6",
"webpack": "^5.90.3", "webpack": "^5.90.3",
"webpack-cli": "^5.1.4", "webpack-cli": "^5.1.4",
"webpack-dev-server": "^5.0.2", "webpack-dev-server": "^5.0.2"
"@playwright/test": "^1.46.0"
}, },
"dependencies": { "dependencies": {
"@angular/elements": "^19.0.1", "@angular/elements": "^19.0.1",
"@types/jsonwebtoken": "^9.0.9",
"@types/qrcode": "^1.5.5", "@types/qrcode": "^1.5.5",
"@vitejs/plugin-react": "^4.3.1", "@vitejs/plugin-react": "^4.3.1",
"@vitejs/plugin-vue": "^5.0.5", "@vitejs/plugin-vue": "^5.0.5",
"axios": "^1.11.0", "axios": "^1.7.8",
"html5-qrcode": "^2.3.8", "html5-qrcode": "^2.3.8",
"jose": "^6.0.13",
"jsonwebtoken": "^9.0.2",
"pdf-lib": "^1.17.1",
"qr-scanner": "^1.4.2", "qr-scanner": "^1.4.2",
"qrcode": "^1.5.4", "qrcode": "^1.5.3",
"sweetalert2": "^11.22.4", "sweetalert2": "^11.14.5",
"vite-plugin-copy": "^0.1.6", "vite-plugin-copy": "^0.1.6",
"vite-plugin-html": "^3.2.2", "vite-plugin-html": "^3.2.2",
"vite-plugin-wasm": "^3.3.0" "vite-plugin-wasm": "^3.3.0"

1
pkg/.gitignore vendored
View File

@ -1 +0,0 @@
*

View File

@ -1,277 +0,0 @@
# sdk_client - Module WASM
Module WebAssembly compilé pour l'intégration des Silent Payments dans l'interface utilisateur `ihm_client`.
## 📋 Vue d'ensemble
Ce package contient le module WASM compilé de `sdk_client`, qui fournit les fonctionnalités de Silent Payments pour l'interface utilisateur.
### Fichiers inclus
- `sdk_client_bg.wasm` - Module WASM principal (3.3 MB)
- `sdk_client.d.ts` - Déclarations TypeScript (12.6 KB)
- `sdk_client.js` - Wrapper JavaScript (182 B)
- `sdk_client_bg.js` - Code JavaScript généré (38 KB)
- `package.json` - Métadonnées du package
- `README.md` - Ce fichier
## 🚀 Utilisation
### Import dans TypeScript
```typescript
import init, {
generate_sp_wallet,
lock_freezed_utxos,
// ... autres fonctions
} from 'pkg/sdk_client';
// Initialiser le module WASM
await init();
// Utiliser les fonctions
const wallet = generate_sp_wallet();
```
### Import dans JavaScript
```javascript
import init, { generate_sp_wallet } from 'pkg/sdk_client';
// Initialiser le module WASM
await init();
// Utiliser les fonctions
const wallet = generate_sp_wallet();
```
## 🔧 Configuration
### Variables d'environnement
```bash
# Configuration pour le développement
NODE_ENV=development
VITE_WASM_PATH=./pkg/sdk_client_bg.wasm
# Configuration pour la production
NODE_ENV=production
VITE_WASM_PATH=/assets/sdk_client_bg.wasm
```
### Configuration Vite
```typescript
// vite.config.ts
import { defineConfig } from 'vite';
import wasm from 'vite-plugin-wasm';
export default defineConfig({
plugins: [
wasm(),
// ... autres plugins
],
optimizeDeps: {
exclude: ['pkg/sdk_client']
}
});
```
## 📚 API Reference
### Fonctions principales
#### `generate_sp_wallet()`
Génère un nouveau wallet Silent Payment.
**Retourne :** `Wallet` - Instance du wallet généré
#### `lock_freezed_utxos(wallet: Wallet, utxos: UTXO[])`
Verrouille les UTXOs gelés dans le wallet.
**Paramètres :**
- `wallet` - Instance du wallet
- `utxos` - Liste des UTXOs à verrouiller
**Retourne :** `boolean` - Succès de l'opération
### Types TypeScript
```typescript
interface Wallet {
id: string;
address: string;
balance: number;
// ... autres propriétés
}
interface UTXO {
txid: string;
vout: number;
amount: number;
// ... autres propriétés
}
```
## 🧪 Tests
### Tests unitaires
```bash
# Tests des fonctions WASM
npm run test:wasm
# Tests avec couverture
npm run test:wasm:coverage
```
### Tests d'intégration
```bash
# Tests d'intégration avec l'interface
npm run test:integration
# Tests end-to-end
npm run test:e2e
```
## 🔍 Debugging
### Logs de développement
```typescript
// Activer les logs détaillés
import { set_panic_hook } from 'pkg/sdk_client';
set_panic_hook();
```
### Inspection du module
```javascript
// Inspecter les exports disponibles
import * as sdk_client from 'pkg/sdk_client';
console.log(Object.keys(sdk_client));
```
## 📦 Build
### Compilation WASM
```bash
# Compiler le module WASM
cd temp-deps/sdk_client
wasm-pack build --target web --out-dir ../../pkg
# Ou utiliser le script automatisé
./scripts/setup-remote-deps.sh
```
### Optimisation
```bash
# Optimiser la taille du module
wasm-opt -O4 -o sdk_client_bg.wasm sdk_client_bg.wasm
# Compresser le module
gzip -9 sdk_client_bg.wasm
```
## 🚨 Dépannage
### Problèmes courants
#### Module non trouvé
```bash
# Vérifier que le module est compilé
ls -la pkg/sdk_client_bg.wasm
# Recompiler si nécessaire
./scripts/setup-remote-deps.sh
```
#### Erreurs de type TypeScript
```bash
# Régénérer les types
cd temp-deps/sdk_client
wasm-pack build --target web --out-dir ../../pkg
# Vérifier la cohérence des types
npm run type-check
```
#### Problèmes de performance
```bash
# Vérifier la taille du module
ls -lh pkg/sdk_client_bg.wasm
# Optimiser si nécessaire
wasm-opt -O4 -o pkg/sdk_client_bg.wasm pkg/sdk_client_bg.wasm
```
## 📈 Performance
### Métriques
- **Taille du module** : 3.3 MB (non compressé)
- **Temps de chargement** : ~500ms (dépendant du réseau)
- **Temps d'initialisation** : ~100ms
- **Mémoire utilisée** : ~10MB
### Optimisations
1. **Compression gzip** : Réduit la taille de ~70%
2. **Lazy loading** : Chargement à la demande
3. **Caching** : Mise en cache du module
4. **Preloading** : Préchargement anticipé
## 🔒 Sécurité
### Bonnes pratiques
- Ne jamais exposer les clés privées
- Valider toutes les entrées utilisateur
- Utiliser HTTPS en production
- Maintenir les dépendances à jour
### Audit de sécurité
```bash
# Vérifier les vulnérabilités
npm audit
# Audit des dépendances Rust
cargo audit
```
## 📚 Documentation
### Liens utiles
- [Documentation WASM](https://webassembly.org/docs/)
- [Documentation wasm-pack](https://rustwasm.github.io/docs/wasm-pack/)
- [Documentation sdk_client](../temp-deps/sdk_client/README.md)
- [Documentation sdk_common](../temp-deps/sdk_common/README.md)
### Exemples
- [Exemples d'utilisation](../docs/API.md)
- [Tests d'intégration](../tests/)
- [Guide de développement](../CONTRIBUTING.md)
## 🤝 Contribution
Pour contribuer au module WASM :
1. Modifier le code source dans `temp-deps/sdk_client/`
2. Recompiler avec `./scripts/setup-remote-deps.sh`
3. Tester les changements
4. Mettre à jour la documentation
## 📄 Licence
Ce module est sous licence MIT. Voir le fichier LICENSE pour plus de détails.
---
**🚀 Module WASM sdk_client - Prêt pour l'intégration !**

View File

@ -1,17 +0,0 @@
{
"name": "sdk_client",
"type": "module",
"version": "1.1.0",
"files": [
"sdk_client_bg.wasm",
"sdk_client.js",
"sdk_client_bg.js",
"sdk_client.d.ts"
],
"main": "sdk_client.js",
"types": "sdk_client.d.ts",
"sideEffects": [
"./sdk_client.js",
"./snippets/*"
]
}

355
pkg/sdk_client.d.ts vendored
View File

@ -1,355 +0,0 @@
/* tslint:disable */
/* eslint-disable */
export function setup(): void;
export function get_address(): string;
export function get_member(): Member;
export function restore_device(device: any): void;
export function create_device_from_sp_wallet(sp_wallet: string): string;
export function create_new_device(birthday: number, network_str: string): string;
export function is_paired(): boolean;
export function pair_device(process_id: string, sp_addresses: string[]): void;
export function unpair_device(): void;
export function dump_wallet(): string;
export function reset_process_cache(): void;
export function dump_process_cache(): string;
export function set_process_cache(processes: any): void;
export function add_to_process_cache(process_id: string, process: string): void;
export function reset_shared_secrets(): void;
export function set_shared_secrets(secrets: string): void;
export function get_pairing_process_id(): string;
export function dump_device(): Device;
export function dump_neutered_device(): Device;
export function reset_device(): void;
export function get_txid(transaction: string): string;
export function parse_new_tx(new_tx_msg: string, block_height: number, members_list: OutPointMemberMap): ApiReturn;
export function parse_cipher(cipher_msg: string, members_list: OutPointMemberMap): ApiReturn;
export function get_outputs(): any;
export function get_available_amount(): bigint;
/**
* We send a transaction that pays at least one output to each address
* The goal can be to establish a shared_secret to be used as an encryption key for further communication
* or if the recipient is a relay it can be the init transaction for a new process
*/
export function create_transaction(addresses: string[], fee_rate: number): ApiReturn;
export function sign_transaction(partial_tx: TsUnsignedTransaction): ApiReturn;
export function create_new_process(private_data: Pcd, roles: Roles, public_data: Pcd, relay_address: string, fee_rate: number, members_list: OutPointMemberMap): ApiReturn;
export function update_process(process: Process, new_attributes: Pcd, roles: Roles, new_public_data: Pcd, members_list: OutPointMemberMap): ApiReturn;
export function request_data(process_id: string, state_ids_str: string[], roles: any, members_list: OutPointMemberMap): ApiReturn;
export function create_update_message(process: Process, state_id: string, members_list: OutPointMemberMap): ApiReturn;
export function validate_state(process: Process, state_id: string, members_list: OutPointMemberMap): ApiReturn;
export function refuse_state(process: Process, state_id: string, members_list: OutPointMemberMap): ApiReturn;
export function evaluate_state(process: Process, state_id: string, members_list: OutPointMemberMap): ApiReturn;
export function create_response_prd(process: Process, state_id: string, members_list: OutPointMemberMap): ApiReturn;
export function create_faucet_msg(): string;
export function get_storages(process_outpoint: string): string[];
export function is_child_role(parent_roles: string, child_roles: string): void;
export function decrypt_data(key: Uint8Array, data: Uint8Array): Uint8Array;
export function encode_binary(data: any): Pcd;
export function encode_json(json_data: any): Pcd;
export function decode_value(value: Uint8Array): any;
export function hash_value(value: any, commited_in: string, label: string): string;
/**
* Generate a merkle proof for a specific attribute in a process state.
*
* This function creates a merkle proof that proves the existence of a specific attribute
* in a given state of a process. The proof can be used to verify that the attribute
* was indeed part of the state without revealing the entire state.
*
* # Arguments
* * `process_state` - The process state object as a JavaScript value
* * `attribute_name` - The name of the attribute to generate a proof for
*
* # Returns
* A MerkleProofResult object containing:
* * `proof` - The merkle proof as a hex string
* * `root` - The merkle root (state_id) as a hex string
* * `attribute` - The attribute name that was proven
* * `attribute_index` - The index of the attribute in the merkle tree
* * `total_leaves_count` - The total number of leaves in the merkle tree
*
* # Errors
* * "Failed to deserialize process state" - If the process state cannot be deserialized from JsValue
* * "Attribute not found in state" - If the attribute doesn't exist in the state
*/
export function get_merkle_proof(process_state: any, attribute_name: string): MerkleProofResult;
/**
* Validate a merkle proof for a specific attribute.
*
* This function verifies that a merkle proof is valid and proves the existence
* of a specific attribute in a given state. It checks that the proof correctly
* leads to the claimed root when combined with the attribute hash.
*
* # Arguments
* * `proof_result` - a JsValue expected to contain a MerkleProofResult with the proof and metadata
* * `hash` - The hash of the attribute data as a hex string (the leaf value)
*
* # Returns
* A boolean indicating whether the proof is valid
*
* # Errors
* * "serde_wasm_bindgen deserialization error" - If the proof is not a valid MerkleProofResult
* * "Invalid proof format" - If the proof cannot be parsed
* * "Invalid hash format" - If the hash is not a valid 32-byte hex string
* * "Invalid root format" - If the root is not a valid 32-byte hex string
*/
export function validate_merkle_proof(proof_result: any, hash: string): boolean;
export type DiffStatus = "None" | "Rejected" | "Validated";
export interface UserDiff {
process_id: string;
state_id: string;
value_commitment: string;
field: string;
roles: Roles;
description: string | null;
notify_user: boolean;
need_validation: boolean;
validation_status: DiffStatus;
}
export interface UpdatedProcess {
process_id: OutPoint;
current_process: Process;
diffs: UserDiff[];
encrypted_data: Record<string, string>;
validated_state: number[] | null;
}
export interface ApiReturn {
secrets: SecretsStore | null;
updated_process: UpdatedProcess | null;
new_tx_to_send: NewTxMessage | null;
ciphers_to_send: string[];
commit_to_send: CommitMessage | null;
push_to_storage: string[];
partial_tx: TsUnsignedTransaction | null;
}
export interface encryptWithNewKeyResult {
cipher: string;
key: string;
}
export interface MerkleProofResult {
proof: string;
root: string;
attribute: string;
attribute_index: number;
total_leaves_count: number;
}
export interface Device {
sp_wallet: SpWallet;
pairing_process_commitment: OutPoint | null;
paired_member: Member;
}
export interface Prd {
prd_type: PrdType;
process_id: OutPoint;
sender: Member;
keys: Record<string, number[]>;
pcd_commitments: PcdCommitments;
validation_tokens: Proof[];
roles: Roles;
public_data: Pcd;
payload: string;
proof: Proof | null;
}
export type PrdType = "None" | "Connect" | "Message" | "Update" | "List" | "Response" | "Confirm" | "TxProposal" | "Request";
/**
* Réponse de synchronisation
*/
export interface SyncResponse {
request_id: string;
relay_id: string;
success: boolean;
messages: SyncMessage[];
error: string | null;
}
/**
* Requête de synchronisation
*/
export interface SyncRequest {
request_id: string;
relay_id: string;
sync_types: SyncType[];
since_timestamp: number | null;
max_items: number | null;
}
/**
* Capacité d\'un relais
*/
export interface Capability {
name: string;
version: string;
enabled: boolean;
parameters: Record<string, string>;
}
/**
* Connexion mesh entre relais
*/
export interface MeshConnection {
from_relay: string;
to_relay: string;
latency: number;
bandwidth: number;
last_heartbeat: number;
}
/**
* Topologie du réseau
*/
export interface NetworkTopology {
total_relays: number;
connected_relays: number;
mesh_connections: MeshConnection[];
network_diameter: number;
avg_latency: number;
}
/**
* Statut de santé d\'un relais
*/
export type HealthStatus = "Healthy" | "Warning" | "Critical" | "Offline";
/**
* Informations sur un relais
*/
export interface RelayInfo {
relay_id: string;
address: string;
sp_address: string;
version: string;
uptime: number;
last_seen: number;
capabilities: string[];
health_status: HealthStatus;
}
/**
* Informations sur un pair
*/
export interface PeerInfo {
address: string;
sp_address: string;
connected_since: number;
last_activity: number;
message_count: number;
capabilities: string[];
}
/**
* Contenu des messages de synchronisation
*/
export type SyncPayload = { StateData: { chain_tip: number; wallet_balance: number; active_processes: number; connected_peers: number } } | { ProcessData: { processes: OutPointProcessMap; last_update: number } } | { MemberData: { members: OutPointMemberMap; last_update: number } } | { TransactionData: { txid: string; height: number | null; confirmed: boolean; sp_outputs: string[] } } | { BlockData: { height: number; hash: string; timestamp: number; tx_count: number } } | { PeerData: { peers: PeerInfo[]; last_seen: number } } | { RelayData: { relays: RelayInfo[]; network_topology: NetworkTopology } } | { HealthData: { uptime: number; memory_usage: number; cpu_usage: number; active_connections: number; last_block_time: number } } | { MetricsData: { messages_processed: number; transactions_broadcast: number; blocks_scanned: number; errors_count: number; avg_response_time: number } } | { ConfigData: { config_hash: string; features: string[]; version: string } } | { CapabilityData: { capabilities: Capability[]; supported_networks: string[] } };
/**
* Types de synchronisation
*/
export type SyncType = "StateSync" | "ProcessSync" | "MemberSync" | "TxSync" | "BlockSync" | "PeerSync" | "RelaySync" | "HealthSync" | "MetricsSync" | "ConfigSync" | "CapabilitySync";
/**
* Message de synchronisation pour le réseau mesh des relais
*/
export interface SyncMessage {
sync_type: SyncType;
relay_id: string;
timestamp: number;
sequence_number: number;
payload: SyncPayload;
signature: string | null;
}
export interface HandshakeMessage {
sp_address: string;
peers_list: OutPointMemberMap;
processes_list: OutPointProcessMap;
chain_tip: number;
}
export interface NewTxMessage {
transaction: string;
tweak_data: string | null;
error: AnkError | null;
}
export interface FaucetMessage {
sp_address: string;
commitment: string;
error: AnkError | null;
}
/**
* Message sent to the server to commit some state in a transaction
* Client must first send a commit message with empty validation_tokens
* Relay will ignore a commit message for an update he\'s not aware of that also bears validation_tokens
*/
export interface CommitMessage {
process_id: OutPoint;
pcd_commitment: PcdCommitments;
roles: Roles;
public_data: Pcd;
validation_tokens: Proof[];
error: AnkError | null;
}
export type AnkFlag = "NewTx" | "Faucet" | "Cipher" | "Commit" | "Handshake" | "Sync" | "Unknown";
export type OutPointProcessMap = Record<OutPoint, Process>;
export type OutPointMemberMap = Record<OutPoint, Member>;
/**
* A process is basically a succession of states
* The latest state MUST be an empty state with only the commited_in field set at the last unspent outpoint
* Commiting this last empty state in a transaction is called obliterating a process, basically terminating it
*/
export interface Process {
states: ProcessState[];
}
export interface ProcessState {
commited_in: OutPoint;
pcd_commitment: Record<string, string>;
state_id: string;
keys: Record<string, string>;
validation_tokens: Proof[];
public_data: Pcd;
roles: Record<string, RoleDefinition>;
}
export type TsUnsignedTransaction = SilentPaymentUnsignedTransaction;
export interface SecretsStore {
shared_secrets: Record<SilentPaymentAddress, AnkSharedSecretHash>;
unconfirmed_secrets: AnkSharedSecretHash[];
}
export type Roles = Record<string, RoleDefinition>;
export interface RoleDefinition {
members: OutPoint[];
validation_rules: ValidationRule[];
storages: string[];
}
export interface ValidationRule {
quorum: number;
fields: string[];
min_sig_member: number;
}
export type PcdCommitments = Record<string, string>;
export type Pcd = Record<string, number[]>;
export interface Member {
sp_addresses: string[];
}

View File

@ -1,5 +0,0 @@
import * as wasm from "./sdk_client_bg.wasm";
export * from "./sdk_client_bg.js";
import { __wbg_set_wasm } from "./sdk_client_bg.js";
__wbg_set_wasm(wasm);
wasm.__wbindgen_start();

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -1,69 +0,0 @@
/* tslint:disable */
/* eslint-disable */
export const memory: WebAssembly.Memory;
export const get_address: () => [number, number, number, number];
export const get_member: () => [number, number, number];
export const restore_device: (a: any) => [number, number];
export const create_device_from_sp_wallet: (a: number, b: number) => [number, number, number, number];
export const create_new_device: (a: number, b: number, c: number) => [number, number, number, number];
export const is_paired: () => [number, number, number];
export const pair_device: (a: number, b: number, c: number, d: number) => [number, number];
export const unpair_device: () => [number, number];
export const dump_wallet: () => [number, number, number, number];
export const reset_process_cache: () => [number, number];
export const dump_process_cache: () => [number, number, number, number];
export const set_process_cache: (a: any) => [number, number];
export const add_to_process_cache: (a: number, b: number, c: number, d: number) => [number, number];
export const reset_shared_secrets: () => [number, number];
export const set_shared_secrets: (a: number, b: number) => [number, number];
export const get_pairing_process_id: () => [number, number, number, number];
export const dump_device: () => [number, number, number];
export const dump_neutered_device: () => [number, number, number];
export const reset_device: () => [number, number];
export const get_txid: (a: number, b: number) => [number, number, number, number];
export const parse_new_tx: (a: number, b: number, c: number, d: any) => [number, number, number];
export const parse_cipher: (a: number, b: number, c: any) => [number, number, number];
export const get_outputs: () => [number, number, number];
export const get_available_amount: () => [bigint, number, number];
export const create_transaction: (a: number, b: number, c: number) => [number, number, number];
export const sign_transaction: (a: any) => [number, number, number];
export const create_new_process: (a: any, b: any, c: any, d: number, e: number, f: number, g: any) => [number, number, number];
export const update_process: (a: any, b: any, c: any, d: any, e: any) => [number, number, number];
export const request_data: (a: number, b: number, c: number, d: number, e: any, f: any) => [number, number, number];
export const create_update_message: (a: any, b: number, c: number, d: any) => [number, number, number];
export const validate_state: (a: any, b: number, c: number, d: any) => [number, number, number];
export const refuse_state: (a: any, b: number, c: number, d: any) => [number, number, number];
export const evaluate_state: (a: any, b: number, c: number, d: any) => [number, number, number];
export const create_response_prd: (a: any, b: number, c: number, d: any) => [number, number, number];
export const create_faucet_msg: () => [number, number, number, number];
export const get_storages: (a: number, b: number) => [number, number, number, number];
export const is_child_role: (a: number, b: number, c: number, d: number) => [number, number];
export const decrypt_data: (a: number, b: number, c: number, d: number) => [number, number, number, number];
export const encode_binary: (a: any) => [number, number, number];
export const encode_json: (a: any) => [number, number, number];
export const decode_value: (a: number, b: number) => [number, number, number];
export const hash_value: (a: any, b: number, c: number, d: number, e: number) => [number, number, number, number];
export const get_merkle_proof: (a: any, b: number, c: number) => [number, number, number];
export const validate_merkle_proof: (a: any, b: number, c: number) => [number, number, number];
export const setup: () => void;
export const rust_zstd_wasm_shim_qsort: (a: number, b: number, c: number, d: number) => void;
export const rust_zstd_wasm_shim_malloc: (a: number) => number;
export const rust_zstd_wasm_shim_memcmp: (a: number, b: number, c: number) => number;
export const rust_zstd_wasm_shim_calloc: (a: number, b: number) => number;
export const rust_zstd_wasm_shim_free: (a: number) => void;
export const rust_zstd_wasm_shim_memcpy: (a: number, b: number, c: number) => number;
export const rust_zstd_wasm_shim_memmove: (a: number, b: number, c: number) => number;
export const rust_zstd_wasm_shim_memset: (a: number, b: number, c: number) => number;
export const rustsecp256k1_v0_9_2_context_create: (a: number) => number;
export const rustsecp256k1_v0_9_2_context_destroy: (a: number) => void;
export const rustsecp256k1_v0_9_2_default_illegal_callback_fn: (a: number, b: number) => void;
export const rustsecp256k1_v0_9_2_default_error_callback_fn: (a: number, b: number) => void;
export const __wbindgen_malloc: (a: number, b: number) => number;
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
export const __wbindgen_exn_store: (a: number) => void;
export const __externref_table_alloc: () => number;
export const __wbindgen_export_4: WebAssembly.Table;
export const __externref_table_dealloc: (a: number) => void;
export const __wbindgen_free: (a: number, b: number, c: number) => void;
export const __externref_drop_slice: (a: number, b: number) => void;
export const __wbindgen_start: () => void;

View File

@ -1,18 +0,0 @@
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests/e2e',
timeout: 30000,
use: {
baseURL: 'http://localhost:3000',
headless: true,
},
webServer: {
command: 'npx vite preview --strictPort --port 3000',
port: 3000,
reuseExistingServer: !process.env.CI,
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
],
});

View File

@ -77,99 +77,6 @@ body {
position: relative; position: relative;
} }
/* Confirmation Modal Styles */
#confirmation-modal {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 1000;
}
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
}
.modal-content {
background: white;
padding: 20px;
border-radius: 8px;
width: 90%;
max-width: 500px;
max-height: 80vh;
overflow-y: auto;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.modal-confirmation {
text-align: left;
padding: 10px;
}
.modal-confirmation h3 {
margin-bottom: 15px;
color: var(--primary-color);
font-size: 1.1em;
}
.modal-confirmation p {
margin: 8px 0;
font-size: 0.9em;
line-height: 1.4;
}
.modal-footer {
display: flex;
justify-content: flex-end;
gap: 10px;
margin-top: 20px;
padding-top: 15px;
border-top: 1px solid #eee;
}
.modal-footer button {
padding: 8px 16px;
border-radius: 4px;
border: none;
cursor: pointer;
font-size: 0.9em;
}
.btn-primary {
background: var(--primary-color);
color: white;
}
.btn-secondary {
background: var(--secondary-color);
color: white;
}
/* Responsive adjustments */
@media only screen and (max-width: 600px) {
.modal-content {
width: 95%;
margin: 10px;
padding: 15px;
}
.modal-confirmation h3 {
font-size: 1em;
}
.modal-confirmation p {
font-size: 0.85em;
}
}
.nav-wrapper { .nav-wrapper {
position: fixed; position: fixed;

View File

@ -427,43 +427,24 @@ body {
/* Style pour la modal de confirmation */ /* Style pour la modal de confirmation */
.confirm-delete-modal { .confirm-delete-modal {
display: none;
position: fixed; position: fixed;
top: 0; top: 50%;
left: 0; left: 50%;
width: 100%; transform: translate(-50%, -50%);
height: 100%; background: white;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
.confirm-delete-content {
background-color: white;
padding: 20px; padding: 20px;
border-radius: 8px; border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
max-width: 400px; z-index: 1100;
width: 90%;
text-align: center; text-align: center;
} }
.confirm-delete-content h3 {
margin-top: 0;
color: #333;
}
.confirm-delete-content p {
margin: 15px 0;
color: #666;
}
.confirm-delete-buttons { .confirm-delete-buttons {
margin-top: 20px;
display: flex; display: flex;
justify-content: center; justify-content: center;
gap: 10px; gap: 10px;
margin-top: 20px;
} }
.confirm-delete-buttons button { .confirm-delete-buttons button {
@ -471,27 +452,25 @@ body {
border: none; border: none;
border-radius: 4px; border-radius: 4px;
cursor: pointer; cursor: pointer;
transition: background-color 0.3s;
} }
.confirm-delete-buttons .confirm-btn { .confirm-btn {
background-color: #dc3545; background-color: #dc3545;
color: white; color: white;
} }
.confirm-delete-buttons .confirm-btn:hover { .cancel-btn {
background-color: #c82333;
}
.confirm-delete-buttons .cancel-btn {
background-color: #6c757d; background-color: #6c757d;
color: white; color: white;
} }
.confirm-delete-buttons .cancel-btn:hover { .delete-account-section {
background-color: #5a6268; border-top: 1px solid #eee;
padding-top: 15px;
margin-top: 15px;
} }
/*-------------------------------------- Export--------------------------------------*/ /*-------------------------------------- Export--------------------------------------*/
.export-section { .export-section {
margin: 20px 0; margin: 20px 0;
@ -1444,64 +1423,3 @@ body {
font-size: 12px; font-size: 12px;
color: #666; color: #666;
} }
.pairing-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
.pairing-modal-content {
background-color: white;
padding: 2rem;
border-radius: 8px;
width: 90%;
max-width: 500px;
}
.pairing-form {
display: flex;
flex-direction: column;
gap: 1rem;
}
.form-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.form-group label {
font-weight: bold;
}
.button-group {
display: flex;
gap: 1rem;
justify-content: flex-end;
margin-top: 1rem;
}
.button-group button {
padding: 0.5rem 1rem;
border-radius: 4px;
cursor: pointer;
}
.confirm-button {
background-color: var(--accent-color);
color: white;
border: none;
}
.cancel-button {
background-color: #ccc;
border: none;
}

View File

@ -1,155 +0,0 @@
#!/bin/bash
# Script d'automatisation des push SSH pour ihm_client
# Utilise automatiquement la clé SSH pour tous les push
set -e
echo "🔑 Configuration automatique SSH pour push ihm_client..."
# Configuration SSH automatique
echo "⚙️ Configuration Git pour utiliser SSH..."
git config --global url."git@git.4nkweb.com:".insteadOf "https://git.4nkweb.com/"
# Vérifier la configuration SSH
echo "🔍 Vérification de la configuration SSH..."
if ! ssh -T git@git.4nkweb.com 2>&1 | grep -q "successfully authenticated"; then
echo "❌ Échec de l'authentification SSH"
echo "💡 Vérifiez que votre clé SSH est configurée :"
echo " 1. ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_4nk"
echo " 2. Ajouter la clé publique à votre compte Gitea"
echo " 3. ssh-add ~/.ssh/id_ed25519_4nk"
exit 1
fi
echo "✅ Authentification SSH réussie"
# Fonction pour push automatique
auto_push() {
local branch=${1:-$(git branch --show-current)}
local commit_message=${2:-"Auto-commit $(date '+%Y-%m-%d %H:%M:%S')"}
echo "🚀 Push automatique sur la branche: $branch"
# Ajouter tous les changements
git add .
# Commiter avec le message fourni
git commit -m "$commit_message"
# Push avec SSH automatique
echo "📤 Push vers origin/$branch..."
git push origin "$branch"
echo "✅ Push réussi !"
}
# Fonction pour push avec message personnalisé
push_with_message() {
local message="$1"
local branch=${2:-$(git branch --show-current)}
echo "💬 Push avec message: $message"
auto_push "$branch" "$message"
}
# Fonction pour push rapide (sans message)
quick_push() {
local branch=${1:-$(git branch --show-current)}
auto_push "$branch"
}
# Fonction pour push sur une branche spécifique
push_branch() {
local branch="$1"
local message=${2:-"Update $branch $(date '+%Y-%m-%d %H:%M:%S')"}
echo "🌿 Push sur la branche: $branch"
auto_push "$branch" "$message"
}
# Fonction pour push et merge vers main
push_and_merge() {
local source_branch=${1:-$(git branch --show-current)}
local target_branch=${2:-main}
echo "🔄 Push et merge $source_branch -> $target_branch"
# Push de la branche source
auto_push "$source_branch"
# Demander confirmation pour le merge
read -p "Voulez-vous créer une Pull Request pour merger vers $target_branch ? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo "🔗 Création de la Pull Request..."
echo "💡 Allez sur: https://git.4nkweb.com/4nk/ihm_client/compare/$target_branch...$source_branch"
fi
}
# Fonction pour status et push conditionnel
status_and_push() {
echo "📊 Statut du repository:"
git status --short
if [[ -n $(git status --porcelain) ]]; then
echo "📝 Changements détectés, push automatique..."
auto_push
else
echo "✅ Aucun changement à pousser"
fi
}
# Menu interactif si aucun argument fourni
if [[ $# -eq 0 ]]; then
echo "🤖 Script de push SSH automatique pour ihm_client"
echo ""
echo "Options disponibles:"
echo " auto-push.sh quick - Push rapide"
echo " auto-push.sh message \"Mon message\" - Push avec message"
echo " auto-push.sh branch nom-branche - Push sur branche spécifique"
echo " auto-push.sh merge [source] [target] - Push et préparation merge"
echo " auto-push.sh status - Status et push conditionnel"
echo ""
echo "Exemples:"
echo " ./scripts/auto-ssh-push.sh quick"
echo " ./scripts/auto-ssh-push.sh message \"feat: nouvelle fonctionnalité\""
echo " ./scripts/auto-ssh-push.sh branch feature/nouvelle-fonctionnalite"
echo " ./scripts/auto-ssh-push.sh merge feature/nouvelle-fonctionnalite main"
echo ""
exit 0
fi
# Traitement des arguments
case "$1" in
"quick")
quick_push
;;
"message")
if [[ -z "$2" ]]; then
echo "❌ Message requis pour l'option 'message'"
exit 1
fi
push_with_message "$2"
;;
"branch")
if [[ -z "$2" ]]; then
echo "❌ Nom de branche requis pour l'option 'branch'"
exit 1
fi
push_branch "$2" "$3"
;;
"merge")
push_and_merge "$2" "$3"
;;
"status")
status_and_push
;;
*)
echo "❌ Option inconnue: $1"
echo "💡 Utilisez './scripts/auto-ssh-push.sh' pour voir les options"
exit 1
;;
esac
echo "🎯 Push SSH automatique terminé !"

View File

@ -1,23 +0,0 @@
#!/bin/bash
set -e
echo "🧹 Nettoyage des dépendances temporaires..."
# Suppression du dossier temporaire
if [ -d "./temp-deps" ]; then
echo " → Suppression de ./temp-deps/"
rm -rf ./temp-deps
echo "✅ Dossier temp-deps supprimé"
else
echo " Aucun dossier temp-deps trouvé"
fi
# Vérification des fichiers WASM
if [ -d "./pkg" ]; then
echo "📁 Fichiers WASM conservés dans ./pkg/"
ls -la ./pkg/
else
echo "⚠️ Aucun fichier WASM trouvé dans ./pkg/"
fi
echo "✅ Nettoyage terminé"

View File

@ -1,152 +0,0 @@
#!/bin/bash
# Script d'initialisation de l'environnement SSH pour ihm_client
# Configure automatiquement SSH pour tous les push
set -e
echo "🚀 Initialisation de l'environnement SSH pour ihm_client..."
# Couleurs pour les messages
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Fonction pour afficher les messages colorés
print_status() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Vérifier si on est dans le bon répertoire
if [[ ! -f "package.json" ]] || [[ ! -d ".git" ]]; then
print_error "Ce script doit être exécuté depuis le répertoire racine de ihm_client"
exit 1
fi
print_status "Configuration de l'environnement SSH..."
# 1. Configuration Git pour SSH
print_status "Configuration Git pour utiliser SSH..."
git config --global url."git@git.4nkweb.com:".insteadOf "https://git.4nkweb.com/"
# 2. Vérifier si une clé SSH existe
print_status "Vérification des clés SSH existantes..."
if [[ -f ~/.ssh/id_rsa ]] || [[ -f ~/.ssh/id_ed25519 ]]; then
print_success "Clé SSH trouvée"
SSH_KEY_EXISTS=true
else
print_warning "Aucune clé SSH trouvée"
SSH_KEY_EXISTS=false
fi
# 3. Tester la connexion SSH
print_status "Test de la connexion SSH vers git.4nkweb.com..."
if ssh -T git@git.4nkweb.com 2>&1 | grep -q "successfully authenticated"; then
print_success "Authentification SSH réussie"
SSH_WORKING=true
else
print_error "Échec de l'authentification SSH"
SSH_WORKING=false
fi
# 4. Configuration des alias Git
print_status "Configuration des alias Git..."
git config --global alias.ssh-push '!f() { git add . && git commit -m "${1:-Auto-commit $(date)}" && git push origin $(git branch --show-current); }; f'
git config --global alias.quick-push '!f() { git add . && git commit -m "Update $(date)" && git push origin $(git branch --show-current); }; f'
print_success "Alias Git configurés"
# 5. Vérifier les remotes
print_status "Vérification des remotes Git..."
if git remote -v | grep -q "git@git.4nkweb.com"; then
print_success "Remotes configurés pour SSH"
else
print_warning "Remotes non configurés pour SSH"
print_status "Mise à jour des remotes..."
git remote set-url origin git@git.4nkweb.com:4nk/ihm_client.git
print_success "Remotes mis à jour"
fi
# 6. Rendre les scripts exécutables
print_status "Configuration des permissions des scripts..."
chmod +x scripts/auto-ssh-push.sh 2>/dev/null || true
chmod +x scripts/setup-ssh-ci.sh 2>/dev/null || true
print_success "Scripts rendus exécutables"
# 7. Créer un fichier de configuration local
print_status "Création du fichier de configuration local..."
cat > .ssh-config << EOF
# Configuration SSH automatique pour ihm_client
# Généré le $(date)
# Configuration Git
git config --global url."git@git.4nkweb.com:".insteadOf "https://git.4nkweb.com/"
# Alias Git
git config --global alias.ssh-push '!f() { git add . && git commit -m "\${1:-Auto-commit \$(date)}" && git push origin \$(git branch --show-current); }; f'
git config --global alias.quick-push '!f() { git add . && git commit -m "Update \$(date)" && git push origin \$(git branch --show-current); }; f'
# Test SSH
ssh -T git@git.4nkweb.com
# Scripts disponibles
./scripts/auto-ssh-push.sh quick
./scripts/auto-ssh-push.sh message "Mon message"
git ssh-push "Mon message"
git quick-push
EOF
print_success "Fichier de configuration créé: .ssh-config"
# 8. Résumé de la configuration
echo ""
print_success "=== Configuration SSH terminée ==="
echo ""
echo "✅ Configuration Git pour SSH"
echo "✅ Alias Git configurés"
echo "✅ Remotes vérifiés"
echo "✅ Scripts configurés"
echo ""
if [[ "$SSH_WORKING" == "true" ]]; then
print_success "SSH fonctionne correctement"
echo ""
echo "🚀 Vous pouvez maintenant utiliser :"
echo " ./scripts/auto-ssh-push.sh quick"
echo " ./scripts/auto-ssh-push.sh message \"Mon message\""
echo " git ssh-push \"Mon message\""
echo " git quick-push"
echo ""
else
print_warning "SSH ne fonctionne pas encore"
echo ""
echo "🔧 Pour configurer SSH :"
echo " 1. Générer une clé SSH : ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_4nk"
echo " 2. Ajouter à l'agent SSH : ssh-add ~/.ssh/id_ed25519_4nk"
echo " 3. Ajouter la clé publique à votre compte Gitea"
echo " 4. Relancer ce script : ./scripts/init-ssh-env.sh"
echo ""
fi
# 9. Test final
if [[ "$SSH_WORKING" == "true" ]]; then
print_status "Test final de push SSH..."
echo "💡 Pour tester, utilisez : ./scripts/auto-ssh-push.sh status"
fi
print_success "Initialisation SSH terminée !"

View File

@ -1,348 +0,0 @@
#!/bin/bash
set -e
# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
TARGET_DIR="${PROJECT_ROOT}/../4NK_node"
# Couleurs pour l'affichage
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Fonction d'affichage
print_info() {
echo -e "${BLUE} $1${NC}"
}
print_success() {
echo -e "${GREEN}$1${NC}"
}
print_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
print_error() {
echo -e "${RED}$1${NC}"
}
# Fonction d'aide
show_help() {
echo "Usage: $0 [options]"
echo ""
echo "Options:"
echo " --target-dir DIR Répertoire cible 4NK_node (défaut: ../4NK_node)"
echo " --dry-run Simulation sans modification"
echo " --backup Créer une sauvegarde avant intégration"
echo " --help Afficher cette aide"
echo ""
echo "Exemples:"
echo " $0 # Intégration standard"
echo " $0 --dry-run # Simulation"
echo " $0 --target-dir /path/to/4NK_node"
}
# Variables
DRY_RUN=false
BACKUP=false
TARGET_DIR="${PROJECT_ROOT}/../4NK_node"
# Parsing des arguments
while [[ $# -gt 0 ]]; do
case $1 in
--target-dir)
TARGET_DIR="$2"
shift 2
;;
--dry-run)
DRY_RUN=true
shift
;;
--backup)
BACKUP=true
shift
;;
--help)
show_help
exit 0
;;
*)
print_error "Option inconnue: $1"
show_help
exit 1
;;
esac
done
# Vérification des prérequis
check_prerequisites() {
print_info "Vérification des prérequis..."
# Vérifier que nous sommes dans le bon répertoire
if [[ ! -f "${PROJECT_ROOT}/package.json" ]]; then
print_error "Ce script doit être exécuté depuis le répertoire ihm_client"
exit 1
fi
# Vérifier que le répertoire cible existe
if [[ ! -d "$TARGET_DIR" ]]; then
print_error "Répertoire cible 4NK_node non trouvé: $TARGET_DIR"
exit 1
fi
# Vérifier que les fichiers d'intégration existent
local required_files=(
"Dockerfile.4nk-node"
"nginx.4nk-node.conf"
"start-4nk-node.sh"
"docker-compose.4nk-node.yml"
)
for file in "${required_files[@]}"; do
if [[ ! -f "${PROJECT_ROOT}/$file" ]]; then
print_error "Fichier requis manquant: $file"
exit 1
fi
done
print_success "Prérequis vérifiés"
}
# Création de la sauvegarde
create_backup() {
if [[ "$BACKUP" == "true" ]]; then
print_info "Création de la sauvegarde..."
local backup_dir="${TARGET_DIR}/backup_$(date +%Y%m%d_%H%M%S)"
if [[ "$DRY_RUN" == "false" ]]; then
mkdir -p "$backup_dir"
cp -r "${TARGET_DIR}/docker-compose.yml" "$backup_dir/" 2>/dev/null || true
cp -r "${TARGET_DIR}/ihm_client" "$backup_dir/" 2>/dev/null || true
print_success "Sauvegarde créée: $backup_dir"
else
print_info "DRY RUN: Sauvegarde serait créée: $backup_dir"
fi
fi
}
# Création du répertoire ihm_client dans 4NK_node
create_ihm_client_directory() {
print_info "Création du répertoire ihm_client dans 4NK_node..."
local ihm_client_dir="${TARGET_DIR}/ihm_client"
if [[ "$DRY_RUN" == "false" ]]; then
mkdir -p "$ihm_client_dir"
print_success "Répertoire créé: $ihm_client_dir"
else
print_info "DRY RUN: Répertoire serait créé: $ihm_client_dir"
fi
}
# Copie des fichiers d'intégration
copy_integration_files() {
print_info "Copie des fichiers d'intégration..."
local files_to_copy=(
"Dockerfile.4nk-node:Dockerfile"
"nginx.4nk-node.conf:nginx.conf"
"start-4nk-node.sh:start.sh"
"package.json:package.json"
"tsconfig.json:tsconfig.json"
"vite.config.ts:vite.config.ts"
"index.html:index.html"
)
for file_mapping in "${files_to_copy[@]}"; do
local source_file=$(echo "$file_mapping" | cut -d: -f1)
local target_file=$(echo "$file_mapping" | cut -d: -f2)
if [[ "$DRY_RUN" == "false" ]]; then
cp "${PROJECT_ROOT}/$source_file" "${TARGET_DIR}/ihm_client/$target_file"
print_success "Copié: $source_file -> ihm_client/$target_file"
else
print_info "DRY RUN: Copié: $source_file -> ihm_client/$target_file"
fi
done
}
# Copie du code source
copy_source_code() {
print_info "Copie du code source..."
local source_dirs=("src" "public")
for dir in "${source_dirs[@]}"; do
if [[ -d "${PROJECT_ROOT}/$dir" ]]; then
if [[ "$DRY_RUN" == "false" ]]; then
cp -r "${PROJECT_ROOT}/$dir" "${TARGET_DIR}/ihm_client/"
print_success "Copié: $dir/"
else
print_info "DRY RUN: Copié: $dir/"
fi
fi
done
}
# Mise à jour du docker-compose.yml
update_docker_compose() {
print_info "Mise à jour du docker-compose.yml..."
local docker_compose_file="${TARGET_DIR}/docker-compose.yml"
local ihm_client_service="
ihm_client:
build:
context: ./ihm_client
dockerfile: Dockerfile
container_name: 4nk-ihm-client
ports:
- \"8080:80\"
environment:
- SDK_RELAY_WS_URL=ws://sdk_relay_1:8090
- SDK_RELAY_HTTP_URL=http://sdk_relay_1:8091
- BITCOIN_RPC_URL=http://bitcoin:18443
- BLINDBIT_URL=http://blindbit:8000
volumes:
- ihm_client_logs:/var/log/nginx
networks:
- btcnet
depends_on:
- sdk_relay_1
- sdk_relay_2
- sdk_relay_3
restart: unless-stopped
healthcheck:
test: [\"CMD\", \"wget\", \"--quiet\", \"--tries=1\", \"--timeout=5\", \"--spider\", \"http://localhost\"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s"
if [[ "$DRY_RUN" == "false" ]]; then
# Vérifier si le service existe déjà
if grep -q "ihm_client:" "$docker_compose_file" 2>/dev/null; then
print_warning "Service ihm_client existe déjà dans docker-compose.yml"
else
# Ajouter le service avant la section volumes
sed -i "/^volumes:/i\\$ihm_client_service" "$docker_compose_file"
# Ajouter les volumes ihm_client
sed -i '/^volumes:/a\ ihm_client_logs:\n driver: local' "$docker_compose_file"
print_success "Service ihm_client ajouté au docker-compose.yml"
fi
else
print_info "DRY RUN: Service ihm_client serait ajouté au docker-compose.yml"
fi
}
# Création du script de démarrage
create_startup_script() {
print_info "Création du script de démarrage..."
local startup_script="${TARGET_DIR}/start-ihm-client.sh"
if [[ "$DRY_RUN" == "false" ]]; then
cat > "$startup_script" << 'EOF'
#!/bin/bash
set -e
echo "🚀 Démarrage de l'interface utilisateur 4NK..."
# Vérifier que nous sommes dans le bon répertoire
if [[ ! -f "docker-compose.yml" ]]; then
echo "❌ Ce script doit être exécuté depuis le répertoire 4NK_node"
exit 1
fi
# Démarrer uniquement le service ihm_client
echo "📦 Démarrage du service ihm_client..."
docker-compose up -d ihm_client
# Attendre que le service soit prêt
echo "⏳ Attente du démarrage..."
sleep 10
# Vérifier la santé du service
if docker-compose ps ihm_client | grep -q "Up"; then
echo "✅ Interface utilisateur démarrée avec succès"
echo " 📍 URL: http://localhost:8080"
echo " 🔍 Logs: docker logs 4nk-ihm-client"
else
echo "❌ Échec du démarrage de l'interface utilisateur"
docker-compose logs ihm_client
exit 1
fi
EOF
chmod +x "$startup_script"
print_success "Script de démarrage créé: $startup_script"
else
print_info "DRY RUN: Script de démarrage serait créé: $startup_script"
fi
}
# Validation de l'intégration
validate_integration() {
print_info "Validation de l'intégration..."
local validation_files=(
"${TARGET_DIR}/ihm_client/Dockerfile"
"${TARGET_DIR}/ihm_client/nginx.conf"
"${TARGET_DIR}/ihm_client/start.sh"
"${TARGET_DIR}/docker-compose.yml"
)
for file in "${validation_files[@]}"; do
if [[ -f "$file" ]]; then
print_success "Validé: $(basename "$file")"
else
print_error "Fichier manquant: $(basename "$file")"
return 1
fi
done
print_success "Validation terminée"
}
# Fonction principale
main() {
echo "🔧 Intégration de ihm_client dans 4NK_node"
echo " Source: $PROJECT_ROOT"
echo " Cible: $TARGET_DIR"
echo " Mode: $([ "$DRY_RUN" == "true" ] && echo "DRY RUN" || echo "EXÉCUTION")"
echo ""
check_prerequisites
create_backup
create_ihm_client_directory
copy_integration_files
copy_source_code
update_docker_compose
create_startup_script
if [[ "$DRY_RUN" == "false" ]]; then
validate_integration
echo ""
print_success "Intégration terminée avec succès !"
echo ""
echo "📋 Prochaines étapes:"
echo " 1. Aller dans le répertoire 4NK_node: cd $TARGET_DIR"
echo " 2. Démarrer l'interface: ./start-ihm-client.sh"
echo " 3. Ou redémarrer tout: ./restart_4nk_node.sh"
echo " 4. Accéder à l'interface: http://localhost:8080"
else
echo ""
print_success "Simulation terminée - Aucune modification effectuée"
fi
}
# Exécution
main "$@"

View File

@ -1,51 +0,0 @@
#!/usr/bin/env sh
set -eu
echo "[ihm_client] Préparation des dépendances wasm (pkg/sdk_client)"
PKG_DIR="$(pwd)/pkg"
if [ -d "$PKG_DIR" ] && [ -f "$PKG_DIR/sdk_client.js" ]; then
echo "[ihm_client] pkg déjà présent, rien à faire."
exit 0
fi
# Sources possibles (priorité: URL tarball > tarball local > base RAW)
SDK_URL="${SDK_CLIENT_PKG_URL:-}"
SDK_TARBALL="${SDK_CLIENT_PKG_TARBALL:-}"
# Par défaut, on pointe vers la branche docker-support du repo public
SDK_BASE="${SDK_CLIENT_PKG_BASE:-https://git.4nkweb.com/4nk/ihm_client/raw/branch/docker-support/pkg}"
mkdir -p "$PKG_DIR"
if [ -n "$SDK_URL" ]; then
echo "[ihm_client] Téléchargement depuis SDK_CLIENT_PKG_URL=$SDK_URL"
TMP_TGZ="/tmp/sdk_client_pkg.tgz"
curl -fsSL "$SDK_URL" -o "$TMP_TGZ"
tar -xzf "$TMP_TGZ" -C "$PKG_DIR" --strip-components=1 || tar -xzf "$TMP_TGZ" -C "$PKG_DIR" || true
rm -f "$TMP_TGZ"
elif [ -n "$SDK_TARBALL" ] && [ -f "$SDK_TARBALL" ]; then
echo "[ihm_client] Extraction du tarball local $SDK_TARBALL"
tar -xzf "$SDK_TARBALL" -C "$PKG_DIR" --strip-components=1 || tar -xzf "$SDK_TARBALL" -C "$PKG_DIR" || true
elif [ -n "$SDK_BASE" ]; then
echo "[ihm_client] Téléchargement des fichiers depuis SDK_CLIENT_PKG_BASE=$SDK_BASE (branche docker-support)"
# Liste des fichiers nécessaires issus de wasm-pack
for f in \
sdk_client.js \
sdk_client_bg.wasm \
sdk_client.d.ts \
sdk_client_bg.js \
sdk_client_bg.wasm.d.ts \
package.json \
README.md; do
echo " - $f"
curl -fsSL "$SDK_BASE/$f" -o "$PKG_DIR/$f"
done
else
echo "[ERREUR] pkg/sdk_client absent et aucune source fournie."
echo "Définissez SDK_CLIENT_PKG_URL (tar.gz), SDK_CLIENT_PKG_BASE (URL raw du dossier pkg) ou montez un tarball local via SDK_CLIENT_PKG_TARBALL."
exit 2
fi
test -f "$PKG_DIR/sdk_client.js" || { echo "[ERREUR] pkg/sdk_client.js introuvable après extraction"; exit 3; }
echo "[ihm_client] Dépendance wasm prête."

View File

@ -1,79 +0,0 @@
#!/bin/bash
# Script de configuration SSH pour CI/CD ihm_client
# Utilise automatiquement la clé SSH pour les opérations Git
set -e
echo "🔑 Configuration automatique de la clé SSH pour ihm_client CI/CD..."
# Vérifier si on est dans un environnement CI
if [ -n "$CI" ]; then
echo "✅ Environnement CI détecté"
# Configuration SSH pour Gitea Actions
if [ -n "$SSH_PRIVATE_KEY" ]; then
echo "🔐 Configuration de la clé SSH privée..."
# Créer le répertoire SSH
mkdir -p ~/.ssh
chmod 700 ~/.ssh
# Écrire la clé privée
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
# Ajouter la clé publique correspondante (si disponible)
if [ -n "$SSH_PUBLIC_KEY" ]; then
echo "$SSH_PUBLIC_KEY" > ~/.ssh/id_rsa.pub
chmod 644 ~/.ssh/id_rsa.pub
fi
# Configuration SSH pour git.4nkweb.com
cat > ~/.ssh/config << EOF
Host git.4nkweb.com
HostName git.4nkweb.com
User git
IdentityFile ~/.ssh/id_rsa
StrictHostKeyChecking no
UserKnownHostsFile=/dev/null
EOF
chmod 600 ~/.ssh/config
# Tester la connexion SSH
echo "🧪 Test de connexion SSH vers git.4nkweb.com..."
if ssh -T git@git.4nkweb.com 2>&1 | grep -q "Welcome"; then
echo "✅ Connexion SSH réussie"
else
echo "⚠️ Connexion SSH établie (message de bienvenue non détecté)"
fi
# Configurer Git pour utiliser SSH
git config --global url."git@git.4nkweb.com:".insteadOf "https://git.4nkweb.com/"
echo "✅ Configuration SSH terminée"
else
echo "⚠️ Variable SSH_PRIVATE_KEY non définie, utilisation de HTTPS"
fi
else
echo " Environnement local détecté"
# Vérifier si une clé SSH existe
if [ -f ~/.ssh/id_rsa ]; then
echo "🔑 Clé SSH locale trouvée"
# Configurer Git pour utiliser SSH localement
git config --global url."git@git.4nkweb.com:".insteadOf "https://git.4nkweb.com/"
echo "✅ Configuration SSH locale terminée"
else
echo "⚠️ Aucune clé SSH trouvée, configuration manuelle requise"
echo "💡 Pour configurer SSH manuellement :"
echo " 1. Générer une clé SSH : ssh-keygen -t rsa -b 4096"
echo " 2. Ajouter la clé publique à votre compte Gitea"
echo " 3. Tester : ssh -T git@git.4nkweb.com"
fi
fi
echo "🎯 Configuration SSH terminée pour ihm_client"

View File

@ -815,4 +815,4 @@ select[data-multi-select-plugin] {
.custom-select::-webkit-scrollbar-thumb:hover { .custom-select::-webkit-scrollbar-thumb:hover {
background: #555; background: #555;
} }

View File

@ -9,7 +9,7 @@ let notifications = [];
export async function unpair() { export async function unpair() {
const service = await Services.getInstance(); const service = await Services.getInstance();
await service.unpairDevice(); await service.unpairDevice();
await navigate('home'); navigate('home');
} }
(window as any).unpair = unpair; (window as any).unpair = unpair;
@ -28,7 +28,7 @@ function toggleMenu() {
async function getNotifications() { async function getNotifications() {
const service = await Services.getInstance(); const service = await Services.getInstance();
notifications = service.getNotifications() || []; notifications = service.getNotifications();
return notifications; return notifications;
} }
function openCloseNotifications() { function openCloseNotifications() {
@ -102,8 +102,8 @@ async function setNotification(notifications: any[]): Promise<void> {
async function fetchNotifications() { async function fetchNotifications() {
const service = await Services.getInstance(); const service = await Services.getInstance();
const data = service.getNotifications() || []; const data = service.getNotifications();
await setNotification(data); setNotification(data);
} }
async function loadUserProfile() { async function loadUserProfile() {
@ -158,18 +158,18 @@ async function createBackUp() {
const service = await Services.getInstance(); const service = await Services.getInstance();
const backUp = await service.createBackUp(); const backUp = await service.createBackUp();
if (!backUp) { if (!backUp) {
console.error('No device to backup'); console.error("No device to backup");
return; return;
} }
try { try {
const backUpJson = JSON.stringify(backUp, null, 2); const backUpJson = JSON.stringify(backUp, null, 2)
const blob = new Blob([backUpJson], { type: 'application/json' }); const blob = new Blob([backUpJson], { type: 'application/json' });
const url = URL.createObjectURL(blob); const url = URL.createObjectURL(blob);
const a = document.createElement('a'); const a = document.createElement('a');
a.href = url; a.href = url;
a.download = '4nk-backup.json'; a.download = '4nk-backup.json';
a.click(); a.click();
URL.revokeObjectURL(url); URL.revokeObjectURL(url);
@ -201,14 +201,15 @@ async function disconnect() {
}); });
const registrations = await navigator.serviceWorker.getRegistrations(); const registrations = await navigator.serviceWorker.getRegistrations();
await Promise.all(registrations.map((registration) => registration.unregister())); await Promise.all(registrations.map(registration => registration.unregister()));
console.log('Service worker unregistered'); console.log('Service worker unregistered');
await navigate('home'); navigate('home');
setTimeout(() => { setTimeout(() => {
window.location.href = window.location.origin; window.location.href = window.location.origin;
}, 100); }, 100);
} catch (error) { } catch (error) {
console.error('Error during disconnect:', error); console.error('Error during disconnect:', error);
// force reload // force reload
@ -216,4 +217,4 @@ async function disconnect() {
} }
} }
(window as any).disconnect = disconnect; (window as any).disconnect = disconnect;

View File

@ -1,9 +1,9 @@
import ModalService from '../../services/modal.service'; import ModalService from '../../services/modal.service';
const modalService = await ModalService.getInstance(); const modalService = await ModalService.getInstance();
// export async function confirm() { export async function confirm() {
// modalService.confirmPairing(); modalService.confirmPairing();
// } }
export async function closeConfirmationModal() { export async function closeConfirmationModal() {
modalService.closeConfirmationModal(); modalService.closeConfirmationModal();

View File

@ -1,14 +1,14 @@
<div id="creation-modal" class="modal"> <div id="creation-modal" class="modal">
<div class="modal-content"> <div class="modal-content">
<div class="modal-title">Login</div> <div class="modal-title">Login</div>
<div class="message"> <div class="message">
Do you want to create a 4NK member?<br /> Do you want to create a 4NK member?<br />
Attempting to create a member with address <br /> Attempting to create a member with address <br />
<strong>{{device1}}</strong> <br /> <strong>{{device1}}</strong> <br />
</div>
<div class="confirmation-box">
<a class="btn confirmation-btn" onclick="confirm()">Confirm</a>
<a class="btn refusal-btn" onclick="closeConfirmationModal()">Refuse</a>
</div>
</div> </div>
<div class="confirmation-box"> </div>
<a class="btn confirmation-btn" onclick="confirm()">Confirm</a>
<a class="btn refusal-btn" onclick="closeConfirmationModal()">Refuse</a>
</div>
</div>
</div>

View File

@ -1,6 +1,8 @@
<div id="waiting-modal" class="modal"> <div id="waiting-modal" class="modal">
<div class="modal-content"> <div class="modal-content">
<div class="modal-title">Login</div> <div class="modal-title">Login</div>
<div class="message">Waiting for Device 2...</div> <div class="message">
</div> Waiting for Device 2...
</div> </div>
</div>
</div>

View File

@ -55,7 +55,7 @@ export default class QrScannerComponent extends HTMLElement {
if (spAddress) { if (spAddress) {
// Call the sendPairingTx function with the extracted sp_address // Call the sendPairingTx function with the extracted sp_address
try { try {
await prepareAndSendPairingTx(); await prepareAndSendPairingTx(spAddress);
} catch (e) { } catch (e) {
console.error('Failed to pair:', e); console.error('Failed to pair:', e);
} }

View File

@ -1,7 +1,9 @@
<div id="validation-modal" class="validation-modal"> <div id="validation-modal" class="validation-modal">
<div class="modal-content"> <div class="modal-content">
<div class="modal-title">Validate Process {{processId}}</div> <div class="modal-title">Validate Process {{processId}}</div>
<div class="validation-box"></div> <div class="validation-box">
</div>
<div class="modal-action"> <div class="modal-action">
<button onclick="validate()">Validate</button> <button onclick="validate()">Validate</button>
</div> </div>

View File

@ -7,11 +7,11 @@ async function validate() {
} }
export async function initValidationModal(processDiffs: any) { export async function initValidationModal(processDiffs: any) {
console.log('🚀 ~ initValidationModal ~ processDiffs:', processDiffs); console.log("🚀 ~ initValidationModal ~ processDiffs:", processDiffs)
for (const diff of processDiffs.diffs) { for(const diff of processDiffs.diffs) {
let diffs = ''; let diffs = ''
for (const value of diff) { for(const value of diff) {
diffs += ` diffs+= `
<div class="radio-buttons"> <div class="radio-buttons">
<label> <label>
<input type="radio" name="validation1" value="old" /> <input type="radio" name="validation1" value="old" />
@ -30,27 +30,27 @@ export async function initValidationModal(processDiffs: any) {
<pre>+${value.new_value}</pre> <pre>+${value.new_value}</pre>
</div> </div>
</div> </div>
`; `
} }
const state = ` const state = `
<div class="expansion-panel"> <div class="expansion-panel">
<div class="expansion-panel-header">State ${diff[0].new_state_merkle_root}</div> <div class="expansion-panel-header">State ${diff[0].new_state_merkle_root}</div>
<div class="expansion-panel-body"> <div class="expansion-panel-body">
${diffs} ${diffs}
</div> </div>
</div> </div>
`; `
const box = document.querySelector('.validation-box'); const box = document.querySelector('.validation-box')
if (box) box.innerHTML += state; if(box) box.innerHTML += state
} }
document.querySelectorAll('.expansion-panel-header').forEach((header) => { document.querySelectorAll('.expansion-panel-header').forEach((header) => {
header.addEventListener('click', function (event) { header.addEventListener('click', function (event) {
const target = event.target as HTMLElement; const target = event.target as HTMLElement;
const body = target.nextElementSibling as HTMLElement; const body = target.nextElementSibling as HTMLElement;
if (body?.style) body.style.display = body.style.display === 'block' ? 'none' : 'block'; if (body?.style) body.style.display = body.style.display === 'block' ? 'none' : 'block';
});
}); });
});
} }
(window as any).validate = validate; (window as any).validate = validate;

View File

@ -1,25 +0,0 @@
<div id="validation-rule-modal" style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); display: none; justify-content: center; align-items: center; z-index: 9999">
<div style="background: white; padding: 2rem; border-radius: 0.5rem; width: 400px; max-width: 90%; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3)">
<h2 style="font-size: 1.2rem; font-weight: bold; margin-bottom: 1rem">Add Validation Rule</h2>
<label style="display: block; margin-bottom: 0.5rem">
Quorum:
<input id="vr-quorum" type="number" style="width: 100%; padding: 0.5rem; margin-top: 0.25rem" />
</label>
<label style="display: block; margin-bottom: 0.5rem">
Min Sig Member:
<input id="vr-minsig" type="number" style="width: 100%; padding: 0.5rem; margin-top: 0.25rem" />
</label>
<label style="display: block; margin-bottom: 1rem">
Fields (comma-separated):
<input id="vr-fields" type="text" placeholder="e.g. field1, field2" style="width: 100%; padding: 0.5rem; margin-top: 0.25rem" />
</label>
<div style="display: flex; justify-content: flex-end; gap: 1rem">
<button id="vr-cancel" style="padding: 0.5rem 1rem">Cancel</button>
<button id="vr-submit" style="padding: 0.5rem 1rem; background-color: #4f46e5; color: white; border: none; border-radius: 0.375rem">Add</button>
</div>
</div>
</div>

View File

@ -1,64 +0,0 @@
export interface ValidationRule {
quorum: number;
fields: string[];
min_sig_member: number;
}
/**
* Loads and injects the modal HTML into the document if not already loaded.
*/
export async function loadValidationRuleModal(templatePath: string = '/src/components/validation-rule-modal/validation-rule-modal.html') {
if (document.getElementById('validation-rule-modal')) return;
const res = await fetch(templatePath);
const html = await res.text();
const tempDiv = document.createElement('div');
tempDiv.innerHTML = html;
const modal = tempDiv.querySelector('#validation-rule-modal');
if (!modal) {
throw new Error('Modal HTML missing #validation-rule-modal');
}
document.body.appendChild(modal);
}
/**
* Opens the modal and lets the user input a ValidationRule.
* Calls the callback with the constructed rule on submit.
*/
export function showValidationRuleModal(onSubmit: (rule: ValidationRule) => void) {
const modal = document.getElementById('validation-rule-modal')!;
const quorumInput = document.getElementById('vr-quorum') as HTMLInputElement;
const minsigInput = document.getElementById('vr-minsig') as HTMLInputElement;
const fieldsInput = document.getElementById('vr-fields') as HTMLInputElement;
const cancelBtn = document.getElementById('vr-cancel')!;
const submitBtn = document.getElementById('vr-submit')!;
// Reset values
quorumInput.value = '';
minsigInput.value = '';
fieldsInput.value = '';
modal.style.display = 'flex';
cancelBtn.onclick = () => {
modal.style.display = 'none';
};
submitBtn.onclick = () => {
const rule: ValidationRule = {
quorum: parseInt(quorumInput.value),
min_sig_member: parseInt(minsigInput.value),
fields: fieldsInput.value
.split(',')
.map((f) => f.trim())
.filter(Boolean),
};
modal.style.display = 'none';
onSubmit(rule);
};
}

View File

@ -1,3 +1,39 @@
export { default as Services } from './services/service'; // import Services from './services/service';
export { default as Database } from './services/database.service';
export { MessageType } from './models/process.model'; // document.addEventListener('DOMContentLoaded', async () => {
// try {
// const services = await Services.getInstance();
// setTimeout( async () => {
// let device = await services.getDevice()
// console.log("🚀 ~ setTimeout ~ device:", device)
// if(!device) {
// device = await services.createNewDevice();
// } else {
// await services.restoreDevice(device)
// }
// await services.restoreProcesses();
// await services.restoreMessages();
// const amount = await services.getAmount();
// if (amount === 0n) {
// const faucetMsg = await services.createFaucetMessage();
// await services.sendFaucetMessage(faucetMsg);
// }
// if (services.isPaired()) { await services.injectProcessListPage() }
// else {
// const queryString = window.location.search;
// const urlParams = new URLSearchParams(queryString)
// const pairingAddress = urlParams.get('sp_address')
// if(pairingAddress) {
// setTimeout(async () => await services.sendPairingTx(pairingAddress), 2000)
// }
// }
// }, 500);
// } catch (error) {
// console.error(error);
// }
// });

View File

@ -1,15 +1,18 @@
/*import { ChatComponent } from './pages/chat/chat-component'; import { SignatureComponent } from './pages/signature/signature-component';
import { ChatElement } from './pages/chat/chat';*/ import { SignatureElement } from './pages/signature/signature';
import { ChatComponent } from './pages/chat/chat-component';
import { ChatElement } from './pages/chat/chat';
import { AccountComponent } from './pages/account/account-component'; import { AccountComponent } from './pages/account/account-component';
import { AccountElement } from './pages/account/account'; import { AccountElement } from './pages/account/account';
export { AccountComponent, AccountElement }; export { SignatureComponent, SignatureElement, ChatComponent, ChatElement, AccountComponent, AccountElement };
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
// Signatures supprimées 'signature-component': SignatureComponent;
/*'chat-component': ChatComponent; 'signature-element': SignatureElement;
'chat-element': ChatElement;*/ 'chat-component': ChatComponent;
'chat-element': ChatElement;
'account-component': AccountComponent; 'account-component': AccountComponent;
'account-element': AccountElement; 'account-element': AccountElement;
} }
@ -18,9 +21,10 @@ declare global {
// Configuration pour le mode indépendant // Configuration pour le mode indépendant
if ((import.meta as any).env.VITE_IS_INDEPENDANT_LIB) { if ((import.meta as any).env.VITE_IS_INDEPENDANT_LIB) {
// Initialiser les composants si nécessaire // Initialiser les composants si nécessaire
// Signatures supprimées customElements.define('signature-component', SignatureComponent);
/*customElements.define('chat-component', ChatComponent); customElements.define('signature-element', SignatureElement);
customElements.define('chat-element', ChatElement);*/ customElements.define('chat-component', ChatComponent);
customElements.define('chat-element', ChatElement);
customElements.define('account-component', AccountComponent); customElements.define('account-component', AccountComponent);
customElements.define('account-element', AccountElement); customElements.define('account-element', AccountElement);
} }

View File

@ -1,7 +1,7 @@
import { Device, Process, SecretsStore } from 'pkg/sdk_client'; import { Device, Process, SecretsStore } from "pkg/sdk_client";
export interface BackUp { export interface BackUp {
device: Device; device: Device,
secrets: SecretsStore; secrets: SecretsStore,
processes: Record<string, Process>; processes: Record<string, Process>,
} }

View File

@ -21,45 +21,3 @@ export interface INotification {
sendToNotificationPage?: boolean; sendToNotificationPage?: boolean;
path?: string; path?: string;
} }
export enum MessageType {
// Establish connection and keep alive
LISTENING = 'LISTENING',
REQUEST_LINK = 'REQUEST_LINK',
LINK_ACCEPTED = 'LINK_ACCEPTED',
CREATE_PAIRING = 'CREATE_PAIRING',
PAIRING_CREATED = 'PAIRING_CREATED',
ERROR = 'ERROR',
VALIDATE_TOKEN = 'VALIDATE_TOKEN',
RENEW_TOKEN = 'RENEW_TOKEN',
// Get various information
GET_PAIRING_ID = 'GET_PAIRING_ID',
GET_PROCESSES = 'GET_PROCESSES',
GET_MY_PROCESSES = 'GET_MY_PROCESSES',
PROCESSES_RETRIEVED = 'PROCESSES_RETRIEVED',
RETRIEVE_DATA = 'RETRIEVE_DATA',
DATA_RETRIEVED = 'DATA_RETRIEVED',
DECODE_PUBLIC_DATA = 'DECODE_PUBLIC_DATA',
PUBLIC_DATA_DECODED = 'PUBLIC_DATA_DECODED',
GET_MEMBER_ADDRESSES = 'GET_MEMBER_ADDRESSES',
MEMBER_ADDRESSES_RETRIEVED = 'MEMBER_ADDRESSES_RETRIEVED',
// Processes
CREATE_PROCESS = 'CREATE_PROCESS',
PROCESS_CREATED = 'PROCESS_CREATED',
UPDATE_PROCESS = 'UPDATE_PROCESS',
PROCESS_UPDATED = 'PROCESS_UPDATED',
NOTIFY_UPDATE = 'NOTIFY_UPDATE',
UPDATE_NOTIFIED = 'UPDATE_NOTIFIED',
VALIDATE_STATE = 'VALIDATE_STATE',
STATE_VALIDATED = 'STATE_VALIDATED',
// Hash and merkle proof
HASH_VALUE = 'HASH_VALUE',
VALUE_HASHED = 'VALUE_HASHED',
GET_MERKLE_PROOF = 'GET_MERKLE_PROOF',
MERKLE_PROOF_RETRIEVED = 'MERKLE_PROOF_RETRIEVED',
VALIDATE_MERKLE_PROOF = 'VALIDATE_MERKLE_PROOF',
MERKLE_PROOF_VALIDATED = 'MERKLE_PROOF_VALIDATED',
// Account management
ADD_DEVICE = 'ADD_DEVICE',
DEVICE_ADDED = 'DEVICE_ADDED',
}

View File

@ -1,10 +1,10 @@
<!doctype html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<title>Account</title> <title>Account</title>
</head> </head>
<body> <body>
<account-component></account-component> <account-component></account-component>
<script type="module" src="./account.ts"></script> <script type="module" src="./account.ts"></script>
</body> </body>
</html> </html>

File diff suppressed because it is too large Load Diff

View File

@ -1,310 +0,0 @@
import type { ProcessState } from '../../../pkg/sdk_client';
import Services from '../../services/service';
interface State {
file: File | null;
fileHash: string | null;
certificate: ProcessState | null;
commitmentHashes: string[];
}
export interface Vin {
txid: string; // The txid of the previous transaction (being spent)
vout: number; // The output index in the previous tx
prevout: {
scriptpubkey: string;
scriptpubkey_asm: string;
scriptpubkey_type: string;
scriptpubkey_address: string;
value: number;
};
scriptsig: string;
scriptsig_asm: string;
witness: string[];
is_coinbase: boolean;
sequence: number;
}
export interface TransactionInfo {
txid: string;
version: number;
locktime: number;
vin: Vin[];
vout: any[];
size: number;
weight: number;
fee: number;
status: {
confirmed: boolean;
block_height: number;
block_hash: string;
block_time: number;
};
}
export function getDocumentValidation(container: HTMLElement) {
const state: State = {
file: null,
fileHash: null,
certificate: null,
commitmentHashes: [],
};
container.innerHTML = '';
container.style.cssText = `
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-height: 100vh;
gap: 2rem;
`;
function createDropButton(label: string, onDrop: (file: File, updateVisuals: (file: File) => void) => void, accept: string = '*/*'): HTMLElement {
const wrapper = document.createElement('div');
wrapper.style.cssText = `
width: 200px;
height: 100px;
border: 2px dashed #888;
border-radius: 8px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
font-weight: bold;
background: #f8f8f8;
text-align: center;
padding: 0.5rem;
box-sizing: border-box;
`;
const title = document.createElement('div');
title.textContent = label;
const filename = document.createElement('div');
filename.style.cssText = `
font-size: 0.85rem;
margin-top: 0.5rem;
color: #444;
word-break: break-word;
text-align: center;
`;
wrapper.appendChild(title);
wrapper.appendChild(filename);
const updateVisuals = (file: File) => {
wrapper.style.borderColor = 'green';
wrapper.style.background = '#e6ffed';
filename.textContent = file.name;
};
// === Hidden file input ===
const fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.accept = accept;
fileInput.style.display = 'none';
document.body.appendChild(fileInput);
fileInput.onchange = () => {
const file = fileInput.files?.[0];
if (file) {
onDrop(file, updateVisuals);
fileInput.value = ''; // reset so same file can be re-selected
}
};
// === Handle drag-and-drop ===
wrapper.ondragover = (e) => {
e.preventDefault();
wrapper.style.background = '#e0e0e0';
};
wrapper.ondragleave = () => {
wrapper.style.background = '#f8f8f8';
};
wrapper.ondrop = (e) => {
e.preventDefault();
wrapper.style.background = '#f8f8f8';
const file = e.dataTransfer?.files?.[0];
if (file) {
onDrop(file, updateVisuals);
}
};
// === Handle click to open file manager ===
wrapper.onclick = () => {
fileInput.click();
};
return wrapper;
}
const fileDropButton = createDropButton('Drop file', async (file, updateVisuals) => {
try {
state.file = file;
updateVisuals(file);
console.log('Loaded file:', state.file);
checkReady();
} catch (err) {
alert('Failed to drop the file.');
console.error(err);
}
});
const certDropButton = createDropButton('Drop certificate', async (file, updateVisuals) => {
try {
const text = await file.text();
const json = JSON.parse(text);
if (typeof json === 'object' && json !== null && typeof json.pcd_commitment === 'object' && typeof json.state_id === 'string') {
state.certificate = json as ProcessState;
state.commitmentHashes = Object.values(json.pcd_commitment).map((h: any) => (h as string).toLowerCase());
updateVisuals(file);
console.log('Loaded certificate, extracted hashes:', state.commitmentHashes);
checkReady();
} else {
alert('Invalid certificate structure.');
}
} catch (err) {
alert('Failed to parse certificate JSON.');
console.error(err);
}
});
const buttonRow = document.createElement('div');
buttonRow.style.display = 'flex';
buttonRow.style.gap = '2rem';
buttonRow.appendChild(fileDropButton);
buttonRow.appendChild(certDropButton);
container.appendChild(buttonRow);
async function checkReady() {
if (state.file && state.certificate && state.commitmentHashes.length > 0) {
// We take the commited_in and all pcd_commitment keys to reconstruct all the possible hash
const fileBlob = {
type: state.file.type,
data: new Uint8Array(await state.file.arrayBuffer()),
};
const service = await Services.getInstance();
const commitedIn = state.certificate.commited_in;
if (!commitedIn) return;
const [prevTxid, prevTxVout] = commitedIn.split(':');
const processId = state.certificate.commited_in;
const stateId = state.certificate.state_id;
const process = await service.getProcess(processId);
if (!process) return;
// Get the transaction that comes right after the commited_in
const nextState = service.getNextStateAfterId(process, stateId);
if (!nextState) {
alert(`❌ Validation failed: No next state, is the state you're trying to validate commited?`);
return;
}
const [outspentTxId, _] = nextState.commited_in.split(':');
console.log(outspentTxId);
// Check that the commitment transaction exists, and that it commits to the state id
const txInfo = await fetchTransaction(outspentTxId);
if (!txInfo) {
console.error(`Validation error: Can't fetch new state commitment transaction`);
alert(`❌ Validation failed: invalid or non existent commited_in for state ${stateId}.`);
return;
}
// We must check that this transaction indeed spend the commited_in we have in the certificate
let found = false;
for (const vin of txInfo.vin) {
if (vin.txid === prevTxid) {
found = true;
break;
}
}
if (!found) {
console.error(`Validation error: new state doesn't spend previous state commitment transaction`);
alert('❌ Validation failed: Unconsistent commitment transactions history.');
return;
}
// set found back to false for next check
found = false;
// is the state_id commited in the transaction?
for (const vout of txInfo.vout) {
console.log(vout);
if (vout.scriptpubkey_type && vout.scriptpubkey_type === 'op_return') {
found = true;
} else {
continue;
}
if (vout.scriptpubkey_asm) {
const hash = extractHexFromScriptAsm(vout.scriptpubkey_asm);
if (hash) {
if (hash !== stateId) {
console.error(`Validation error: expected stateId ${stateId}, got ${hash}`);
alert('❌ Validation failed: Transaction does not commit to that state.');
return;
}
}
}
}
if (!found) {
alert('❌ Validation failed: Transaction does not contain data.');
return;
}
// set found back to false for next check
found = false;
for (const label of Object.keys(state.certificate.pcd_commitment)) {
// Compute the hash for this label
console.log(`Computing hash with label ${label}`);
const fileHex = service.getHashForFile(commitedIn, label, fileBlob);
console.log(`Found hash ${fileHex}`);
found = state.commitmentHashes.includes(fileHex);
if (found) break;
}
if (found) {
alert('✅ Validation successful: file hash found in pcd_commitment.');
} else {
alert('❌ Validation failed: file hash NOT found in pcd_commitment.');
}
}
}
async function fetchTransaction(txid: string): Promise<TransactionInfo> {
const url = `https://mempool.4nkweb.com/api/tx/${txid}`;
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to fetch outspend status: ${response.statusText}`);
}
const outspend: TransactionInfo = await response.json();
return outspend;
}
function extractHexFromScriptAsm(scriptAsm: string): string | null {
const parts = scriptAsm.trim().split(/\s+/);
const last = parts[parts.length - 1];
// Basic validation: must be 64-char hex (32 bytes)
if (/^[0-9a-fA-F]{64}$/.test(last)) {
return last.toLowerCase();
}
return null;
}
}

View File

@ -1,202 +0,0 @@
import type { ValidationRule, RoleDefinition } from '../../../pkg/sdk_client';
import { showValidationRuleModal } from '../../components/validation-rule-modal/validation-rule-modal';
export function createKeyValueSection(title: string, id: string, isRoleSection = false) {
const section = document.createElement('div');
section.id = id;
section.style.cssText = 'margin-bottom: 2rem; background: #fff; padding: 1rem; border-radius: 0.5rem; box-shadow: 0 1px 3px rgba(0,0,0,0.1);';
const titleEl = document.createElement('h2');
titleEl.textContent = title;
titleEl.style.cssText = 'font-size: 1.25rem; font-weight: bold; margin-bottom: 1rem;';
section.appendChild(titleEl);
const rowContainer = document.createElement('div');
section.appendChild(rowContainer);
const addBtn = document.createElement('button');
addBtn.textContent = '+ Add Row';
addBtn.style.cssText = `
margin-top: 1rem;
padding: 0.5rem 1rem;
border: 1px solid #888;
border-radius: 0.375rem;
background-color: #f9f9f9;
cursor: pointer;
`;
section.appendChild(addBtn);
const roleRowStates: {
roleNameInput: HTMLInputElement;
membersInput: HTMLInputElement;
storagesInput: HTMLInputElement;
validationRules: ValidationRule[];
}[] = [];
type fileBlob = {
type: string;
data: Uint8Array;
};
const nonRoleRowStates: {
keyInput: HTMLInputElement;
valueInput: HTMLInputElement;
fileInput: HTMLInputElement;
fileBlob: fileBlob | null;
}[] = [];
const inputStyle = 'flex: 1; height: 2.5rem; padding: 0.5rem; border: 1px solid #ccc; border-radius: 0.375rem;';
const createRow = () => {
const row = document.createElement('div');
row.style.cssText = 'display: flex; gap: 1rem; margin-bottom: 0.5rem; align-items: center;';
const deleteBtn = document.createElement('button');
deleteBtn.textContent = '🗑️';
deleteBtn.style.cssText = 'background: none; border: none; font-size: 1.2rem; cursor: pointer;';
deleteBtn.onclick = () => {
row.remove();
updateDeleteButtons();
};
if (isRoleSection) {
const roleName = document.createElement('input');
const members = document.createElement('input');
const storages = document.createElement('input');
roleName.placeholder = 'Role name';
members.placeholder = 'members';
storages.placeholder = 'storages';
[roleName, members, storages].forEach((input) => {
input.type = 'text';
input.style.cssText = inputStyle;
});
const ruleButton = document.createElement('button');
ruleButton.textContent = 'Add Validation Rule';
ruleButton.style.cssText = 'padding: 0.3rem 0.75rem; border: 1px solid #ccc; border-radius: 0.375rem; background: #f0f0f0; cursor: pointer;';
const rules: ValidationRule[] = [];
ruleButton.onclick = () => {
showValidationRuleModal((rule) => {
rules.push(rule);
ruleButton.textContent = `Rules (${rules.length})`;
});
};
row.appendChild(roleName);
row.appendChild(members);
row.appendChild(storages);
row.appendChild(ruleButton);
row.appendChild(deleteBtn);
roleRowStates.push({ roleNameInput: roleName, membersInput: members, storagesInput: storages, validationRules: rules });
} else {
const fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.style.display = 'none';
fileInput.onchange = async () => {
const file = fileInput.files?.[0];
if (!file) return;
const buffer = await file.arrayBuffer();
const uint8 = new Uint8Array(buffer);
rowState.fileBlob = {
type: file.type,
data: uint8,
};
valueInput.value = `📄 ${file.name}`;
valueInput.disabled = true;
attachBtn.textContent = `📎 ${file.name}`;
};
const attachBtn = document.createElement('button');
attachBtn.textContent = '📎 Attach';
attachBtn.style.cssText = 'padding: 0.3rem 0.75rem; border: 1px solid #ccc; border-radius: 0.375rem; background: #f0f0f0; cursor: pointer;';
attachBtn.onclick = () => fileInput.click();
const keyInput = document.createElement('input');
const valueInput = document.createElement('input');
const rowState = {
keyInput,
valueInput,
fileInput,
fileBlob: null as fileBlob | null,
};
nonRoleRowStates.push(rowState);
keyInput.placeholder = 'Key';
valueInput.placeholder = 'Value';
[keyInput, valueInput].forEach((input) => {
input.type = 'text';
input.style.cssText = inputStyle;
});
row.appendChild(keyInput);
row.appendChild(valueInput);
row.appendChild(attachBtn);
row.appendChild(fileInput);
row.appendChild(deleteBtn);
}
rowContainer.appendChild(row);
updateDeleteButtons();
};
const updateDeleteButtons = () => {
const rows = Array.from(rowContainer.children);
rows.forEach((row) => {
const btn = row.querySelector('button:last-child') as HTMLButtonElement;
if (rows.length === 1) {
btn.disabled = true;
btn.style.visibility = 'hidden';
} else {
btn.disabled = false;
btn.style.visibility = 'visible';
}
});
};
createRow();
addBtn.addEventListener('click', createRow);
return {
element: section,
getData: () => {
if (isRoleSection) {
const data: Record<string, RoleDefinition> = {};
for (const row of roleRowStates) {
const key = row.roleNameInput.value.trim();
if (!key) continue;
data[key] = {
members: row.membersInput.value
.split(',')
.map((x) => x.trim())
.filter(Boolean),
storages: row.storagesInput.value
.split(',')
.map((x) => x.trim())
.filter(Boolean),
validation_rules: row.validationRules,
};
}
return data;
} else {
const data: Record<string, string | fileBlob> = {};
for (const row of nonRoleRowStates) {
const key = row.keyInput.value.trim();
if (!key) continue;
if (row.fileBlob) {
data[key] = row.fileBlob;
} else {
data[key] = row.valueInput.value.trim();
}
}
return data;
}
},
};
}

View File

@ -1,93 +0,0 @@
import { createKeyValueSection } from './key-value-section';
import { loadValidationRuleModal } from '../../components/validation-rule-modal/validation-rule-modal';
import Services from '../../services/service';
import type { RoleDefinition } from '../../../pkg/sdk_client';
export async function getProcessCreation(container: HTMLElement) {
await loadValidationRuleModal();
container.style.display = 'block';
container.innerHTML = `<div class="parameter-header">Process Creation</div>`;
const privateSec = createKeyValueSection('Private Data', 'private-section');
const publicSec = createKeyValueSection('Public Data', 'public-section');
const rolesSec = createKeyValueSection('Roles', 'roles-section', true);
container.appendChild(privateSec.element);
container.appendChild(publicSec.element);
container.appendChild(rolesSec.element);
const btn = document.createElement('button');
btn.textContent = 'Create Process';
btn.style.cssText = `
display: block;
margin: 2rem auto 0;
padding: 0.75rem 2rem;
font-size: 1rem;
font-weight: bold;
background-color: #4f46e5;
color: white;
border: none;
border-radius: 0.5rem;
cursor: pointer;
`;
btn.onclick = async () => {
const privateData = privateSec.getData();
const publicData = publicSec.getData();
const roles = rolesSec.getData() as Record<string, RoleDefinition>;
console.log('Private:', privateData);
console.log('Public:', publicData);
console.log('Roles:', roles);
const service = await Services.getInstance();
const createProcessResult = await service.createProcess(privateData, publicData, roles);
const processId = createProcessResult.updated_process!.process_id;
const stateId = createProcessResult.updated_process!.current_process.states[0].state_id;
await service.handleApiReturn(createProcessResult);
// Now we want to validate the update and register the first state of our new process
const updateProcessResult = await service.createPrdUpdate(processId, stateId);
await service.handleApiReturn(createProcessResult);
const approveChangeResult = await service.approveChange(processId, stateId);
await service.handleApiReturn(approveChangeResult);
if (approveChangeResult) {
const process = await service.getProcess(processId);
let newState = process ? service.getStateFromId(process, stateId) : null;
if (!newState) return;
for (const label of Object.keys(newState.keys)) {
const hash = newState.pcd_commitment[label];
const encryptedData = await service.getBlobFromDb(hash);
if (!encryptedData) continue;
const filename = `${label}-${hash.slice(0, 8)}.bin`;
const blob = new Blob([encryptedData], { type: 'application/octet-stream' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = filename;
link.click();
setTimeout(() => URL.revokeObjectURL(link.href), 1000);
}
// await service.generateProcessPdf(processId, newState);
// Add processId to the state we export
// newState n'a pas de propriété process_id, on utilise commited_in
// newState['process_id'] = processId;
const blob = new Blob([JSON.stringify(newState, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `process_${processId}_${stateId}.json`;
a.click();
URL.revokeObjectURL(url); // Clean up
}
};
container.appendChild(btn);
}

View File

@ -1,66 +0,0 @@
export function createProcessTab(container: HTMLElement, processes: { name: string; publicData: Record<string, any> }[]): HTMLElement {
container.id = 'process-tab';
container.style.display = 'block';
container.style.cssText = 'padding: 1.5rem;';
const title = document.createElement('h2');
title.textContent = 'Processes';
title.style.cssText = 'font-size: 1.5rem; font-weight: bold; margin-bottom: 1rem;';
container.appendChild(title);
processes.forEach((proc) => {
const card = document.createElement('div');
card.style.cssText = 'margin-bottom: 1rem; padding: 1rem; border: 1px solid #ddd; border-radius: 0.5rem; background: #fff;';
const nameEl = document.createElement('h3');
nameEl.textContent = proc.name;
nameEl.style.cssText = 'font-size: 1.2rem; font-weight: bold; margin-bottom: 0.5rem;';
card.appendChild(nameEl);
const dataList = document.createElement('div');
for (const [key, value] of Object.entries(proc.publicData)) {
const item = document.createElement('div');
item.style.cssText = 'margin-bottom: 0.5rem;';
const label = document.createElement('strong');
label.textContent = key + ': ';
item.appendChild(label);
// Let's trim the quotes
const trimmed = value.replace(/^'|'$/g, '');
let parsed;
try {
parsed = JSON.parse(trimmed);
} catch (_) {
parsed = trimmed;
}
if (parsed && typeof parsed === 'object') {
const saveBtn = document.createElement('button');
saveBtn.textContent = '💾 Save as JSON';
saveBtn.style.cssText = 'margin-left: 0.5rem; padding: 0.25rem 0.5rem; border: 1px solid #ccc; border-radius: 0.375rem; background: #f0f0f0; cursor: pointer;';
saveBtn.onclick = () => {
const blob = new Blob([JSON.stringify(parsed, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `${proc.name}_${key}.json`;
a.click();
URL.revokeObjectURL(url);
};
item.appendChild(saveBtn);
} else {
const span = document.createElement('span');
span.textContent = String(parsed);
item.appendChild(span);
}
dataList.appendChild(item);
}
card.appendChild(dataList);
container.appendChild(card);
});
return container;
}

View File

@ -0,0 +1,49 @@
import { ChatElement } from './chat';
import chatCss from '../../../public/style/chat.css?raw';
import Services from '../../services/service.js';
class ChatComponent extends HTMLElement {
_callback: any;
chatElement: ChatElement | null = null;
constructor() {
super();
console.log('INIT');
this.attachShadow({ mode: 'open' });
this.chatElement = this.shadowRoot?.querySelector('chat-element') || null;
}
connectedCallback() {
console.log('CALLBACKs');
this.render();
if (!customElements.get('chat-element')) {
customElements.define('chat-element', ChatElement);
}
}
set callback(fn) {
if (typeof fn === 'function') {
this._callback = fn;
} else {
console.error('Callback is not a function');
}
}
get callback() {
return this._callback;
}
render() {
if (this.shadowRoot) {
// Créer l'élément chat-element
const chatElement = document.createElement('chat-element');
this.shadowRoot.innerHTML = `<style>${chatCss}</style>`;
this.shadowRoot.appendChild(chatElement);
}
}
}
export { ChatComponent };
customElements.define('chat-component', ChatComponent);

13
src/pages/chat/chat.html Executable file
View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Chat</title>
</head>
<body>
<chat-component></chat-component>
<script type="module" src="./chat.ts"></script>
</body>
</html>

1748
src/pages/chat/chat.ts Executable file

File diff suppressed because it is too large Load Diff

View File

@ -36,7 +36,7 @@
<select name="memberSelect" id="memberSelect" size="5" class="custom-select"> <select name="memberSelect" id="memberSelect" size="5" class="custom-select">
<!-- Options --> <!-- Options -->
</select> </select>
<button id="okButton" style="display: none">OK</button> <button id="okButton" style="display: none">OK</button>
</div> </div>
</div> </div>

View File

@ -4,8 +4,6 @@ import { addSubscription } from '../../utils/subscription.utils';
import { displayEmojis, generateQRCode, generateCreateBtn, addressToEmoji } from '../../utils/sp-address.utils'; import { displayEmojis, generateQRCode, generateCreateBtn, addressToEmoji } from '../../utils/sp-address.utils';
import { getCorrectDOM } from '../../utils/html.utils'; import { getCorrectDOM } from '../../utils/html.utils';
import QrScannerComponent from '../../components/qrcode-scanner/qrcode-scanner-component'; import QrScannerComponent from '../../components/qrcode-scanner/qrcode-scanner-component';
import { navigate, registerAllListeners } from '../../router';
export { QrScannerComponent }; export { QrScannerComponent };
export async function initHomePage(): Promise<void> { export async function initHomePage(): Promise<void> {
console.log('INIT-HOME'); console.log('INIT-HOME');
@ -23,9 +21,9 @@ export async function initHomePage(): Promise<void> {
const service = await Services.getInstance(); const service = await Services.getInstance();
const spAddress = await service.getDeviceAddress(); const spAddress = await service.getDeviceAddress();
// generateQRCode(spAddress); // generateQRCode(spAddress);
generateCreateBtn(); generateCreateBtn ();
displayEmojis(spAddress); displayEmojis(spAddress);
// Add this line to populate the select when the page loads // Add this line to populate the select when the page loads
await populateMemberSelect(); await populateMemberSelect();
} }
@ -54,19 +52,19 @@ function scanDevice() {
async function populateMemberSelect() { async function populateMemberSelect() {
const container = getCorrectDOM('login-4nk-component') as HTMLElement; const container = getCorrectDOM('login-4nk-component') as HTMLElement;
const memberSelect = container.querySelector('#memberSelect') as HTMLSelectElement; const memberSelect = container.querySelector('#memberSelect') as HTMLSelectElement;
if (!memberSelect) { if (!memberSelect) {
console.error('Could not find memberSelect element'); console.error('Could not find memberSelect element');
return; return;
} }
const service = await Services.getInstance(); const service = await Services.getInstance();
const members = await service.getAllMembersSorted(); const members = service.getAllMembersSorted();
for (const [processId, member] of Object.entries(members)) { for (const [processId, member] of Object.entries(members)) {
const process = await service.getProcess(processId); const process = await service.getProcess(processId);
let memberPublicName; let memberPublicName;
if (process) { if (process) {
const publicMemberData = service.getPublicData(process); const publicMemberData = service.getPublicData(process);
if (publicMemberData) { if (publicMemberData) {
@ -76,14 +74,14 @@ async function populateMemberSelect() {
} }
} }
} }
if (!memberPublicName) { if (!memberPublicName) {
memberPublicName = 'Unnamed Member'; memberPublicName = 'Unnamed Member';
} }
// Récupérer les emojis pour ce processId // Récupérer les emojis pour ce processId
const emojis = await addressToEmoji(processId); const emojis = await addressToEmoji(processId);
const option = document.createElement('option'); const option = document.createElement('option');
option.value = processId; option.value = processId;
option.textContent = `${memberPublicName} (${emojis})`; option.textContent = `${memberPublicName} (${emojis})`;

View File

@ -0,0 +1,51 @@
import processHtml from './process-element.html?raw';
import processScript from './process-element.ts?raw';
import processCss from '../../4nk.css?raw';
import { initProcessElement } from './process-element';
export class ProcessListComponent extends HTMLElement {
_callback: any;
id: string = '';
zone: string = '';
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
connectedCallback() {
console.log('CALLBACK PROCESS LIST PAGE');
this.render();
setTimeout(() => {
initProcessElement(this.id, this.zone);
}, 500);
}
set callback(fn) {
if (typeof fn === 'function') {
this._callback = fn;
} else {
console.error('Callback is not a function');
}
}
get callback() {
return this._callback;
}
render() {
if (this.shadowRoot)
this.shadowRoot.innerHTML = `
<style>
${processCss}
</style>${processHtml}
<script type="module">
${processScript}
</scipt>
`;
}
}
if (!customElements.get('process-4nk-component')) {
customElements.define('process-4nk-component', ProcessListComponent);
}

View File

@ -0,0 +1,5 @@
<div class="title-container">
<h1>Process {{processTitle}}</h1>
</div>
<div class="process-container"></div>

View File

@ -0,0 +1,50 @@
import { interpolate } from '../../utils/html.utils';
import Services from '../../services/service';
import { Process } from 'pkg/sdk_client';
import { getCorrectDOM } from '~/utils/document.utils';
let currentPageStyle: HTMLStyleElement | null = null;
export async function initProcessElement(id: string, zone: string) {
const processes = await getProcesses();
const container = getCorrectDOM('process-4nk-component');
// const currentProcess = processes.find((process) => process[0] === id)[1];
// const currentProcess = {title: 'Hello', html: '', css: ''};
// await loadPage({ processTitle: currentProcess.title, inputValue: 'Hello World !' });
// const wrapper = document.querySelector('.process-container');
// if (wrapper) {
// wrapper.innerHTML = interpolate(currentProcess.html, { processTitle: currentProcess.title, inputValue: 'Hello World !' });
// injectCss(currentProcess.css);
// }
}
async function loadPage(data?: any) {
const content = document.getElementById('containerId');
if (content && data) {
if (data) {
content.innerHTML = interpolate(content.innerHTML, data);
}
}
}
function injectCss(cssContent: string) {
removeCss(); // Ensure that the previous CSS is removed
currentPageStyle = document.createElement('style');
currentPageStyle.type = 'text/css';
currentPageStyle.appendChild(document.createTextNode(cssContent));
document.head.appendChild(currentPageStyle);
}
function removeCss() {
if (currentPageStyle) {
document.head.removeChild(currentPageStyle);
currentPageStyle = null;
}
}
async function getProcesses(): Promise<Record<string, Process>> {
const service = await Services.getInstance();
const processes = await service.getProcesses();
return processes;
}

Some files were not shown because too many files have changed in this diff Show More