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_nametier(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_idtenant_idtype(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_idtenant_idnamedefault_pack(optional)default_policies(refs)budget(optional, monthly cap with alerts)
API Key
Credential a client uses to authenticate. Scoped to a project.
key_idtenant_id,project_idhashed_secretscopesexpires_at,last_used_at,revoked_at
Policy
A versioned, declarative rule set evaluated by OPA. Inbound or outbound.
policy_idtenant_id(ornullfor system-wide)namedirection(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_idname(e.g.healthcare-radiology)versionrouting_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_idpack_id(optional)received_atresidency_tagrouted_to(provider, model, endpoint)cache_hit(bool)tokens_in,tokens_outcost_centslatency_mspolicy_decisions(list)redactions(list of redaction events)status(success | error | rejected)
Audit Event
An entry in the append-only ledger.
event_idtenant_idactor(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,hashtimestamp
Model Adapter
A registered provider connection.
adapter_idtenant_id(or null for global)provider(anthropic | openai | google | bedrock | azure_oai | ollama | vllm | custom)endpointauth(KMS-encrypted)regionmodels(list of available models with capability metadata)health_status
Cost Event
A financial fact for the ledger.
event_idtenant_id,project_id,principal_idrequest_idprovider,modeltokens_in,tokens_outcost_cents(provider cost)markup_cents(our margin)currencytimestamp
Relationships
Tenant 1—* Project 1—* APIKeyTenant 1—* PrincipalTenant 1—* PolicyTenant 1—* AdapterPack *—* PolicyProject *—1 Pack (optional)Request *—1 Project, *—1 Principal, *—* Policy (decisions)AuditEvent *—1 TenantCostEvent *—1 RequestAPI 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/tenantsGET/POST /admin/v1/projectsGET/POST /admin/v1/keysGET/POST /admin/v1/policiesGET/POST /admin/v1/adaptersGET /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.receivedpolicy.evaluatedredaction.appliedmodel.invokedmodel.respondedrequest.completedcost.recordedadmin.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.