# Songwhip Profile Creator Lambda

AWS Lambda function that creates Songwhip profiles in Neo4j for users based on CSV input from S3.

## Overview

This lambda is triggered by an S3 EventBridge notification when a CSV file is uploaded. It processes the CSV to create `SongwhipProfile` nodes in Neo4j, linking identities to their respective tenants (ParentCompany, CompanyBrand, or Vendor/Account).

## Input

The lambda expects an EventBridge S3 event pointing to a CSV file with the following columns:

| Column | Description |
|--------|-------------|
| `identity_id` | The identity UUID to create the profile for |
| `tenant_type` | One of: `parent_company`, `company_brand`, `account` |
| `tenant_uuid` | The UUID of the tenant to grant access to |

## Processing

For each row, the lambda:
1. Validates required fields and tenant_type
2. Verifies the identity exists in Neo4j
3. Verifies the tenant exists in Neo4j
4. Creates a `SongwhipProfile` node with `HAS_PROFILE` and `HAS_ACCESS_TO` relationships

## Output

The lambda produces:

- **PDP CSV** (`songwhip_output/{timestamp}/{timestamp}.csv`): Contains successful rows formatted for PDP backfill with `songwhip_read` role
- **Manifest JSON** (`songwhip_output/{timestamp}/manifest.json`): Job manifest for PDP backfill processing
- **Failed Rows CSV** (`songwhip_output/{timestamp}/failed_rows.csv`): Contains rows that failed validation or processing with error reasons

## Environment Variables

| Variable | Description | Default |
|----------|-------------|---------|
| `ENVIRONMENT` | Deployment environment (`qa` or `prod`) | `qa` |
| `NEO4J_URL` | Neo4j database URL | - |
| `LOGGER_LEVEL` | Logging level | `INFO` |
| `NEO4J_MAX_RETRY_TIME` | Max retry time for Neo4j transactions (seconds) | `30` |

Credentials (`NEO4J_USERNAME`, `NEO4J_PASSWORD`) are fetched via `LambdaSecretsManager`.

## Development

### Prerequisites

- Python 3.13
- [uv](https://docs.astral.sh/uv/) package manager

### Setup

```bash
uv sync --all-extras
```

### Run Locally with Docker

```bash
docker compose up --build -d function

# Invoke the function
curl --request POST \
  --url http://localhost:9000/2015-03-31/functions/function/invocations \
  --header 'Content-Type: application/json' \
  --data @tests/sample_event.json

# Restart after code changes
docker compose restart function
```

### Testing

```bash
# Unit tests
uv run pytest tests/unit

# Single test
uv run pytest tests/unit -k test_name

# Integration tests (requires Docker)
make ci_test_integration
```

### Linting

```bash
# Check
uv run ruff check && uv run ruff format --check && uv run mypy .

# Auto-format
uv run ruff format
```

## Project Structure

```
songwhip_profile_creator/
├── config.py           # Configuration, logging, Neo4j client setup
├── src/
│   ├── app.py          # Lambda handler and core logic
│   └── constants.py    # Cypher queries and mappings
├── tests/
│   ├── unit/           # Unit tests
│   ├── integration/    # Integration tests
│   └── sample_event.json
├── Dockerfile          # Lambda deployment image
├── Dockerfile.tests    # Test runner image
└── docker-compose.yaml
```
