API Gateway¶
Path:
services/api-gateway/· Type: API · Port: 8000
The API Gateway is the single entry-point for all client traffic. Built with FastAPI, it exposes a versioned REST API (/v1/) backed by async SQLAlchemy (PostgreSQL) and ClickHouse for analytics queries.
Architecture¶
graph LR
UI[Dashboard UI] -->|HTTPS| AG[API Gateway :8000]
CLI[CLI / SDK] -->|HTTPS| AG
AG --> PG[(PostgreSQL)]
AG --> CH[(ClickHouse)]
AG --> Kafka{{Kafka}}
AG -->|OAuth2| AAD[Azure AD]
Authentication¶
The gateway supports two authentication modes controlled by the AUTH_MODE environment variable:
| Mode | Description |
|---|---|
azure_ad |
Production — validates Azure AD OAuth 2.0 Bearer tokens. Requires API_AZURE_AD_TENANT_ID, API_AZURE_AD_CLIENT_ID, and API_AZURE_AD_AUDIENCE. |
dev |
Development — bypasses token validation. All requests are treated as an authenticated dev user. Never use in production. |
Routers¶
| Router | Prefix | Description |
|---|---|---|
principals |
/v1/principals |
CRUD for identities (users, service accounts, groups) |
assets |
/v1/assets |
CRUD for data assets and resources |
grants |
/v1/grants |
Access-grant relationships between principals and assets |
scores |
/v1/scores |
Decay scores — read-only, computed by the Decay Engine |
reviews |
/v1/reviews |
Review packets and reviewer decisions |
audit |
/v1/audit |
Immutable audit log queries (backed by ClickHouse) |
reports |
/v1/reports |
Compliance report generation and download |
health |
/v1/health |
Liveness and readiness probes |
metrics |
/v1/metrics |
Prometheus-format metrics endpoint |
Pagination¶
All list endpoints use cursor-based pagination via the PaginatedResponse model:
| Parameter | Type | Default | Description |
|---|---|---|---|
cursor |
str |
null |
Opaque cursor from a previous response |
limit |
int |
50 |
Page size (max 100) |
Error Handling¶
The gateway defines a set of domain-specific HTTP exceptions:
| Exception | HTTP Status | Usage |
|---|---|---|
NotFoundError |
404 | Resource does not exist |
BadRequestError |
400 | Validation or business-rule violation |
ConflictError |
409 | Duplicate or version conflict |
All errors are returned in a consistent JSON envelope:
Configuration¶
Configuration is managed via Pydantic BaseSettings with env_prefix="API_":
| Variable | Required | Default | Description |
|---|---|---|---|
API_DATABASE_URL |
Yes | — | PostgreSQL async connection string |
API_CLICKHOUSE_URL |
Yes | — | ClickHouse HTTP URL |
API_KAFKA_BOOTSTRAP |
Yes | — | Kafka bootstrap servers |
API_AUTH_MODE |
No | azure_ad |
azure_ad or dev |
API_AZURE_AD_TENANT_ID |
Cond. | — | Required when AUTH_MODE=azure_ad |
API_AZURE_AD_CLIENT_ID |
Cond. | — | Required when AUTH_MODE=azure_ad |
API_AZURE_AD_AUDIENCE |
Cond. | — | Required when AUTH_MODE=azure_ad |
API_LOG_LEVEL |
No | INFO |
Python log level |
API_CORS_ORIGINS |
No | * |
Allowed CORS origins (comma-separated) |
Observability¶
- Prometheus metrics are exposed at
/v1/metrics(request count, latency histograms, error rates). - Structured JSON logs are written to
stdout. - Readiness probe:
GET /v1/healthreturns200when both PostgreSQL and ClickHouse are reachable.
Request Flow¶
sequenceDiagram
participant Client
participant Gateway as API Gateway
participant Auth as Azure AD
participant DB as PostgreSQL
participant CH as ClickHouse
Client->>Gateway: GET /v1/scores?cursor=...
Gateway->>Auth: Validate Bearer token
Auth-->>Gateway: Token valid
Gateway->>DB: Query scores (cursor-based)
DB-->>Gateway: Rows
Gateway-->>Client: 200 PaginatedResponse