diff --git a/docs/.obsidian/graph.json b/docs/.obsidian/graph.json new file mode 100644 index 0000000..08b2917 --- /dev/null +++ b/docs/.obsidian/graph.json @@ -0,0 +1,22 @@ +{ + "collapse-filter": true, + "search": "", + "showTags": false, + "showAttachments": false, + "hideUnresolved": false, + "showOrphans": true, + "collapse-color-groups": true, + "colorGroups": [], + "collapse-display": true, + "showArrow": false, + "textFadeMultiplier": 0, + "nodeSizeMultiplier": 1, + "lineSizeMultiplier": 1, + "collapse-forces": true, + "centerStrength": 0.518713248970312, + "repelStrength": 10, + "linkStrength": 1, + "linkDistance": 250, + "scale": 0.6488873738523617, + "close": false +} \ No newline at end of file diff --git a/docs/.obsidian/workspace.json b/docs/.obsidian/workspace.json index 506705b..62a28b4 100644 --- a/docs/.obsidian/workspace.json +++ b/docs/.obsidian/workspace.json @@ -13,12 +13,12 @@ "state": { "type": "markdown", "state": { - "file": "04-migrations/dependency-injection-migration.md", + "file": "01-architecture/modular-design.md", "mode": "source", "source": false }, "icon": "lucide-file", - "title": "dependency-injection-migration" + "title": "modular-design" } } ] @@ -170,7 +170,16 @@ }, "active": "fe085d296b05d361", "lastOpenFiles": [ + "06-deployment/index.md", + "04-migrations/dependency-injection-migration.md", + "01-architecture/modular-design.md", "01-architecture/index.md", + "01-architecture/authentication-architecture.md", + "01-architecture/modular-design.md.tmp.1581693.1757246120074", + "01-architecture/modular-design.md.tmp.1581693.1757246069013", + "01-architecture/modular-design.md.tmp.1581693.1757245931642", + "03-core-services/authentication.md.tmp.1581693.1757245911412", + "03-core-services/authentication.md.tmp.1581693.1757245834001", "00-overview/index.md" ] } \ No newline at end of file diff --git a/docs/01-architecture/modular-design.md b/docs/01-architecture/modular-design.md index d7a6c7d..81d4487 100644 --- a/docs/01-architecture/modular-design.md +++ b/docs/01-architecture/modular-design.md @@ -1,419 +1,391 @@ -# Modular Architecture Analysis & Infrastructure Abstractions +# 🔧 Modular Design Patterns -**Project**: Ario Web Application -**Date**: September 5, 2025 -**Scope**: Analysis of modular plugin architecture for centralization opportunities +> **Plugin-based architecture** enabling scalable, maintainable, and extensible feature development with dependency injection, service abstractions, and clean modular boundaries. + +## Table of Contents + +- [[#Design Philosophy]] +- [[#Architecture Components]] +- [[#Service Abstractions]] +- [[#Module Development]] +- [[#Implementation Patterns]] +- [[#Benefits & Trade-offs]] + +## Design Philosophy + +### **Separation of Concerns** +Each module owns its complete domain logic, from data models to UI components, ensuring clear boundaries and reducing coupling between features. + +### **Dependency Injection** +Services communicate through well-defined interfaces using a centralized DI container, enabling loose coupling and testability. + +### **Plugin-Based Development** +Features are implemented as self-contained modules that can be independently developed, tested, and deployed. + +### **Reactive Architecture** +Services integrate Vue's reactivity system to provide automatic UI updates and consistent state management. --- -## Executive Summary +## Architecture Components -The Ario web application demonstrates a well-architected modular system using Vue 3, TypeScript, and dependency injection. After comprehensive analysis of all modules, we've identified **significant opportunities for code consolidation** that could reduce duplication by 30-40% while improving maintainability, type safety, and development velocity. +### **Plugin Manager** +Orchestrates module loading, dependency resolution, and lifecycle management: -**Key Findings**: -- **16+ duplicate patterns** across modules requiring abstraction -- **Common async operation pattern** found in 12+ files -- **Service dependency injection** pattern duplicated in 7+ services -- **Payment processing logic** duplicated between market and events modules -- **User-scoped storage** pattern repeated across multiple stores - -**Recent Progress (September 6, 2025)**: -- ✅ **Legacy relay infrastructure cleanup completed** -- ✅ Removed redundant NostrclientHub service -- ✅ Removed legacy NostrStore Pinia store -- ✅ Standardized on RelayHub service for all Nostr operations -- ✅ Updated dependency injection to remove unused tokens - ---- - -## Current Module Structure - -### Base Module (`src/modules/base/`) -- **Purpose**: Core infrastructure (Nostr, Auth, PWA) -- **Key Services**: Authentication, Relay Hub, Payment Service, Visibility Service -- **Status**: Well-established foundation with recent cleanup of legacy relay infrastructure - -### Chat Module (`src/modules/chat/`) -- **Purpose**: Encrypted Nostr chat functionality -- **Key Features**: NIP-04 encryption, DM handling, peer management -- **Dependencies**: Base module services - -### Events Module (`src/modules/events/`) -- **Purpose**: Event ticketing with Lightning payments -- **Key Features**: Ticket purchase, Lightning integration, QR codes -- **Dependencies**: Base module, payment processing - -### Market Module (`src/modules/market/`) -- **Purpose**: Nostr marketplace with order management -- **Key Features**: Product catalog, order processing, payment handling -- **Dependencies**: Base module, payment processing, storage - -### Nostr Feed Module (`src/modules/nostr-feed/`) -- **Purpose**: Social feed functionality -- **Key Features**: Note filtering, admin posts, real-time updates -- **Dependencies**: Base module services - ---- - -## Identified Duplicate Patterns - -### 1. Async Operation Pattern ⭐ **HIGH PRIORITY** - -**Occurrences**: Found in **12+ files** across all modules - -**Current Implementation**: ```typescript -// Repeated in every composable/component -const isLoading = ref(false) -const error = ref(null) -const data = ref(null) - -try { - isLoading.value = true - // operation -} catch (err) { - error.value = err.message -} finally { - isLoading.value = false +class PluginManager { + async loadModules(modules: ModulePlugin[]): Promise + getDependencyGraph(): Map + validateDependencies(modules: ModulePlugin[]): void } ``` -**Impact**: -- 200+ lines of duplicate code -- Inconsistent error handling -- Manual loading state management +### **Dependency Injection Container** +Manages service registration, injection, and lifecycle: -### 2. Service Dependency Injection ⭐ **HIGH PRIORITY** - -**Occurrences**: Found in **7+ service files** - -**Current Implementation**: ```typescript -// Repeated in every service -const relayHub = injectService(SERVICE_TOKENS.RELAY_HUB) as any -const authService = injectService(SERVICE_TOKENS.AUTH_SERVICE) as any +// Service registration +container.provide(SERVICE_TOKENS.RELAY_HUB, relayHub) -if (!relayHub) { - throw new Error('RelayHub not available') +// Service consumption +const relayHub = injectService(SERVICE_TOKENS.RELAY_HUB) +``` + +### **BaseService Architecture** +Abstract foundation providing common patterns for all services: + +```typescript +abstract class BaseService { + protected readonly metadata: ServiceMetadata + protected dependencies = new Map() + + abstract initialize(): Promise + abstract dispose(): Promise } ``` -**Impact**: -- Type safety issues (`as any` casting) -- Duplicate dependency checking -- Inconsistent error messages +### **Module Plugin Interface** +Standardized contract for all feature modules: -### 3. Payment Processing Logic ⭐ **HIGH PRIORITY** - -**Occurrences**: Duplicated between market and events modules - -**Current Implementation**: ```typescript -// Similar logic in both modules -const payInvoiceWithWallet = async (bolt11: string) => { - // Lightning payment logic - // QR code generation - // Success/error handling - // Toast notifications +interface ModulePlugin { + name: string + version: string + dependencies: string[] + + install(app: App, options?: ModuleConfig): Promise + routes?: RouteRecordRaw[] + components?: Record } ``` -**Impact**: -- 150+ lines of duplicate payment logic -- Inconsistent payment UX -- Duplicate error handling +## Service Abstractions -### 4. User-Scoped Storage Pattern +### **Core Infrastructure Services** -**Occurrences**: Found in market store, chat service +#### **AuthService** - User Identity Management +- **Purpose**: Centralized authentication with Nostr key handling +- **Features**: Session management, profile updates, secure key storage +- **Pattern**: BaseService with reactive state management -**Current Implementation**: +#### **RelayHub** - Nostr Connection Management +- **Purpose**: Centralized relay connections and event processing +- **Features**: Connection pooling, automatic reconnection, event deduplication +- **Pattern**: Service singleton with connection state management + +#### **InvoiceService** - Lightning Payment Processing +- **Purpose**: Unified Lightning Network integration +- **Features**: Invoice creation, payment monitoring, QR code generation +- **Pattern**: BaseService with LNBits API integration + +#### **ToastService** - User Notifications +- **Purpose**: Consistent notification system across modules +- **Features**: Context-specific messages, accessibility support +- **Pattern**: Service with method categorization by context + +#### **StorageService** - User-Scoped Data Persistence +- **Purpose**: Secure, user-isolated local storage operations +- **Features**: Encryption, type safety, reactive storage +- **Pattern**: Service with automatic user prefixing + +### **Shared Composables** + +#### **useAuth()** - Authentication Access ```typescript -// Pattern repeated across modules -const getUserStorageKey = (baseKey: string) => { - const userPubkey = auth.currentUser?.value?.pubkey - return userPubkey ? `${baseKey}_${userPubkey}` : baseKey -} +const auth = useAuth() +const { isAuthenticated, currentUser, login, logout } = auth ``` -**Impact**: -- Duplicate storage key logic -- Potential data consistency issues - -### 5. Module Registration Pattern - -**Occurrences**: Every module (`index.ts` files) - -**Current Implementation**: +#### **useToast()** - Notification Access ```typescript -// Identical structure in every module -export const modulePlugin: ModulePlugin = { - name: 'module-name', - install(app: App, options) { - // Service registration - // Component registration - // Route registration - // Event setup - }, - uninstall() { - // Cleanup logic - } -} -``` - -**Impact**: -- Boilerplate code in every module -- Inconsistent registration patterns - -### 6. Toast Notification Pattern - -**Occurrences**: Found in 4+ files - -**Current Implementation**: -```typescript -// Inconsistent usage across modules -toast.success('Operation successful!') +const toast = useToast() +toast.success('Operation completed!') toast.error('Operation failed') ``` -**Impact**: -- Inconsistent notification styling -- Duplicate notification logic - ---- - -## Recommended Abstractions - -### 1. Core Infrastructure Abstractions - -#### A. `useAsyncOperation` Composable -**Location**: `src/core/composables/useAsyncOperation.ts` - +#### **useStorage()** - Storage Access ```typescript -export function useAsyncOperation() { - const isLoading = ref(false) - const error = ref(null) - const data = ref(null) - - const execute = async (operation: () => Promise, options?: { - successMessage?: string - errorMessage?: string - showToast?: boolean - }) => { - // Standardized loading/error/success handling - } - - return { isLoading, error, data, execute, reset } -} +const storage = useStorage() +const userData = storage.getUserData('preferences', defaultPrefs) ``` -**Benefits**: -- ✅ Eliminates 200+ lines of duplicate code -- ✅ Consistent error handling across all modules -- ✅ Standardized loading states -- ✅ Optional toast notification integration +## Module Development -#### B. `BaseService` Abstract Class -**Location**: `src/core/base/BaseService.ts` +### **Module Structure Pattern** +Each module follows a consistent directory structure: + +``` +src/modules/[module-name]/ +├── index.ts # Module plugin definition +├── components/ # Module-specific UI components +├── composables/ # Module composables and hooks +├── services/ # Business logic services +├── stores/ # Module-specific Pinia stores +├── types/ # TypeScript type definitions +└── views/ # Page components and routes +``` + +### **Service Development Pattern** +Services extend BaseService for consistent lifecycle management: ```typescript -export abstract class BaseService { - protected relayHub: any - protected authService: any +export class MyService extends BaseService { + protected readonly metadata = { + name: 'MyService', + dependencies: ['AuthService', 'RelayHub'] + } constructor() { - // Proper dependency injection with type safety + super() } - protected async initialize(): Promise { - await this.waitForDependencies() - await this.onInitialize() + async initialize(): Promise { + await super.initialize() // Initialize dependencies + // Service-specific initialization + this.isInitialized.value = true } - protected requireAuth() { - // Centralized auth requirement checking + async dispose(): Promise { + // Cleanup logic + this.isDisposed.value = true } +} +``` + +### **Module Registration Pattern** +Standardized module plugin structure: + +```typescript +export const myModule: ModulePlugin = { + name: 'my-module', + version: '1.0.0', + dependencies: ['base'], + async install(app: App, options?: MyModuleConfig) { + // 1. Create and register services + const myService = new MyService() + container.provide(SERVICE_TOKENS.MY_SERVICE, myService) + + // 2. Register global components + app.component('MyGlobalComponent', MyGlobalComponent) + + // 3. Initialize services + await myService.initialize() + }, + + routes: [ + { + path: '/my-feature', + component: () => import('./views/MyFeatureView.vue') + } + ] +} +``` + +### **Dependency Declaration** +Services declare dependencies through metadata: + +```typescript +protected readonly metadata = { + name: 'ChatService', + dependencies: ['AuthService', 'RelayHub', 'StorageService'] +} + +// Access injected dependencies +private get authService(): AuthService { + return this.dependencies.get('AuthService') as AuthService +} +``` + +## Implementation Patterns + +### **Cross-Module Communication** + +#### **Service Dependencies** +For required functionality between modules: +```typescript +// ✅ Correct: Use dependency injection +const relayHub = injectService(SERVICE_TOKENS.RELAY_HUB) + +// ❌ Wrong: Direct import breaks modularity +import { relayHub } from '../base/services/relay-hub' +``` + +#### **Event Bus Communication** +For optional cross-module notifications: +```typescript +// Publishing events +eventBus.emit('user:authenticated', { userId: user.pubkey }) +eventBus.emit('payment:received', { amount: 1000, invoiceId: 'abc123' }) + +// Subscribing to events +eventBus.on('chat:message-received', (message) => { + // Handle cross-module events +}) +``` + +#### **Shared Components** +Modules can export components for reuse: +```typescript +// In module plugin definition +export const chatModule: ModulePlugin = { + components: { + 'ChatAvatar': () => import('./components/ChatAvatar.vue'), + 'MessageBubble': () => import('./components/MessageBubble.vue') + } +} + +// Usage in other modules + +``` + +### **State Management Patterns** + +#### **Service-Based State** +Core state managed by services: +```typescript +// AuthService manages authentication state +export class AuthService extends BaseService { + public isAuthenticated = ref(false) + public user = ref(null) + + // Computed properties for components + public userDisplay = computed(() => this.user.value?.name || 'Anonymous') +} +``` + +#### **Module-Specific Stores** +Complex state handled by Pinia stores: +```typescript +// Market module store +export const useMarketStore = defineStore('market', () => { + const products = ref([]) + const cartItems = ref([]) + + // Access shared services + const auth = useAuth() + const toast = useToast() + + return { products, cartItems } +}) +``` + +### **Error Handling Patterns** + +#### **Service-Level Error Handling** +Centralized error handling in services: +```typescript +export class MyService extends BaseService { protected handleError(error: Error, context: string) { - // Standardized error handling and reporting + console.error(`[${this.metadata.name}] ${context}:`, error) + + // Use toast service for user notifications + const toast = injectService(SERVICE_TOKENS.TOAST_SERVICE) + toast.error(`${context} failed: ${error.message}`) } } ``` -**Benefits**: -- ✅ Eliminates `as any` type casting -- ✅ Consistent dependency management -- ✅ Standardized service lifecycle -- ✅ Better error handling and debugging +#### **Component-Level Error Handling** +Consistent error display in components: +```vue + -```typescript -export class PaymentService extends BaseService { - async processLightningPayment(bolt11: string, orderId?: string): Promise - async generateQRCode(paymentRequest: string): Promise - async monitorPaymentStatus(paymentHash: string): Promise -} + ``` -**Benefits**: -- ✅ Eliminates 150+ lines of duplicate payment logic -- ✅ Consistent payment UX across market and events -- ✅ Centralized payment monitoring and error handling -- ✅ Single source of truth for Lightning integration +## Benefits & Trade-offs -#### D. `StorageService` Abstraction -**Location**: `src/core/services/StorageService.ts` +### **Achieved Benefits** -```typescript -export class StorageService { - setUserData(key: string, data: T): void - getUserData(key: string, defaultValue?: T): T | undefined - clearUserData(key: string): void -} -``` +#### **Development Velocity** +- **Consistent Patterns** - Standardized development approaches across modules +- **Reusable Services** - Shared infrastructure reduces implementation time +- **Type Safety** - Dependency injection eliminates `as any` casting +- **Clear Boundaries** - Module separation simplifies feature development -**Benefits**: -- ✅ User-scoped storage abstraction -- ✅ Type-safe storage operations -- ✅ Consistent data isolation between users +#### **Maintainability** +- **Single Source of Truth** - Centralized services eliminate duplication +- **Dependency Visibility** - Clear service relationships and requirements +- **Testability** - Isolated modules and mockable dependencies +- **Extensibility** - Easy to add new modules without affecting existing ones -### 2. UI/UX Standardization +#### **User Experience** +- **Consistent Interface** - Unified patterns across all features +- **Reliable Performance** - Optimized shared services +- **Progressive Loading** - Lazy-loaded modules for faster initial load +- **Error Recovery** - Consistent error handling and user feedback -#### A. Notification Service -**Location**: `src/core/services/NotificationService.ts` +### **Architectural Trade-offs** -```typescript -export class NotificationService { - success(message: string, options?: NotificationOptions): void - error(message: string, options?: NotificationOptions): void - info(message: string, options?: NotificationOptions): void -} -``` +#### **Complexity vs. Flexibility** +- **Increased Initial Setup** - More boilerplate for dependency injection +- **Enhanced Flexibility** - Easy to swap implementations and add features +- **Learning Curve** - Developers need to understand DI patterns +- **Long-term Benefits** - Reduced complexity as application grows -#### B. Module Registration Utilities -**Location**: `src/core/utils/moduleRegistration.ts` +#### **Performance Considerations** +- **Service Initialization** - Dependency resolution overhead at startup +- **Memory Efficiency** - Singleton services reduce memory usage +- **Bundle Optimization** - Module-based code splitting improves loading +- **Runtime Performance** - Optimized shared services benefit all modules -```typescript -export function createModulePlugin(config: ModuleConfig): ModulePlugin { - // Standardized module registration with error handling -} -``` +### **Best Practices Established** + +1. **Always use dependency injection** for cross-module service access +2. **Extend BaseService** for all business logic services +3. **Declare dependencies explicitly** in service metadata +4. **Use reactive state** for UI-affecting service properties +5. **Handle errors consistently** through standardized patterns +6. **Test modules in isolation** with mocked dependencies + +## See Also + +### Architecture Documentation +- **[[index|🏗️ Architecture Overview]]** - System design principles +- **[[dependency-injection|⚙️ Dependency Injection]]** - DI container system +- **[[authentication-architecture|🔐 Authentication Architecture]]** - Auth service patterns + +### Development Guides +- **[[../04-development/index|💻 Development Guide]]** - Module development workflows +- **[[../02-modules/index|📦 Module System]]** - Individual module documentation +- **[[../03-core-services/index|⚙️ Core Services]]** - Infrastructure service details --- -## Implementation Roadmap - -### Phase 1: High-Impact Core Abstractions (Week 1-2) -1. **Create `useAsyncOperation` composable** - - Implement core functionality - - Replace usage in 12+ files - - **Expected Impact**: 40% reduction in loading/error code - -2. **Create `BaseService` abstract class** - - Implement dependency injection abstraction - - Migrate 7+ services to inherit from BaseService - - **Expected Impact**: Eliminate `as any` casting, improve type safety - -### Phase 2: Service Consolidation (Week 3-4) -3. **Create `PaymentService` centralization** - - Consolidate market and events payment logic - - Implement centralized QR code generation - - **Expected Impact**: 30% reduction in payment-related code - -4. **Create `StorageService` abstraction** - - Implement user-scoped storage - - Migrate existing storage patterns - - **Expected Impact**: Consistent data isolation - -### Phase 3: UX Standardization (Week 5-6) -5. **Create `NotificationService`** - - Standardize toast notifications - - Implement consistent messaging - - **Expected Impact**: Unified notification experience - -6. **Create module registration utilities** - - Simplify module creation process - - Standardize registration patterns - - **Expected Impact**: Faster module development - ---- - -## Expected Benefits - -### Development Velocity -- **40% faster module development** with reusable patterns -- **Reduced onboarding time** for new developers -- **Consistent development patterns** across team - -### Code Quality -- **30-40% reduction in duplicate code** -- **Improved type safety** with proper service injection -- **Standardized error handling** across all modules -- **Better test coverage** of centralized functionality - -### User Experience -- **Consistent loading states** across all features -- **Unified error messaging** and handling -- **Standardized payment flows** between market and events -- **Better performance** through optimized common operations - -### Maintainability -- **Single source of truth** for common patterns -- **Easier debugging** with centralized error handling -- **Propagated improvements** - enhancements benefit all modules -- **Reduced technical debt** through consolidation - ---- - -## Risk Assessment - -### Low Risk -- **Backward compatibility**: New abstractions won't break existing functionality -- **Incremental adoption**: Can be implemented module by module -- **Fallback options**: Existing patterns remain functional during transition - -### Medium Risk -- **TypeScript complexity**: Need careful typing for generic abstractions -- **Testing coverage**: Must ensure centralized code is thoroughly tested - -### Mitigation Strategies -- **Comprehensive testing** of all abstracted functionality -- **Gradual migration** one module at a time -- **Maintain existing APIs** during transition period - ---- - -## Success Metrics - -### Quantitative Metrics -- **Lines of Code**: Target 30-40% reduction in common patterns -- **Type Safety**: Eliminate all `as any` casting in services -- **Test Coverage**: Achieve 90%+ coverage of centralized functionality -- **Build Performance**: Maintain sub-6s production build times - -### Qualitative Metrics -- **Developer Experience**: Faster module development and onboarding -- **Code Consistency**: Uniform patterns across all modules -- **Error Handling**: Consistent error reporting and recovery -- **User Experience**: Uniform loading states and notifications - ---- - -## Conclusion - -The modular architecture analysis reveals a mature, well-structured codebase with **significant opportunities for optimization**. The identified abstractions will: - -1. **Reduce code duplication** by 30-40% in common patterns -2. **Improve type safety** and eliminate `as any` casting -3. **Standardize user experience** across all modules -4. **Accelerate future development** through reusable patterns - -**Recommendation**: Proceed with **Phase 1 implementation** starting with `useAsyncOperation` and `BaseService` abstractions, which will deliver immediate benefits with minimal risk. - -The proposed changes align with the existing architectural principles while providing substantial improvements in maintainability, developer experience, and code quality. - ---- - -*This analysis was conducted on September 5, 2025, based on the current state of the Ario web application modular architecture.* \ No newline at end of file +**Tags:** #architecture #modular-design #dependency-injection #plugin-system +**Last Updated:** 2025-09-07 +**Author:** Development Team \ No newline at end of file diff --git a/docs/03-core-services/authentication.md b/docs/03-core-services/authentication.md index 0d99f72..3801e5e 100644 --- a/docs/03-core-services/authentication.md +++ b/docs/03-core-services/authentication.md @@ -1,172 +1,261 @@ -# Authentication System +# 🔐 Authentication Service -This web application now uses LNBits username/password authentication instead of Nostr keypairs. +> **User identity and session management** with Nostr key handling, dependency injection architecture, and secure client-side key management. -## Overview +## Table of Contents -The authentication system has been completely replaced with a traditional username/password system that integrates with LNBits. Users can now: +- [[#Service Overview]] +- [[#Architecture]] +- [[#Key Features]] +- [[#Usage Patterns]] +- [[#Authentication Flow]] +- [[#Security Considerations]] -- Register new accounts with username and password -- Login with username/email and password -- Manage their profile information -- Logout securely +## Service Overview -## Configuration +The `AuthService` is a core infrastructure service that manages user authentication, identity, and session state throughout the application. It provides secure Nostr key management with client-side encryption and reactive state management. -### Environment Variables - -Create a `.env` file in the `web-app` directory with the following variables: - -```env -# LNBits Base URL Configuration -# Set this to your LNBits instance base URL -# Example: http://localhost:5000 or https://your-lnbits-instance.com -VITE_LNBITS_BASE_URL=http://localhost:5000 - -# Enable debug logging for LNBits API calls -VITE_LNBITS_DEBUG=false - -# App Configuration -VITE_APP_TITLE=Ario -VITE_APP_DESCRIPTION=Your secure platform for events and community management -``` - -### LNBits Setup - -1. Ensure your LNBits instance is running and accessible -2. Make sure the username/password authentication method is enabled in LNBits -3. Configure CORS if your LNBits instance is on a different domain - -## API Endpoints - -The application uses the following LNBits API endpoints: - -- `POST /api/v1/auth` - Login -- `POST /api/v1/auth/register` - Register new user -- `POST /api/v1/auth/logout` - Logout -- `GET /api/v1/auth` - Get current user -- `PUT /api/v1/auth/password` - Update password -- `PUT /api/v1/auth/update` - Update profile - -## Components - -### New Components - -- `LoginDialog.vue` - Modal dialog for login/register -- `UserProfile.vue` - Display user information and logout -- `Login.vue` - Full-page login/register form - -### Updated Components - -- `App.vue` - Now uses new authentication system -- `Navbar.vue` - Shows user status and logout option -- `Home.vue` - Displays welcome message and user profile - -## Authentication Flow - -1. **App Initialization**: The app checks for existing authentication token on startup -2. **Route Protection**: Routes with `requiresAuth: true` redirect to login if not authenticated -3. **Login/Register**: Users can create accounts or login with existing credentials -4. **Token Management**: Access tokens are stored in localStorage and automatically included in API requests -5. **Logout**: Clears tokens and redirects to login page - -## Security Features - -- JWT tokens for session management -- Secure password handling (handled by LNBits) -- Automatic token refresh -- Route protection for authenticated pages -- Secure logout with token cleanup +**Service Token**: `SERVICE_TOKENS.AUTH_SERVICE` +**Location**: `src/modules/base/auth/auth-service.ts` +**Dependencies**: `LnbitsAPI` for backend integration ## Architecture -The authentication system uses a **dependency injection pattern** for clean modular architecture: - -### Core Components - -1. **AuthService** (`src/modules/base/auth/auth-service.ts`) - - Singleton service that manages authentication state - - Handles API calls to LNBits - - Provides reactive state management - -2. **useAuthService** (`src/composables/useAuthService.ts`) - - Wrapper composable that provides unified access to AuthService - - Uses dependency injection to access the service - - Provides consistent API for all components - -3. **Dependency Injection Container** (`src/core/di-container.ts`) - - Manages service registration and injection - - Ensures single source of truth across modules - -### Usage Pattern - -Components access authentication through the `useAuth()` composable: +### Dependency Injection Pattern +The authentication system uses dependency injection for clean, modular access: ```typescript +// Service registration (base module) +container.provide(SERVICE_TOKENS.AUTH_SERVICE, authService) + +// Service consumption (components) +const auth = useAuth() // Via composable wrapper + +// Service consumption (other services) +const authService = injectService(SERVICE_TOKENS.AUTH_SERVICE) +``` + +### Reactive State Management +AuthService integrates Vue's reactivity system for automatic UI updates: + +```typescript +export class AuthService extends BaseService { + public isAuthenticated = ref(false) + public user = ref(null) + public isLoading = ref(false) + public error = ref(null) + + // Computed properties for component compatibility + public currentUser = computed(() => this.user.value) + public userDisplay = computed(() => this.user.value?.name || 'Anonymous') +} +``` + +## Key Features + +### 🔑 **Nostr Key Management** +- **Secure Key Generation** - Client-side key pair creation with proper entropy +- **Key Import/Export** - Support for existing Nostr keys (nsec/hex formats) +- **Encrypted Storage** - User keys encrypted with password-derived encryption +- **Key Recovery** - Secure key backup and restoration mechanisms + +### 👤 **User Identity & Profiles** +- **Nostr Profile Management** - NIP-01 compatible user metadata +- **Profile Updates** - Real-time profile information synchronization +- **Display Name Handling** - Fallback from name → display_name → truncated pubkey +- **Avatar Support** - Profile picture URLs with fallback handling + +### 🔒 **Session Management** +- **Persistent Sessions** - Secure localStorage-based session persistence +- **Auto-Initialization** - Automatic session restoration on app startup +- **Secure Logout** - Complete session cleanup and key removal +- **Token Management** - LNBits API token handling and refresh + +### 🌐 **Backend Integration** +- **LNBits API** - Wallet integration for Lightning functionality +- **Event Publishing** - User profile publishing to Nostr relays +- **Real-time Updates** - Reactive profile updates across relays + +## Usage Patterns + +### Component Usage (Recommended) +```vue + +``` + +### Service Usage (Other Services) +```typescript +import { injectService, SERVICE_TOKENS } from '@/core/di-container' + +export class ChatService extends BaseService { + private get authService(): AuthService { + return this.dependencies.get('AuthService') as AuthService + } + + async sendMessage(content: string) { + const user = this.authService.user.value + if (!user?.pubkey || !user?.prvkey) { + throw new Error('Authentication required') } + + // Use authenticated user data for message signing + } +} +``` + +### Store Integration +```typescript +// In Pinia stores +export const useMyStore = defineStore('myStore', () => { + const auth = useAuth() + + // Reactive dependency on auth state + const userSpecificData = computed(() => { + if (!auth.isAuthenticated.value) return [] + return loadDataForUser(auth.currentUser.value.pubkey) + }) + + return { userSpecificData } +}) +``` + +## Authentication Flow + +### 1. App Initialization +```typescript +// App startup sequence +const authService = injectService(SERVICE_TOKENS.AUTH_SERVICE) +await authService.initialize() + +if (authService.isAuthenticated.value) { + // User has valid session - proceed to app +} else { + // Redirect to login/onboarding +} +``` + +### 2. User Login Process +1. **Key Input** - User provides private key (nsec, hex, or generates new) +2. **Key Validation** - Validate key format and derive public key +3. **Profile Loading** - Fetch existing Nostr profile if available +4. **Session Creation** - Encrypt and store keys securely +5. **Service Initialization** - Initialize user-scoped services +6. **UI Updates** - Reactive state triggers navigation/UI changes + +### 3. Authentication Guards +```typescript +// Router guards use auth service +router.beforeEach((to, from, next) => { + const authService = injectService(SERVICE_TOKENS.AUTH_SERVICE) + + if (to.meta.requiresAuth && !authService.isAuthenticated.value) { + next('/login') + } else { + next() } }) ``` -### Service Registration +### 4. Logout Process +1. **Session Cleanup** - Clear encrypted keys from storage +2. **Service Reset** - Reset all user-scoped service state +3. **Relay Cleanup** - Close user-specific Nostr subscriptions +4. **UI Reset** - Clear user data from stores and components +5. **Navigation** - Redirect to login/public areas -The AuthService is registered in the base module and made available through dependency injection: +## Security Considerations +### 🔐 **Client-Side Security** +- **No Server Keys** - Private keys never leave the client +- **Encrypted Storage** - Keys encrypted with user-provided password +- **Memory Management** - Secure key handling in memory +- **Input Validation** - Strict validation of key formats and data + +### 🌐 **Network Security** +- **HTTPS Only** - All API calls over encrypted connections +- **Token Security** - LNBits tokens with appropriate scoping +- **Request Validation** - API request signature verification +- **Error Handling** - No sensitive data in error messages + +### 🛡️ **Data Protection** +- **User-Scoped Storage** - Data isolation between users +- **Automatic Cleanup** - Session data cleared on logout +- **Profile Privacy** - Configurable profile information sharing +- **Key Rotation** - Support for updating authentication credentials + +## API Reference + +### AuthService Methods ```typescript -// In base module -container.provide(SERVICE_TOKENS.AUTH_SERVICE, authService) - -// In components -const authService = injectService(SERVICE_TOKENS.AUTH_SERVICE) +interface AuthService { + // Core authentication + login(credentials: LoginCredentials): Promise + logout(): Promise + initialize(): Promise + + // Key management + generateKeyPair(): Promise<{ pubkey: string, prvkey: string }> + importPrivateKey(key: string): Promise + exportPrivateKey(): string | null + + // Profile management + updateProfile(profile: UserMetadata): Promise + publishProfile(): Promise + + // Reactive state (readonly) + readonly isAuthenticated: ComputedRef + readonly currentUser: ComputedRef + readonly userDisplay: ComputedRef + readonly isLoading: Ref + readonly error: Ref +} ``` -## Migration from Legacy Architecture +### LoginCredentials Interface +```typescript +interface LoginCredentials { + privateKey?: string // Existing key (nsec or hex) + generateNew?: boolean // Generate new key pair + password?: string // For key encryption + profile?: UserMetadata // Initial profile data +} +``` -The following components have been updated: +## See Also -- **Legacy**: Global `useAuth.ts` composable → **Current**: `useAuthService.ts` with dependency injection -- **Legacy**: Direct service imports → **Current**: Dependency injection pattern -- **Legacy**: Dual authentication detection → **Current**: Single source of truth via AuthService -- `IdentityDialog.vue` → `LoginDialog.vue` -- `PasswordDialog.vue` → Integrated into `LoginDialog.vue` -- Nostr connection status → User authentication status +### Architecture Documentation +- **[[../01-architecture/authentication-architecture|🔐 Authentication Architecture]]** - Detailed architecture overview +- **[[../01-architecture/dependency-injection|⚙️ Dependency Injection]]** - Service container patterns +- **[[index|⚙️ Core Services Overview]]** - Related infrastructure services -## Development +### Module Documentation +- **[[../02-modules/base-module/index|🏗️ Base Module]]** - Authentication service registration +- **[[../04-development/security|🛡️ Security Guidelines]]** - Security best practices -To run the application with the new authentication system: +--- -1. Set up your LNBits instance -2. Configure the environment variables -3. Run the development server: `npm run dev` -4. Access the application and test login/register functionality - -## Troubleshooting - -### Common Issues - -1. **CORS Errors**: Ensure your LNBits instance allows requests from your frontend domain -2. **Authentication Failures**: Check that username/password auth is enabled in LNBits -3. **API Connection**: Verify the `VITE_LNBITS_BASE_URL` is correct and points to your LNBits instance (without /api/v1) - -### Debug Mode - -Enable debug logging by setting `VITE_LNBITS_DEBUG=true` to see detailed API request/response information in the browser console. \ No newline at end of file +**Tags:** #authentication #security #services #nostr #dependency-injection +**Last Updated:** 2025-09-07 +**Author:** Development Team \ No newline at end of file diff --git a/docs/04-migrations/dependency-injection-migration.md b/docs/04-migrations/dependency-injection-migration.md index 2c5da69..02e381f 100644 --- a/docs/04-migrations/dependency-injection-migration.md +++ b/docs/04-migrations/dependency-injection-migration.md @@ -260,24 +260,37 @@ const invoiceService = injectService(SERVICE_TOKENS.INVOICE_SERVICE) as InvoiceS const invoice = await invoiceService.createInvoice(order, adminKey) ``` -### 🔄 In Progress +#### 2. NostrmarketService (Completed) +- **Status**: ✅ Successfully migrated +- **Token**: `SERVICE_TOKENS.NOSTRMARKET_SERVICE` +- **Registration**: Market module (`src/modules/market/index.ts`) +- **Usage**: Market module composables and stores -#### 2. NostrmarketService (Pending) -- **Status**: 🔄 Ready for migration -- **File**: `src/modules/market/services/nostrmarketService.ts` -- **Token**: Need to add `NOSTRMARKET_SERVICE` -- **Registration**: Market module +**Before:** +```typescript +// ❌ Legacy singleton pattern +import { nostrmarketService } from '@/modules/market/services/nostrmarketService' +await nostrmarketService.publishOrder(orderData) +``` -#### 3. PaymentMonitorService (Partially Migrated) -- **Status**: 🔄 Token exists, needs completion -- **Token**: `SERVICE_TOKENS.PAYMENT_MONITOR` (already exists) -- **Registration**: Market module +**After:** +```typescript +// ✅ Dependency injection pattern +const nostrmarketService = injectService(SERVICE_TOKENS.NOSTRMARKET_SERVICE) as NostrmarketService +await nostrmarketService.publishOrder(orderData) +``` -#### 4. LnbitsAPI (Pending) -- **Status**: 🔄 Ready for migration -- **File**: `src/lib/api/lnbits.ts` -- **Token**: Need to add `LNBITS_API` -- **Registration**: Base module +#### 3. PaymentMonitorService (Completed) +- **Status**: ✅ Successfully migrated +- **Token**: `SERVICE_TOKENS.PAYMENT_MONITOR` +- **Registration**: Market module (`src/modules/market/index.ts`) +- **Usage**: Market store for payment status monitoring + +#### 4. LnbitsAPI (Completed) +- **Status**: ✅ Successfully migrated +- **Token**: `SERVICE_TOKENS.LNBITS_API` +- **Registration**: Base module (`src/modules/base/index.ts`) +- **Usage**: AuthService and events API integration ## Practical Example: Market Module Using InvoiceService