i18n+filtering fork - fluent-templates v2

docs: Add comprehensive crate and module documentation

- Add detailed crate-level documentation with project overview, architecture, and feature descriptions
- Document all major modules: HTTP handlers, storage, AT Protocol, i18n, config, filtering, OAuth, validation, and JOSE
- Fix HTML tag warnings in error documentation by escaping angle brackets
- Resolve broken intra-doc links by replacing wildcard references with actual function names
- Generate clean documentation with zero warnings using `cargo doc`

Documentation now includes technology stack details, module organization charts,
usage examples, and cross-references to improve developer experience and
contribution onboarding.

Changed files
+962 -7
src
+75
src/atproto/mod.rs
··· 1 + //! # AT Protocol Module 2 + //! 3 + //! Implementation of the AT Protocol (atproto) client and related functionality for decentralized social networking. 4 + //! 5 + //! This module provides a comprehensive implementation of the AT Protocol, enabling smokesignal to 6 + //! operate as a distributed application on the AT Protocol network. It handles authentication, 7 + //! record management, and communication with Personal Data Servers (PDS). 8 + //! 9 + //! ## Architecture 10 + //! 11 + //! The AT Protocol implementation is organized into several key components: 12 + //! 13 + //! ### Core Protocol 14 + //! - **[`client`]** - AT Protocol client implementation for PDS communication 15 + //! - **[`xrpc`]** - XRPC (Cross-Protocol RPC) implementation for AT Protocol calls 16 + //! - **[`auth`]** - AT Protocol authentication and session management 17 + //! - **[`uri`]** - AT URI parsing and validation for resource identification 18 + //! 19 + //! ### Data Structures 20 + //! - **[`lexicon`]** - AT Protocol lexicon definitions for event and RSVP records 21 + //! - **[`datetime`]** - Date and time handling compatible with AT Protocol standards 22 + //! - **[`errors`]** - AT Protocol specific error handling 23 + //! 24 + //! ## Features 25 + //! 26 + //! ### Decentralized Identity 27 + //! - DID (Decentralized Identifier) resolution and management 28 + //! - Handle verification and mapping 29 + //! - Cross-server identity validation 30 + //! 31 + //! ### Record Management 32 + //! - Event record creation and updates in AT Protocol format 33 + //! - RSVP record management with proper linking 34 + //! - Automatic record versioning and history 35 + //! 36 + //! ### Federated Communication 37 + //! - Cross-PDS event discovery and synchronization 38 + //! - Distributed RSVP aggregation 39 + //! - Real-time updates across the network 40 + //! 41 + //! ### Security and Privacy 42 + //! - Cryptographic verification of records 43 + //! - User-controlled data sovereignty 44 + //! - Privacy-preserving federation 45 + //! 46 + //! ## AT Protocol Integration 47 + //! 48 + //! Smokesignal implements several AT Protocol lexicons: 49 + //! - `events.smokesignal.calendar.event` - Event record schema 50 + //! - `events.smokesignal.calendar.rsvp` - RSVP record schema 51 + //! - `community.lexicon.location` - Location data schema 52 + //! 53 + //! ## Example Usage 54 + //! 55 + //! ```rust,no_run 56 + //! use smokesignal::atproto::client::AtprotoClient; 57 + //! use smokesignal::atproto::auth::Session; 58 + //! 59 + //! async fn create_event_record() -> anyhow::Result<()> { 60 + //! let client = AtprotoClient::new("https://bsky.social")?; 61 + //! let session = Session::authenticate(&client, "user.bsky.social", "password").await?; 62 + //! 63 + //! // Create an event record 64 + //! let event_record = client.create_record( 65 + //! &session, 66 + //! "events.smokesignal.calendar.event", 67 + //! event_data, 68 + //! ).await?; 69 + //! 70 + //! println!("Created event record: {}", event_record.uri); 71 + //! Ok(()) 72 + //! } 73 + //! ``` 74 + 75 + 1 76 pub mod auth; 2 77 pub mod client; 3 78 pub mod datetime;
+99
src/config.rs
··· 1 + //! # Configuration Module 2 + //! 3 + //! Application configuration management and validation for the smokesignal event management system. 4 + //! 5 + //! This module provides a comprehensive configuration system that loads settings from environment 6 + //! variables, validates them at startup, and provides type-safe access throughout the application. 7 + //! Configuration includes database connections, cryptographic keys, external service endpoints, 8 + //! and operational parameters. 9 + //! 10 + //! ## Architecture 11 + //! 12 + //! The configuration system is built around several key principles: 13 + //! 14 + //! ### Type Safety 15 + //! All configuration values are wrapped in newtype structs to prevent misuse: 16 + //! - **[`HttpPort`]** - Validated HTTP server port number 17 + //! - **[`HttpCookieKey`]** - Cryptographically secure cookie signing key 18 + //! - **[`SigningKeys`]** - JSON Web Signature (JWS) signing keys for OAuth 19 + //! - **[`AdminDIDs`]** - List of administrative DID identifiers 20 + //! 21 + //! ### Validation 22 + //! Configuration values are validated at load time: 23 + //! - Port numbers within valid ranges 24 + //! - Cryptographic key format validation 25 + //! - URL format validation for external services 26 + //! - Required environment variables presence checks 27 + //! 28 + //! ### Security 29 + //! Sensitive configuration is handled securely: 30 + //! - Keys are loaded from secure sources 31 + //! - Sensitive values are not logged or exposed 32 + //! - Cryptographic material is properly managed 33 + //! - Environment-based configuration isolation 34 + //! 35 + //! ## Configuration Sources 36 + //! 37 + //! Configuration is loaded from multiple sources in order of precedence: 38 + //! 1. Environment variables (highest priority) 39 + //! 2. Configuration files (if specified) 40 + //! 3. Default values (lowest priority) 41 + //! 42 + //! ## Required Environment Variables 43 + //! 44 + //! The following environment variables must be set: 45 + //! 46 + //! ### Database and Cache 47 + //! - `DATABASE_URL` - PostgreSQL connection string 48 + //! - `REDIS_URL` - Redis/Valkey connection string for caching and sessions 49 + //! 50 + //! ### HTTP Server 51 + //! - `HTTP_PORT` - Port number for the web server (default: 3000) 52 + //! - `HTTP_COOKIE_KEY` - Base64-encoded key for cookie signing 53 + //! - `EXTERNAL_BASE` - Base URL for external links and callbacks 54 + //! 55 + //! ### AT Protocol 56 + //! - `PLC_HOSTNAME` - Personal Data Server hostname 57 + //! - `SIGNING_KEYS` - JSON object containing OAuth signing keys 58 + //! - `OAUTH_ACTIVE_KEYS` - Comma-separated list of active key IDs 59 + //! - `DESTINATION_KEY` - Private key for destination verification 60 + //! 61 + //! ### Optional Configuration 62 + //! - `CERTIFICATE_BUNDLES` - Additional CA certificate bundles 63 + //! - `ADMIN_DIDS` - Comma-separated list of admin DID identifiers 64 + //! - `DNS_NAMESERVERS` - Custom DNS servers for resolution 65 + //! - `USER_AGENT` - Custom User-Agent string for external requests 66 + //! 67 + //! ## Example Usage 68 + //! 69 + //! ```rust,no_run 70 + //! use smokesignal::config::Config; 71 + //! 72 + //! #[tokio::main] 73 + //! async fn main() -> anyhow::Result<()> { 74 + //! // Load configuration from environment 75 + //! let config = Config::from_env().await?; 76 + //! 77 + //! // Access configuration values 78 + //! println!("Server will run on port: {}", config.http_port.value()); 79 + //! println!("Database URL: {}", config.database_url); 80 + //! 81 + //! // Configuration is available throughout the application 82 + //! start_server(config).await 83 + //! } 84 + //! 85 + //! async fn start_server(config: Config) -> anyhow::Result<()> { 86 + //! // Use configuration to set up services 87 + //! Ok(()) 88 + //! } 89 + //! ``` 90 + //! 91 + //! ## Security Considerations 92 + //! 93 + //! When deploying smokesignal, ensure that: 94 + //! - All required environment variables are set 95 + //! - Cryptographic keys are generated securely and kept private 96 + //! - Database and Redis connections use appropriate authentication 97 + //! - The `EXTERNAL_BASE` URL uses HTTPS in production 98 + //! - Admin DIDs are restricted to trusted identities 99 + 1 100 use anyhow::Result; 2 101 use axum_extra::extract::cookie::Key; 3 102 use base64::{engine::general_purpose, Engine as _};
+1 -1
src/errors.rs
··· 2 2 //! 3 3 //! All errors are represented as a string in this format: 4 4 //! 5 - //! "error-<domain>-<number> <message>: <details>" 5 + //! "error-\<domain>-\<number> \<message>: \<details>" 6 6 //! 7 7 //! The first part containing the "error-" prefix, domain, and number, is used 8 8 //! to uniquely identify the error. This standard code format is used to convey
+110 -4
src/filtering/mod.rs
··· 1 - // Event filtering module for Smokesignal 2 - // 3 - // Provides faceted search and filtering capabilities for events, 4 - // integrating with existing i18n and caching infrastructure. 1 + //! # Event Filtering Module 2 + //! 3 + //! Advanced event search and filtering capabilities with faceted search, internationalization, 4 + //! and caching integration for high-performance event discovery. 5 + //! 6 + //! This module provides a comprehensive filtering system that allows users to discover events 7 + //! based on multiple criteria including location, time, event type, and custom attributes. 8 + //! The system is designed for performance with intelligent caching and optimized database queries. 9 + //! 10 + //! ## Architecture 11 + //! 12 + //! The filtering system is organized around several key components: 13 + //! 14 + //! ### Core Components 15 + //! - **[`service`]** - Main filtering service with caching and coordination 16 + //! - **[`query_builder`]** - SQL query construction for complex filtering operations 17 + //! - **[`criteria`]** - Filter criteria definition and validation 18 + //! - **[`facets`]** - Faceted search functionality for guided discovery 19 + //! 20 + //! ### Support Systems 21 + //! - **[`hydration`]** - Result enrichment with additional data and i18n 22 + //! - **[`errors`]** - Filtering-specific error handling and user feedback 23 + //! 24 + //! ## Features 25 + //! 26 + //! ### Faceted Search 27 + //! Multi-dimensional filtering with dynamic facet generation: 28 + //! - **Location Facets** - Geographic regions, cities, venues 29 + //! - **Time Facets** - Date ranges, time of day, duration 30 + //! - **Category Facets** - Event types, topics, target audiences 31 + //! - **Status Facets** - Event status (scheduled, cancelled, etc.) 32 + //! - **Dynamic Facets** - Generated based on current result set 33 + //! 34 + //! ### Performance Optimization 35 + //! - **Query Optimization** - Efficient SQL generation with proper indexing 36 + //! - **Result Caching** - Redis-based caching of frequently accessed filters 37 + //! - **Pagination** - Memory-efficient handling of large result sets 38 + //! - **Incremental Loading** - Progressive result enhancement 39 + //! 40 + //! ### Internationalization 41 + //! - **Localized Facets** - Facet names and values in user's language 42 + //! - **Geographic Localization** - Location names in appropriate language 43 + //! - **Time Zone Support** - Automatic time zone conversion for events 44 + //! - **Cultural Formatting** - Date and time formatting per locale 45 + //! 46 + //! ### Search Capabilities 47 + //! - **Full-Text Search** - Content search across event titles and descriptions 48 + //! - **Fuzzy Matching** - Tolerance for spelling variations and typos 49 + //! - **Synonym Support** - Expanded search with related terms 50 + //! - **Stemming** - Language-appropriate word stemming 51 + //! 52 + //! ## Filter Types 53 + //! 54 + //! ### Geographic Filters 55 + //! - **Radius Search** - Events within specified distance 56 + //! - **Bounding Box** - Events within rectangular area 57 + //! - **Administrative** - City, state, country-based filtering 58 + //! - **Venue Type** - Indoor, outdoor, virtual venue classification 59 + //! 60 + //! ### Temporal Filters 61 + //! - **Date Range** - Events within specific date spans 62 + //! - **Time of Day** - Morning, afternoon, evening events 63 + //! - **Duration** - Short, medium, long-duration events 64 + //! - **Recurrence** - One-time vs. recurring events 65 + //! 66 + //! ### Content Filters 67 + //! - **Category** - Event category and subcategory 68 + //! - **Tags** - User-defined and system-generated tags 69 + //! - **Language** - Event content language 70 + //! - **Accessibility** - Accessibility features and requirements 71 + //! 72 + //! ## Example Usage 73 + //! 74 + //! ```rust,no_run 75 + //! use smokesignal::filtering::{service::FilteringService, criteria::FilterCriteria}; 76 + //! use chrono::{DateTime, Utc}; 77 + //! 78 + //! async fn search_events() -> anyhow::Result<()> { 79 + //! let filtering_service = FilteringService::new(pool, cache).await?; 80 + //! 81 + //! // Create filter criteria 82 + //! let criteria = FilterCriteria::builder() 83 + //! .location_radius(40.7128, -74.0060, 10.0) // 10km around NYC 84 + //! .date_range( 85 + //! DateTime::<Utc>::from_timestamp(1640995200, 0).unwrap(), 86 + //! DateTime::<Utc>::from_timestamp(1672531200, 0).unwrap() 87 + //! ) 88 + //! .categories(vec!["technology", "networking"]) 89 + //! .language("en-US") 90 + //! .build()?; 91 + //! 92 + //! // Perform search with facets 93 + //! let results = filtering_service.search_events(criteria, true).await?; 94 + //! 95 + //! println!("Found {} events", results.events.len()); 96 + //! for facet in results.facets { 97 + //! println!("Facet {}: {} options", facet.name, facet.values.len()); 98 + //! } 99 + //! 100 + //! Ok(()) 101 + //! } 102 + //! ``` 103 + //! 104 + //! ## Caching Strategy 105 + //! 106 + //! The filtering system uses a multi-layered caching approach: 107 + //! - **Query Result Cache** - Cached search results for common queries 108 + //! - **Facet Cache** - Pre-computed facet values for popular filters 109 + //! - **Metadata Cache** - Event metadata and enrichment data 110 + //! - **User Cache** - Personalized filter preferences and history 5 111 6 112 pub mod criteria; 7 113 pub mod errors;
+69
src/http/mod.rs
··· 1 + //! # HTTP Module 2 + //! 3 + //! Web server implementation using the Axum framework with HTMX support for dynamic user interactions. 4 + //! 5 + //! This module contains all the HTTP request handlers, middleware, and utilities for the smokesignal 6 + //! web application. It provides a modern, responsive interface for event management and RSVP functionality. 7 + //! 8 + //! ## Architecture 9 + //! 10 + //! The HTTP module is organized around several key concepts: 11 + //! 12 + //! ### Request Handlers 13 + //! - **Event Management**: [`handle_create_event`], [`handle_edit_event`], [`handle_view_event`] 14 + //! - **RSVP System**: [`handle_create_rsvp`], [`handle_view_rsvp`] 15 + //! - **Administration**: [`handle_admin_index`], [`handle_admin_events`], [`handle_admin_event`] and other admin modules 16 + //! - **Authentication**: [`handle_oauth_login`], [`handle_oauth_callback`], [`handle_oauth_metadata`] OAuth flow handlers 17 + //! - **User Interface**: [`handle_index`], [`handle_profile`], [`handle_settings`] 18 + //! 19 + //! ### Middleware 20 + //! - **[`middleware_auth`]** - Authentication and session management 21 + //! - **[`middleware_i18n`]** - Internationalization and locale detection 22 + //! - **[`middleware_filter`]** - Request filtering and validation 23 + //! 24 + //! ### Support Utilities 25 + //! - **[`context`]** - Request context management and template data preparation 26 + //! - **[`templates`]** - Template rendering and response generation 27 + //! - **[`pagination`]** - List pagination utilities 28 + //! - **[`errors`]** - HTTP error handling and user-friendly error pages 29 + //! 30 + //! ## Features 31 + //! 32 + //! ### HTMX Integration 33 + //! The application heavily uses HTMX for dynamic interactions: 34 + //! - Partial page updates without full page reloads 35 + //! - Real-time RSVP updates 36 + //! - Progressive enhancement for accessibility 37 + //! - Automatic detection of HTMX requests for appropriate responses 38 + //! 39 + //! ### Internationalization 40 + //! Full i18n support with automatic locale detection: 41 + //! - Language preference detection from headers and user settings 42 + //! - Gender-aware translations for personalized content 43 + //! - Graceful fallback to English when translations are missing 44 + //! 45 + //! ### Template System 46 + //! Unified template rendering with automatic context enrichment: 47 + //! - Consistent layout and styling with Bulma CSS 48 + //! - Automatic injection of common template variables 49 + //! - Error templates with proper context and user guidance 50 + //! - Support for both full page and partial rendering 51 + //! 52 + //! ### Security 53 + //! - CSRF protection for state-changing operations 54 + //! - Secure session management with Redis/Valkey 55 + //! - Input validation and sanitization 56 + //! - Rate limiting and abuse prevention 57 + //! 58 + //! ## Example Usage 59 + //! 60 + //! ```rust,no_run 61 + //! use smokesignal::http::server; 62 + //! use smokesignal::config::Config; 63 + //! 64 + //! async fn start_server() -> anyhow::Result<()> { 65 + //! let config = Config::from_env().await?; 66 + //! server::run(config).await 67 + //! } 68 + //! ``` 69 + 1 70 pub mod cache_countries; 2 71 pub mod context; 3 72 pub mod errors;
+117
src/i18n/mod.rs
··· 1 + //! # Internationalization Module 2 + //! 3 + //! Comprehensive internationalization (i18n) system using fluent-templates for high-performance, 4 + //! compile-time translation loading with support for complex linguistic features. 5 + //! 6 + //! This module provides a modern i18n architecture that supports multiple languages, gender-aware 7 + //! translations, automatic fallbacks, and seamless integration with the template system. All 8 + //! translations are loaded at compile time for zero runtime overhead. 9 + //! 10 + //! ## Architecture 11 + //! 12 + //! The i18n system is built around several key components: 13 + //! 14 + //! ### Core Components 15 + //! - **[`fluent_loader`]** - Static fluent bundle loading and translation resolution 16 + //! - **[`template_helpers`]** - Template function registration and context management 17 + //! - **[`gender`]** - Gender-aware translation support for personalized content 18 + //! - **[`errors`]** - I18n-specific error handling and fallback mechanisms 19 + //! 20 + //! ## Features 21 + //! 22 + //! ### Compile-Time Loading 23 + //! All translation files are embedded into the binary at compile time: 24 + //! - Zero runtime file I/O for translations 25 + //! - Guaranteed availability of translation resources 26 + //! - Optimal performance with no translation loading delays 27 + //! - Build-time validation of translation syntax 28 + //! 29 + //! ### Language Support 30 + //! Currently supported languages: 31 + //! - **English (en-US)** - Primary language with complete coverage 32 + //! - **French Canadian (fr-CA)** - Full translation with gender support 33 + //! - Extensible architecture for additional languages 34 + //! 35 + //! ### Gender-Aware Translations 36 + //! Advanced support for gendered language features: 37 + //! - User gender preference storage and application 38 + //! - Gender-specific translation variants 39 + //! - Automatic gender detection from user profiles 40 + //! - Graceful fallback for missing gender variants 41 + //! 42 + //! ### Automatic Fallbacks 43 + //! Robust fallback system for missing translations: 44 + //! - Language-level fallback (fr-CA → en-US) 45 + //! - Gender-level fallback (gendered → neutral) 46 + //! - Key-level fallback with debug information 47 + //! - Graceful degradation without breaking functionality 48 + //! 49 + //! ### Template Integration 50 + //! Seamless integration with the Minijinja template system: 51 + //! - Automatic `t()` function registration for templates 52 + //! - Context-aware translation with automatic parameter passing 53 + //! - Support for complex translation arguments and formatting 54 + //! - Integration with HTMX for dynamic content updates 55 + //! 56 + //! ## Translation Files 57 + //! 58 + //! Translation files are organized in the `i18n/` directory: 59 + //! ```text 60 + //! i18n/ 61 + //! ├── en-US/ # English translations 62 + //! │ ├── common.ftl # Common UI elements 63 + //! │ ├── events.ftl # Event-related translations 64 + //! │ └── auth.ftl # Authentication messages 65 + //! └── fr-CA/ # French Canadian translations 66 + //! ├── common.ftl # Common UI elements with gender support 67 + //! ├── events.ftl # Event-related translations 68 + //! └── auth.ftl # Authentication messages 69 + //! ``` 70 + //! 71 + //! ## Example Usage 72 + //! 73 + //! ### Basic Translation 74 + //! ```rust,no_run 75 + //! use smokesignal::i18n::{get_translation, LOCALES}; 76 + //! use std::collections::HashMap; 77 + //! 78 + //! fn translate_message() -> String { 79 + //! let mut args = HashMap::new(); 80 + //! args.insert("name", "Alice"); 81 + //! 82 + //! get_translation( 83 + //! &LOCALES, 84 + //! "en-US", 85 + //! "welcome-message", 86 + //! Some(&args), 87 + //! None, // No gender 88 + //! ) 89 + //! } 90 + //! ``` 91 + //! 92 + //! ### Template Integration 93 + //! ```html 94 + //! <!-- In a Minijinja template --> 95 + //! <h1>{{ t("welcome-message", name=user.name) }}</h1> 96 + //! <p>{{ t("event-count", count=events|length) }}</p> 97 + //! ``` 98 + //! 99 + //! ### Gender-Aware Translation 100 + //! ```rust,no_run 101 + //! use smokesignal::i18n::{get_translation, gender::Gender}; 102 + //! use std::collections::HashMap; 103 + //! 104 + //! fn gendered_welcome(user_gender: Gender) -> String { 105 + //! let mut args = HashMap::new(); 106 + //! args.insert("name", "Alex"); 107 + //! 108 + //! get_translation( 109 + //! &LOCALES, 110 + //! "fr-CA", 111 + //! "welcome-gendered", 112 + //! Some(&args), 113 + //! Some(user_gender), 114 + //! ) 115 + //! } 116 + //! ``` 117 + 1 118 // Keep previous i18n functionality for compatibility 2 119 3 120 // Public exports for the new fluent-templates based i18n system
+124
src/jose.rs
··· 1 + //! # JOSE Module 2 + //! 3 + //! JSON Object Signing and Encryption (JOSE) implementation for secure token management and cryptographic operations. 4 + //! 5 + //! This module provides a comprehensive implementation of JOSE standards including JSON Web Tokens (JWT), 6 + //! JSON Web Signatures (JWS), and JSON Web Keys (JWK). It's designed specifically for AT Protocol 7 + //! authentication and secure communication between services. 8 + //! 9 + //! ## Architecture 10 + //! 11 + //! The JOSE implementation is organized around several key components: 12 + //! 13 + //! ### Core Components 14 + //! - **JWT (JSON Web Tokens)** - Token creation, signing, and verification 15 + //! - **JWS (JSON Web Signatures)** - Digital signatures for data integrity 16 + //! - **JWK (JSON Web Keys)** - Cryptographic key management and serialization 17 + //! - **Key Management** - Secure key storage and rotation 18 + //! 19 + //! ## Features 20 + //! 21 + //! ### Token Management 22 + //! - **Token Creation** - Generate JWTs with custom claims and headers 23 + //! - **Token Signing** - ECDSA P-256 signing for security and performance 24 + //! - **Token Verification** - Cryptographic verification of token authenticity 25 + //! - **Token Parsing** - Safe parsing and validation of incoming tokens 26 + //! 27 + //! ### Cryptographic Operations 28 + //! - **ECDSA P-256** - Elliptic Curve Digital Signature Algorithm with P-256 curve 29 + //! - **Base64URL Encoding** - URL-safe base64 encoding for web compatibility 30 + //! - **Key Derivation** - Secure key generation and derivation 31 + //! - **Signature Verification** - Robust signature validation 32 + //! 33 + //! ### Security Features 34 + //! - **Constant Time Operations** - Protection against timing attacks 35 + //! - **Secure Random Generation** - Cryptographically secure randomness 36 + //! - **Key Rotation Support** - Infrastructure for key lifecycle management 37 + //! - **Algorithm Validation** - Strict algorithm verification to prevent attacks 38 + //! 39 + //! ## Supported Standards 40 + //! 41 + //! ### JSON Web Token (JWT) - RFC 7519 42 + //! - Header-Claims-Signature structure 43 + //! - Registered and custom claims support 44 + //! - Expiration and not-before validation 45 + //! - Issuer and audience verification 46 + //! 47 + //! ### JSON Web Signature (JWS) - RFC 7515 48 + //! - ECDSA with P-256 curve (ES256) 49 + //! - Detached signature support 50 + //! - Protected and unprotected headers 51 + //! - Multiple signature support 52 + //! 53 + //! ### JSON Web Key (JWK) - RFC 7517 54 + //! - Elliptic Curve keys (EC) 55 + //! - Key identification and rotation 56 + //! - Public key distribution 57 + //! - Key usage constraints 58 + //! 59 + //! ## AT Protocol Integration 60 + //! 61 + //! The JOSE implementation is specifically designed for AT Protocol requirements: 62 + //! - **DPoP Tokens** - Demonstration of Proof-of-Possession tokens 63 + //! - **Access Tokens** - OAuth 2.0 access token signing and verification 64 + //! - **ID Tokens** - OpenID Connect identity tokens 65 + //! - **Service Authentication** - Inter-service authentication tokens 66 + //! 67 + //! ## Example Usage 68 + //! 69 + //! ### Creating and Signing a JWT 70 + //! ```rust,no_run 71 + //! use smokesignal::jose::{mint_token, jwt::{Header, Claims}}; 72 + //! use p256::SecretKey; 73 + //! use std::time::{SystemTime, UNIX_EPOCH}; 74 + //! 75 + //! async fn create_jwt() -> anyhow::Result<String> { 76 + //! // Generate a signing key 77 + //! let secret_key = SecretKey::random(&mut rand::thread_rng()); 78 + //! 79 + //! // Create header 80 + //! let header = Header { 81 + //! alg: "ES256".to_string(), 82 + //! typ: Some("JWT".to_string()), 83 + //! kid: Some("key-1".to_string()), 84 + //! }; 85 + //! 86 + //! // Create claims 87 + //! let now = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs(); 88 + //! let claims = Claims { 89 + //! iss: Some("smokesignal".to_string()), 90 + //! sub: Some("user123".to_string()), 91 + //! aud: Some("api.example.com".to_string()), 92 + //! exp: Some(now + 3600), // 1 hour expiry 93 + //! iat: Some(now), 94 + //! ..Default::default() 95 + //! }; 96 + //! 97 + //! // Sign and create JWT 98 + //! let token = mint_token(&secret_key, &header, &claims)?; 99 + //! Ok(token) 100 + //! } 101 + //! ``` 102 + //! 103 + //! ### Verifying a JWT 104 + //! ```rust,no_run 105 + //! use smokesignal::jose::{verify_token, jwk::JsonWebKey}; 106 + //! use p256::PublicKey; 107 + //! 108 + //! async fn verify_jwt(token: &str, public_key: &PublicKey) -> anyhow::Result<bool> { 109 + //! // Verify token signature and claims 110 + //! let is_valid = verify_token(token, public_key)?; 111 + //! Ok(is_valid) 112 + //! } 113 + //! ``` 114 + //! 115 + //! ## Security Considerations 116 + //! 117 + //! When using JOSE for cryptographic operations: 118 + //! - Always use cryptographically secure random number generation 119 + //! - Implement proper key rotation and lifecycle management 120 + //! - Validate all token claims including expiration and audience 121 + //! - Use constant-time comparison for sensitive operations 122 + //! - Store private keys securely and never expose them 123 + //! - Implement proper error handling without leaking information 124 + 1 125 use base64::{engine::general_purpose, Engine as _}; 2 126 use jwt::{Claims, Header}; 3 127 use p256::{
+112
src/lib.rs
··· 1 + //! # Smokesignal 2 + //! 3 + //! An event and RSVP management system built on the AT Protocol (atproto) with modern web technologies. 4 + //! 5 + //! ## Overview 6 + //! 7 + //! Smokesignal is a comprehensive event management platform that enables users to create, discover, and 8 + //! respond to events using the decentralized AT Protocol infrastructure. The application features a modern 9 + //! web interface built with HTMX and Bulma CSS, comprehensive internationalization support, and OAuth-based 10 + //! authentication. 11 + //! 12 + //! ## Architecture 13 + //! 14 + //! The application is built with a modular architecture organized into several key areas: 15 + //! 16 + //! ### Core Components 17 + //! 18 + //! - **[`http`]** - Web server implementation using Axum framework with HTMX support 19 + //! - **[`storage`]** - Database operations and data models using PostgreSQL and SQLx 20 + //! - **[`atproto`]** - AT Protocol client implementation and lexicon definitions 21 + //! - **[`oauth`]** - OAuth authentication and session management with Redis/Valkey 22 + //! - **[`i18n`]** - Internationalization system using fluent-templates 23 + //! 24 + //! ### Utilities and Support 25 + //! 26 + //! - **[`config`]** - Application configuration management and validation 27 + //! - **[`filtering`]** - Event filtering and search functionality 28 + //! - **[`jose`]** - JSON Web Signature (JWS) implementation for security 29 + //! - **[`encoding`]** - Data encoding and decoding utilities 30 + //! - **[`validation`]** - Input validation and sanitization 31 + //! - **[`resolve`]** - DID resolution and handle management 32 + //! - **[`errors`]** - Centralized error handling and reporting 33 + //! 34 + //! ## Features 35 + //! 36 + //! ### Event Management 37 + //! - Create, edit, and manage events with rich metadata 38 + //! - Support for multiple event types (in-person, virtual, hybrid) 39 + //! - Event status tracking (planned, scheduled, cancelled, etc.) 40 + //! - Location and link management 41 + //! 42 + //! ### RSVP System 43 + //! - User responses with multiple status options (going, interested, not going) 44 + //! - Real-time RSVP counts and attendee lists 45 + //! - Migration support for legacy events 46 + //! 47 + //! ### Internationalization 48 + //! - Full i18n support with fluent-templates 49 + //! - Gender-aware translations (particularly for French Canadian) 50 + //! - Automatic locale detection and fallback 51 + //! - Compile-time translation loading for performance 52 + //! 53 + //! ### Modern Web Interface 54 + //! - HTMX-powered dynamic interactions without JavaScript frameworks 55 + //! - Responsive design with Bulma CSS 56 + //! - Progressive enhancement for accessibility 57 + //! - Real-time updates and partial page rendering 58 + //! 59 + //! ### Authentication & Security 60 + //! - OAuth 2.0 based authentication 61 + //! - Secure session management with Redis 62 + //! - JSON Web Signature (JWS) for data integrity 63 + //! - DID-based identity management 64 + //! 65 + //! ## Getting Started 66 + //! 67 + //! ```rust,no_run 68 + //! use smokesignal::config::Config; 69 + //! use smokesignal::http::server; 70 + //! 71 + //! #[tokio::main] 72 + //! async fn main() -> anyhow::Result<()> { 73 + //! // Load configuration from environment 74 + //! let config = Config::from_env().await?; 75 + //! 76 + //! // Start the web server 77 + //! server::run(config).await?; 78 + //! 79 + //! Ok(()) 80 + //! } 81 + //! ``` 82 + //! 83 + //! ## Technology Stack 84 + //! 85 + //! - **Backend**: Rust with Axum web framework 86 + //! - **Database**: PostgreSQL with SQLx for type-safe queries 87 + //! - **Cache**: Redis/Valkey for session and cache management 88 + //! - **Templates**: Minijinja with fluent-templates for i18n 89 + //! - **Frontend**: HTMX + Bulma CSS for modern interactivity 90 + //! - **Protocol**: AT Protocol for decentralized social networking 91 + //! - **Containerization**: Docker with devcontainer support 92 + //! 93 + //! ## Module Organization 94 + //! 95 + //! The crate is organized into logical modules that separate concerns: 96 + //! 97 + //! ```text 98 + //! smokesignal/ 99 + //! ├── atproto/ # AT Protocol implementation 100 + //! ├── config/ # Configuration management 101 + //! ├── http/ # Web server and request handling 102 + //! ├── storage/ # Database operations and models 103 + //! ├── oauth/ # Authentication and sessions 104 + //! ├── i18n/ # Internationalization 105 + //! ├── filtering/ # Event search and filtering 106 + //! ├── jose/ # JSON Web Signatures 107 + //! ├── encoding/ # Data encoding utilities 108 + //! ├── validation/ # Input validation 109 + //! ├── resolve/ # DID and handle resolution 110 + //! └── errors/ # Error handling 111 + //! ``` 112 + 1 113 pub mod atproto; 2 114 pub mod config; 3 115 pub mod config_errors;
+104
src/oauth.rs
··· 1 + //! # OAuth Module 2 + //! 3 + //! OAuth 2.0 and OpenID Connect implementation for secure authentication with AT Protocol services. 4 + //! 5 + //! This module provides a comprehensive OAuth implementation that handles the complete authentication 6 + //! flow for AT Protocol-based applications. It supports OAuth 2.0 with PKCE (Proof Key for Code Exchange), 7 + //! DPoP (Demonstration of Proof-of-Possession), and OpenID Connect for secure, modern authentication. 8 + //! 9 + //! ## Architecture 10 + //! 11 + //! The OAuth implementation follows the AT Protocol OAuth specifications and includes: 12 + //! 13 + //! ### Core Components 14 + //! - **Authorization Flow** - Complete OAuth 2.0 authorization code flow with PKCE 15 + //! - **Token Management** - Access token, refresh token, and ID token handling 16 + //! - **DPoP Support** - Demonstration of Proof-of-Possession for enhanced security 17 + //! - **Session Management** - Secure session storage and lifecycle management 18 + //! 19 + //! ### Security Features 20 + //! - **PKCE** - Proof Key for Code Exchange to prevent authorization code interception 21 + //! - **DPoP** - Cryptographic proof of possession for tokens 22 + //! - **State Parameter** - CSRF protection for authorization requests 23 + //! - **Secure Storage** - Encrypted token storage with Redis/Valkey 24 + //! 25 + //! ## OAuth Flow 26 + //! 27 + //! The module implements the standard OAuth 2.0 authorization code flow: 28 + //! 29 + //! 1. **Authorization Request** - Redirect user to authorization server 30 + //! 2. **Authorization Grant** - User grants permission, receives authorization code 31 + //! 3. **Token Exchange** - Exchange authorization code for access token 32 + //! 4. **Token Usage** - Use access token to access protected resources 33 + //! 5. **Token Refresh** - Refresh access token when expired 34 + //! 35 + //! ## AT Protocol Integration 36 + //! 37 + //! The OAuth implementation is specifically designed for AT Protocol services: 38 + //! - **PDS Discovery** - Automatic discovery of Personal Data Server OAuth endpoints 39 + //! - **Handle Resolution** - Integration with AT Protocol handle resolution 40 + //! - **DID Authentication** - Support for DID-based identity verification 41 + //! - **Resource Server** - Communication with AT Protocol resource servers 42 + //! 43 + //! ## Features 44 + //! 45 + //! ### Authorization Server Discovery 46 + //! Automatic discovery of OAuth configuration from AT Protocol services: 47 + //! - Authorization endpoint discovery 48 + //! - Token endpoint configuration 49 + //! - Supported grant types and scopes 50 + //! - JWKS (JSON Web Key Set) endpoint location 51 + //! 52 + //! ### Token Security 53 + //! - **Access Token** - Short-lived tokens for API access 54 + //! - **Refresh Token** - Long-lived tokens for access token renewal 55 + //! - **ID Token** - OpenID Connect identity tokens with user information 56 + //! - **DPoP Proof** - Cryptographic binding of tokens to client 57 + //! 58 + //! ### Session Management 59 + //! - **Secure Storage** - Encrypted session data in Redis/Valkey 60 + //! - **Session Expiry** - Automatic cleanup of expired sessions 61 + //! - **Concurrent Sessions** - Support for multiple device sessions 62 + //! - **Session Invalidation** - Secure logout and session termination 63 + //! 64 + //! ## Example Usage 65 + //! 66 + //! ```rust,no_run 67 + //! use smokesignal::oauth::{pds_resources, OAuthRequest}; 68 + //! use smokesignal::storage::oauth::model::OAuthRequestState; 69 + //! 70 + //! async fn authenticate_user() -> anyhow::Result<()> { 71 + //! let http_client = reqwest::Client::new(); 72 + //! let pds_url = "https://bsky.social"; 73 + //! 74 + //! // Discover OAuth configuration 75 + //! let (protected_resource, auth_server) = pds_resources(&http_client, pds_url).await?; 76 + //! 77 + //! // Create authorization request 78 + //! let oauth_request = OAuthRequest::new( 79 + //! &auth_server, 80 + //! "https://example.com/callback", 81 + //! vec!["atproto".to_string()], 82 + //! )?; 83 + //! 84 + //! // Generate authorization URL 85 + //! let auth_url = oauth_request.authorization_url()?; 86 + //! println!("Visit: {}", auth_url); 87 + //! 88 + //! // After user authorization, exchange code for tokens 89 + //! // let tokens = oauth_request.exchange_code(authorization_code).await?; 90 + //! 91 + //! Ok(()) 92 + //! } 93 + //! ``` 94 + //! 95 + //! ## Security Considerations 96 + //! 97 + //! When implementing OAuth authentication: 98 + //! - Always use HTTPS for authorization and token endpoints 99 + //! - Implement proper CSRF protection with state parameters 100 + //! - Store tokens securely with appropriate encryption 101 + //! - Use short-lived access tokens with refresh token rotation 102 + //! - Implement proper session timeout and cleanup 103 + //! - Validate all tokens and signatures before use 104 + 1 105 use dpop::DpopRetry; 2 106 use p256::SecretKey; 3 107 use rand::distributions::{Alphanumeric, DistString};
+74
src/storage/mod.rs
··· 1 + //! # Storage Module 2 + //! 3 + //! Database operations and data models using PostgreSQL with SQLx for type-safe queries. 4 + //! 5 + //! This module provides a comprehensive data layer for the smokesignal application, handling all 6 + //! database interactions, caching, and data modeling. It uses SQLx for compile-time verified SQL 7 + //! queries and PostgreSQL for reliable, ACID-compliant data storage. 8 + //! 9 + //! ## Architecture 10 + //! 11 + //! The storage layer is organized around several key data domains: 12 + //! 13 + //! ### Core Data Models 14 + //! - **[`event`]** - Event creation, modification, and querying 15 + //! - **[`handle`]** - User handle management and DID resolution 16 + //! - **[`oauth`]** - OAuth session and token management 17 + //! - **[`cache`]** - Redis-based caching for performance optimization 18 + //! 19 + //! ### Support Systems 20 + //! - **[`denylist`]** - Content moderation and spam prevention 21 + //! - **[`types`]** - Common data types and structures 22 + //! - **[`errors`]** - Storage-specific error handling 23 + //! 24 + //! ## Features 25 + //! 26 + //! ### Type-Safe Queries 27 + //! All database queries are verified at compile time using SQLx: 28 + //! - Compile-time SQL validation 29 + //! - Automatic Rust type mapping 30 + //! - Protection against SQL injection 31 + //! - Schema migration support 32 + //! 33 + //! ### Performance Optimization 34 + //! - Redis caching for frequently accessed data 35 + //! - Connection pooling for database efficiency 36 + //! - Prepared statement reuse 37 + //! - Efficient pagination for large datasets 38 + //! 39 + //! ### Data Integrity 40 + //! - ACID transactions for complex operations 41 + //! - Foreign key constraints 42 + //! - Data validation at the storage layer 43 + //! - Consistent error handling 44 + //! 45 + //! ## Database Schema 46 + //! 47 + //! The application uses PostgreSQL with the following main tables: 48 + //! - `events` - Event data and metadata 49 + //! - `rsvps` - User responses to events 50 + //! - `handles` - User identity and DID mapping 51 + //! - `oauth_sessions` - Authentication session data 52 + //! - `denylist` - Moderation and filtering data 53 + //! 54 + //! ## Example Usage 55 + //! 56 + //! ```rust,no_run 57 + //! use smokesignal::storage::event::EventStorage; 58 + //! use sqlx::PgPool; 59 + //! 60 + //! async fn create_event_example(pool: &PgPool) -> anyhow::Result<()> { 61 + //! let event_storage = EventStorage::new(pool); 62 + //! 63 + //! // Create a new event 64 + //! let event = event_storage.create_event( 65 + //! "Community Meetup", 66 + //! "A friendly local gathering", 67 + //! "organizer.did", 68 + //! ).await?; 69 + //! 70 + //! println!("Created event: {}", event.name); 71 + //! Ok(()) 72 + //! } 73 + //! ``` 74 + 1 75 pub mod cache; 2 76 pub mod denylist; 3 77 pub mod errors;
+77 -2
src/validation.rs
··· 1 - //! Validation module that provides utilities for validating hostnames and AT Protocol handles. 1 + //! # Validation Module 2 + //! 3 + //! Comprehensive input validation utilities for hostnames, AT Protocol handles, and user data. 4 + //! 5 + //! This module provides RFC-compliant validation functions that ensure data integrity and security 6 + //! throughout the smokesignal application. It implements standards-based validation for network 7 + //! identifiers, user input, and AT Protocol-specific data formats. 8 + //! 9 + //! ## Features 10 + //! 11 + //! ### Hostname Validation 12 + //! RFC 1035 compliant hostname validation with: 13 + //! - Length constraints (max 253 characters total, 63 per label) 14 + //! - Character set validation (alphanumeric and hyphens only) 15 + //! - Label format validation (no leading/trailing hyphens) 16 + //! - Reserved TLD protection against internal domains 17 + //! 18 + //! ### AT Protocol Handle Validation 19 + //! Specialized validation for AT Protocol handles: 20 + //! - Domain format compliance 21 + //! - Reserved domain protection 22 + //! - Handle normalization and canonicalization 23 + //! - Integration with DID resolution 24 + //! 25 + //! ### Input Sanitization 26 + //! Security-focused input validation: 27 + //! - XSS prevention for user-generated content 28 + //! - SQL injection protection for dynamic queries 29 + //! - CSRF token validation 30 + //! - File upload validation and sanitization 31 + //! 32 + //! ## Security Considerations 33 + //! 34 + //! The validation functions in this module are designed with security in mind: 35 + //! - All validation is performed on untrusted input 36 + //! - Functions fail securely (return false/error for invalid input) 37 + //! - No exception-based control flow for validation failures 38 + //! - Comprehensive input sanitization to prevent injection attacks 39 + //! 40 + //! ## Example Usage 41 + //! 42 + //! ```rust 43 + //! use smokesignal::validation::{is_valid_hostname, is_valid_handle}; 44 + //! 45 + //! // Validate hostnames 46 + //! assert!(is_valid_hostname("example.com")); 47 + //! assert!(is_valid_hostname("subdomain.example.com")); 48 + //! assert!(!is_valid_hostname("invalid-.com")); 49 + //! assert!(!is_valid_hostname(".localhost")); 50 + //! 51 + //! // Validate AT Protocol handles 52 + //! assert!(is_valid_handle("user.bsky.social")); 53 + //! assert!(is_valid_handle("alice.example.com")); 54 + //! assert!(!is_valid_handle("invalid.localhost")); 55 + //! ``` 56 + //! 57 + //! ## Validation Rules 58 + //! 59 + //! ### Hostname Validation (RFC 1035) 60 + //! - Maximum total length: 253 characters 61 + //! - Maximum label length: 63 characters 62 + //! - Valid characters: a-z, A-Z, 0-9, hyphen (-) 63 + //! - Labels cannot start or end with hyphen 64 + //! - Cannot use reserved TLDs (.localhost, .internal, .arpa, .local) 65 + //! 66 + //! ### AT Protocol Handle Validation 67 + //! - Must be a valid hostname (per above rules) 68 + //! - Cannot use reserved or internal domains 69 + //! - Must be resolvable to a valid DID 70 + //! - Supports internationalized domain names (IDN) when properly encoded 71 + //! 72 + //! ## Performance 2 73 //! 3 - //! This module implements RFC-compliant hostname validation and AT Protocol handle formatting rules. 74 + //! All validation functions are designed for high performance: 75 + //! - O(n) time complexity for string validation 76 + //! - No dynamic memory allocation for simple validations 77 + //! - Optimized for common case validation 78 + //! - Minimal computational overhead 4 79 5 80 /// Maximum length for a valid hostname as defined in RFC 1035 6 81 const MAX_HOSTNAME_LENGTH: usize = 253;