3.7 KiB
3.7 KiB
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_roleandrequire_scopeuse 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_userdependency - 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 headruns in app lifespan (notcreate_all) APIKeyEntity.key_hashisbytes(sha256 digest), ORM model usesLargeBinary(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_limitcolumn) - 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