docs: Fusion et simplification documentation features/

- Fusion tous documents implémentations en features.md
- Suppression documents redondants/obsolètes :
  - final-cleanup-summary.md, storage-encryption.md
  - storage-improvement-implementation.md, notifications-scope.md
  - user-profile-implementation.md, filtering-search-implementation.md
  - article-edit-delete.md, priority1-implementation.md
  - alby-integration.md, nostr-paywall-implementation.md
  - technical-doc.md (redondant avec docs/technical.md)
  - rizful-integration.md (obsolète, remplacé par Alby)
- Documentation fidèle au code actuel
- Garde zapwall4science-refactoring.md (spécifications)
- Garde series-and-media-spec.md (spécifications)
- Garde notifications-implementation.md (détails techniques)
This commit is contained in:
Nicolas Cantu 2025-12-27 21:31:20 +01:00
parent 9ea4965c05
commit a099f3c24a
14 changed files with 103 additions and 1392 deletions

View File

@ -89,4 +89,3 @@ Tous les événements sont loggés avec IDs, timestamps et statuts.
## Limitations ## Limitations
**Transferts Lightning automatiques** : Nécessitent un nœud Lightning de la plateforme. Actuellement, les transferts sont loggés dans `lib/automaticTransfer.ts` et peuvent être exécutés manuellement. Les adresses Lightning sont récupérées automatiquement depuis les profils Nostr. **Transferts Lightning automatiques** : Nécessitent un nœud Lightning de la plateforme. Actuellement, les transferts sont loggés dans `lib/automaticTransfer.ts` et peuvent être exécutés manuellement. Les adresses Lightning sont récupérées automatiquement depuis les profils Nostr.

View File

@ -1,145 +0,0 @@
# Intégration Alby/WebLN pour paiements Lightning
**Auteur** : Équipe 4NK
## Objectif
Remplacer l'intégration Rizful par Alby/WebLN pour les paiements Lightning, permettant une intégration directe avec les portefeuilles Lightning du navigateur sans nécessiter d'API backend.
## Impacts
### Utilisateurs
- Paiements Lightning facilités via l'extension Alby ou autres portefeuilles WebLN
- Pas besoin de compte externe (Rizful) pour recevoir des paiements
- Interface de paiement native du navigateur
- Vérification des paiements via zap receipts sur Nostr
### Développeurs
- Pas besoin de clé API externe
- Pas besoin d'API routes backend pour les paiements
- Utilisation du standard WebLN (compatible avec tous les portefeuilles WebLN)
- Architecture simplifiée
### Technique
- Service `AlbyService` utilisant le standard WebLN
- Vérification des paiements via zap receipts Nostr
- Compatible avec Alby et autres portefeuilles WebLN
## Modifications
### Nouveaux fichiers
#### `lib/alby.ts` - Service Alby/WebLN
Service principal pour interagir avec les portefeuilles Lightning via WebLN :
- `enable()` : Demander l'autorisation à l'utilisateur
- `createInvoice()` : Créer une facture Lightning via le portefeuille
- `sendPayment()` : Envoyer un paiement via le portefeuille
- `checkPaymentStatus()` : Placeholder (vérification via zap receipts)
- `waitForPayment()` : Attendre la confirmation via zap receipts
#### `types/alby.ts` - Types TypeScript
Types pour Alby/WebLN :
- `AlbyInvoice` : Structure d'une facture Lightning
- `AlbyPaymentStatus` : Statut d'un paiement
- `AlbyInvoiceRequest` : Requête de création de facture
### Fichiers modifiés
#### `lib/payment.ts`
- Remplacement de `RizfulService` par `AlbyService`
- Utilisation de zap receipts pour la vérification des paiements
- Simplification du flux de paiement
#### `components/PaymentModal.tsx`
- Intégration de `AlbyService` pour le paiement
- Utilisation de `sendPayment()` pour payer directement via WebLN
- Fallback vers URI Lightning si WebLN n'est pas disponible
#### `components/ArticleCard.tsx`
- Mise à jour des types (remplacement de `RizfulInvoice` par `AlbyInvoice`)
#### `next.config.js`
- Suppression des variables d'environnement Rizful
#### `README.md`
- Mise à jour de la documentation pour Alby
- Instructions pour installer l'extension Alby
### Fichiers supprimés
- `lib/rizful.ts` - Service Rizful (remplacé par `lib/alby.ts`)
- `types/rizful.ts` - Types Rizful (remplacé par `types/alby.ts`)
- `pages/api/rizful/invoice.ts` - API route Rizful (plus nécessaire)
- `pages/api/rizful/payment/[hash].ts` - API route Rizful (plus nécessaire)
### Flux de paiement avec Alby
1. **Utilisateur clique sur "Unlock for X sats"**
- Vérification de la connexion Nostr
- Demande d'activation de WebLN (Alby)
- Création d'une facture Lightning via WebLN
2. **Affichage de la modal de paiement**
- Facture Lightning affichée
- Option pour payer directement via WebLN (bouton "Pay with Alby")
- Option pour copier la facture
3. **Paiement utilisateur**
- Utilisateur paie via son portefeuille WebLN (Alby)
- Le portefeuille gère le paiement
4. **Vérification du paiement**
- Polling des zap receipts sur Nostr
- Vérification de la signature et du montant
- Confirmation du paiement
5. **Déblocage du contenu**
- Une fois le paiement confirmé via zap receipt, chargement du contenu privé
- Affichage du contenu complet
## Modalités de déploiement
### Prérequis
- Extension Alby installée (pour les utilisateurs)
- Ou autre portefeuille WebLN compatible
### Installation pour les utilisateurs
Les utilisateurs doivent installer l'extension Alby :
1. Aller sur [https://getalby.com/](https://getalby.com/)
2. Installer l'extension pour leur navigateur (Chrome, Firefox, etc.)
3. Créer un compte Alby ou connecter un portefeuille Lightning existant
### Configuration
Aucune configuration serveur nécessaire ! Tout fonctionne côté client via WebLN.
### Déploiement
Aucun changement dans le processus de déploiement standard. Le code fonctionne entièrement côté client.
### Sécurité
- **WebLN** : Standard ouvert et sécurisé pour les portefeuilles Lightning
- **Vérification** : Les paiements sont vérifiés via zap receipts Nostr avec signatures cryptographiques
- **Pas d'API key** : Plus besoin de gérer des clés API côté serveur
## Avantages par rapport à Rizful
1. **Pas de clé API** : Plus besoin de configuration serveur
2. **Standard ouvert** : WebLN est un standard, compatible avec plusieurs portefeuilles
3. **Meilleure UX** : Intégration native avec le navigateur
4. **Décentralisé** : Les utilisateurs gardent le contrôle de leur portefeuille
5. **Pas de frais d'API** : Pas de service externe à payer
## Limitations
1. **Extension requise** : Les utilisateurs doivent avoir une extension WebLN installée
2. **Vérification via zap receipts** : La vérification des paiements dépend des zap receipts sur Nostr (ce qui est normal pour un système Nostr)
## Points d'amélioration
1. **Détection automatique** : Améliorer la détection de l'extension WebLN
2. **Guide d'installation** : Ajouter un guide d'installation de l'extension pour les utilisateurs
3. **Support de plusieurs portefeuilles** : Tester et supporter d'autres portefeuilles WebLN
4. **Gestion des erreurs** : Améliorer les messages d'erreur si WebLN n'est pas disponible

View File

@ -1,22 +0,0 @@
# Article edit/delete via Nostr events
**Objectif**
Permettre aux auteurs déditer ou supprimer leurs articles en publiant des événements Nostr dédiés (update + delete), avec confirmation explicite côté UI.
**Impacts**
- Parcours auteur : édition depuis la liste de mes articles, suppression confirmée avant envoi de lévénement kind 5.
- Stockage local : contenu privé ré-encrypté et ré-enregistré pour les mises à jour.
- Pas dimpact côté lecteurs (pas de fallback).
**Modifications**
- `lib/articleMutations.ts` : publication update/delete (tags e, replace), réutilisation du stockage chiffré.
- `components/UserArticles.tsx`, `components/UserArticlesList.tsx`, `components/UserArticlesEditPanel.tsx` : UI édition/suppression avec confirmation, découpage pour respecter lint/max-lines.
- `lib/articleInvoice.ts` : factorisation des tags de preview.
**Modalités de déploiement**
Standard front : build Next.js habituel. Pas de migrations ni dépendances supplémentaires.
**Modalités danalyse**
- Vérifier quun auteur connecté peut éditer puis voir son article mis à jour dans la liste.
- Vérifier que la suppression publie lévénement et retire larticle de la liste locale.
- Sur erreur de publication, message derreur affiché (aucun fallback silencieux).

103
features/features.md Normal file
View File

@ -0,0 +1,103 @@
# Fonctionnalités implémentées
**Auteur** : Équipe 4NK
## Architecture de base
### Nostr Paywall → zapwall4Science
- Publication d'articles avec aperçus gratuits et contenu payant
- Paiement Lightning via Alby/WebLN (remplacement de Rizful)
- Connexion via NostrConnect (use.nsec.app)
- Interface TypeScript/Next.js
### Services principaux
- **Nostr** : Pool de connexions, publication/récupération d'événements, profils
- **Paiements** : Invoices Lightning, vérification zap receipts (NIP-57), envoi automatique contenu privé
- **Stockage** : IndexedDB avec chiffrement AES-GCM pour contenu privé
- **Notifications** : Surveillance des paiements en temps réel (zap receipts)
## Fonctionnalités utilisateur
### Profil et articles
- Page profil (`/profile`) avec informations utilisateur
- Liste des articles publiés par l'utilisateur
- Recherche et filtres (auteur, prix, texte)
- Tri (date, prix)
### Édition et suppression
- Édition d'articles via événements Nostr (kind 1 avec tag `replace`)
- Suppression d'articles via événements Nostr (kind 5)
- Confirmation avant suppression
- Ré-encryptage du contenu privé lors de l'édition
### Notifications
- Surveillance automatique des zap receipts (kind:9735) destinés à l'utilisateur
- Badge avec nombre de notifications non lues dans le header
- Centre de notifications (panneau latéral) avec liste des paiements
- Formatage du temps relatif (il y a X minutes/heures/jours)
- Marquer comme lu / marquer tout comme lu
- Tri par date (plus récentes en premier)
**Scope** : Uniquement notifications de paiements. Pas de mentions, reposts, likes. Si commentaires demandés plus tard, approbation explicite requise.
## Stockage
### IndexedDB avec chiffrement
- Remplacement de localStorage par IndexedDB
- Chiffrement AES-GCM du contenu privé
- Clé maître générée une fois et stockée en localStorage
- Secret par article : `<masterKey>:<articleId>`
- Expiration automatique (30 jours)
- Pas de fallback : échec si IndexedDB ou Web Crypto indisponible
### Fichiers
- `lib/storage/indexedDB.ts` : Service IndexedDB
- `lib/storage/cryptoHelpers.ts` : Helpers AES-GCM
- `lib/articleStorage.ts` : Gestion du stockage avec chiffrement
## Séries et médias (NIP-95)
### Séries
- Événements kind 1 avec tag `kind_type: series`
- Tags : `site`, `category`, `author`, `series` (self id), `title`, `description`, `cover`, `preview`
- Agrégation du sponsoring et des paiements par série
### Médias
- Upload d'images (≤5Mo) et vidéos (≤45Mo) via NIP-95
- Tags `banner` et `media` dans les événements
- Validations de taille et type
- Support dans les articles et séries
### Avis (reviews)
- Événements kind 1 avec tag `kind_type: review`
- Tags : `site`, `category`, `author`, `series`, `article`, `reviewer`, `title`
- Rémunération possible avec tags `rewarded` et `reward_amount`
## Optimisations et nettoyage
### Refactoring
- Division des fichiers > 250 lignes
- Extraction des fonctions > 40 lignes
- Modules dédiés : parsing, messages privés, vérification zap, subscriptions, polling, résolution invoices, stockage, handlers
### Code quality
- Respect strict `exactOptionalPropertyTypes`
- Fonctions < 40 lignes, fichiers < 250 lignes
- Pas de fallback implicite
- Logs structurés
- Pas d'analytics
## Intégrations
### Alby/WebLN
- Remplacement de Rizful par Alby/WebLN
- Standard WebLN compatible avec tous les portefeuilles
- Pas d'API backend nécessaire
- Service `AlbyService` pour enable, makeInvoice, sendPayment
### Priorité 1 (implémenté)
- Génération d'invoice côté auteur lors de la publication
- Invoice stockée dans tags Nostr et localStorage
- Vérification de l'invoice avant création d'une nouvelle
- Signature distante (NIP-46) préparée

View File

@ -1,138 +0,0 @@
# Implémentation du filtrage et de la recherche d'articles
**Date** : Décembre 2024
**Status** : ✅ Complété
## Objectif
Permettre aux utilisateurs de rechercher et filtrer les articles sur la page d'accueil.
## Fonctionnalités implémentées
### 1. Recherche par texte
- Barre de recherche permettant de rechercher dans les titres, aperçus et contenus des articles
- Recherche insensible à la casse
- Bouton pour effacer la recherche rapidement
### 2. Filtres
- **Filtre par auteur** : Sélectionner un auteur spécifique parmi les auteurs disponibles
- **Filtre par prix minimum** : Filtrer les articles avec un prix minimum en satoshis
- **Filtre par prix maximum** : Filtrer les articles avec un prix maximum en satoshis
### 3. Tri
- **Plus récent** (par défaut) : Articles les plus récents en premier
- **Plus ancien** : Articles les plus anciens en premier
- **Prix croissant** : Articles du moins cher au plus cher
- **Prix décroissant** : Articles du plus cher au moins cher
### 4. Affichage des résultats
- Compteur affichant le nombre d'articles correspondant aux filtres
- Message lorsque aucun article ne correspond aux critères
## Fichiers créés
### `components/SearchBar.tsx`
Composant de barre de recherche avec :
- Icône de recherche
- Champ de saisie
- Bouton pour effacer la recherche
- Gestion de l'état local avec synchronisation
### `components/ArticleFilters.tsx`
Composant de filtres avec :
- Filtre par auteur (dropdown)
- Filtres par prix min/max (inputs numériques)
- Tri (dropdown)
- Bouton "Clear all" pour réinitialiser tous les filtres
- Affichage conditionnel du bouton "Clear all" seulement si des filtres sont actifs
**Types exportés** :
- `SortOption` : Type pour les options de tri
- `ArticleFilters` : Interface pour les filtres
### `lib/articleFiltering.ts`
Logique de filtrage et de tri avec :
- `filterArticlesBySearch()` : Filtre par texte de recherche
- `filterArticles()` : Filtre par auteur et prix
- `sortArticles()` : Trie les articles selon l'option sélectionnée
- `applyFiltersAndSort()` : Applique tous les filtres et le tri
## Fichiers modifiés
### `hooks/useArticles.ts`
- Ajout des paramètres `searchQuery` et `filters` au hook
- Utilisation de `useMemo` pour optimiser le filtrage
- Retour de `allArticles` (tous les articles non filtrés) pour permettre au composant de filtres de connaître les options disponibles
- Retour de `articles` (articles filtrés et triés) pour l'affichage
**Signature modifiée** :
```typescript
export function useArticles(
searchQuery: string = '',
filters: ArticleFilters | null = null
)
```
**Retour modifié** :
```typescript
{
articles: Article[], // Articles filtrés et triés
allArticles: Article[], // Tous les articles (pour les filtres)
loading: boolean,
error: string | null,
loadArticleContent: (articleId: string, authorPubkey: string) => Promise<Article | null>
}
```
### `pages/index.tsx`
- Ajout de l'état pour `searchQuery` et `filters`
- Intégration du composant `SearchBar`
- Intégration du composant `ArticleFilters`
- Passage des paramètres au hook `useArticles`
- Affichage du compteur d'articles filtrés
- Message amélioré lorsque aucun article ne correspond
## Impact
### Utilisateur
- Recherche rapide d'articles par mots-clés
- Filtrage précis par auteur et prix
- Tri flexible pour trouver facilement ce qui intéresse
- Interface intuitive avec boutons de réinitialisation
### Technique
- Code modulaire et réutilisable
- Performance optimisée avec `useMemo`
- Types TypeScript stricts pour la sécurité
- Séparation claire des responsabilités (UI vs logique)
## Tests recommandés
1. **Recherche** :
- Rechercher par titre
- Rechercher par contenu d'aperçu
- Rechercher avec plusieurs mots
- Effacer la recherche
2. **Filtres** :
- Filtrer par auteur
- Filtrer par prix minimum
- Filtrer par prix maximum
- Combiner plusieurs filtres
- Réinitialiser les filtres
3. **Tri** :
- Trier par date (nouveaux/anciens)
- Trier par prix (croissant/décroissant)
- Combiner tri et filtres
4. **Performance** :
- Vérifier que le filtrage ne bloque pas l'UI
- Vérifier avec un grand nombre d'articles
## Notes techniques
- Le filtrage est effectué côté client (pas de requête au serveur/relay)
- Les articles sont filtrés et triés à chaque changement de recherche ou filtres
- L'utilisation de `useMemo` évite de recalculer les filtres à chaque render
- Les filtres sont appliqués dans l'ordre : recherche → filtres → tri

View File

@ -1,134 +0,0 @@
# Résumé final du nettoyage et optimisation
**Date** : Décembre 2025 (addendum)
## ✅ Objectifs complétés
### 1. Nettoyage des fichiers/dossiers obsolètes
- ✅ Supprimé `pages/api/rizful/` (dossier vide après migration vers Alby)
- ✅ Documentation Rizful conservée pour référence historique
### 2. Optimisation des fichiers > 250 lignes
Tous les fichiers sont maintenant **< 250 lignes** :
- `lib/nostr.ts` : 331 → **232 lignes** (-30%)
- `lib/articlePublisher.ts` : 237 → **210 lignes** (-11%)
- `lib/payment.ts` : 195 → **113 lignes** (-42%)
- `lib/nostrconnect.ts` : 156 → **145 lignes** (-7%)
### 3. Division des fonctions > 40 lignes
Toutes les fonctions longues ont été extraites dans des modules dédiés :
- Parsing d'événements → `nostrEventParsing.ts`
- Messages privés → `nostrPrivateMessages.ts`
- Vérification zap → `nostrZapVerification.ts`
- Subscriptions → `nostrSubscription.ts`
- Polling paiements → `paymentPolling.ts`
- Résolution invoices → `invoiceResolver.ts`
- Stockage articles → `articleStorage.ts`
- Création invoices → `articleInvoice.ts`
- Handler NostrConnect → `nostrconnectHandler.ts`
### 4. Correction des erreurs de lint
- ✅ Aucune erreur de lint dans le code TypeScript (déc. 2025 : `npm run lint` OK)
- ✅ Code propre et optimisé
## Addendum Déc 2025
- Séries, critiques, agrégations zap : nouvelles sections UI/logic (`Series*`, `ArticleReviews`, `zapAggregation*`).
- Upload médias NIP-95 (images/vidéos) avec validations de taille et type.
- Stockage contenu privé chiffré en IndexedDB + helpers WebCrypto.
- Respect strict `exactOptionalPropertyTypes`, fonctions < 40 lignes, fichiers < 250 lignes (refactors composants profil/articles, sélecteurs de séries).
- Pas de tests ajoutés, pas danalytics.
## Nouveaux fichiers créés (9 fichiers)
1. **`lib/nostrEventParsing.ts`** (40 lignes)
- Parsing des événements Nostr en articles
- Extraction des tags (title, preview, zap, invoice)
2. **`lib/nostrPrivateMessages.ts`** (59 lignes)
- Gestion des messages privés chiffrés
- Décryptage avec NIP-04
3. **`lib/nostrZapVerification.ts`** (61 lignes)
- Vérification des zap receipts
- Intégration avec zapVerificationService
4. **`lib/nostrSubscription.ts`** (44 lignes)
- Utilitaires pour subscriptions avec timeout
- Gestion propre des timeouts et cleanup
5. **`lib/paymentPolling.ts`** (85 lignes)
- Polling pour vérification des paiements
- Envoi automatique du contenu privé après paiement
6. **`lib/invoiceResolver.ts`** (39 lignes)
- Résolution intelligente des invoices
- Priorité : tags → localStorage → création nouvelle
7. **`lib/articleStorage.ts`** (93 lignes)
- Gestion du stockage localStorage
- Fonctions pour stocker/récupérer/supprimer
8. **`lib/articleInvoice.ts`** (50 lignes)
- Création d'invoices Lightning
- Création d'événements preview avec tags
9. **`lib/nostrconnectHandler.ts`** (32 lignes)
- Handler pour messages NostrConnect
- Validation de sécurité (origin)
## Statistiques finales
### Taille des fichiers lib/ (par ordre décroissant)
```
nostr.ts 232 lignes
articlePublisher.ts 210 lignes
alby.ts 184 lignes
payment.ts 113 lignes ✅ (réduit de 195)
nostrconnect.ts 145 lignes
zapVerification.ts 97 lignes
articleStorage.ts 93 lignes (nouveau)
paymentPolling.ts 85 lignes (nouveau)
retry.ts 76 lignes
nostrZapVerification.ts 61 lignes (nouveau)
nostrPrivateMessages.ts 59 lignes (nouveau)
nostrRemoteSigner.ts 51 lignes
articleInvoice.ts 50 lignes (nouveau)
nostrSubscription.ts 44 lignes (nouveau)
nostrEventParsing.ts 40 lignes (nouveau)
invoiceResolver.ts 39 lignes (nouveau)
nostrconnectHandler.ts 32 lignes (nouveau)
```
### Réduction totale
- **Avant** : 4 fichiers > 250 lignes
- **Après** : 0 fichiers > 250 lignes ✅
- **Réduction moyenne** : -25% de lignes dans les fichiers principaux
- **Fonctions** : Toutes < 40 lignes
## Architecture finale
### Séparation des responsabilités
- **Parsing** : `nostrEventParsing.ts`
- **Communication** : `nostr.ts`, `nostrSubscription.ts`
- **Chiffrement** : `nostrPrivateMessages.ts`
- **Vérification** : `nostrZapVerification.ts`, `zapVerification.ts`
- **Paiements** : `payment.ts`, `paymentPolling.ts`, `invoiceResolver.ts`
- **Articles** : `articlePublisher.ts`, `articleStorage.ts`, `articleInvoice.ts`
- **Connectivité** : `nostrconnect.ts`, `nostrconnectHandler.ts`
- **Lightning** : `alby.ts`, `retry.ts`
- **Signature** : `nostrRemoteSigner.ts`
### Avantages
- ✅ Code modulaire et réutilisable
- ✅ Responsabilités bien séparées (SRP)
- ✅ Tests unitaires facilités
- ✅ Maintenance simplifiée
- ✅ Imports clairs et explicites
- ✅ Pas de dépendances circulaires
## Prochaines étapes
Le code est maintenant propre, optimisé et maintenable. Prêt pour :
- Tests unitaires
- Documentation utilisateur
- Fonctionnalités avancées (priorité 3)

View File

@ -1,217 +0,0 @@
# Nostr Paywall - Site d'articles avec aperçus gratuits et contenu payant
**Auteur** : Équipe 4NK
## Objectif
Implémenter un site d'articles sur Nostr permettant :
- L'affichage d'aperçus gratuits (notes publiques)
- Le déblocage du contenu complet après un zap Lightning de 800 sats
- La connexion via NostrConnect (préconisé use.nsec.app)
- Une interface moderne et intuitive en TypeScript/Next.js
## Impacts
### Utilisateurs
- Accès gratuit aux aperçus d'articles
- Possibilité de débloquer le contenu complet via paiement Lightning instantané
- Connexion sécurisée via NostrConnect sans partager de clés privées
- Expérience utilisateur fluide avec gestion des paiements intégrée
### Développeurs
- Architecture modulaire avec séparation des responsabilités
- Utilisation de `nostr-tools` pour toutes les opérations Nostr
- TypeScript pour la sécurité de type
- Hooks React personnalisés pour la gestion de l'état
- Service de connexion NostrConnect réutilisable
### Technique
- Dépendance principale : `nostr-tools` (bibliothèque standard Nostr)
- Framework : Next.js 14 avec React 18
- Styling : Tailwind CSS
- Relay par défaut : wss://relay.damus.io
- Bridge NostrConnect : https://use.nsec.app
## Modifications
### Structure du projet
```
nostr_paywall/
├── pages/
│ ├── index.tsx # Page principale avec liste des articles
│ └── _app.tsx # Configuration Next.js
├── components/
│ ├── ConnectButton.tsx # Bouton de connexion NostrConnect
│ └── ArticleCard.tsx # Carte d'article avec aperçu et déblocage
├── hooks/
│ ├── useNostrConnect.ts # Hook pour la connexion NostrConnect
│ └── useArticles.ts # Hook pour la gestion des articles
├── lib/
│ ├── nostr.ts # Service Nostr (publications, abonnements, zaps)
│ └── nostrconnect.ts # Service NostrConnect (NIP-46)
├── types/
│ └── nostr.ts # Types TypeScript pour Nostr
└── styles/
└── globals.css # Styles globaux avec Tailwind
```
### Composants clés
#### `lib/nostr.ts` - Service Nostr
- `SimplePool` pour la gestion des connexions aux relais
- Méthodes pour publier et s'abonner aux événements
- Parsing des articles depuis les événements kind:1
- Gestion des messages privés chiffrés (kind:4) avec NIP-04
- Création de zap requests (kind:9734)
- Vérification des zap receipts (kind:9735)
#### `lib/nostrconnect.ts` - Service NostrConnect
- Implémentation du protocole NIP-46 via use.nsec.app
- Communication via messages postMessage avec popup
- Persistance de l'état de connexion dans localStorage
- Gestion du profil utilisateur
#### `components/ArticleCard.tsx`
- Affichage de l'aperçu (contenu public)
- Bouton de déblocage conditionnel (nécessite connexion)
- Création de zap request lors du clic
- Vérification du paiement et chargement du contenu privé
- Affichage du contenu complet une fois débloqué
### Format des articles
Les articles sont publiés sous forme d'événements Nostr avec :
**Note publique (kind:1)** - Aperçu :
- Tags : `title`, `preview`, `zap` (montant en sats)
- Contenu : Aperçu de l'article
**Message privé (kind:4)** - Contenu complet :
- Tag `e` : ID de l'article lié
- Contenu : Contenu complet chiffré avec NIP-04
- Envoyé après réception du zap
### Flux de paiement
1. Utilisateur clique sur "Unlock for 800 sats"
2. Création d'un zap request (kind:9734) avec tags `p`, `e`, `amount`
3. Le zap request est publié sur le relay
4. L'utilisateur complète le paiement via son wallet Lightning
5. Vérification du zap receipt (kind:9735) sur le relay
6. Déchiffrement et affichage du contenu privé
## Modalités de déploiement
### Prérequis
- Node.js 18+ et npm
- Accès à un relay Nostr public ou privé
- Configuration de variables d'environnement optionnelles
### Variables d'environnement
Créer un fichier `.env.local` :
```env
NEXT_PUBLIC_NOSTR_RELAY_URL=wss://relay.damus.io
NEXT_PUBLIC_NOSTRCONNECT_BRIDGE=https://use.nsec.app
```
### Installation
```bash
npm install
```
### Développement
```bash
npm run dev
```
Le site sera accessible sur http://localhost:3000
### Build de production
```bash
npm run build
npm start
```
### Déploiement
Le projet peut être déployé sur :
- Vercel (recommandé pour Next.js)
- Netlify
- Tout hébergeur supportant Node.js
**Important** : Pour la production, configurer :
- Variables d'environnement dans le panneau d'administration
- HTTPS (obligatoire pour NostrConnect)
- Relay Nostr fiable et performant
## Modalités d'analyse
### Logs et debugging
Les erreurs sont loggées dans la console du navigateur :
- Erreurs de connexion aux relais
- Erreurs de déchiffrement
- Erreurs de parsing d'articles
### Métriques à surveiller
1. **Connectivité**
- Taux de connexion réussie via NostrConnect
- Temps de réponse des relais
2. **Articles**
- Nombre d'articles chargés
- Temps de chargement des aperçus
- Taux de conversion (aperçu → déblocage)
3. **Paiements**
- Nombre de zap requests créés
- Taux de confirmation des zaps
- Temps moyen entre zap request et receipt
4. **Utilisateurs**
- Nombre d'utilisateurs connectés
- Profils chargés avec succès
### Points d'amélioration
1. **Gestion des zaps**
- Implémentation complète du flux Lightning avec intégration wallet
- Webhooks pour les confirmations de zap
- Interface de paiement intégrée (LNURL, Lightning Address)
2. **Sécurité**
- Vérification des signatures des zap receipts
- Validation stricte des événements reçus
- Gestion des erreurs de déchiffrement
3. **Performance**
- Mise en cache des articles chargés
- Pagination pour les grandes listes
- Indexation des articles par tags
4. **UX**
- Feedback visuel pendant le traitement des zaps
- Gestion des états de chargement
- Messages d'erreur plus explicites
### Tests recommandés
1. **Tests unitaires**
- Parsing d'événements en articles
- Déchiffrement de messages privés
- Création de zap requests
2. **Tests d'intégration**
- Flux complet de connexion NostrConnect
- Flux complet de déblocage d'article
- Gestion des erreurs réseau
3. **Tests end-to-end**
- Scénario utilisateur complet (connexion → aperçu → paiement → contenu)

View File

@ -1,14 +0,0 @@
# Notifications scope (Dec 2025)
**Decision:** Do not implement notifications for mentions, reposts, or likes. Only payment notifications remain active. If comment notifications are later requested, they must be explicitly approved.
**Impacts:**
- No parsing/subscription for mention/repost/like events.
- UI does not surface badges or panels for these types.
- Avoids extra relay traffic and parsing logic.
**Constraints/quality:**
- No fallbacks.
- No analytics.
- Keep error logging structured if new notification types are ever added.
- Respect accessibility and lint/typing rules already in place.

View File

@ -1,85 +0,0 @@
# Implémentation Priorité 1
**Auteur** : Équipe 4NK
## Objectif
Implémenter les fonctionnalités critiques de priorité 1 :
1. Signature distante pour publication d'articles (NIP-46)
2. Génération d'invoice côté auteur lors de la publication
## Modifications
### 1. Génération d'invoice côté auteur
**Fichiers modifiés** :
- `lib/articlePublisher.ts` : Ajout de la création d'invoice lors de la publication
- `lib/payment.ts` : Vérification de l'invoice de l'auteur avant d'en créer une nouvelle
**Fonctionnement** :
- Lors de la publication, l'auteur crée une facture Lightning via Alby/WebLN
- L'invoice est stockée dans les tags de l'événement Nostr (`invoice`, `payment_hash`)
- L'invoice est également stockée dans localStorage (pour récupération rapide)
- Lors du paiement, le système vérifie d'abord si une invoice existe et n'est pas expirée
- Si aucune invoice valide, le lecteur peut en créer une nouvelle
**Avantages** :
- Meilleure traçabilité (invoice créée par l'auteur)
- L'invoice peut être réutilisée par plusieurs lecteurs
- L'invoice est visible dans l'événement Nostr (tags)
### 2. Signature distante améliorée
**Fichiers modifiés** :
- `lib/nostrRemoteSigner.ts` : Amélioration du support de signature
- `lib/articlePublisher.ts` : Support optionnel de la clé privée
- `components/ArticleEditor.tsx` : Utilisation améliorée
**Fonctionnement** :
- Si la clé privée est disponible (via NostrConnect), utilisation de la signature directe
- Si pas de clé privée, message d'erreur explicite
- Préparation pour future implémentation NIP-46 complète
**Note** : L'implémentation complète de NIP-46 nécessiterait une connexion WebSocket permanente avec un relay, ce qui est complexe. Pour l'instant, le système fonctionne avec les clés privées fournies par NostrConnect via postMessage.
## Détails techniques
### Invoice dans les tags Nostr
Les invoices créées par l'auteur sont stockées dans les tags de l'événement :
```
tags: [
['invoice', 'lnbc...'], // Invoice BOLT11
['payment_hash', 'abc123...'], // Payment hash
]
```
### Stockage local
Les invoices sont également stockées dans localStorage avec le contenu privé :
```json
{
"content": "...",
"authorPubkey": "...",
"articleId": "...",
"invoice": {
"invoice": "lnbc...",
"paymentHash": "...",
"amount": 800,
"expiresAt": 1234567890
},
"createdAt": 1234567890
}
```
## Limitations actuelles
1. **Signature distante** : NIP-46 complet non implémenté (nécessite WebSocket relay)
2. **Stockage invoice** : localStorage côté client (pas accessible entre lecteurs)
3. **Récupération invoice** : Actuellement via localStorage, idéalement depuis les tags de l'événement
## Améliorations futures
1. Parser l'invoice directement depuis les tags de l'événement Nostr
2. Implémenter NIP-46 complet pour la signature distante
3. Utiliser une base de données pour le stockage au lieu de localStorage

View File

@ -1,215 +0,0 @@
# Intégration Rizful.com API pour paiements Lightning et identités
**Auteur** : Équipe 4NK
## Objectif
Intégrer l'API de Rizful.com pour :
- Générer des identités Nostr
- Créer et gérer des factures Lightning pour les paiements d'articles
- Vérifier le statut des paiements Lightning
- Fournir une expérience de paiement fluide via Rizful
## Impacts
### Utilisateurs
- Paiements Lightning facilités via l'infrastructure Rizful
- Interface de paiement améliorée avec modal dédiée
- Vérification automatique des paiements
- Possibilité de générer des identités Nostr via Rizful
### Développeurs
- Service Rizful centralisé pour toutes les opérations de paiement
- Intégration transparente avec le système de paiement existant
- Gestion des factures Lightning standardisée
- API unifiée pour les identités et paiements
### Technique
- Nouveau service `RizfulService` pour les appels API
- Service `PaymentService` intégrant Rizful avec Nostr
- Composant `PaymentModal` pour l'affichage des factures
- Variables d'environnement pour la configuration API
## Modifications
### Nouveaux fichiers
#### `lib/rizful.ts` - Service Rizful API
Service principal pour interagir avec l'API Rizful.com :
- `createInvoice()` : Créer une facture Lightning
- `checkPaymentStatus()` : Vérifier le statut d'un paiement
- `waitForPayment()` : Polling jusqu'à confirmation du paiement
- `generateIdentity()` : Générer une nouvelle identité Nostr
- `getLightningAddress()` : Obtenir l'adresse Lightning d'une identité
- `createPaymentLink()` : Créer un lien de paiement avec URL Lightning
#### `lib/payment.ts` - Service de paiement intégré
Service intégrant Rizful avec le système Nostr :
- `createArticlePayment()` : Créer une facture pour un article
- `checkArticlePayment()` : Vérifier le paiement d'un article
- `waitForArticlePayment()` : Attendre la confirmation du paiement
- `getPaymentUrl()` : Obtenir l'URL de paiement pour un article
#### `types/rizful.ts` - Types TypeScript
Types pour l'API Rizful :
- `RizfulConfig` : Configuration du service
- `RizfulInvoice` : Structure d'une facture Lightning
- `RizfulPaymentStatus` : Statut d'un paiement
- `RizfulIdentity` : Identité Nostr générée
- `RizfulInvoiceRequest` : Requête de création de facture
#### `components/PaymentModal.tsx` - Modal de paiement
Composant React pour afficher la facture Lightning :
- Affichage de la facture en texte
- Bouton pour copier la facture
- Bouton pour ouvrir le wallet Lightning
- Interface utilisateur claire et intuitive
### Modifications des fichiers existants
#### `components/ArticleCard.tsx`
- Intégration du `PaymentService` au lieu du système de zap direct
- Affichage de `PaymentModal` lors de la création d'une facture
- Polling automatique pour vérifier le paiement en arrière-plan
- Gestion améliorée des états de paiement
#### `next.config.js`
- Ajout des variables d'environnement Rizful :
- `RIZFUL_API_KEY` : Clé API Rizful
- `RIZFUL_API_URL` : URL de l'API Rizful (défaut: https://api.rizful.com)
### Flux de paiement avec Rizful
1. **Utilisateur clique sur "Unlock for X sats"**
- Vérification de la connexion Nostr
- Création d'une facture Lightning via Rizful API
2. **Affichage de la modal de paiement**
- Facture Lightning affichée
- Options pour copier ou ouvrir dans wallet
3. **Paiement utilisateur**
- Utilisateur paie via son wallet Lightning
- Paiement traité par Rizful
4. **Vérification du paiement**
- Polling automatique du statut via Rizful API
- Vérification supplémentaire via zap receipt sur Nostr (double confirmation)
5. **Déblocage du contenu**
- Une fois le paiement confirmé, chargement du contenu privé
- Affichage du contenu complet
## Modalités de déploiement
### Prérequis
- Compte Rizful.com avec clé API
- Variables d'environnement configurées
### Configuration
Créer ou mettre à jour le fichier `.env.local` :
```env
# Rizful API Configuration
NEXT_PUBLIC_RIZFUL_API_KEY=your_rizful_api_key_here
NEXT_PUBLIC_RIZFUL_API_URL=https://api.rizful.com
# Existing Nostr configuration
NEXT_PUBLIC_NOSTR_RELAY_URL=wss://relay.damus.io
NEXT_PUBLIC_NOSTRCONNECT_BRIDGE=https://use.nsec.app
```
### Obtenir une clé API Rizful
1. Créer un compte sur [Rizful.com](https://rizful.com/)
2. Accéder aux paramètres du compte
3. Générer une clé API
4. Configurer l'adresse Lightning personnalisée (optionnel)
5. Copier la clé API dans les variables d'environnement
### Déploiement
Aucun changement dans le processus de déploiement standard :
- Les variables d'environnement doivent être configurées dans l'environnement de production
- Le code client peut accéder aux variables `NEXT_PUBLIC_*`
- Les appels API se font depuis le navigateur (CORS doit être configuré côté Rizful)
### Sécurité
- **Clé API** : Stockée côté client (NEXT_PUBLIC_*), donc accessible dans le navigateur
- Rizful devrait implémenter des restrictions par domaine/origine
- Considérer un proxy backend pour protéger la clé API en production
- **Factures Lightning** : Valides uniquement pendant la période d'expiration
- **Vérification double** : Combinaison Rizful API + zap receipts Nostr pour validation
## Modalités d'analyse
### Logs et debugging
Les erreurs sont loggées dans la console du navigateur :
- Erreurs de création de facture
- Erreurs de vérification de paiement
- Timeouts de polling
### Métriques à surveiller
1. **API Rizful**
- Taux de succès des créations de factures
- Temps de réponse de l'API
- Taux de confirmation des paiements
- Erreurs API (rate limiting, authentification, etc.)
2. **Paiements**
- Temps moyen entre création de facture et paiement
- Taux d'abandon de paiement
- Taux de confirmation de paiement
- Échecs de vérification de paiement
3. **Expérience utilisateur**
- Utilisation de la modal vs ouverture directe du wallet
- Taux de copie de facture
- Temps d'attente pour confirmation
### Points d'amélioration
1. **Backend proxy (recommandé pour production)**
- Créer un endpoint Next.js API route pour protéger la clé API
- Appels API depuis le serveur au lieu du client
- Validation supplémentaire côté serveur
2. **Gestion des erreurs**
- Retry logic pour les appels API échoués
- Gestion des timeouts réseau
- Messages d'erreur utilisateur plus explicites
3. **QR Code**
- Génération de QR code pour les factures Lightning
- Affichage dans la modal de paiement
- Compatible avec wallets mobiles
4. **Webhooks**
- Intégration webhooks Rizful pour notifications en temps réel
- Éviter le polling continu
- Réactivité améliorée
5. **Identités**
- Utilisation de `generateIdentity()` pour créer des identités
- Stockage sécurisé des clés privées générées
- Intégration avec le système d'authentification
### Tests recommandés
1. **Tests unitaires**
- `RizfulService.createInvoice()`
- `RizfulService.checkPaymentStatus()`
- `PaymentService.createArticlePayment()`
2. **Tests d'intégration**
- Flux complet de paiement (création → paiement → vérification)
- Gestion des timeouts
- Gestion des erreurs API
3. **Tests end-to-end**
- Scénario utilisateur complet avec paiement réel
- Vérification du déblocage de contenu après paiement

View File

@ -1,23 +0,0 @@
# Storage encryption (IndexedDB) Dec 2025
**Scope**
- Encrypt private article content and invoices stored in IndexedDB using Web Crypto (AES-GCM).
- Deterministic per-article secret derived from a persisted master key.
- No fallbacks; fails if IndexedDB or Web Crypto is unavailable.
**Key management**
- Master key generated once in browser (`article_storage_master_key`, random 32 bytes, base64) and kept in localStorage.
- Per-article secret: `<masterKey>:<articleId>` (used only client-side).
**Implementation**
- `lib/storage/cryptoHelpers.ts`: AES-GCM helpers (base64 encode/decode, encrypt/decrypt).
- `lib/storage/indexedDB.ts`: store/get now require a secret; payloads encrypted; unchanged API surface via `storageService`.
- `lib/articleStorage.ts`: derives per-article secret, encrypts content+invoice on write, decrypts on read, same expiration (30 days).
**Behavior**
- If IndexedDB or crypto is unavailable, operations throw (no silent fallback).
- Existing data written before encryption wont decrypt; new writes are encrypted.
**Next steps (optional)**
- Rotate master key with migration plan.
- Add per-user secrets or hardware-bound keys if required.

View File

@ -1,158 +0,0 @@
# Implémentation de l'amélioration du stockage du contenu privé
**Date** : Décembre 2024
**Status** : ✅ Complété
## Objectif
Remplacer localStorage par IndexedDB pour le stockage du contenu privé des articles, offrant une meilleure fiabilité, une plus grande capacité de stockage et la gestion de l'expiration des données.
## Fonctionnalités implémentées
### 1. Service IndexedDB
- Service IndexedDB complet avec gestion d'initialisation
- Support des index pour les recherches (createdAt, expiresAt)
- Gestion des erreurs
- Utilisation exclusive d'IndexedDB (pas de fallback)
### 3. Gestion de l'expiration
- Expiration automatique des données (30 jours par défaut)
- Suppression automatique des données expirées lors de la récupération
- Méthode pour nettoyer toutes les données expirées
### 4. Migration des fonctions
- Toutes les fonctions de stockage sont maintenant async
- Compatibilité avec l'API existante (même signature, mais async)
- Migration transparente pour le code existant
## Fichiers créés
### `lib/storage/indexedDB.ts`
Service IndexedDB complet :
- `IndexedDBStorage` : Classe pour gérer IndexedDB
- `storageService` : Instance exportée de IndexedDBStorage
- Méthodes : `set()`, `get()`, `delete()`, `clearExpired()`
- Gestion de l'expiration automatique
- Utilisation exclusive d'IndexedDB (pas de fallback)
**Caractéristiques** :
- Base de données : `nostr_paywall`
- Version : 1
- Object store : `article_content`
- Index : `createdAt`, `expiresAt`
### `features/storage-improvement-implementation.md`
Documentation de l'implémentation.
## Fichiers modifiés
### `lib/articleStorage.ts`
- `storePrivateContent()` : Maintenant async, utilise `storageService`
- `getStoredPrivateContent()` : Maintenant async, utilise `storageService`
- `getStoredInvoice()` : Maintenant async
- `removeStoredPrivateContent()` : Maintenant async
- Expiration par défaut : 30 jours
**Changements** :
- Remplacement de `localStorage` par `storageService`
- Ajout de l'expiration automatique (30 jours)
- Toutes les fonctions deviennent async
### `lib/articlePublisher.ts`
- Mise à jour pour utiliser les nouvelles fonctions async
- Suppression des méthodes privées dupliquées
- Utilisation directe des fonctions exportées de `articleStorage`
### `lib/invoiceResolver.ts`
- `getStoredInvoice()` : Maintenant async avec `await`
### `lib/paymentPolling.ts`
- `getStoredPrivateContent()` : Maintenant async avec `await`
## Avantages d'IndexedDB vs localStorage
### IndexedDB
- **Capacité** : Plusieurs Go vs ~5-10 MB pour localStorage
- **Performance** : Meilleure pour les grandes quantités de données
- **Structured** : Base de données structurée avec index
- **Transactions** : Support des transactions
- **Types** : Support des types complexes (Blob, ArrayBuffer, etc.)
### localStorage
- **Simplicité** : API plus simple (clé-valeur)
- **Compatibilité** : Meilleure compatibilité navigateur (mais IndexedDB est maintenant bien supporté)
- **Synchronisation** : API synchrone (plus simple mais peut bloquer)
## Gestion de l'expiration
### Expiration par défaut
- **Durée** : 30 jours (configurable via `DEFAULT_EXPIRATION`)
- **Vérification** : Automatique lors de la récupération
- **Nettoyage** : Les données expirées sont supprimées automatiquement
### Expiration personnalisée
Les données peuvent être stockées avec une expiration personnalisée :
```typescript
await storageService.set(key, data, customExpirationInMs)
```
## Exigence IndexedDB
L'application nécessite IndexedDB pour fonctionner :
- Si IndexedDB n'est pas disponible, une erreur sera levée
- IndexedDB est supporté par tous les navigateurs modernes
- Pas de fallback vers localStorage
## Migration des données existantes
Les données existantes dans localStorage restent accessibles :
- Les nouvelles données sont stockées dans IndexedDB (ou localStorage en fallback)
- Les anciennes données dans localStorage peuvent être lues (si nécessaire)
- Pas de migration automatique nécessaire (les données anciennes seront progressivement remplacées)
## Impact
### Utilisateur
- Stockage plus fiable et performant
- Pas de changement visible dans l'interface
### Technique
- Meilleure gestion du stockage
- Expiration automatique des données
- Support de plus grandes quantités de données
- Code plus robuste avec fallback
## Limitations et améliorations futures
### Limitations actuelles
- Expiration fixe à 30 jours (pas de configuration utilisateur)
- Pas de nettoyage périodique automatique (seulement lors de la récupération)
- Nécessite IndexedDB (pas de fallback)
### Améliorations possibles
- **Migration automatique** : Migrer les données localStorage vers IndexedDB au premier chargement
- **Nettoyage périodique** : Tâche de nettoyage périodique pour supprimer les données expirées
- **Configuration** : Permettre à l'utilisateur de configurer l'expiration
- **Compression** : Compresser les données avant stockage pour économiser l'espace
- **Chiffrement** : Chiffrer les données sensibles avant stockage
## Tests recommandés
1. **Stockage** :
- Stocker du contenu privé
- Vérifier qu'il est stocké correctement
- Vérifier qu'il peut être récupéré
2. **Expiration** :
- Stocker avec expiration courte
- Attendre l'expiration
- Vérifier que les données sont supprimées
3. **IndexedDB requis** :
- Vérifier que l'application fonctionne avec IndexedDB
- Vérifier que les erreurs sont gérées correctement si IndexedDB n'est pas disponible
4. **Performance** :
- Tester avec un grand nombre d'articles
- Vérifier que les performances sont bonnes
- Vérifier qu'il n'y a pas de blocage de l'UI

View File

@ -1,71 +0,0 @@
# Documentation technique zapwall4science (Dec 2025)
## 1) Cartographie services/hooks/types (responsabilités, dépendances)
- **Services Nostr**
- `lib/nostr.ts` : pool SimplePool, publish générique, clés locales; queries article.
- `lib/nostrEventParsing.ts` : parsing events → Article/Series/Review (tags kind_type, series, media, banner).
- `lib/nostrTags.ts` : construction des tags article/série/avis (site, type science-fiction/research, kind_type, media/bannière).
- `lib/seriesQueries.ts`, `lib/articleQueries.ts`, `lib/reviews.ts` : fetch séries, articles par série, critiques.
- `lib/articlePublisher.ts`, `lib/articleMutations.ts` : publication article/preview/presentation, update/delete, kind_type, séries, médias, bannière.
- `lib/seriesAggregation.ts`, `lib/reviewAggregation.ts`, `lib/zapAggregation.ts` : agrégats sponsoring/achats/remerciements.
- `lib/zapVerification.ts` : vérification zap receipts (verifyEvent).
- `lib/nostrconnect.ts` : Nostr Connect (handler, sécurité).
- `lib/nostrRemoteSigner.ts` : signature distante (pas de fallback silencieux).
- `lib/nip95.ts` : upload médias NIP-95 (images ≤5Mo, vidéos ≤45Mo, types restreints).
- **Paiement / Lightning**
- `lib/alby.ts` : WebLN (enable, makeInvoice, sendPayment).
- `lib/payment.ts`, `lib/paymentPolling.ts` : statut paiements, polling.
- `lib/articleInvoice.ts` : facture article (zapAmount, expiry), tags preview.
- **Stockage**
- `lib/storage/cryptoHelpers.ts` : AES-GCM, dérivation/import clé, conversions b64.
- `lib/storage/indexedDB.ts` : set/get/delete/clearExpired chiffré, TTL.
- `lib/articleStorage.ts` : clé maître locale (base64), secret par article, persistance contenu privé + facture.
- **Hooks**
- `hooks/useArticles.ts`, `hooks/useUserArticles.ts` : subscriptions articles, filtres catégorie, unsubscribe direct (pas de .then).
- `hooks/useArticleEditing.ts` : édition/suppression article.
- Autres : `useNotificationCenter`, `useNostrConnect`, etc.
- **Types**
- `types/nostr.ts` : Article, Series, Review, MediaRef, KindType, catégories; exactOptionalPropertyTypes respecté.
- `types/nostr-tools-extended.ts` : extensions SimplePool/Sub.
- `types/alby.ts` : WebLNProvider, invoice types.
## 2) Guide Nostr (publication, update/delete, zap, remote signer)
- Publication générique : `nostrService.publishEvent(eventTemplate)` (signEvent, created_at contrôlé).
- Article : `articlePublisher.publishArticle` (preview + tags kind_type/site/category/series/banner/media), contenu privé chiffré stocké.
- Update article : `publishArticleUpdate` (`lib/articleMutations.ts`) tags `e` (original) + `replace`, publie preview + contenu privé chiffré.
- Delete article : `deleteArticleEvent` (kind 5, tag e) — erreurs remontées, pas de fallback.
- Série : `publishSeries` (kind 1, tags kind_type=series, cover, description).
- Avis : `publishReview` (kind 1, kind_type=review, article/series/author tags).
- Zap verification : `lib/zapVerification.ts` (verifyEvent).
- Agrégats : `aggregateZapSats` / `getSeriesAggregates` / `getReviewTipsForArticle`.
- Remote signer : `lib/nostrRemoteSigner.ts` (clé fournie), sans valeurs de repli implicites.
## 3) Guide Stockage
- Chiffrement : `cryptoHelpers` (AES-GCM), entrée BufferSource conforme Web Crypto.
- IndexedDB : `storage/indexedDB.ts` stocke `{ iv, ciphertext, expiresAt }`, purge `clearExpired`.
- Secret : `articleStorage` génère clé maître (localStorage, base64, 32 bytes) puis secret `<master>:<articleId>`.
- Données : contenu privé + facture, TTL 30 jours, suppression via `removeStoredPrivateContent`.
## 4) Guide Paiements
- WebLN/Alby : `lib/alby.ts` (enable, makeInvoice, sendPayment).
- Facture article : `createArticleInvoice` (zapAmount, expiry).
- Publication article : `articlePublisher` gère preview event + stockage contenu privé.
- Polling / vérif : `paymentPolling.ts`, `payment.ts`; agrégats via zap receipts (`zapAggregation.ts`).
- Envoi contenu privé : via publisher/mutations après paiement confirmé.
## 5) Médias / NIP-95
- Upload via `uploadMedia(file)` (URL `NEXT_PUBLIC_NIP95_UPLOAD_URL`), validation type/taille.
- Utilisation dans `MarkdownEditor` (insertion markdown), bannière dans ArticleDraft.
## 6) Contrib (référence rapide)
- Lint/typage obligatoires (`npm run lint`, `npm run type-check`).
- Pas de tests/analytics ajoutés.
- Pas de fallback implicite, pas de `ts-ignore`/`any` non justifié.
- Accessibilité : ARIA/clavier/contraste.
- Documentation : corrections dans `fixKnowledge/`, features dans `features/`.

View File

@ -1,169 +0,0 @@
# Implémentation du profil utilisateur et des articles de l'utilisateur
**Date** : Décembre 2024
**Status** : ✅ Complété
## Objectif
Permettre aux utilisateurs de visualiser leur profil et la liste de leurs articles publiés.
## Fonctionnalités implémentées
### 1. Page de profil
- Page `/profile` accessible uniquement aux utilisateurs connectés
- Affichage des informations du profil (nom, photo, description, pubkey, nip05)
- Redirection automatique vers la page d'accueil si non connecté
- Compteur d'articles publiés
### 2. Liste des articles de l'utilisateur
- Affichage de tous les articles publiés par l'utilisateur connecté
- Recherche et filtres (comme sur la page d'accueil)
- Tri des articles (nouveaux/anciens, prix)
- Compteur d'articles affichés vs total
### 3. Lien vers le profil
- Le nom/avatar dans `ConnectButton` est maintenant cliquable
- Lien vers `/profile` pour accéder rapidement au profil
### 4. Gestion du profil minimal
- Si aucun profil Nostr n'existe, affichage d'un profil minimal avec le pubkey
- Pas d'erreur si le profil n'existe pas
## Fichiers créés
### `hooks/useUserArticles.ts`
Hook personnalisé pour charger les articles d'un utilisateur spécifique :
- Filtre automatiquement les articles par `pubkey` de l'auteur
- Supporte la recherche et les filtres (comme `useArticles`)
- Gestion de l'état de chargement et des erreurs
- Méthode `loadArticleContent` pour charger le contenu privé
**Signature** :
```typescript
export function useUserArticles(
userPubkey: string,
searchQuery: string = '',
filters: ArticleFilters | null = null
)
```
### `components/UserProfile.tsx`
Composant d'affichage du profil utilisateur :
- Affichage de la photo de profil (ou initiale si pas de photo)
- Nom, pubkey tronqué, nip05
- Description/about si disponible
- Compteur d'articles publiés
**Props** :
```typescript
interface UserProfileProps {
profile: NostrProfile
pubkey: string
articleCount?: number
}
```
### `components/UserArticles.tsx`
Composant pour afficher la liste des articles de l'utilisateur :
- Réutilise `ArticleCard` pour la cohérence UI
- Gestion de l'état de chargement
- Gestion des erreurs
- Message si aucun article publié
- Gestion du déverrouillage des articles payants
**Props** :
```typescript
interface UserArticlesProps {
articles: Article[]
loading: boolean
error: string | null
onLoadContent: (articleId: string, authorPubkey: string) => Promise<Article | null>
showEmptyMessage?: boolean
}
```
### `pages/profile.tsx`
Page de profil utilisateur :
- Vérifie la connexion et redirige si non connecté
- Charge le profil de l'utilisateur connecté
- Affiche le profil avec `UserProfile`
- Affiche les articles avec recherche et filtres
- Header cohérent avec le reste de l'application
- Bouton retour vers la page d'accueil
## Fichiers modifiés
### `components/ConnectButton.tsx`
- Ajout d'un `Link` autour du nom/avatar de l'utilisateur
- Lien vers `/profile` pour accéder au profil
- Hover effect pour indiquer que c'est cliquable
**Changements** :
- Import de `Link` de `next/link`
- Le nom/avatar est maintenant dans un `Link` vers `/profile`
## Flux utilisateur
1. **Accès au profil** :
- L'utilisateur clique sur son nom/avatar dans le header
- Redirection vers `/profile`
- Si non connecté, redirection vers `/`
2. **Visualisation du profil** :
- Affichage des informations du profil
- Compteur d'articles publiés
3. **Gestion des articles** :
- Liste de tous les articles publiés
- Possibilité de rechercher et filtrer
- Possibilité de déverrouiller les articles payants (si l'utilisateur les a payés)
## Impact
### Utilisateur
- Accès facile à son profil et ses articles
- Vue d'ensemble de ses publications
- Recherche et filtres pour trouver rapidement un article spécifique
### Technique
- Code modulaire et réutilisable
- Hook personnalisé pour charger les articles par auteur
- Composants réutilisables (UserProfile, UserArticles)
- Cohérence UI avec le reste de l'application
## Limitations et améliorations futures
### Limitations actuelles
- Pas de statistiques détaillées (vues, paiements reçus)
- Pas d'édition/suppression d'articles
- Le profil ne peut être modifié que via Nostr (pas d'édition dans l'app)
### Améliorations possibles
- **Statistiques** : Ajouter un composant `ArticleStats` pour afficher :
- Nombre total de vues
- Nombre de paiements reçus
- Revenus totaux
- **Édition d'articles** : Permettre d'éditer/supprimer les articles publiés
- **Profil public** : Créer `/user/[pubkey]` pour voir le profil de n'importe quel utilisateur
- **Optimisation** : Filtrer les articles par auteur au niveau du relay (au lieu du client)
## Tests recommandés
1. **Accès au profil** :
- Se connecter et cliquer sur le nom/avatar
- Vérifier la redirection vers `/profile`
- Se déconnecter et essayer d'accéder à `/profile` directement
2. **Affichage du profil** :
- Vérifier l'affichage du nom, photo, description
- Vérifier le compteur d'articles
- Tester avec un profil qui n'a pas de photo/nom
3. **Articles** :
- Publier quelques articles et vérifier qu'ils apparaissent
- Tester la recherche et les filtres
- Vérifier le compteur d'articles
4. **Performance** :
- Tester avec un grand nombre d'articles
- Vérifier que le chargement n'est pas bloquant