Robotico.Nexus.Client - unified gRPC client SDK for Mishima Nexus (Graph/Time ports + Document/Relational connect helpers)
Go to file
Sergej Kern c8803c6096 Sync library build props and README tech stack badges. 2026-08-11 07:32:36 +02:00
.github feat: initial Robotico.Nexus.Client (NexusClient, Graph/Time ports, Document/Relational helpers) 2026-07-25 03:44:53 +02:00
docs/adr feat: initial Robotico.Nexus.Client (NexusClient, Graph/Time ports, Document/Relational helpers) 2026-07-25 03:44:53 +02:00
scripts feat: initial Robotico.Nexus.Client (NexusClient, Graph/Time ports, Document/Relational helpers) 2026-07-25 03:44:53 +02:00
src/Robotico.Nexus.Client feat: initial Robotico.Nexus.Client (NexusClient, Graph/Time ports, Document/Relational helpers) 2026-07-25 03:44:53 +02:00
tests feat: initial Robotico.Nexus.Client (NexusClient, Graph/Time ports, Document/Relational helpers) 2026-07-25 03:44:53 +02:00
.editorconfig feat: initial Robotico.Nexus.Client (NexusClient, Graph/Time ports, Document/Relational helpers) 2026-07-25 03:44:53 +02:00
.gitignore feat: initial Robotico.Nexus.Client (NexusClient, Graph/Time ports, Document/Relational helpers) 2026-07-25 03:44:53 +02:00
.woodpecker.yml ci: install python3 before woodpecker-verify.sh (missing in dotnet/sdk:10.0 image) 2026-07-25 03:49:23 +02:00
CHANGELOG.md feat: initial Robotico.Nexus.Client (NexusClient, Graph/Time ports, Document/Relational helpers) 2026-07-25 03:44:53 +02:00
Directory.Build.props Sync library build props and README tech stack badges. 2026-08-11 07:32:36 +02:00
Directory.Packages.props Sync library build props and README tech stack badges. 2026-08-11 07:32:36 +02:00
LICENSE feat: initial Robotico.Nexus.Client (NexusClient, Graph/Time ports, Document/Relational helpers) 2026-07-25 03:44:53 +02:00
README.md docs: add tech stack badges to README 2026-07-25 04:03:04 +02:00
Robotico.Library.AnalyzerDefaults.props feat: initial Robotico.Nexus.Client (NexusClient, Graph/Time ports, Document/Relational helpers) 2026-07-25 03:44:53 +02:00
Robotico.Library.MeziantouNoWarn.props feat: initial Robotico.Nexus.Client (NexusClient, Graph/Time ports, Document/Relational helpers) 2026-07-25 03:44:53 +02:00
Robotico.Library.Shared.props feat: initial Robotico.Nexus.Client (NexusClient, Graph/Time ports, Document/Relational helpers) 2026-07-25 03:44:53 +02:00
global.json feat: initial Robotico.Nexus.Client (NexusClient, Graph/Time ports, Document/Relational helpers) 2026-07-25 03:44:53 +02:00
nuget.config feat: initial Robotico.Nexus.Client (NexusClient, Graph/Time ports, Document/Relational helpers) 2026-07-25 03:44:53 +02:00
robotico-nexus-client-csharp.slnx feat: initial Robotico.Nexus.Client (NexusClient, Graph/Time ports, Document/Relational helpers) 2026-07-25 03:44:53 +02:00

README.md

Robotico.Nexus.Client

Woodpecker CI

.NET 10 C# gRPC NuGet Robotico

Unified client SDK for a remote Mishima Nexus server: connect via a nexus+*:// URI and get Robotico.Graph / Robotico.Time ports bound to a logical database over gRPC, plus thin Document/Relational connect helpers.

  • NuGet: Robotico.Nexus.Client
  • Feed: https://download.robotico.dev/nuget/v3/index.json
  • Brokkr: https://brokkr.robotico.dev/robotico/robotico-nexus-client-csharp

This package does not reference Mishima.Nexus.Node.* (the server host assemblies) — it only depends on the generated Mishima.Nexus.Wire.V1 gRPC stubs, Robotico.Graph, and Robotico.Time.

Quick start

using Robotico.Nexus.Client;

Result<NexusClient> connected = NexusClient.Connect("nexus+graph://localhost:50051/pathways");
using NexusClient client = connected.ExpectSuccess();

client.CheckHealth().ExpectSuccess();

Result<IGraphSession> opened = client.Graph.Open("pathways");
using IGraphSession session = opened.ExpectSuccess();
session.RegisterLabel("Person").ExpectSuccess();
session.UpsertVertex(1, ["Person"]).ExpectSuccess();

Connection URIs

Scheme Plane Default database (empty path)
nexus+graph:// Graph pathways
nexus+time:// Time telemetry
nexus+document:// Document catalog
nexus+relational:// Relational ledger
nexus+sql:// — rejected — use Mishima.Nexus.Sql directly
  • The URI host:port is the gRPC endpoint; the port is always explicit (no default port is ever inferred, so a typo can't silently connect to the wrong service).
  • The URI path (e.g. /pathways) is the logical database name, sent as the x-nexus-database gRPC metadata header on every call — it is not a filesystem path, even though the underlying IGraphStore/ITimeStore port parameter is historically named databaseFilePath.
  • One NexusClient is bound to a single scheme + logical database from the connect URI. Open a second client to talk to another plane or database.

TLS / mTLS / bearer auth

NexusClientOptions mirrors Mishima.Nexus.Wire.Clients.WireTlsMaterial's environment variables (same names, no shared assembly dependency):

Variable Purpose
NEXUS_TLS_CA_FILE CA certificate PEM (trust root)
NEXUS_TLS_CLIENT_CERT_FILE Client (machine credential) certificate
NEXUS_TLS_CLIENT_KEY_FILE Client private key PEM
NEXUS_TLS_MODE https (default) or insecure
NEXUS_WIRE_BEARER Bearer token attached as Authorization
NEXUS_WIRE_DEFAULT_BEARER Fallback bearer token

Pass an explicit NexusTlsMaterial / BearerToken via NexusClientOptions to override the environment. When no TLS material is present and UseHttps is unset, the client dials plaintext h2c (loopback/dev only).

Create / Open / OpenOrCreate semantics (POLA)

Nexus provisions logical databases lazily — the host creates a database's on-disk state the first time an RPC actually touches it, not via a separate "create database" call on the Graph/Time wire services. This client documents that behavior explicitly rather than pretending otherwise:

  • Open(name) — pings the engine with x-nexus-database: name and returns a session bound to that logical name. Succeeds even for a database the host hasn't materialized yet (the host creates it lazily on first write).
  • OpenOrCreate(name) — identical to Open(name). There is no separate provisioning step to race against, so "open if exists, else create" collapses to "open" once the engine is reachable.
  • Create(name) — fails with NXS_ALREADY_EXISTS when Ping against name succeeds, because Nexus's Ping is an engine-liveness probe, not a per-database existence check — once the Graph/Time engine is reachable at all, Create cannot distinguish "database already has data" from "database is merely reachable". Use OpenOrCreate for greenfield databases instead.

Document / Relational

NexusClient.CreateDocumentClient() / CreateRelationalClient() return small façades (Ping plus, for Document, single-document upsert/get/delete) — enough for MVP smoke usage. They are not a full IMishimaDatabase façade. For the complete generated RPC surface, use CreateDocumentWireClient() / CreateRelationalWireClient(), which return the raw Mishima.Nexus.Wire.V1 gRPC clients bound to the same channel and x-nexus-database metadata.

Error codes

All failures map to Robotico.Result.Result with NXS_* codes (NexusErrors): NXS_URI_INVALID, NXS_URI_UNSUPPORTED_SCHEME, NXS_CONNECT_FAILED, NXS_TLS_REJECTED, NXS_ALREADY_EXISTS, NXS_NOT_FOUND, NXS_INVALID_ARGUMENT, NXS_DISPOSED, NXS_UNAVAILABLE, NXS_WIRE_FAILED. Robotico.Graph (GR_*) and Robotico.Time (TM_*) codes surface unchanged from the ports.

Quality gate

Same Library 10 bar as other Robotico C# packages:

  • Analyzers on (TreatWarningsAsErrors, Meziantou MA0004/MA0042/MA0155, IDE0008/IDE0090/IDE0301/IDE0330)
  • dotnet test with coverlet ≥ 90% line coverage on Robotico.Nexus.Client, exercised against an in-process fake gRPC server (Kestrel + in-memory fake NexusGraphEngineService / NexusTimeEngineService / NexusDocumentEngineService / NexusRelationalEngineService / NexusHealthService) — no live Nexus process required.
  • Woodpecker / GitHub CI run bash scripts/woodpecker-verify.sh

Build

bash scripts/woodpecker-verify.sh
bash scripts/pack-release.sh