Skip to main content

Governance framework for OpenAPI contracts with validation, transformation, and controlled exposure

Project description

Contract Governor v2.0.1

A governance framework for OpenAPI contracts that enforces security policies, tenant isolation, and audit compliance through validation, transformation, and controlled exposure.

Why Do You Need an OpenAPI Contract Governor?

The Problem

Backend services expose OpenAPI contracts that contain:

  • ❌ Internal service URLs (http://backend-service.internal:8080)
  • ❌ Unsafe HTTP methods (DELETE, PATCH on production data)
  • ❌ No audit trail or governance metadata
  • ❌ No tenant isolation in multi-tenant systems
  • ❌ Direct exposure of internal API structure

Exposing these contracts directly to clients is a security risk.

The Solution

Contract Governor acts as a governance layer between your backend services and clients:

Backend APIs → Contract Governor → Safe, Governed APIs → Clients
   (unsafe)      (governance)         (safe, audited)     (protected)

What It Does

  1. Security Enforcement

    • Strips dangerous HTTP methods (DELETE, PATCH)
    • Enforces authentication requirements
    • Validates contract structure
  2. URL Rewriting

    • Replaces internal URLs with safe proxy URLs
    • Supports environment-specific URLs (prod, staging, dev)
    • Template-based URL resolution with ${VARIABLES}
  3. Multi-Tenant Isolation

    • Tenant-scoped URLs: /tenant/{tenant_id}/api/v1
    • Prevents cross-tenant data access
    • Enforces tenant parameter validation
  4. Audit Compliance

    • Injects governance metadata into every contract
    • Non-repudiation with stipulation hashes
    • Complete transformation audit trail
  5. API Versioning

    • Support multiple contract versions simultaneously
    • Version alignment validation
    • Backward compatibility enforcement

Overview

Contract Governor ensures backend API contracts are never directly exposed to clients. Instead, contracts are:

  1. Ingested from backend services (stored as raw, internal-only contracts)
  2. Validated against stipulation policies (security, versioning, tenant scoping)
  3. Transformed with safe URLs, method filtering, and audit metadata
  4. Exposed as governed contracts safe for client consumption
  5. Documented via Scalar or custom renderers

Key Features

  • 🔒 Security Enforcement - Forbid dangerous HTTP methods, enforce authentication
  • 🏢 Multi-Tenant Isolation - Tenant-scoped URLs with parameter validation
  • 📋 Audit Compliance - Non-repudiation tracking with stipulation hashes
  • 🔄 API Versioning - Support multiple contract versions simultaneously
  • 🌐 URL Template Resolution - Environment variable substitution in server URLs
  • 📦 Multiple Environments - Support PROD, DEV, STAGING with named URLs
  • 🎨 Extensible - Add custom validators, transformers, and renderers
  • 🏗️ SOLID Architecture - Clean separation of concerns, dependency injection

Use Cases

  • API Gateway: Govern contracts before exposing to external clients
  • Multi-Tenant SaaS: Enforce tenant isolation at the contract level
  • Microservices: Centralize contract governance across services
  • Compliance: Maintain audit trail for all API exposures
  • Security: Prevent accidental exposure of internal APIs

Architecture

Backend Services → Raw Contracts → Validation → Transformation → Exposed Contracts → Clients
                        ↓              ↓              ↓                ↓
                   (Internal)    (Stipulations)  (Proxy URLs)    (Catalog/Docs)

Core Components

  • ContractGovernor - Orchestrates ingestion, validation, transformation, exposure
  • ValidationPipeline - Enforces stipulation policies (methods, versions, scoping)
  • TransformationPipeline - Rewrites URLs, strips methods, injects audit metadata
  • ContractRegistry - Stores raw (internal) and exposed (public) contracts separately
  • FastAPICatalogServer - Serves catalog and contracts via HTTP endpoints
  • ScalarDocumentationRenderer - Generates interactive API documentation

Quick Start

Installation

# From PyPI
pip install contract-governor

# For development (editable install with dev extras)
pip install -e ".[dev]"

Basic Usage

from contract_governor.core.contract_governor import ContractGovernor
from contract_governor.core.registry import InMemoryContractRegistry
from contract_governor.core.models import StipulationConfig, ExposurePolicy

# Create stipulation
stipulation = StipulationConfig(
    exposure_policy=ExposurePolicy.TENANT_SCOPED,
    proxy_prefix_format="/tenant/{tenant_id}/api/v1",
    requires_scope_parameter=True,
    forbid_methods=["delete", "patch"]
)

# Initialize governor
registry = InMemoryContractRegistry()
governor = ContractGovernor(registry, {"api:v1": stipulation})

# Ingest backend contract
governor.ingest_backend_contract(
    contract=openapi_spec,
    category="api",
    api_major="v1",
    source_service="backend-service",
    contract_file_path="/path/to/contract.yaml"
)

# Expose contract with governance
exposed = governor.expose_contract(
    category="api",
    api_major="v1",
    gateway_base_url="https://api.example.com",
    scope_parameters={"tenant_id": "acme"}
)

# Access transformed contract
print(exposed.exposed_openapi_spec)

FastAPI Server

from contract_governor.integrations.fastapi_server import FastAPIAppFactory
from contract_governor.integrations.scalar_renderer import ScalarDocumentationRenderer

# Create providers (see examples/ for details)
catalog_provider = MyCatalogProvider(governor)
contract_provider = MyContractProvider(governor)
health_provider = MyHealthProvider()

# Create FastAPI app
app = FastAPIAppFactory.create_catalog_app(
    catalog_provider=catalog_provider,
    contract_provider=contract_provider,
    health_provider=health_provider,
    documentation_renderer=ScalarDocumentationRenderer()
)

# Run server
# uvicorn main:app --host 0.0.0.0 --port 8000

Configuration

Stipulation Configuration (YAML)

stipulation_id: "evidence-query:v1"
exposure_policy: "tenant-scoped"
proxy_prefix_format: "/tenant/{tenant_id}/evidence-query/v1"
requires_scope_parameter: true
forbid_methods:
  - "delete"
  - "patch"
inject_metadata: true
metadata_block:
  audit_note: "All requests brokered by control-plane"
  tenant_isolation: true
extension_namespace: "x-governance"

Configuration Sources (Stipulations)

  • LocalFileConfigSource - YAML/JSON in config/stipulations/
  • S3ConfigSource - Cloud-based stipulation storage
  • DynamoDBConfigSource - Database-backed stipulation storage

Contract Sources (OpenAPI Specs)

  • S3ContractSource - Load contracts from S3 recursively
from contract_governor.loaders.s3_loader import S3ContractSource
import boto3

# Load contracts from S3
s3_client = boto3.client('s3')
source = S3ContractSource(
    s3_client,
    bucket_name="my-contracts",
    prefix="contracts/",
    category_from_path=True,
    version_from_path=True
)

contracts = source.load_contracts()

# Ingest all contracts
for contract_data in contracts:
    governor.ingest_backend_contract(**contract_data)

API Endpoints

Catalog Server

  • GET /api-catalog - List all exposed contracts
  • GET /api-catalog/docs - Scalar documentation for catalog
  • GET /contracts/{category}/{api_major}/openapi.json - Contract spec
  • GET /contracts/{category}/{api_major}/metadata - Governance metadata
  • GET /contracts/{category}/{api_major}/docs - Scalar documentation
  • GET /health - Liveness probe
  • GET /ready - Readiness probe

Governance Metadata

Every exposed contract includes governance metadata:

{
  "x-governance": {
    "capability_category": "evidence-query",
    "api_major_version": "v1",
    "contract_version": "1.0.2",
    "stipulation_id": "evidence-query:v1",
    "stipulation_hash": "sha256:...",
    "exposed_at": "2024-01-15T10:30:00Z",
    "tenant_scope": "acme",
    "audit_note": "All requests brokered by control-plane"
  }
}

Extensibility

Custom Validator

from contract_governor.interfaces.validator import Validator


class CustomValidator(Validator):
    def validate(self, contract, stipulation):
        # Your validation logic
        return ValidationResult(is_valid=True)

    def get_validator_name(self):
        return "CustomValidator"

Custom Transformer

from contract_governor.interfaces.transformer import Transformer


class CustomTransformer(Transformer):
    def transform(self, contract, context, stipulation):
        # Your transformation logic
        return transformed_contract

    def get_execution_order(self):
        return 50

Custom Renderer

from contract_governor.interfaces.documentation_renderer import DocumentationRenderer


class CustomRenderer(DocumentationRenderer):
    def render_contract_page(self, contract_url, title):
        return f"<html>...</html>"

Logging

Basic Configuration

from contract_governor.logging import set_logging_config
import logging

# Set logging level
set_logging_config(logging.INFO)

# Use logger
logger = logging.getLogger(__name__)
logger.info("Contract ingested")

Advanced Configuration

from contract_governor.logging import set_advanced_logging_config
import logging

# Configure with module filtering
set_advanced_logging_config(
    logging_level=logging.INFO,
    included_modules={logging.INFO: ['contract_governor.core']},
    excluded_modules={logging.INFO: ['boto', 'urllib']},
    filename='contract-governor.log'  # Optional file output
)

Environment-Based Configuration

import os
import logging
from contract_governor.logging import set_logging_config

# Configure from environment
log_level = os.getenv('LOG_LEVEL', 'INFO')
set_logging_config(log_level)

Testing

# Run all tests
pytest

# Run specific test suite
pytest tests/test_e2e_integration.py -v

# Run with coverage
pytest --cov=contract_governor --cov-report=html

Deployment

Kubernetes/EKS

apiVersion: apps/v1
kind: Deployment
metadata:
  name: contract-governor
spec:
  template:
    spec:
      containers:
      - name: app
        image: contract-governor:latest
        env:
        - name: LOG_LEVEL
          value: "INFO"
        - name: STRUCTURED_LOGGING
          value: "true"
        - name: SERVICE_NAME
          value: "contract-governor"
# Apply deployment
kubectl apply -f deployment/kubernetes/

# Check health
curl http://service-url/health
curl http://service-url/ready

# View logs
kubectl logs -f deployment/contract-governor

Docker

# Build image
docker build -t contract-governor:latest .

# Run with structured logging
docker run -p 8000:8000 \
  -e LOG_LEVEL=INFO \
  -e STRUCTURED_LOGGING=true \
  -e SERVICE_NAME=contract-governor \
  contract-governor:latest

SOLID Principles

  • Single Responsibility - Each class has one reason to change
  • Open/Closed - Extend via validators/transformers without modifying core
  • Liskov Substitution - Any implementation can replace another
  • Interface Segregation - Focused interfaces (CatalogProvider, ContractProvider)
  • Dependency Inversion - Depend on abstractions, inject dependencies

Documentation

License

MIT License. Copyright (c) 2024-2026 Evan Erwee. See LICENSE for details.

Contributing

See CONTRIBUTING.md for guidelines.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

contract_governor-2.0.1.tar.gz (148.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

contract_governor-2.0.1-py3-none-any.whl (142.3 kB view details)

Uploaded Python 3

File details

Details for the file contract_governor-2.0.1.tar.gz.

File metadata

  • Download URL: contract_governor-2.0.1.tar.gz
  • Upload date:
  • Size: 148.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for contract_governor-2.0.1.tar.gz
Algorithm Hash digest
SHA256 3f075f1ca8f1865e9bf1319079aa5a3e84093982835e565353756dc488d155ba
MD5 e7f17a6328ad826361f5bc96ce044878
BLAKE2b-256 9d73333a6aad7b1e49da67658b6e2ccec67c79bd5fd3e20d8d6eb2258e92ddf4

See more details on using hashes here.

File details

Details for the file contract_governor-2.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for contract_governor-2.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 81a0ca1ddf12588e3fb7adaf19c406e35270ee2f68febc10daabae1657ec7eb9
MD5 e1200baeb3e631321d7a5520f2a145f5
BLAKE2b-256 903eb957d75219de91c9d60151094759a5d35d71d8b8f97f73cbe4f9c91e7918

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page