3 - A CMD App
A CMD App
The smallest thing that talks to XRUIOS: a console program that connects to the Manager broker with its own credentials and calls capabilities by name. This is the reference shell - XRUIOS.SampleApp (the Höllvania calendar) is exactly this, and every other client is a variation on it.
The .csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>XRUIOS.MyApp</RootNamespace>
<AssemblyName>XRUIOS.MyApp</AssemblyName>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\XRUIOS.SecureLayer\XRUIOS.SecureLayer.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Spectre.Console" Version="0.49.1" />
</ItemGroup>
<ItemGroup>
<Reference Include="EclipseProject"><HintPath>..\..\libs\EclipseProject.dll</HintPath></Reference>
</ItemGroup>
</Project>
Why each reference:
| Reference | Why |
|---|---|
XRUIOS.SecureLayer (project) |
EclipseSecureClient (connect + invoke) and XruiosEnrollment (self-enroll) |
EclipseProject.dll |
the encrypted transport types the client is built on |
Spectre.Console (package) |
optional - only if you want the UI. A headless job can drop it. |
That's the entire dependency set. An app needs nothing from the system classes, no keys, no Pariah - it only knows how to ask the broker.
Credentials
An app needs three things, none of which it invents: its id, its PSK, and the broker address. The Manager provisions them. Look for them in this order:
// 1. environment handoff (the Manager can launch you with these set)
string? appId = Environment.GetEnvironmentVariable("XRUIOS_APP_ID");
string? pskB64 = Environment.GetEnvironmentVariable("XRUIOS_APP_PSK");
string? brokerAddr = Environment.GetEnvironmentVariable("XRUIOS_BROKER_ADDR");
// 2. a creds file the Manager wrote (dev convenience)
if (appId is null || pskB64 is null || brokerAddr is null)
(appId, pskB64, brokerAddr) = TryCredsFile("myapp"); // %LocalAppData%\XRUIOS\Public\myapp.creds
// 3. self-enroll against the running Manager
if (appId is null || pskB64 is null || brokerAddr is null)
{
var prov = await XruiosEnrollment.EnrollAsync("myapp");
appId = prov.AppId; pskB64 = prov.PskBase64; brokerAddr = prov.BrokerAddress;
}
byte[] appPsk = Convert.FromBase64String(pskB64!);
The PSK never lives in your binary. Copy the exe to another machine and it authenticates as nobody, because the id and PSK were minted by this machine's Manager. That's what makes "just send me the exe" safe.
Connect and call
using XRUIOS.Interfaces; // brings SecureLayer's client types
// post-quantum handshake (Kyber + AES-256-GCM). identity: is your stable app id.
var mgr = await EclipseSecureClient.ConnectAsync(brokerAddr!, "myapp-client", appPsk, identity: appId!);
// a granted capability runs in the owning worker and returns its result
string uid = await mgr.InvokeAsync<string>("AddEvent",
new Dictionary<string, object?> { ["day"] = "2026-08-21", ["summary"] = "Ship it" });
// an ungranted capability is refused at the broker before it reaches a worker
try { await mgr.InvokeAsync<string>("DeleteEvent", new() { ["uid"] = uid }); }
catch (Exception ex) { /* XRUIOS.Permission denied 'DeleteEvent' for app:myapp */ }
await mgr.DisposeAsync();
InvokeAsync<T> packs the args, sends them over the encrypted channel, and deserializes the reply to T. The capability name is the whole API - what you can call is exactly what the Manager granted you.
Get it granted
On the Manager side, registering an app and granting it is two lines (see ManagerHost.StartCoreAsync):
var cred = apps.Register("myapp"); // mints the app's own PSK
await permissions.GrantAsync(cred.AppId, "AddEvent"); // grant each capability by name
// then WriteDevCreds(cred, brokerAddr, "myapp.creds"); // so the app can find its creds
Anything you don't grant is denied. That's not an error path to code around - it's the model. A good app doesn't offer actions it wasn't granted.
The three failure modes
| Failure | Means | Do |
|---|---|---|
| Handshake fails | Manager locked / not running / wrong PSK | tell the user to XRUIOS.Manager login then run - don't retry-storm |
| Capability denied | you weren't granted it | expected; don't crash, explain |
| Worker error | the granted call ran but failed inside the worker | surface the worker's message - it's a real error, not a permission one |
Next: the same client behind a window - 4 - A Desktop App.