Skip to content

Domain model

Core entities, their relationships, and the contracts that bind them. Implementations must match these definitions; changes go through ADR.

Entities

Tenant

A customer organisation. The unit of isolation, billing, policy, and contract.

  • tenant_id (UUID, immutable)
  • name, display_name
  • tier (Starter | Business | Enterprise)
  • home_region (US | EU | AU | UK | …)
  • allowed_regions (set)
  • key_management (managed | byok)
  • created_at, status

Principal

Anyone or anything that authenticates: a human user or a service account.

  • principal_id
  • tenant_id
  • type (user | service_account)
  • email (users), name (service accounts)
  • roles (admin | developer | analyst | finance | compliance | viewer)
  • auth_method (api_key | oauth | saml)

Project

A logical grouping inside a tenant — typically one application or one team.

  • project_id
  • tenant_id
  • name
  • default_pack (optional)
  • default_policies (refs)
  • budget (optional, monthly cap with alerts)

API Key

Credential a client uses to authenticate. Scoped to a project.

  • key_id
  • tenant_id, project_id
  • hashed_secret
  • scopes
  • expires_at, last_used_at, revoked_at

Policy

A versioned, declarative rule set evaluated by OPA. Inbound or outbound.

  • policy_id
  • tenant_id (or null for system-wide)
  • name
  • direction (inbound | outbound)
  • version (semver)
  • rego (the policy source)
  • attached_to (project IDs or pack IDs)

Pack

An industry pack — bundle of routing rules, prompt templates, policies, and compliance mappings.

  • pack_id
  • name (e.g. healthcare-radiology)
  • version
  • routing_rules (YAML)
  • prompt_templates (YAML)
  • policies (refs)
  • compliance_mappings (refs)

Request

A single inference call through the bus.

  • request_id (UUID)
  • tenant_id, project_id, principal_id
  • pack_id (optional)
  • received_at
  • residency_tag
  • routed_to (provider, model, endpoint)
  • cache_hit (bool)
  • tokens_in, tokens_out
  • cost_cents
  • latency_ms
  • policy_decisions (list)
  • redactions (list of redaction events)
  • status (success | error | rejected)

Audit Event

An entry in the append-only ledger.

  • event_id
  • tenant_id
  • actor (principal or system)
  • event_type (request_received | policy_decision | redaction | model_invocation | admin_action | …)
  • subject (request_id or admin object)
  • payload (structured, no PII)
  • prev_hash, hash
  • timestamp

Model Adapter

A registered provider connection.

  • adapter_id
  • tenant_id (or null for global)
  • provider (anthropic | openai | google | bedrock | azure_oai | ollama | vllm | custom)
  • endpoint
  • auth (KMS-encrypted)
  • region
  • models (list of available models with capability metadata)
  • health_status

Cost Event

A financial fact for the ledger.

  • event_id
  • tenant_id, project_id, principal_id
  • request_id
  • provider, model
  • tokens_in, tokens_out
  • cost_cents (provider cost)
  • markup_cents (our margin)
  • currency
  • timestamp

Relationships

Tenant 1—* Project 1—* APIKey
Tenant 1—* Principal
Tenant 1—* Policy
Tenant 1—* Adapter
Pack *—* Policy
Project *—1 Pack (optional)
Request *—1 Project, *—1 Principal, *—* Policy (decisions)
AuditEvent *—1 Tenant
CostEvent *—1 Request

API contracts (external)

  • POST /v1/chat/completions — OpenAI-compatible chat completions endpoint.
  • POST /v1/messages — Anthropic-compatible messages endpoint.
  • POST /v1/embeddings — OpenAI-compatible embeddings. Planned; not yet routed.
  • GET /v1/models — Lists models available to the caller (filtered by policy and residency).
  • POST /v1/files — File upload for vision/document use cases. Planned; not yet routed.
  • Admin / control plane:
    • GET/POST /admin/v1/tenants
    • GET/POST /admin/v1/projects
    • GET/POST /admin/v1/keys
    • GET/POST /admin/v1/policies
    • GET/POST /admin/v1/adapters
    • GET /admin/v1/audit (read-only, paginated)
    • GET /admin/v1/usage (FinOps)
    • DELETE /admin/v1/data/{principal_id} (right-to-erasure)
    • GET /admin/v1/compliance/evidence (auditor-facing)

Internal events

Emitted to the internal bus (NATS) for fan-out:

  • request.received
  • policy.evaluated
  • redaction.applied
  • model.invoked
  • model.responded
  • request.completed
  • cost.recorded
  • admin.tenant_created

Errors (canonical shape)

{
"error": {
"code": "policy_violation",
"message": "Request blocked by policy 'no-pii-to-external'.",
"type": "policy",
"details": { "policy_id": "...", "rule": "..." },
"request_id": "..."
}
}

Error type values: auth, rate_limit, policy, provider, validation, internal.

Status code mapping is documented in docs/runbooks/error-codes.md.