this repo has no description

CLAUDE.md#

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview#

xrpcs-emailer is an ATProtocol XRPC service that sends emails in response to webhook events. It's specifically designed for the smokesignal.events platform to handle event notifications, particularly RSVP confirmations. The service provides OAuth-protected webhook endpoints and integrates with SMTP for email delivery.

Repository: https://tangled.sh/@smokesignal.events/xrpcs-emailer

Development Commands#

Build and Run#

# Build the project
cargo build

# Build for release
cargo build --release

# Run the service (requires environment variables)
cargo run

# Run with environment variables
SERVICE_KEY="did:key:your-service-key" \
EXTERNAL_BASE="emailer.example.com" \
SMTP_CREDENTIALS="smtp://username:password@smtp.server:port" \
cargo run

Testing and Quality#

# Run tests
cargo test

# Run tests with output
cargo test -- --nocapture

# Check code without building
cargo check

# Format code
cargo fmt

# Run linter
cargo clippy

# Run linter with all targets
cargo clippy --all-targets --all-features

Architecture#

Core Components#

  1. WebContext (src/main.rs): Central application state containing:

    • HTTP client for external requests
    • LRU cache for DID document storage (3 entries)
    • Key provider for service keys
    • Service configuration
    • SMTP mailer for sending emails
  2. Key Management:

    • SimpleKeyProvider: Manages cryptographic keys
    • Service key: Used for service identity and authentication
  3. HTTP Endpoints:

    • GET / - Service index page with link to repository
    • GET /.well-known/did.json - DID:web document
    • GET /.well-known/atproto-did - ATProtocol DID identifier
    • GET /.well-known/oauth-protected-resource - OAuth Protected Resource Metadata
    • POST /xrpc/events.smokesignal.automation.InvokeWebhook - Webhook handler for event processing (OAuth protected)

Webhook Processing Flow#

  1. Client sends POST request to webhook endpoint with OAuth bearer token
  2. Service validates:
    • Bearer token is present and valid
    • Request contains valid webhook payload
  3. Service processes webhook events:
    • Currently handles rsvp.created events
    • Extracts email address from event context
  4. For RSVP events, service:
    • Constructs confirmation email with plain text and HTML parts
    • Sends email via configured SMTP server
    • Logs success or failure
  5. Returns empty JSON response

Environment Variables#

Required:

  • SERVICE_KEY: Service identity private key (e.g., did:key:z42tj...)
  • EXTERNAL_BASE: External hostname for the service (e.g., emailer.example.com)
  • SMTP_CREDENTIALS: SMTP connection URL (e.g., smtp://username:password@smtp.server:port)

Optional:

  • PORT: Server port (default: 8080)
  • PLC_HOSTNAME: PLC directory hostname (default: plc.directory)
  • USER_AGENT: HTTP client user agent
  • DNS_NAMESERVERS: Custom DNS nameservers (comma-separated)
  • CERTIFICATE_BUNDLES: Additional CA certificates (comma-separated paths)

Code Patterns#

  • All code is in a single src/main.rs file
  • Uses Axum web framework with Tower middleware
  • Async/await patterns with Tokio runtime
  • Error handling with custom error types that implement Axum's IntoResponse
  • DID resolution with LRU caching
  • OAuth bearer token validation
  • Email sending via lettre with SMTP
  • Webhook event processing with JSON parsing
  • Unsafe code is forbidden via #![forbid(unsafe_code)]

Key Generation#

Generate service keys using:

goat key generate -t p256

The public key derived from the service key is included in the DID:web document for identity verification.

Email Configuration#

The service sends emails using SMTP. The SMTP_CREDENTIALS environment variable should be a connection URL in the format:

  • smtp://username:password@smtp.server:port for standard SMTP
  • smtps://username:password@smtp.server:port for SMTP over TLS

Currently, the service sends RSVP confirmation emails with:

  • From: "Smoke Signal Emailer" events@smokesignal.events
  • Subject: "RSVP'd to event"
  • Body: Multipart message with both plain text and HTML versions

Docker Build#

The project includes a multi-stage Dockerfile for containerized deployment. Note that the Dockerfile currently references the old binary name xrpcs-semeion instead of xrpcs-emailer - this should be updated to match the Cargo.toml package name.