Metadata-Version: 2.4
Name: govpal-reach
Version: 0.1.0
Summary: Civic engagement library: address → reps → delivery
Author: GovPal
License: MIT
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Sociology
Requires-Python: >=3.12
Description-Content-Type: text/markdown
Requires-Dist: PyYAML>=6.0
Requires-Dist: cryptography>=44.0
Requires-Dist: pgqueuer>=0.25.3
Requires-Dist: playwright>=1.58.0
Requires-Dist: plivo>=4.50.0
Requires-Dist: psycopg[binary]>=3.3.2
Requires-Dist: shapely>=2.0
Requires-Dist: twilio>=9.0
Requires-Dist: usaddress-scourgify>=0.6.0

# GovPal Reach

Civic engagement library: discover representatives from an address and deliver messages via email or web forms. Resistbot-like functionality with modular, pluggable architecture.

## Project overview

GovPal Reach maps **address → representatives** (federal, state, local) and supports **message delivery** via email (Postmark) or web forms (Playwright). Users onboard via SMS/OTP (Twilio Verify, or Plivo).

- **Discovery:** Geocode address (Census Geocoder), then look up reps (Google Civic, Open States, LA local).
- **Delivery:** Send messages via email or submit web forms; PGQueuer for durable queue.
- **Identity:** User profiles, PII encryption, SMS OTP (Twilio primary, or Plivo).
- **Orchestrator:** High-level API composing discovery and delivery.

## Quick start

### 1. Install

Requires [uv](https://docs.astral.sh/uv/) (install: `curl -LsSf https://astral.sh/uv/install.sh | sh`).

```bash
uv sync
```

### 2. Configure environment

Copy `.env.example` to `.env` and fill in values. See [SETUP.md](SETUP.md) for how to obtain credentials.

```bash
cp .env.example .env
# Edit .env with your credentials
```

### 3. Run a simple example

The library is intended to be imported by a host app. Example usage:

```python
from govpal.orchestrator.api import discover_reps_for_address, send_message_to_representatives

# Discover reps for an address
reps = discover_reps_for_address("123 Main St, Los Angeles, CA 90012")

# Send a message to one or more representatives (library adds preamble + closing)
# body = middle content only; subject, profile, phone, and list of reps
results = send_message_to_representatives(
    "Your message body here.",
    "Subject line",
    profile,  # constituent profile (first_name, last_name, email, full_address_for_display)
    phone,
    reps,     # list of rep dicts with contact_email
)
# results = [(rep, success), ...]
```

### 4. Database (optional)

Apply the schema if using Postgres (Identity module requires 002 for OTP):

```bash
psql $DATABASE_URL -f schema/001_initial.sql
psql $DATABASE_URL -f schema/002_verify_session_uuid.sql
```

## Modules

| Module       | Responsibility                                      |
|--------------|-----------------------------------------------------|
| **Discovery**| Address → reps (Google Civic, Open States, Census)  |
| **Delivery** | Email (Postmark), web forms (Playwright), queue     |
| **Identity** | Users, PII, SMS OTP (Twilio or Plivo)               |
| **Orchestrator** | High-level API: discovery, send_message_to_representatives (preamble + closing) |

## How to run the system

- **As a library:** Import `govpal` in your app; configure env vars; use orchestrator API.
- **Production queue path:** For durable delivery, use the queue path: **create_message** → optional **update_message** → **enqueue_messages_for_address**. Set `GOVPAL_USE_REAL_QUEUE=1` and run the **GovPal delivery worker** so jobs are processed: `uv run pgq run govpal.delivery.worker:create_pgqueuer --max-concurrent-tasks 2`. See [SETUP.md](SETUP.md) (PGQueuer section) for create_message/update_message usage and worker run command.
- **Railway:** Deploy with Postgres; run the queue worker as a separate process or worker dyno; env vars set in Railway dashboard.

## Using in another project

Install GovPal Reach as a dependency from **PyPI** (recommended for released versions):

```bash
# With uv (recommended)
uv add "govpal-reach>=0.1.0"

# Or with pip
pip install govpal-reach
```

To pin to a specific GitHub tag (e.g. before a version is on PyPI or to try a release tag):

```bash
uv add "govpal-reach @ git+https://github.com/YOUR_ORG/govpal-reach@v0.1.0"
```

Replace `YOUR_ORG` and the tag (`v0.1.0`) as needed. The **import name** is `govpal`:

```python
from govpal.orchestrator.api import discover_reps_for_address, create_message, update_message, enqueue_messages_for_address
```

## How to test

```bash
# Unit tests (runs in project .venv)
uv run pytest

# With coverage
uv run pytest --cov=govpal --cov-report=term-missing

# Integration tests (uses VCR cassettes; no live API calls by default)
uv run pytest -m integration

# Linter
uv run ruff check src/ tests/
uv run ruff format --check src/ tests/
```

Full test suite (lint + pytest + coverage): see [TEST_PLAN_SUMMARY.md](docs/TEST_PLAN_SUMMARY.md).

## Documentation

- [RESEARCH_SUMMARY.md](docs/RESEARCH_SUMMARY.md) – APIs, data sources, architecture research
- [PLAN_SUMMARY.md](docs/PLAN_SUMMARY.md) – Implementation plan, beads, schema, modules
- [TEST_PLAN_SUMMARY.md](docs/TEST_PLAN_SUMMARY.md) – Testing strategy per phase
- [SETUP.md](SETUP.md) – External services, credentials, permissions; **Releasing** (PyPI and GitHub) in section 13

## License

MIT
