# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

This is `augint-billing-lib`, a Python library that provides billing service functionality for API usage tracking with Stripe integration. It follows a clean architecture pattern with ports and adapters, designed to be deployed as an AWS Lambda layer.

## Critical Rules

- **No rebase on main**: NEVER use `git pull --rebase` or `git rebase` on the default branch. Use merge commits only.
- **No manual versioning**: NEVER manually edit version numbers. Semantic Release manages versions via conventional commits.
- **No lock file edits**: NEVER directly write text into lock files (uv.lock, package-lock.json, poetry.lock, yarn.lock). Always use package manager commands (`uv lock`, `uv add`, `npm install`) to regenerate them.
- **No .env commits**: NEVER commit .env files. Use .env.example for templates.
- **No force push to main**: NEVER use `git push --force` on main or the default branch.

## Development Commands

### Setup & Dependencies (uv)
```bash
uv sync --all-extras                         # Install dependencies
uv run pytest                                # Run tests
uv run pytest --cov=src --cov-fail-under=80  # Tests with coverage
uv run ruff check src/                       # Lint
uv run mypy src/                             # Type check
uv run pre-commit run --all-files            # Run all pre-commit hooks
```

### Testing
```bash
# Run fast tests (default, excludes e2e)
make test

# Run specific test categories
make test-unit        # Unit tests with coverage
make test-integration # Integration tests (requires AWS)
make test-e2e         # End-to-end tests with mocked services
make test-all         # All tests
make test-slow        # Slow tests only

# Direct pytest commands
uv run pytest tests/unit/test_service.py  # Single test file
uv run pytest -k "test_handle_stripe"      # Test by pattern
uv run pytest -m "not slow and not ci_only"  # By markers
```

### Code Quality
```bash
# Pre-commit hooks (runs ruff, mypy, etc.)
uv run pre-commit run --all-files

# Individual tools
uv run ruff check --fix    # Linting with fixes
uv run ruff format .       # Format code
uv run mypy src/           # Type checking
uv run bandit -r src/      # Security scanning
```

### CLI Commands (ai-billing)
```bash
# Show environment configuration
uv run ai-billing env-dump

# Handle Stripe events locally
uv run ai-billing handle-event --file tests/fixtures/setup_intent.succeeded.json

# Report usage to Stripe
uv run ai-billing sync-usage

# Manage API keys
uv run ai-billing promote --api-key ABC123
uv run ai-billing demote --api-key ABC123
```

## Architecture

### Core Pattern: Ports & Adapters
- **Ports** (`src/augint_billing_lib/ports.py`): Abstract interfaces for external dependencies
  - `StripePort`: Stripe operations interface
  - `UsageSourcePort`: API Gateway usage retrieval
  - `CustomerRepoPort`: DynamoDB persistence
  - `PlanAdminPort`: API Gateway plan management

- **Service** (`src/augint_billing_lib/service.py`): Core business logic
  - `BillingService`: Orchestrates billing operations

- **Adapters** (`src/augint_billing_lib/adapters/`): Concrete implementations
  - `stripe.py`: Stripe API integration
  - `ddb_repo.py`: DynamoDB repository
  - `apigw_usage.py`: API Gateway usage collection
  - `apigw_admin.py`: API Gateway plan administration

- **Bootstrap** (`src/augint_billing_lib/bootstrap.py`): Dependency injection and Lambda handler setup

### Key Models (`src/augint_billing_lib/models.py`)
- `Link`: Maps API keys to Stripe customers and usage plans
- Fields: `api_key_id`, `stripe_customer_id`, `plan`, `usage_plan_id`, `metered_subscription_item_id`

## Environment Configuration

### Required Environment Variables
- `STACK_NAME`: CloudFormation stack name
- `AWS_REGION`: AWS region
- `STRIPE_SECRET_KEY` or `STRIPE_SECRET_ARN`: Stripe authentication

### Optional Environment Variables
- `TABLE_NAME`: DynamoDB table (default: `{STACK_NAME}-customer-links`)
- `FREE_USAGE_PLAN_ID`: Free tier plan ID (default: `FREE_10K`)
- `METERED_USAGE_PLAN_ID`: Paid tier plan ID (default: `METERED`)
- `API_USAGE_PRODUCT_ID`: API Gateway product (defaults to stack discovery)

## Testing Strategy

### Test Markers
- `unit`: Fast, no external dependencies
- `integration`: Requires AWS/Stripe test accounts
- `e2e`: End-to-end with mocked services
- `slow`: Long-running tests
- `ci_only`: CI environment only
- `stream_sensitive`: May fail in bulk runs (Click stream issues)

### Coverage Requirements
- Minimum: 70% (configured in pyproject.toml)
- Run with: `make coverage`

## Key Workflows

### Stripe Event Processing Flow
1. Stripe sends event to EventBridge partner bus
2. Lambda handler calls `bootstrap.process_event_and_apply_plan_moves()`
3. Service determines target plan based on payment status
4. Updates DynamoDB and moves API key between usage plans

### Usage Reporting Flow  
1. Hourly EventBridge schedule triggers Lambda
2. Handler calls `service.reconcile_usage_window()`
3. Fetches usage from API Gateway for metered customers
4. Reports usage to Stripe with idempotency
5. Updates DynamoDB with reporting timestamps

## Billing Architecture Philosophy (Zero-Ops)

### What This Library Does
- **Reacts to Stripe webhooks** to keep our database synchronized
- **Moves API keys between usage plans** based on payment status  
- **Reports usage to Stripe** for metered billing

### What This Library Does NOT Do
- **No checkout sessions** - Stripe's Customer Portal handles all payment UI
- **No payment collection** - Stripe handles billing, retries, and dunning
- **No customer-facing features** - All UI/UX is through Stripe's hosted pages

### The Zero-Ops Flow
1. Customers manage all billing through Stripe's Customer Portal (billing.stripe.com)
2. Stripe sends webhooks when customers add/remove payment methods or when payments succeed/fail
3. We react to these webhooks by moving API keys between free/metered plans
4. We report usage hourly, Stripe handles invoicing and collection

**Important**: Any issues suggesting checkout session creation, payment forms, or customer-facing billing UI should be rejected. These violate our zero-ops principle - Stripe already provides all of this.

## Integration Points

### Cross-Repository Contract
- **Library** (`augint-billing-lib`): Business logic, Stripe operations, DynamoDB persistence
- **Infrastructure** (`augint-billing-infra`): Lambda handlers, EventBridge, IAM, CloudFormation
- Communication via shared DynamoDB table and environment variables

### DynamoDB Schema (customer_links)
- **Primary Key**: `api_key_id`
- **GSI**: `gsi_stripe_customer` (hash: `stripe_customer_id`)
- **Key Attributes**: `plan`, `usage_plan_id`, `metered_subscription_item_id`, `last_reported_usage_ts`

## Development Notes

### Branch Naming Convention
Format: `{type}/issue-N-description` where type is one of: feat, fix, docs, refactor, test, chore, ci, build, style, revert, perf.
Example: `feat/issue-42-add-usage-caching`

### Commit Convention
- Use conventional commits: `fix:` = patch, `feat:` = minor, `feat!:` / `BREAKING CHANGE` = major.
- Reference issues: `feat: add usage caching closes #42`

### PR Convention
- Target the default development branch. Enable automerge.

### Pre-commit Configuration
- Run `uv run pre-commit run --all-files` explicitly before committing (no automatic git hooks -- they break across Windows/WSL).
- If checks fail, fix the issue and create a NEW commit (do not amend).
- Enforces: files end with single newline, no trailing whitespace, Python formatting with ruff, type checking with mypy (on src/ only).

### Test Convention
- Write tests for all new functionality. Bug fixes require regression tests.

### Error Handling Patterns
- Use custom exceptions from `exceptions.py`
- Implement retry logic for transient failures
- Log errors with structured logging
- Maintain idempotency for all operations

## Development Workflow

**IMPORTANT**: Always follow this sequence. Do NOT skip to step 3 without completing step 2 first.

1. **Pick an issue**: `/ai-pick-issue` -- find or get assigned work
2. **Prepare branch**: `/ai-prepare-branch` -- REQUIRED before any code changes. Creates a fresh branch from the latest base (main or dev), syncs upstream, sets up remote tracking. Never start coding on an existing branch from a previous task.
3. **Develop**: Write code with tests, following project conventions
4. **Submit**: `/ai-submit-work` -- runs all checks locally, commits, pushes, creates automerge PR
5. **Monitor**: `/ai-monitor-pipeline` -- watches CI, diagnoses failures, auto-fixes and re-pushes

## Key Commands

```bash
# Git
git status                    # Check working tree
git log --oneline -10         # Recent commits

# GitHub CLI
gh issue list --state open    # View open issues
gh pr create                  # Create pull request
gh pr merge --auto --squash   # Enable automerge
gh run list                   # List workflow runs
gh run view <id>              # View run details
gh run watch <id>             # Watch run in real-time
```

## Common Development Tasks

### Adding a New Stripe Event Handler
1. Update `BillingService.handle_stripe_event()` in `service.py`
2. Add test fixture in `tests/fixtures/`
3. Write unit test in `tests/unit/test_service.py`
4. Update CONTRACT.md if changing cross-repo interface

### Modifying Database Schema
1. Update `Link` model in `models.py`
2. Update repository methods in `adapters/ddb_repo.py`
3. Update CONTRACT.md with schema changes
4. Coordinate with infra repo for table updates

### Running Against Test AWS Account
1. Copy TEST_* environment variables to .env (remove TEST_ prefix)
2. Run: `make test-aws`
3. Check CloudWatch logs for Lambda execution details
