# openalice-ml-gateway

> ML Gateway — API key auth, rate limiting, and usage tracking in front of embed/rerank/NER backends.

## At a glance
| field | value |
|---|---|
| kind | `service` |
| priority | `P4` |
| default branch | `mvp` |
| last activity | 2026-05-22T01:02:41+00:00 |
| features catalogued | **10** |
| runtime deps declared | **2** |

## Manifest
`.atlas-deps.yml` — parsed cleanly: **yes**

### Runtime deps
- **`openalice-ml`** · `http` · via `EMBED_SERVICE_URL` — Proxy /v1/embed and /v1/rerank requests to the BGE-M3 embedding + reranker backend
- **`openalice-ner`** · `http` · via `NER_SERVICE_URL` — Proxy /v1/ner requests to the GLiNER zero-shot NER backend

### Consumed env
- `ADMIN_KEY`
- `EMBED_SERVICE_URL`
- `NER_SERVICE_URL`
- `BACKEND_API_KEY`
- `ALICE_ML_KEY`
- `KEYS_FILE`
- `USAGE_FILE`
- `PORT`

### Owns tables
- `api_keys`
- `usage`

### Exposes
- `http_endpoint` — POST /v1/embed
- `http_endpoint` — POST /v1/rerank
- `http_endpoint` — POST /v1/ner
- `http_endpoint` — GET /v1/usage
- `http_endpoint` — POST /admin/keys
- `http_endpoint` — GET /metrics

## Env drift

**Manifest declares, code unused (1):**
- `PORT`

## Features (10)

### ml-gateway/admin
- **`ml-gateway.keys.create`** · _stable_ · since 0.1.0 — Admin endpoint — issue an API key with per-day request limit and per-month token cap.  
  *src/main.rs:639*

### ml-gateway/embed
- **`ml-gateway.embed.proxy`** · _stable_ · since 0.1.0 — Authenticated, rate-limited proxy to the embedding backend (/v1/embed).  
  *src/main.rs:700*

### ml-gateway/health
- **`ml-gateway.health.endpoint`** · _stable_ · since 0.1.0 — GET /health probes the embed-rerank and NER backends with a 3s timeout and returns per-service status + gateway uptime — used by Traefik and the docs site status badge.  
  *src/main.rs:468*

### ml-gateway/keys
- **`ml-gateway.keys.validate`** · _stable_ · since 0.1.0 — SHA-256 hashed API key store — constant-time bearer comparison, per-endpoint permission allowlist on the key, daily reset of request counters at UTC midnight.  
  *src/main.rs:8*

### ml-gateway/metrics
- **`ml-gateway.metrics.endpoint`** · _stable_ · since 0.1.0 — GET /metrics emits Prometheus text — uptime + total/active key count + cluster-wide requests/tokens/requests_today; gated by admin key (constant-time hash compare) so SaaS tenants can't enumerate other customers' traffic.  
  *src/main.rs:519*

### ml-gateway/ner
- **`ml-gateway.ner.proxy`** · _stable_ · since 0.1.0 — Authenticated, rate-limited proxy to the NER backend (/v1/ner).  
  *src/main.rs:739*

### ml-gateway/openapi
- **`ml-gateway.openapi.spec`** · _stable_ · since 0.1.0 — GET /v1/openapi.json serves the OpenAPI 3.0.3 spec covering /v1/embed, /v1/rerank, /v1/ner, /v1/usage, and /health with BearerAuth security scheme — consumed by client SDK generators + the docs site.  
  *src/main.rs:808*

### ml-gateway/persistence
- **`ml-gateway.persistence.background-saver`** · _stable_ · since 0.1.0 — 5-second background task — snapshots keys + usage under read-lock, writes JSON to disk without holding any lock, then clears `dirty` only after a successful write so process death never loses a counter increment (crash-safe write-behind cache).  
  *src/main.rs:759*

### ml-gateway/rerank
- **`ml-gateway.rerank.proxy`** · _stable_ · since 0.1.0 — Authenticated, rate-limited proxy to the reranker backend (/v1/rerank).  
  *src/main.rs:716*

### ml-gateway/usage
- **`ml-gateway.usage.report`** · _stable_ · since 0.1.0 — Per-key usage report — requests today + tokens this month vs configured caps.  
  *src/main.rs:601*

---

*Generated by [openalice-atlas](https://atlas.blal.pro) — single source of truth for the openalicelabs ecosystem.*
