Skip to main content

Context Rules

context is the protocol section that lets you delete your API layer. It declares automatic row-level scoping rules — one per "kind of caller."

Shape

"<entity>": {
"context": {
"<context-name>": "<onql-query-fragment>"
}
}

A context name is whatever string you want — it identifies a type of caller. Common ones: account, admin, service, support, auditor.

A simple example

"orders": {
"context": {
"account": "shop.orders[user_id = $1]",
"admin": "shop.orders"
}
}

When a client sends shop.orders{id, total} with ctxkey: "account" and ctxvalues: ["42"], ONQL rewrites the query to shop.orders[user_id = "42"]{id, total} before running it.

When the same query comes in with ctxkey: "admin", no rewriting happens — admins see everything.

Multiple parameters

"orders": {
"context": {
"account": "shop.orders[user_id = $1 and org_id = $2]"
}
}

Pass them in order:

{ "ctxkey": "account", "ctxvalues": ["42", "acme"] }

Per-relation context

Context rules can also walk relations. This is useful for hierarchical scoping:

"orders": {
"context": {
"agency_admin": "shop.agencies[id = $1].customers.orders"
}
}

An agency admin sees orders that belong to customers that belong to their agency.

Multiple contexts on the same entity

You can have as many as you want:

"orders": {
"context": {
"account": "shop.orders[user_id = $1]",
"admin": "shop.orders",
"support": "shop.orders[org_id = $1]",
"internal_etl": "shop.orders"
}
}

What if no context is provided?

If a query comes in without a ctxkey, no scoping is applied — the query runs as-written. Be careful: this is effectively admin mode. In production you should require a ctxkey at the API gateway before letting requests reach ONQL.

What if the entity has no context block?

The query runs as-written, regardless of ctxkey. The protocol author opted out of scoping for that entity.

Best practices

  • Always set a default-deny stance at your gateway: reject queries that don't include a ctxkey.
  • Test each context by issuing the same query under different ctxkeys and asserting different results.
  • Keep rules simple. A single [col = $1] filter is usually enough. Resist the temptation to make context rules into mini-business-logic.
  • Version your protocol if context semantics change. Existing clients shouldn't suddenly start seeing different rows.