# INDELIS API

**Cemetery & Gravesite Management SaaS Platform**

A multi-tenant FastAPI backend for managing cemetery operations — records, plots, memorials, scheduling, billing, and public tribute pages.

---

## Tech Stack

| Layer | Technology |
|-------|-----------|
| Web Framework | FastAPI 0.115 + Uvicorn |
| Database | PostgreSQL 15 + PostGIS |
| ORM | SQLAlchemy 2.0 (async) |
| Migrations | Alembic |
| Cache / Queue | Redis 7 |
| Background Jobs | ARQ (async Redis queue) |
| Auth | JWT (PyJWT) + bcrypt |
| Validation | Pydantic v2 |
| AI Features | Anthropic Claude (biographies), OpenAI GPT-4o (record extraction) |
| Payments | Stripe |
| Storage | AWS S3 + SES |
| Containerization | Docker + Docker Compose |

---

## Project Structure

```
indelis-api/
├── src/
│   ├── main.py                      # FastAPI app entry point
│   ├── core/
│   │   ├── config.py                # Settings (pydantic-settings)
│   │   ├── constants.py             # Domain enums (roles, statuses)
│   │   ├── security.py              # JWT + password hashing
│   │   ├── dependencies.py          # FastAPI dependency injection
│   │   ├── exceptions.py            # Exception hierarchy
│   │   └── schemas/response.py      # Standard response envelope
│   ├── middleware/
│   │   ├── tenant.py                # Multi-tenant subdomain resolution
│   │   ├── logging.py               # Structured request logging
│   │   └── security.py              # Security headers
│   ├── database/
│   │   ├── base.py                  # Base models + mixins
│   │   ├── session.py               # Async engine + session factory
│   │   └── migrations/              # Alembic migrations
│   ├── apps/
│   │   ├── auth/                    # Authentication (login, refresh, logout)
│   │   ├── tenants/                 # Tenant/account management
│   │   ├── users/                   # User management (RBAC)
│   │   ├── sections/                # Cemetery sections
│   │   ├── plots/                   # Plot inventory
│   │   ├── records/                 # Deceased records + burial info
│   │   ├── sales/                   # Opportunities + contracts
│   │   ├── billing/                 # Invoices + payments
│   │   ├── scheduling/              # Service events
│   │   ├── memorials/               # Online memorials + tributes
│   │   ├── news/                    # Cemetery news posts
│   │   ├── reports/                 # Occupancy + revenue reports
│   │   ├── settings/                # Cemetery settings + fee catalog
│   │   ├── public/                  # Unauthenticated public API
│   │   ├── site_admin/              # Platform administration
│   │   └── ai/                      # AI biography + record extraction
│   └── worker/
│       └── arq_app.py               # ARQ background job worker
├── tests/
├── Dockerfile
├── docker-compose.yml
├── .env.example
├── alembic.ini
└── requirements.txt
```

---

## Quick Start

See [PROJECT_SETUP.txt](PROJECT_SETUP.txt) for the full setup guide.

```bash
# 1. Configure
cp .env.example .env

# 2. Start services
docker-compose up -d

# 3. Run migrations
docker-compose exec api alembic upgrade head

# 4. API docs
open http://localhost:8000/api/docs
```

---

## API Overview

### Authentication

All protected endpoints require:
```
Authorization: Bearer <access_token>
```

Tenant context is required for all non-public endpoints, resolved from:
1. `X-Tenant-ID` header (UUID)
2. `X-Tenant-Slug` header (subdomain string)
3. Subdomain: `riverside.indelis.com`

### Endpoints

| Module | Prefix | Description |
|--------|--------|-------------|
| Auth | `/api/v1/auth` | Login, refresh, logout, /me |
| Tenants | `/api/v1/tenants` | Tenant account management |
| Users | `/api/v1/users` | User CRUD + role management |
| Sections | `/api/v1/sections` | Cemetery section CRUD |
| Plots | `/api/v1/plots` | Plot inventory + status |
| Records | `/api/v1/records` | Deceased records + burial info |
| Sales | `/api/v1/sales` | Opportunities + contracts |
| Billing | `/api/v1/billing` | Invoices + payments |
| Scheduling | `/api/v1/scheduling` | Service events |
| Memorials | `/api/v1/memorials` | Online memorials + tribute moderation |
| News | `/api/v1/news` | Cemetery news posts |
| Reports | `/api/v1/reports` | Occupancy + revenue reports |
| Settings | `/api/v1/settings` | Cemetery profile + fee catalog |
| AI | `/api/v1/ai` | Biography generation, record extraction |
| Public | `/api/public` | Unauthenticated public portal |
| Site Admin | `/api/site-admin` | Platform administration |

### Response Format

All responses follow a consistent envelope:

**Success:**
```json
{
  "success": true,
  "message": "Record created",
  "data": { ... }
}
```

**Paginated:**
```json
{
  "success": true,
  "data": {
    "items": [...],
    "total": 100,
    "page": 1,
    "page_size": 20,
    "pages": 5
  }
}
```

**Error:**
```json
{
  "success": false,
  "message": "Validation failed",
  "errors": [{ "field": "email", "message": "Invalid format" }]
}
```

---

## Multi-Tenancy

Each tenant (cemetery) is an `Account` record identified by a unique `subdomain`. All tenant-scoped tables carry a `tenant_id` FK and are protected by PostgreSQL Row-Level Security policies:

```sql
CREATE POLICY tenant_isolation ON plots
  USING (tenant_id = NULLIF(current_setting('app.tenant', TRUE), '')::uuid);
```

---

## RBAC Roles

| Role | Level | Permissions |
|------|-------|-------------|
| `site_admin` | 99 | Full platform access |
| `administrator` | 4 | Full tenant access |
| `manager` | 3 | Manage operations, no billing |
| `staff` | 2 | Read + create records |
| `view_only` | 1 | Read only |

---

## Background Jobs (ARQ)

| Job | Trigger |
|-----|---------|
| `send_welcome_email` | New tenant provisioned |
| `send_invoice_reminder` | Invoice due date approaching |
| `generate_qr_code` | New memorial published |
| `check_overdue_invoices` | Daily cron |

---

## Database Migrations

```bash
# Run all migrations
alembic upgrade head

# Check current revision
alembic current

# Create a new migration
alembic revision --autogenerate -m "add column X"

# Rollback one
alembic downgrade -1
```

---

## Tests

```bash
pytest tests/ -v
pytest tests/ --cov=src --cov-report=html
```

---

## Environment Variables

See [.env.example](.env.example) for the full list. Required:

- `DATABASE_URL` — PostgreSQL connection string
- `JWT_SECRET` — Access token signing secret
- `JWT_REFRESH_SECRET` — Refresh token signing secret
- `REDIS_URL` — Redis connection string

---

## Health Checks

```
GET /health           # Basic health status
GET /health/live      # Kubernetes liveness probe
GET /health/ready     # Kubernetes readiness probe (DB + Redis check)
```
