2 - A Worker
A Worker
A worker is one system class running in its own process, exposing a curated set of capabilities the Manager can route to. This is where a new class from Barebones becomes a first-class part of the fleet. Every worker follows the exact shape of the Calendar worker.
The layout
A worker is three files plus its system source:
src/workers/XRUIOS.Worker.<Class>/
├─ XRUIOS.Worker.<Class>.csproj compiles ONLY this class's source
├─ Program.cs boot: bind context, init, run the secured host
├─ <Class>Capabilities.cs the [SeaOfDirac] curated surface
└─ (the class source lives once at src/systems/<Class>.cs, not copied here)
The isolation is the point: the worker <Compile Include>s just its own class file, so a breached Songs worker doesn't even contain Calendar's code. See 1 - The Model.
The .csproj
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<OutputType>Exe</OutputType>
<RootNamespace>XRUIOS.Worker.<Class></RootNamespace>
<AssemblyName>XRUIOS.Worker.<Class></AssemblyName>
</PropertyGroup>
<!-- This worker compiles ONLY its own class. Refs + packages come from Directory.Build.props. -->
<ItemGroup>
<Compile Include="..\..\systems\<Class>.cs" />
</ItemGroup>
</Project>
That's the whole file. Two things to notice:
Microsoft.NET.Sdk.Web, not the plain SDK - a worker hosts a MagicOnion/gRPC endpoint the Manager connects to.- No references here. Everything a worker needs is in
src/workers/Directory.Build.props, which every worker undersrc/workers/inherits automatically:
From Directory.Build.props |
Why |
|---|---|
XRUIOS.SecureLayer (project) |
SecureWorkerHost, WorkerOcean, NotaryGuard - the secured host |
XRUIOS.Contracts / Core / Interfaces (project) |
the context shim, DTOs, the IModuleInitializer seam |
YuukoProtocol.XRUIOS.Interfaces (project) |
the file layer the system classes use |
EclipseProject.dll |
the [SeaOfDirac] attribute + the encrypted transport |
PariahCybersecurity.dll |
SecureData, the anti-tamper watchdog |
KeeperOfTomes.dll, Secure Store.dll |
storage the classes depend on |
| the Barebones package set | so any single class compiles (Ical.Net, GeoCoordinate, etc.) |
If your class needs a package no other class does, add it to that class's own .csproj rather than the shared props - keep the shared set to what every class needs.
The capability surface
Capabilities are static methods marked [SeaOfDirac]. WorkerOcean scans the assembly for them; the Manager routes a call by the capability name. Keep the surface curated - the cross-program calls, not every public method.
using EclipseProject;
using XRUIOS.Barebones;
namespace XRUIOS.Worker.<Class>
{
public static class <Class>Capabilities
{
// [SeaOfDirac(name, argNames, returnType, argTypes...)]. Return plain strings/DTOs so any
// client can read them without sharing the class's internal types.
[SeaOfDirac("DoThing", new[] { "input" }, typeof(string), typeof(string))]
public static string DoThing(string input) => <Class>Class.DoThing(input);
// Async is supported - return Task / Task<T>.
[SeaOfDirac("AddThing", new[] { "a", "b" }, typeof(string), typeof(string), typeof(string))]
public static async Task<string> AddThing(string a, string b) => await <Class>Class.Add(a, b);
}
}
Name capabilities uniquely across the fleet. The broker routes by capability name to the first worker that exposes it, so two workers exposing the same name collide. The convention is a worker-qualified name (Calendar.Ping, Alarm.Ping); the display form in the catalog is Group.Worker:Capability. See 5 - Permission Catalog.
Boot (Program.cs)
Every worker boots the same way: take the context the Manager handed it, do its own one-time init, then run the secured host.
using System.Reflection;
using XRUIOS.Interfaces;
// 1. Bind the paths + key the Manager passed via environment (XRUIOS_DATA_PATH, _PUBLIC_PATH, _WORKER_KEY).
global::XRUIOS.Barebones.XRUIOS.BindFromEnvironment();
// 2. This worker's OWN init. Each worker sets up its own store - the Manager never reaches into it.
// (The old monolithic InitializeSystemAsync is gone; its per-class Initiate... step moves here.)
System.IO.Directory.CreateDirectory(
System.IO.Path.Combine(global::XRUIOS.Barebones.XRUIOS.DataPath, "<Class>"));
const string ServerName = "XRUIOS.Worker.<Class>";
// 3. Run: hardens the process, Notary-checks the folder, locks to the Manager's PSK, then serves.
await SecureWorkerHost.Run(
serverName: ServerName,
capabilityAssembly: Assembly.GetExecutingAssembly(),
gate: new AllowAllPermissionGate(),
guard: NotaryGuard.ForCurrentWorker(ServerName));
Two things people ask about:
- Why
AllowAllPermissionGateinside the worker? Because the permission check already happened at the Manager broker before the call was relayed. A worker only ever receives calls the Manager approved, and it only completes a handshake with the Manager's PSK - nothing else can reach it. The wall is at the broker; the gate here is just the seam. - The init step is yours to wire. If your class assumed the old
InitializeSystemAsyncran first, move that setup into step 2. Each worker is responsible for its own directories and defaults.
Register it with the Manager
Two edits outside the worker:
- Add the class to
WorkerCatalog.Defsin the Manager (short name + itsPermissionGroup) so the Manager launches and supervises it. - Add the project to
XRUIOS.slnx.
Then grant apps the capabilities you exposed (permissions.GrantAsync(appId, "<Class>.DoThing")). Ungranted names are denied at the broker before they reach the worker.
Next: the client that calls it - 3 - A CMD App.