# fansifter-common

Shared Python library for Fansifter services.

## Scope

The package provides common code used across OWS services and lambdas:

- Authentication and authorization
- Database adapters (SQLAlchemy)
- FastAPI API helpers (security, middleware, error handlers)
- Integrations for external services (AWS, Snowflake, SendGrid, Twilio, POEditor, Stripo)
- Legal info and translation utilities
- Shared logging, testing, and utility modules

## Installation

Make sure you have `uv` installed:

```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
```

Install the library from the private Orchard PyPI with `pip`:

```bash
pip install --index-url https://pypi.theorchard.io/pypi/ fansifter-common
```

Or using `uv`:

```bash
uv pip install --index-url https://pypi.theorchard.io/pypi/ fansifter-common
```

### Optional Dependencies

The library has optional dependency groups for different use cases:

```bash
# CLI tools
pip install --index-url https://pypi.theorchard.io/pypi/ "fansifter-common[cli]"

# Database support (SQLAlchemy, PostgreSQL)
pip install --index-url https://pypi.theorchard.io/pypi/ "fansifter-common[db]"

# Cryptography (JWT with crypto)
pip install --index-url https://pypi.theorchard.io/pypi/ "fansifter-common[crypto]"

# All optional dependencies
pip install --index-url https://pypi.theorchard.io/pypi/ "fansifter-common[cli,db,crypto]"
```

Use extras based on the modules you import:

- `cli`: required for translation CLI and other Click-based commands
- `db`: required for `fansifter_common.adapters.db` modules
- `crypto`: required for JWT crypto features

## Consumer Integration

Add dependency in your service `pyproject.toml`:

```toml
[project]
dependencies = [
	"fansifter-common>=0.150.0",
]
```

If your service uses DB or crypto modules, install with extras:

```toml
[project]
dependencies = [
	"fansifter-common[db]>=0.150.0",
	# or
	"fansifter-common[crypto]>=0.150.0",
]
```

For `uv`, configure the private index:

```toml
[tool.uv]

[[tool.uv.index]]
name = "theorchard"
url = "https://pypi.theorchard.io/pypi/"
```

## Modules

- `auth`: account and permission handling
- `api`: FastAPI helpers (security, middleware, error handlers, OpenAPI)
- `adapters.db`: database/session/transaction abstractions
- `adapters.aws`, `adapters.snowflake`, `adapters.sendgrid`, `adapters.twilio`, `adapters.poeditor`, `adapters.stripo`, `adapters.graphql_router`: external integrations
- `legal_info`: legal entities and privacy links
- `translation`: translation loaders and CLI integration
- `logging`: filters, formatters, logging helpers
- `testing`: reusable test DB and factories
- `utils`: common helper modules

Detailed DB docs: [docs/db.md](docs/db.md)

## Local Development

### Prerequisites

- Python 3.12+
- `uv` package manager

### Environment Setup

```bash
cd python-fansifter-common
make env
```

This installs dependencies in a virtual environment.

### Common Commands

```bash
# Show available make targets
make help

# Install runtime + all development extras
make pip_dev

# Run formatting fixes
make fmt

# Regenerate requirements-dev.txt
make pip-compile

# Remove local environment and caches
make clean
```

### Running Tests

```bash
# Run all tests
make test

# Run tests with coverage report
make test_cov

# Run specific test file
uv run pytest tests/test_email.py -v
```

Fast local loop for one module:

```bash
uv run pytest tests/adapters/test_ows_users.py -v
uv run ruff check fansifter_common/adapters/ tests/adapters/
uv run ty check fansifter_common/adapters tests/adapters
```

### Code Quality

```bash
# Run linter and type checker
make lint

# Format code (using Ruff)
uv run ruff format fansifter_common tests
```

### Publishing

The library is published to the private Orchard index: https://pypi.theorchard.io/pypi/

## Known Consumers

These services depend on `fansifter-common`. If you change shared behavior, validate affected consumers.

### Using Legal Information
- **ows-preference-center** — User preference management
- **ows-email-campaigns** — Email campaign orchestration
- **sendgrid-send-emails** (lambda-audience) — Email sending via Lambda
- **songwhip-fan-consent-handler** (lambda-audience) — Consent handling via Lambda

### Additional Usage in lambda-audience
- **automated-emails-sender** — Uses AWS, Snowflake, constants, and logging utilities
- **text-campaigns-dispatcher** — Uses DB adapters, Snowflake converter, testing factories, and utils
- **fivetran-webhooks** — Uses context, M2M token manager, AWS secrets adapter, and logging
- **refresh-m2m-token** — Uses constants, logging helpers, timezone utils, and AWS secrets adapter
- **twilio-webhooks-outbound** — Uses AWS secrets adapter, constants, functional utils, and logging
- **export-audience-file** — Uses constants and logging configuration helpers
- **share-audience** — Uses crypto extras from `fansifter-common[crypto]`
- **sendgrid-webhooks** — Uses `fansifter-common` package dependency

### Using Database Adapters
- **ows-email-campaigns** — Campaign data persistence
- **ows-dmp** — Data management platform
- **ows-preference-center** — Preference data storage

### Using API Utilities
- **ows-email-campaigns** — FastAPI error handling and middleware
- **ows-dmp** — API security and OpenAPI documentation
- **ows-preference-center** — Request/response handling

### Using Authentication
- **ows-email-campaigns** — User authorization
- **ows-preference-center** — Account management
- **ows-dmp** — Permission checking

## Project Structure

```
fansifter_common/
├── auth/                    # Authentication & authorization
├── api/                     # FastAPI integration
├── adapters/               # Third-party service adapters
│   ├── aws/               # AWS S3, KMS, Secrets Manager
│   ├── db/                # Database (SQLAlchemy)
│   ├── sendgrid/          # Email service
│   ├── twilio/            # SMS/WhatsApp
│   ├── stripo/            # Email templates
│   ├── snowflake/         # Data warehouse
│   ├── poeditor/          # Translation management
│   └── graphql_router/    # GraphQL proxy
├── artist/                 # Artist management
├── context/                # Request context utilities
├── core/                   # Core enums and types
├── email.py               # Email encoding/decoding
├── encrypter.py           # Encryption utilities
├── legal_info/            # Legal entity management
├── logging/               # Structured logging
├── translation/           # Multi-language support
├── testing/               # Testing utilities
├── httpclient/            # HTTP client utilities
├── identifiers/           # Identifier management
├── protocols.py           # Protocol definitions
└── utils/                 # General utilities
```

## Change Guidelines

When making changes to this library:

1. **Ensure backward compatibility** — This is a dependency for multiple services
2. **Update tests** — Add tests for new features
3. **Run quality checks** — `make lint` and `make test`
4. **Update documentation** — Add docstrings and update README as needed
5. **Notify dependents** — Services listed above may need updates

### Shared-Change Checklist

Before merging changes in commonly used modules (`auth`, `adapters.db`, `api`, `logging`, `legal_info`):

1. Verify backward compatibility for public behavior and signatures.
2. Run `make lint` and `make test` in this repository.
3. Validate at least one known consumer service that uses the changed module.
4. If behavior changed, update service-level integration code and tests.
5. Update docs where consumers copy usage patterns.
