Waratah cluster API (server contract)

This document is the server-side HTTP contract for the cluster dashboard. The WebUI is a different project in a different git repo. Hand this page and ref/waratah_openapi.yaml to the frontend agent — that YAML is the same spec as the ingest API, not a second OpenAPI file. RDF4J stays in ref/rdf4j_openapi.yaml.

Every compute process is coordinator for that HTTP request only. It does not ask peers to probe storage. Membership is a static list in cluster config; gossip/etcd is out of scope (Phase 10).

Base URL

waratah start default (foreground or daemonized):

http://127.0.0.1:8080
API Prefix

RDF4J (SPARQL, repository list, size, …)

http://127.0.0.1:8080/rdf4j/

Waratah admin (ingest + cluster)

http://127.0.0.1:8080/waratah/

There is no CORS. Proxy /waratah and /rdf4j onto the same origin as the UI.

waratah start also binds compute gRPC Describe/Health on ClusterConfig::compute() (127.0.0.1:7005 in local_dev) so a peer compute can list advertised HTTP URLs.

Endpoints

Process health

GET /waratah/health

This process only. Does not probe storage or peers.

{ "status": "ok" }

Cluster snapshot

GET /waratah/cluster

Always 200 when this compute has a cluster config. A down hexastore, registry, or peer compute is a row with "status": "down" and "error", not an HTTP error. Mocks / backends without a cluster view return 501.

storage[] is this coordinator’s live probes of its configured S/P/O
registry. Each compute’s routing is what that compute is configured to see (self: local router; peers: their Describe). The UI can highlight routing mismatches.

waratah standalone sets computes[].standalone on the self row (self: true). Compute gRPC (computes[].grpc) is still bound. storage[].grpc is omitted because those processes were not started. RocksDB metrics size/key fields are the sum of that process’s named column families (SPOG+SOPG on S, PSOG+POSG on P, OPSG+TSG on O, plus S named_graphs_catalog). named_graph_count is S-axis only. Describe reloads sealed SST statistics when they are stale before it reports that count.

Every live row also carries a version string — semver+git-describe (for example 0.1.0+v0.2.0-3-g1a2b3c4-dirty), baked into each binary at compile time by waratah_buildinfo (--build-info prints the full provenance block). computes[].version on the self row is this process’s build; peer rows echo the peer’s Compute Describe RPC. storage[].version echoes each partition / registry process’s Describe RPC. Rows that did not answer their probe omit version, so a mixed-version cluster (say, a stale waratah-partition binary left in target/debug) is visible at a glance.

Authoritative field names, types, and examples: ClusterSnapshot in ref/waratah_openapi.yaml.

Notebook service

GET /waratah/notebooks

Discovery for the grevillea notebook UI. available means the feature is enabled on this compute and the jupyter-server sidecar answered readiness. token is the startup-minted jupyter token (dev stub — loopback single-user, no auth model yet; it will move behind a real auth iteration).

{ "available": true, "path": "/jupyter", "token": "…" }

The same-origin reverse proxy /jupyter/* serves the full jupyter-server REST + WebSocket surface (kernel channels included). When notebooks are disabled the body is { "available": false, "path": "/jupyter" } with no token. Kernel/session start bodies may carry env: {"WARATAH_REPO": …}; the proxy translates it into the matching python3-{repo} kernelspec (stock jupyter-server drops request env).

GET /waratah/cluster: the self compute entry additionally carries "notebooks": {"available": …, "path": "/jupyter"} when the feature is enabled; peer entries carry no block in v1.

RDF4J repository list

GET /rdf4j/repositories is SPARQL Results (uri, id, title, readable, writable) for repository main. Use /waratah/cluster for topology; this listing exists for Workbench-compatible clients.

Out of scope

  • Frontend

  • Gossip / etcd membership

  • Multi-Raft

  • Multi-repository storage

  • Putting compute nodes on Murmur3 hexastore rings

  • Dumping the full planner StatsProfile (CMS/HLL) over HTTP