DB
Concepts

Direct application access

How browsers and platform clients can execute or subscribe to operator-published queries without an application query proxy.

NYXDB can expose a deliberately narrow, read-only application surface directly to a browser, mobile application, edge worker, or other platform client. The operator publishes a typed query, configures how an application token becomes a trusted claims row, and optionally attaches per-user limits. The client invokes the published surface by name; it never sends the SQL body.

Application endpoints, auth providers, access policies, rate limits, and the WebSocket protocol are Experimental. The native server speaks raw TCP and ws:// without TLS and accepts WebSocket origins at the transport layer. Direct public or zero-trust production exposure is therefore unsupported. Keep the engine on a trusted network and terminate TLS plus origin and network policy at a reviewed edge before any untrusted client can reach it. Start the engine with --require-auth for every browser-facing or otherwise untrusted listener; without that flag, a client can skip OP_AUTH and retain the implicit operator SQL and write surface.

What “no proxy” means

The application does not need a custom service whose only job is to accept an API request, interpolate parameters, run SQL, and relay rows. The database owns that query boundary:

browser / mobile / edge client
        |
        | WebSocket binary frames
        v
external TLS + origin/network policy   required on an untrusted network
        |
        v
NYXDB OP_AUTH
        |
        +-- token -> trusted claims row
        v
OP_ENDPOINT_EXEC or OP_ENDPOINT_SUB
        |
        +-- typed client parameters
        +-- server-injected auth claims
        v
published SELECT / STREAM SELECT
        |
        +-- one-shot TSV result
        +-- or snapshot followed by live deltas

Removing the application query proxy does not remove the need for a security perimeter. Native TLS termination, a stable public wire contract, Origin enforcement, cross-node continuity, and a zero-trust deployment profile do not ship in the current engine.

Two identity planes

Application users and database operators are intentionally different principals.

PlaneIdentity sourceConnection behaviorAuthorization and limits
Application end userA row returned by an operator-defined auth-provider query over the customer data modelMay use one-time capability setup, ping, auth, endpoint execute, and endpoint subscribe; raw SQL and block ingest are refusedPublished endpoints carry their pre-authorized query; invocable views require application grants. Endpoint and query-driven limits apply.
Database operatorAn engine-managed system.users entry authenticated with a passwordMay use the SQL and operational wire surfaces after operator authenticationadmin has implicit management access. Other named operators are default-deny against the separate base-relation operator-grant catalog for raw query/stream and endpoint/view execute/subscribe operations. All operator-class calls remain exempt from application endpoint quotas.

The application role claim and an operator role with the same spelling share no state. A grant in one plane cannot authorize the other plane.

If --require-auth is omitted, an unauthenticated connection remains an implicit operator with the complete SQL surface. Creating auth providers for application users does not close that operator path. Operator authentication and end-user authentication solve separate problems. --require-auth is a mandatory launch control for every listener reachable by an untrusted or browser client.

Published endpoint versus granted view

NYXDB provides two application-facing invocation models through the same wire operations.

Published endpoint

CREATE ENDPOINT is an explicit API contract. It bundles:

  • a one-shot SELECT or live STREAM SELECT body;
  • an ordered, typed client-parameter signature;
  • an optional set of trusted auth claims;
  • a provider reference used to validate the claim schema at definition time, when claims are declared; and
  • six static governance settings.

An endpoint is pre-authorized by its definition. The operator must put every tenant or visibility predicate in that body and bind the sensitive values from $auth.*. The client cannot inspect the body or supply an auth claim.

USING provider does not pin invocation to that provider. A session admitted by any provider can invoke the endpoint when its claim names and types are compatible. Treat the provider reference as schema validation, never as an authorization boundary.

Granted invocable view

A logical view may declare typed ${name:Type} parameters and reference ${auth.claim} values. An authenticated application user can invoke that view by name or relation UUID only when the application grant catalog contains the required verb:

  • read for one-shot execution; or
  • subscribe for a live subscription.

The default is deny. GRANT ... TO ROLE writes the application domain; GRANT ... TO OPERATOR ROLE writes a different operator domain.

Endpoint names resolve before view names. If both catalogs contain the same name, the endpoint wins and its pre-authorized definition bypasses the view grant the caller may have expected. Keep names collision-free and use a relation UUID when a client must target one logical view unambiguously.

The current application wire exposes read and subscribe operations only. It does not expose arbitrary SQL or an application-user write operation, even though the policy catalog accepts table, view, and materialized-view targets and reserves other verbs. Only logical-view read and subscribe grants are consumable by the end-user wire today; other target/verb rows are future-facing catalog vocabulary.

That application default-deny statement applies to end-user view invocation. Named non-admin operators use the separate operator policy: raw SQL and the canonical stored query behind OP_ENDPOINT_EXEC or OP_ENDPOINT_SUB require read or subscribe on every scanned base relation. Admin and default-open implicit operators bypass this check. All operator-class invocations remain exempt from application endpoint quotas.

Trusted claims and untrusted parameters

The parameter boundary is the central isolation property:

ValueSupplied byBinding rule
Endpoint $symbol or view ${symbol:String}ClientPositional text value, validated and coerced against the declared type before execution
Endpoint $auth.tenant_id or view ${auth.tenant_id}ServerTaken from the authenticated claims row; absent or incompatible claims fail the invocation
Endpoint or view SQL bodyOperatorStored in the catalog and never accepted from the end-user connection

For endpoints, client parameters occupy the declared leading slots and claims are appended server-side. For invocable views, the engine builds the complete slot vector from the parameter and claim declarations. In both cases, a client cannot forge a claims slot by sending an extra parameter.

Every provider should return a stable, non-secret user_id claim. It is used for rate-limit keys and subscriber attribution. If it is absent, the engine falls back to the presented bearer token as the application-user identity, and that fallback value can surface in subscriber and governance telemetry. Never use a bearer token as a display identity. A role claim is the key for application grants; a session without one cannot match a non-empty role and is therefore denied on a granted view.

One-shot and live query paths

OP_ENDPOINT_EXEC executes a published one-shot query and returns a header plus rows. OP_ENDPOINT_SUB establishes a stream and returns an initial snapshot followed by updates until the subscription ends.

Channel identity includes the canonical query and the full binding vector, including server-injected claims. Subscribers with the same effective query and bindings can share one execution. Different tenant claims produce different bindings and do not share that channel.

Shared execution does not create a durable cursor. A connection loss, revocation, source drop, server restart, or terminal error ends the subscription. Reconnect, authenticate again, open a new subscription, and treat its initial snapshot as a replacement for the abandoned client replica.

Catalog mutation is not subscription revocation. Replacing or dropping an endpoint does not rebind or terminate an existing subscription; a drop also removes its governor and metering state. Operators must drain or terminate live subscriptions before changing a query, provider, claims, or limits when the old behavior must stop.

Authentication choices

Provider formBehaviorRevocation boundary
Lookup providerRuns a parameterized point query where $token is the presented token; exactly one row becomes the claims setThe result is cached for cache_ttl_ms and revalidated after that age when the connection invokes again
Streaming auth gateMaintains a token-keyed live replica from STREAM SELECT; the remaining columns are claimsA token leaving the replica revokes every admitted connection at event latency; time predicates are also re-evaluated by the gate ticker

No configured provider means no successful end-user authentication. Dropping a streaming provider revokes its sessions, but a provider referenced by an endpoint cannot be dropped until those endpoints are removed or replaced.

Changing a streaming-gate claim row affects future invocations, not an existing subscription's frozen bindings, user_id, tenant, or role. Remove the old token to revoke its connections, issue a new token, and require reconnect when an identity or authorization claim changes. Likewise, OP_AUTH is not logout: a failed re-authentication does not clear the socket's prior principal. Close the socket and authenticate once on a fresh connection for every principal or token change.

Governance placement

Static endpoint settings and query-driven rate limits are enforced in the single nyxdb process. They cover endpoint/user admission and per-subscription delivery. Gateway placement, cross-node totals, and cluster-wide quota coordination are not shipped capabilities.

Operators can inspect live definitions and counters through system.endpoints, access policies through system.grants, and enforcement events through the volatile system.governance_log. See Application access SQL, Browser and platform clients, and Operator governance for executable procedures.

On this page