# PIP Platform — State Tracker

## Current Phase: 3 (Complete)

### Phase 1 — Foundation ✅
- FastAPI app skeleton, Settings, Docker Compose (Postgres, Redis, RabbitMQ)
- SQLAlchemy async models + Alembic migration `001_initial`
- Auth: JWT (access/refresh), RBAC (admin/operator/viewer), user CRUD
- Entities: Pharmacy, Connector, Medication, Inventory, Reservation, ERP System
- Repositories + Services for all entities
- API v1 endpoints for all entities
- Middleware: CORS, request logging, metrics
- Observability: OpenTelemetry traces, Prometheus metrics

### Phase 2 — Connector SDK ✅
- Abstract connector interface + Mock connector implementation
- Connector registry, version management, config CRUD
- Medicationcatalog + inventory sync plumbing

### Phase 3 — Sync, Audit, API Keys, Rate Limiting ✅
- **Sync Jobs**: Repository, service, API endpoints (create, list, get, trigger, complete, fail, cancel, logs, status filter)
- **Audit Logging**: AuditService (`log_action`, `list_logs`), AuditMiddleware (auto-logs POST/PUT/PATCH/DELETE), audit endpoint
- **API Key Auth**: Dual auth via `get_authenticated_user` — supports both Bearer JWT and X-API-Key header; `require_role` and `require_scope` use it; API Key CRUD endpoints
- **Rate Limiting**: Custom `RateLimitMiddleware` (sliding window, X-RateLimit-* headers, 429 with Retry-After); exempt paths (docs, metrics, health)
- **RabbitMQ**: Routing keys for `sync_created`, `sync_triggered`, `sync_completed`, `sync_failed`, `sync_cancelled`

## Architecture Decisions
- Clean Architecture: domain entities → services → API endpoints → infrastructure
- Repository pattern with SQLAlchemy async
- Dual auth: JWT Bearer + X-API-Key in single `get_current_user` dependency
- Audit middleware uses separate DB session (via `async_session_factory`) to decouple from request session
- Rate limiting: custom middleware replacing slowapi (incompatible with FastAPI 0.138+ `_IncludedRouter`)
- DB migrations: Alembic `upgrade head` runs in app lifespan (not `create_all`)
- `APIKeyEntity.key_hash` is `bytes` (sha256 digest), ORM model uses `LargeBinary(64)`

## Key Files
| File | Purpose |
|------|---------|
| `src/main.py` | App factory, lifespan (alembic upgrade), middleware chain |
| `src/api/v1/dependencies/auth.py` | Dual auth: JWT + API Key, require_role, require_scope |
| `src/api/middleware/audit.py` | Auto-audit for write endpoints |
| `src/api/middleware/rate_limit.py` | Custom sliding window rate limiter |
| `src/api/v1/endpoints/sync_jobs.py` | Sync job CRUD + lifecycle |
| `src/api/v1/endpoints/api_clients.py` | API client + key management |
| `src/api/v1/endpoints/audit.py` | Audit log query endpoint |
| `src/services/synchronization/sync_service.py` | Sync job business logic |
| `src/services/audit/audit_service.py` | Audit service |
| `src/infrastructure/messaging/rabbitmq.py` | Event publishing routing keys |
| `alembic/versions/001_initial.py` | Full schema (all tables including sync_jobs, sync_logs, audit_logs) |

## Configuration (env)
| Variable | Default | Description |
|----------|---------|-------------|
| `RATE_LIMIT_PER_MINUTE` | 60 | Max requests per client per minute |
| `RATE_LIMIT_AUTH_PER_MINUTE` | 10 | (reserved) Auth endpoint limit |
| `JWT_SECRET_KEY` | change-me-in-production | Must be set in production |
| `API_KEY_PREFIX` | pip | (reserved) Key namespace prefix |

## Next Phase Ideas
- Redis-backed rate limiter (for multi-instance)
- Per-client rate limits (use `api_clients.rate_limit` column)
- API Key scope enforcement on specific endpoints (currently role-only)
- Sync job execution worker (consume RabbitMQ events, run connector)
- IP allowlist enforcement for API clients
- Alembic migration 002 for any schema changes
