Smokesignal#
A decentralized event and RSVP management application built for the AT Protocol ecosystem. Smokesignal enables users to create, discover, and RSVP to events using their AT Protocol identity. Features include email notifications, RSVP acceptance workflows, private event content, profile caching, and flexible content storage.
Features#
- Decentralized Identity: Full AT Protocol OAuth integration with support for both PDS and AIP backends
- Event Management: Create, edit, and manage calendar events with timezone and location support
- RSVP System: Attendees can respond to events with status updates and validation workflows
- RSVP Acceptance: Ticket-based acceptance system for validating RSVP attendance
- Private Event Content: Conditional content display based on RSVP status and validation
- Email Notifications: Configurable email alerts for RSVPs, event changes, and daily summaries
- Real-time Updates: Jetstream consumer for live event ingestion from the AT Protocol firehose
- Search: Full-text event search powered by OpenSearch
- Webhooks: Configurable notifications for event and RSVP actions
- Profile Caching: Efficient AT Protocol profile storage and retrieval
- Internationalization: Multi-language support with Fluent
- Flexible Storage: Support for filesystem and S3-compatible object storage
- Image Processing: Automatic resizing and optimization for avatars and uploaded content
- Rate Limiting: Redis-backed throttling for API protection
- Service Identity: did:web support for federated interactions
Tech Stack#
- Language: Rust (edition 2024, minimum version 1.90)
- Web Framework: Axum with async/await
- Database: PostgreSQL with SQLx migrations
- Caching: Redis/Valkey for sessions, tokens, and profiles
- Search: OpenSearch for full-text event search
- Frontend: HTMX + Bulma CSS + FontAwesome
- Templates: MiniJinja with server-side rendering
- Email: Lettre for SMTP-based notifications
- Image Processing: Image resizing and optimization
- Authentication: AT Protocol OAuth with JOSE/JWT (P-256 ECDSA)
Quick Start#
Using DevContainer (Recommended)#
- Install Visual Studio Code and the Dev Containers extension
- Clone this repository
- Open in VS Code and click "Reopen in Container" when prompted
- The devcontainer will set up PostgreSQL, Redis, and all dependencies
Manual Setup#
Prerequisites#
- Rust toolchain (1.90 or newer)
- PostgreSQL
- Redis or Valkey
- OpenSearch (optional, for search functionality)
- SMTP server (optional, for email notifications)
- SQLx CLI:
cargo install sqlx-cli --no-default-features --features postgres
Building#
# Development build with template reloading
cargo build --bin smokesignal
# Production build with embedded templates
cargo build --bin smokesignal --no-default-features -F embed
# Run tests
cargo test
# Run linting
cargo clippy
Database Setup#
# Run migrations
sqlx migrate run
# Reset database (warning: deletes all data)
sqlx database reset
Configuration#
Required Environment Variables#
# Core configuration
HTTP_COOKIE_KEY=<64-character hex key for session encryption>
DATABASE_URL=postgres://user:pass@localhost/smokesignal
REDIS_URL=redis://localhost:6379
EXTERNAL_BASE=https://your-domain.com
PLC_HOSTNAME=plc.directory
ADMIN_DIDS=did:plc:admin1,did:plc:admin2
# Service identity
SERVICE_KEY=<service identity key for did:web>
# Storage backend (filesystem path or S3 URL)
CONTENT_STORAGE=/path/to/storage
# or
CONTENT_STORAGE=s3://bucket-name/prefix?region=us-east-1
OAuth Backend Configuration#
For PDS OAuth (default):#
OAUTH_BACKEND=pds
SIGNING_KEYS=did:key:foobarbaz
For AIP OAuth:#
OAUTH_BACKEND=aip
AIP_HOSTNAME=oauth.provider.com
AIP_CLIENT_ID=your-client-id
AIP_CLIENT_SECRET=your-client-secret
Optional Features#
# Jetstream (real-time events)
ENABLE_JETSTREAM=true
# Webhooks
ENABLE_WEBHOOKS=true
ENABLE_TASK_WEBHOOKS=true
# Search
ENABLE_OPENSEARCH=true
ENABLE_TASK_OPENSEARCH=true
OPENSEARCH_ENDPOINT=https://localhost:9200
# Email notifications
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USERNAME=user@example.com
SMTP_PASSWORD=your-password
SMTP_FROM=noreply@your-domain.com
# Server configuration
PORT=3000
BIND_ADDR=0.0.0.0
RUST_LOG=info
Generating Keys#
Use the included crypto utility to generate required keys:
# Generate HTTP cookie key
$ cargo run --bin crypto -- key
# Generate a private key OAuth signing
$ goat key generate -t p256
Key Type: P-256 / secp256r1 / ES256 private key
Secret Key (Multibase Syntax): save this securely (eg, add to password manager)
z42tmsxs...
export SIGNING_KEYS=did:key:z42tmsxs...
Running the Application#
# Start the server
cargo run --bin smokesignal
# With debug logging
RUST_LOG=debug cargo run --bin smokesignal
The application will be available at http://localhost:3000
AT Protocol Integration#
Smokesignal integrates deeply with the AT Protocol ecosystem:
- Lexicons: Supports standard community schemas
community.lexicon.calendar.event- Event recordscommunity.lexicon.calendar.rsvp- RSVP responsesevents.smokesignal.profile- User profilesevents.smokesignal.calendar.acceptance- RSVP acceptance recordscommunity.lexicon.location- Location data
- XRPC: Provides server endpoints for search and service operations
- Jetstream: Consumes real-time events from the firehose
- Identity: Full DID resolution and verification with caching
- Attestation: Support for verified claims via AT Protocol attestations
Development#
See BUILD.md for detailed development setup instructions.
Project Structure#
src/
├── atproto/ # AT Protocol integration
│ └── lexicon/ # Lexicon definitions (profile, acceptance)
├── bin/ # Executables (smokesignal, crypto)
├── http/ # Web handlers and middleware
│ ├── handle_*.rs # Route handlers
│ └── errors/ # HTTP error handling
├── storage/ # Data access layer
│ ├── event.rs # Event storage
│ ├── acceptance.rs # RSVP acceptance storage
│ ├── profile.rs # Profile caching
│ ├── notification.rs # Email preferences
│ └── private_event_content.rs # Conditional content
├── consumer.rs # Jetstream event consumer
├── processor.rs # Event content fetcher
├── service.rs # Service identity
├── emailer.rs # Email sending
├── email_templates.rs # Email rendering
├── identity_cache.rs # Identity/profile caching
├── image.rs # Image processing
├── throttle_redis.rs # Rate limiting
└── task_*.rs # Background tasks
License#
This project is licensed under the MIT License - see the LICENSE file for details.