# 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