ocmo-api
REST API for the OCMO configuration service. HTTP surface is implemented with
django-ninja; routes live under /api/ (application routes under
/api/v1/).
Distribution: PyPI name ocmo-api · Python: 3.13+ · License: Apache-2.0
Features
- Versioned config, template, secret, and resolver trees per namespace
- Resolve pipeline (extend, render, cast) with artifact download URLs and optional Redis offload
- OIDC JWT validation and resolver-token authentication
- Namespace policies, global permissions, audit log
- OpenAPI / Swagger UI at
/api/docs
Product behavior is documented in ../docs/. This README covers running and developing the service.
Requirements
- Python 3.13+
- PostgreSQL 15+ (required)
- Redis 7+ (optional — RQ workers, resolve cache/artifact backends)
- OIDC provider (any; Dex is bundled in the dev Docker stack)
Installation
From this directory:
uv sync # runtime + dev dependencies
uv sync --no-dev # production install (containers use this)
The install provides:
- Django project package
ocmoapi - Application package
core - Console script
ocmo-api(management CLI)
Management CLI
ocmo-api migrate # interactive migrations
ocmo-api migrate --noinput # non-interactive (containers, CI)
ocmo-api serve # gunicorn WSGI server
serve options and environment variables:
| Option / variable | Default | Description |
|---|---|---|
--bind / GUNICORN_BIND |
0.0.0.0:8000 |
Listen address |
--workers / GUNICORN_WORKERS |
4 |
Worker processes |
--timeout / GUNICORN_TIMEOUT |
120 |
Worker timeout (seconds) |
Equivalent: python -m ocmoapi.
Legacy Django entry point remains available:
uv run python manage.py migrate
uv run python manage.py runserver 0.0.0.0:8000 # development only
Configuration
Settings are read from environment variables in ocmoapi/settings.py. Copy .env.example
for local development; see ../.env.example for production Docker Compose.
Common variables:
| Variable | Description |
|---|---|
DJANGO_SECRET_KEY |
Django secret (required in production) |
DJANGO_DEBUG |
True / False |
DJANGO_ALLOWED_HOSTS |
Comma-separated host names |
POSTGRES_* |
Database connection (HOST, PORT, DB, USER, PASSWORD) |
REDIS_HOST, REDIS_PORT, REDIS_DB |
Redis when using worker or Redis-backed resolve |
OIDC_* |
Discovery, JWKS, issuer, client ID, audiences, Swagger redirect |
OCMO_MASTER_KEY |
Base64 master key for secret encryption |
OCMO_PUBLIC_URL |
Public gateway URL for absolute download links |
OCMO_RESOLVE_ARTIFACT_* |
Artifact storage backend (fs / redis) and paths |
OCMO_RESOLVE_CACHE_BACKEND |
Short-circuit cache (locmem / redis) |
ADMIN_EMAIL |
Bootstrap admin identity hint for dev stacks |
See the dev compose file for a full local example: ../docker-compose.dev.yml.
Production security
Before exposing the API to a network:
- Set unique
DJANGO_SECRET_KEY,POSTGRES_PASSWORD, andOCMO_MASTER_KEY(required for secrets). - Set
DJANGO_DEBUG=Falseand restrictDJANGO_ALLOWED_HOSTS. - Use your organization's OIDC provider — do not use the Dex stack from
docker-compose.dev.yml. - Set
OCMO_PUBLIC_URLwhen running behind a reverse proxy.
See ../SECURITY.md and ../docs/quickstart/configuration.md.
Local development
Without Docker
uv sync
export DJANGO_SETTINGS_MODULE=ocmoapi.settings
# configure POSTGRES_* and OIDC_* to point at your database and IdP
ocmo-api migrate
uv run python manage.py runserver 0.0.0.0:8000
With Docker (recommended)
From the repository root:
docker compose -f docker-compose.dev.yml -f docker-compose.hmr.yml up --build
The API container bind-mounts ./api and uses Dockerfile.dev with Django runserver.
OpenAPI export
uv run python manage.py dump_openapi --output /tmp/openapi.json
Used by the SDK code generation pipeline (sdk/Makefile).
Testing
uv run python manage.py test --keepdb
Focused example:
uv run python manage.py test core.tests.test_system --keepdb -v2
Linting and type checking
uv run ruff check .
uv run mypy core ocmoapi
Docker
| File | Purpose |
|---|---|
Dockerfile |
Production image (ocmo-api serve) |
Dockerfile.dev |
Dev image with full uv sync |
docker/entrypoint.prod.sh |
migrate --noinput + exec ocmo-api serve |
Build production image:
docker build -f Dockerfile -t ocmo-api:local .
Project structure
api/
├── core/ # Models, managers, Ninja routes, schemas, tests
├── ocmoapi/ # Django settings, URLs, WSGI, management CLI
├── manage.py # Django manage.py (development)
├── pyproject.toml
└── uv.lock
Business logic belongs in managers (core/managers/). Ninja handlers in core/api/ should stay
thin.
API documentation
When the service is running:
- Swagger UI:
/api/docs - Health:
/api/health - Version + public OIDC bootstrap:
/api/version
Related components
- Python SDK: ../sdk/README.md
- CLI: ../cli/README.md
- Web UI: ../frontend/README.md
- Monorepo overview: ../README.md
Metadata
Release files for ocmo-api 0.8.21
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ocmo_api-0.8.21-py3-none-any.whl | Python 3 | none | any | Details |
Release files / ocmo_api-0.8.21-py3-none-any.whl
| Download URL | ocmo_api-0.8.21-py3-none-any.whl |
|---|---|
| Size | 318.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
af8e1ab8154f41cd9e624db1789b8bc1a9432794b86cd1dd42de775e1d5fac7b
|
|
BLAKE2b-256 checksum How to use checksums |
76087681f4fedae357f7c68da41bad341ddaab2606186dd46dd7032a20f1a004
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|