Run the web console
Build and host the static NYXDB console, connect it directly to the engine over WebSocket, and understand failure and compatibility behavior.
The experimental NYXDB console is a statically exported Next.js application. The browser connects directly to the engine over WebSocket; there is no application server or proxy in the data path.
The console is a database-operator surface, not an application end-user
client. Start every browser-reachable listener with --require-auth.
Otherwise the browser can skip login and is an implicit operator with the
complete SQL and write surface. The engine provides ws:// but no native TLS
or public Origin policy; use a reviewed wss:// edge and keep the engine on a
trusted network.
Build the static application
The console lives in the engine repository and requires Node.js 22 for the release-tested toolchain.
git clone https://github.com/NYXL-io/db.git
cd db/console
npm ci
NEXT_PUBLIC_NYXDB_WS_URL=ws://127.0.0.1:7777 npm run buildThe build writes a static site to console/out/. Serve that directory from any
static host. For a local preview:
python3 -m http.server 3000 --directory outOpen http://127.0.0.1:3000/. The default engine URL is
ws://127.0.0.1:7777, the same listener used by raw TCP clients. You can change
the URL under Settings → Connection; the browser stores that override
locally.
Connection model
- One-shot operations use a six-member persistent WebSocket pool. Each member permits exactly one request on wire because server dispatch is sequential per connection; excess calls queue locally and parallelism comes from separate members. Every request uses a fresh nonzero 16-byte ID and verifies the echoed response bytes.
- Every live stream owns a dedicated WebSocket, so cancelling one subscription closes only that stream and a slow consumer does not own another stream's transport.
- The console probes the open connection with the wire-level ping operation. That measures a warm transport round trip and does not create query-log noise.
- Engine SQL diagnostics are query results, not transport outages. A syntax or execution error does not mark the engine connection as down.
Each queued one-shot starts its response-timeout window only when its frame is
actually sent. The displayed client round-trip begins before pool dispatch and
therefore includes local pool wait; exact server execution time excludes it. If
that response deadline expires, the console rejects the caller immediately and
best-effort sends OP_CANCEL_REQUEST on a separate WebSocket. When operator
credentials are configured, it authenticates that control socket before the
cancel operation. The original member remains occupied until its terminal reply
arrives; a miss, malformed acknowledgement, auxiliary timeout, or missing
terminal after a bounded successful-acknowledgement grace period closes that
exact member before it can dispatch another queued statement.
The opaque 16-byte request ID is the cancellation lookup key. It is not the
numeric engine query_id exposed by schema-2 metadata and query telemetry. See
Query identity, cancellation, and retries for
the full lifecycle.
The shell remains usable when the engine is unavailable: a global banner shows the connection state while each page keeps its own error state. A transport failure rejects affected requests and streams. The console reconnects its one-shot connection pool, but it does not represent a terminated stream as cursor-resumed; start a new subscription and reconcile its new snapshot.
Operator login and credential handling
When the engine returns authentication required, the application shell shows
the operator login gate. Enter the engine WebSocket URL and credentials for a
system.users account. A successful login does not create a transferable
browser session token: the console sends the operator OP_AUTH payload before
the first real operation on every one-shot, pooled, reconnect, and stream
socket it opens.
Credential storage is deliberately explicit:
| Choice | Actual behavior |
|---|---|
| Remember me off (default) | Username and plaintext password remain in the page's JavaScript memory and disappear on reload. |
| Remember me on | Credentials are written to same-origin localStorage under nyxdb.console.operator, survive reloads, and are shared with same-origin tabs. Cross-tab sign-out removes them. |
Only opt into browser persistence on a managed operator workstation whose
origin, extensions, storage, and local account are trusted. Sign out after the
session; do not rely on tab close to clear a remembered password. Credentials
travel inside each engine WebSocket auth frame, so wss:// at the external
edge is mandatory outside an entirely trusted transport boundary.
The console detects default-open mode because its initial SQL probe succeeds
without credentials. That preserves development compatibility, but it is not a
secure browser deployment. Provision the admin with a mounted secret file,
enable --require-auth, create named non-admin operators for daily work, and
review their separate operator grants. See
Operator governance.
Product areas
| Area | Purpose |
|---|---|
| Overview | Connection health and live catalog/workload summaries. |
| SQL Console | One-shot and STREAM SELECT queries in the browser. |
| Tables, Views, Materialized Views | Browse relations and schemas. |
| Queries | Active and historical query telemetry. |
Subscribers (/subscribers) | Live subscriptions, principal class and identity, auth claims, PSI delivery health, and quota outcomes. |
| Transformations | Continuous-transform state, lag, and controls. |
| Storage | Policies, disks, pools, and part accounting. |
| Lineage | Source, transform, view, and target relationships. |
Endpoints (/endpoints) | Published one-shot/live endpoints plus registered auth-provider definitions and counters. |
Auth gate (/auth) | Inspect live application sessions and the provider-backed admission surface. |
Rate limits (/rate-limits) | Query-driven governance definitions and dimensions. |
Application grants (/grants) and Roles (/roles) | The application role policy domain used by invocable logical views. |
Users (/users) | Create, rotate, re-role, and remove engine-managed database operators. No password/hash column is rendered. |
Operator grants (/operator-grants) | The isolated database-operator relation policy domain. |
Governance (/governance) | Denials, subscription kills, auth revocations, operator login outcomes, and user-management events from the volatile governance log. |
| Settings | Engine URL, connection state, and workspace preferences. |
Version compatibility
The console tries handshake schema 2, then schema 1, then plain TSV on fresh
connections. Its production one-shot pool uses OP_QUERY_META for ordinary SQL
and OP_QUERY_PARAMS for parameterized calls: schema 2 with typed-metadata
capability 0x0004 returns one strict NR
TypedResultEnvelope containing exact elapsed time, numeric engine query ID,
server identity, cache state, and one nested typed frame. The JavaScript surface
retains elapsed time and query identity as bigint; compatibility display
fields may be lossy numbers and should not be used for uint64 identity.
On a schema-1 peer, the same pool receives #meta plus TSV. Writes and
unsupported/no-row shapes also use text fallback, but the server renders that
fallback from the already executed captured result—it does not replay the SQL.
The protocol defines LZ4, but this console revision requests binary results plus
typed metadata and does not enable LZ4.
This downgrade path is tested, but both wire versions and the console are experimental. Build the console from the same engine revision you deploy, or validate the full console protocol suite against the exact server pair before upgrading.
npm run typecheck
npm test
NYXDB_WS_E2E=ws://127.0.0.1:7777 \
npx vitest run src/lib/nyx/live-engine.e2e.test.tsSee Drivers & protocol for operator-client retry rules. For a custom read-only browser or platform integration that calls published endpoints instead of exposing the operator console, use Browser and platform endpoint clients.