# songwhip-fan-consent-handler

## Overview

An AWS Lambda handler triggered by MSK (Managed Streaming for Kafka) events that processes Songwhip fan consent requests. For each incoming record, it validates the fan's email address, generates a double opt-in confirmation email via Amazon SES, and constructs a subscribe button link via the OWS Preference Center. Processed records are cached in Redis to prevent duplicate sends.

## Getting Started

### Requirements

Minimum requirements and recommended tooling:

- Python 3.13+
- UV (astral `uv` tool) for environment and task running (see `pyproject.toml` `tool.uv` configuration)
- Docker and Docker Compose (used for CI targets)
- Make (for provided Makefile targets)

Developer tooling (used in CI / recommended):

- `pytest` (unit tests)
- `ruff` and `pyright` (linting / type checks)
- Redis (required by the deduplication cache in runtime environments)

### Installation

```bash
make env
```

### Configuration

For local development copy the provided example environment file to `.env`:

```bash
cp .env.example .env
```

After copying, edit `.env` and fill in any required values before running the service or tests.

Key environment variables:

- `ENVIRONMENT` — deployment environment (e.g. `dev`, `qa`, `prod`)
- `SENTRY_DSN` — Sentry DSN (required in `qa` and `prod`)
- `REDIS_HOST`, `REDIS_PORT`, `REDIS_SSL` — Redis connection settings for the deduplication cache
- `CACHE_BACKEND` — cache backend (`redis` or `localhost`)

## Testing

Run the project's unit tests with:

```bash
make test
```

## Linting and formatting

Run the linter with:

```bash
make lint
```

Run the code formatter with:

```bash
make fmt
```

## Project Structure

- `app/` - Main application code
  - `__init__.py` - Application setup (logging and Sentry initialisation)
  - `config.py` - Configuration management (Redis, SES, email wording, Sentry settings)
  - `handlers.py` - `SongwhipFanConsentHandler` — processes MSK records, validates emails, sends confirmation emails
  - `models.py` - Pydantic event and record models
  - `main.py` - Lambda handler entry point
  - `modules.py` - Dependency injection configuration
  - `exceptions.py` - Custom exception types
  - `connectors/` - External service connectors
    - `ows_preference_center.py` - OWS Preference Center client (fan consent ID encryption)
    - `aws/ses/email_client.py` - Amazon SES email client
  - `templates/` - Jinja2 HTML email templates
    - `email.html` - Confirmation email template
    - `privacy_link.html` - Privacy link fragment template
- `tests/` - Test suite
  - `unit/` - Unit tests
    - `conftest.py` - Shared pytest fixtures
    - `module.py` - Test DI module
    - `test_handler.py` - Handler tests
    - `test_main.py` - Lambda entry point tests
    - `templates/` - Test template copies
