Omnigraph
Operations

HTTP Server

omnigraph-server's HTTP surface. Endpoints, auth, error model, admission control.

omnigraph-server is an Axum-based HTTP front end for a single graph process. Run multiple processes for multi-graph or multi-tenant setups.

For startup options and deployment patterns, see Deployment and Policy for the authorization model.

Endpoint inventory

MethodPathAuth actionPurpose
GET/healthznoneLiveness probe
GET/openapi.jsonnoneOpenAPI schema (strips security scheme when running unauthenticated)
GET/snapshot?branch=readSnapshot of a branch
POST/readreadRun a named query
POST/exportexportStream the graph as NDJSON
POST/changechangeRun a mutation
GET/schemareadGet the current accepted .pg schema
POST/schema/applyschema_apply (target=main)Apply a migration
POST/ingestbranch_create (if new) + changeBulk load onto a named branch (32 MB body limit)
GET/branchesreadList branches
POST/branchesbranch_createCreate a branch
DELETE/branches/{branch}branch_deleteDelete a branch
POST/branches/mergebranch_mergeThree-way merge a source branch into a target
GET/commits?branch=readList graph commits on a branch
GET/commits/{commit_id}readShow a single commit

Only /export streams (application/x-ndjson); every other response is buffered JSON.

Error model

Every error response uses a uniform shape:

{
  "error": "<message>",
  "code": "<code>",
  "merge_conflicts": [],
  "manifest_conflict": null
}

code is one of unauthorized, forbidden, bad_request, not_found, conflict, too_many_requests, internal. merge_conflicts is populated on branch merge failures; manifest_conflict is set on publisher compare-and-swap rejections (HTTP 409). It tells the client which (table, branch) raced and what its current manifest version is, so the client can refresh and retry.

HTTP status codes used: 200, 400, 401, 403, 404, 409, 429, 500.

Per-actor admission control

Disjoint (table, branch) writes from different actors run concurrently. To prevent one heavy actor from exhausting shared capacity, every mutating handler is gated through a per-actor workload controller:

Env varDefaultPurpose
OMNIGRAPH_PER_ACTOR_INFLIGHT_MAX16Concurrent in-flight mutations per actor
OMNIGRAPH_PER_ACTOR_BYTES_MAX4 GiBIn-flight estimated bytes per actor

When either ceiling is hit, the server returns HTTP 429 with code: too_many_requests and a Retry-After header (seconds). Other actors are unaffected.

Cedar policy authorization runs before admission accounting. Denied requests don't consume admission slots.

Admission gates: /change, /ingest, /branches/{create,delete,merge}, /schema/apply. Read-only endpoints (/snapshot, /read, /export, /branches GET, /commits, /schema GET) are not admission-gated.

Body limits

  • Default request body limit: 1 MB
  • /ingest: 32 MB

Larger payloads are rejected with 413 Payload Too Large. For bulk loads beyond 32 MB, drive the load locally with omnigraph load against the graph URI directly.

Auth model

Bearer tokens are SHA-256 hashed at startup; plaintext never persists in memory. Comparison is constant-time. Tokens map to actor identities, which Cedar policy (if configured) uses for authorization decisions.

Token sources, in priority order:

  1. OMNIGRAPH_SERVER_BEARER_TOKENS_AWS_SECRET. AWS Secrets Manager (requires the --features aws build)
  2. OMNIGRAPH_SERVER_BEARER_TOKENS_FILE or _JSON. JSON map of { "<token>": "<actor>" }
  3. OMNIGRAPH_SERVER_BEARER_TOKEN. Single legacy token, mapped to actor default

With no tokens configured, the server refuses to start unless --unauthenticated (or OMNIGRAPH_UNAUTHENTICATED=1) is set. When that flag is set, the server runs Open and /openapi.json strips its security scheme.

The actor identity used for every policy decision comes from the matched bearer token. Clients cannot override it via request header, query parameter, or body field. See Policy for the broader actor-identity contract.

Runtime states

Three startup configurations, classified at boot:

StateTokensPolicy fileBehavior
OpennonenoneEvery request permitted. Requires explicit --unauthenticated to start.
DefaultDenyyesnoneEvery authenticated request for an action other than read returns HTTP 403. Catches the "tokens but no policy" trap.
PolicyEnabledanyyesCedar evaluates every request against the configured policy.

omnigraph policy validate and omnigraph policy explain cover the PolicyEnabled rules end-to-end without standing up a server. See Policy.

Tracing and observability

  • HTTP requests are traced via tower_http::TraceLayer::new_for_http().
  • Policy decisions log at INFO with actor, action, branch, decision, and matched rule.
  • Startup logs include token source name, graph URI, and bind address.
  • Graceful SIGINT shutdown.

Not implemented

  • CORS. Not configured. Add tower_http::cors at the edge if a browser client needs it.
  • Global rate limiting. Per-actor admission handles per-actor backpressure; add tower_http::limit for a graph-wide cap.
  • Pagination. List endpoints return the full set; /export streams.
  • Multi-tenant routing. One graph per process; run multiple processes for multi-tenancy.

On this page