DotBoxD.Codecs.MessagePack 0.1.0-ci.3622

This is a prerelease version of DotBoxD.Codecs.MessagePack.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package DotBoxD.Codecs.MessagePack --version 0.1.0-ci.3622
                    
NuGet\Install-Package DotBoxD.Codecs.MessagePack -Version 0.1.0-ci.3622
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="DotBoxD.Codecs.MessagePack" Version="0.1.0-ci.3622" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DotBoxD.Codecs.MessagePack" Version="0.1.0-ci.3622" />
                    
Directory.Packages.props
<PackageReference Include="DotBoxD.Codecs.MessagePack" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add DotBoxD.Codecs.MessagePack --version 0.1.0-ci.3622
                    
#r "nuget: DotBoxD.Codecs.MessagePack, 0.1.0-ci.3622"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package DotBoxD.Codecs.MessagePack@0.1.0-ci.3622
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=DotBoxD.Codecs.MessagePack&version=0.1.0-ci.3622&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=DotBoxD.Codecs.MessagePack&version=0.1.0-ci.3622&prerelease
                    
Install as a Cake Tool

DotBoxD

Contract-first plugin development for .NET hosts. Three interaction modes - call (typed RPC), react (server-filtered events), extend (plugin-shipped batch operations) - and one validated, fuel-metered sandbox for plugin-authored logic that runs inside the host.

CI CodeQL NuGet packages License: MIT .NET Docs

DotBoxD is a complete plugin system for .NET hosts - game servers, desktop apps, backend services - that must run untrusted third-party plugins safely. Everything you author is plain, contract-first C# (interfaces, records, attributes) that source generators turn into wiring, and it ships the whole architecture: process isolation over IPC, transports, codecs, generated proxies, event pipelines, plugin lifecycle, and the piece .NET itself doesn't give you - a safe way to run plugin logic inside the host process.

Why that last piece matters: AssemblyLoadContext is not a security boundary, so untrusted plugins must live in a sidecar process behind IPC. That is safe but costly: every interaction pays a round-trip, and the host vendor has to design event-filter APIs blind. DotBoxD keeps the process boundary and moves the plugin's logic (never its code) into the host: filters, projections, and batches compile to restricted kernel IR (never C#/IL) that the host validates, capability-gates, and fuel-meters before running next to its data. Full story in three diagrams: Why DotBoxD?

📖 Docs, tutorials, and API reference: https://dotboxd.kamsker.at/

Quick start

dotnet new console -n CatalogQuickstart
cd CatalogQuickstart
dotnet add package DotBoxD --prerelease   # full net10.0 stack; DotBoxD.Services.All = netstandard2.1/Unity bundle

Replace Program.cs with this complete file - it defines a contract, hosts it on a named pipe, and calls it through the generated typed proxy:

using DotBoxD.Pushdown.Services;        // RpcMessagePackIpc helper
using DotBoxD.Services.Attributes;      // [RpcService]
using DotBoxD.Services.Generated;       // generated ProvideCatalogService / Get<T>

// A unique pipe name, so parallel runs never collide.
var pipeName = $"dotboxd-quickstart-{Guid.NewGuid():N}";
var prices = new Dictionary<string, int> { ["sword"] = 120, ["shield"] = 80 };

// Host: turn every accepted connection into a peer that serves the contract.
await using var host = RpcMessagePackIpc.ListenNamedPipe(
    pipeName,
    peer => peer.ProvideCatalogService(new CatalogService(prices)));
await host.StartAsync();

// Client: connect and call the generated typed proxy. The client lives in the
// same process here to keep the demo to one file; the call still crosses the
// named pipe exactly like an out-of-process client would.
await using var connection = await RpcMessagePackIpc.ConnectNamedPipeAsync(pipeName);
var catalog = connection.Get<ICatalogService>();

var price = await catalog.GetUnitPriceAsync("sword");
Console.WriteLine($"sword costs {price}");

// The contract: one attribute, no base classes, no marshaling code.
[RpcService]
public interface ICatalogService
{
    ValueTask<int> GetUnitPriceAsync(string itemId, CancellationToken cancellationToken = default);
}

// The host-side implementation is plain C#.
public sealed class CatalogService(Dictionary<string, int> prices) : ICatalogService
{
    public ValueTask<int> GetUnitPriceAsync(string itemId, CancellationToken cancellationToken = default)
        => ValueTask.FromResult(prices[itemId]);
}

dotnet run prints sword costs 120. The same steps, with expected output at every checkpoint, are in Getting started. To see every feature working together, clone the repo and run the maintained end-to-end sample:

dotnet run -c Release --project samples/GameServer/Examples.GameServer.Server/Examples.GameServer.Server.csproj

Three interaction modes

Every plugin interaction is one of three shapes. What differs is where the author's logic runs and what crosses the wire:

Mode You author Wire behavior Typical use
1 · Services (RPC) - call the host An [RpcService] interface; the host implements it, clients get a generated typed proxy. Request → response; 1 round-trip per call. Fetch a price, compute a total.
2 · Event pipelines - react to the host A Where/Select chain over a host event; the filter runs inside the host as sandboxed IR. One-way push of matching, projected events; 0 round-trips (a result terminal such as RegisterLocal returns one reply per match). High-frequency event streams you need a slice of.
3 · Pushdown - extend the host A [ServerExtension] batch method; it runs inside the host as sandboxed IR, looping the host's existing bindings. One submission replaces N per-entity calls. Chatty loops against a host that is frozen at release.

Modes 2 and 3 compile to the same engine, the kernel sandbox - validated, capability-gated, fuel-metered IR, never loaded C#/IL. Mode 1 is a trusted, hand-written host implementation with no sandbox involved.

Mode 2 in five lines (from the GameServer sample; built end to end in the event-pipelines walkthrough):

server.Hooks.On<MonsterAggroEvent>()
    .Where(e => e.Distance <= 4)                    // lowered: runs on the SERVER as verified IR
    .Select(e => e.MonsterId)                       // lowered: runs on the SERVER; projects one field
    .RunLocal(monsterId => calmedMonsters.Add(monsterId)); // native C#, runs in YOUR plugin process

SDK value objects can expose eligible public instance methods with shared host-binding defaults. The receiver becomes argument zero, and ids derive from the prefix, method name, and parameter types:

[HostBindingObject("host.player", "game.player.inventory.read",
                   SandboxEffect.Cpu | SandboxEffect.HostStateRead)]
public sealed record PlayerSnapshot(int Id, IReadOnlyList<int> ItemIds)
{
    public bool HasItem(int itemId) => ItemIds.Contains(itemId); // host.player.HasItem.i32

    [HostBindingIgnore]
    public string LocalLabel() => $"player:{Id}"; // remains local-only
}

Mode 3, abridged (the host is frozen and exposes only a fine-grained bool Kill(int id) binding; the plugin ships the batch, and one round-trip replaces N):

[ServerExtension("monster-killer", typeof(IMonsterKillerService))]
public sealed partial class MonsterKillerKernel
{
    public List<KillResult> KillMonsters(List<int> monsterIds, HookContext ctx)
    {
        var results = new List<KillResult>();
        foreach (var id in monsterIds)
            results.Add(new KillResult(id, ctx.Host<IGameWorld>().Kill(id))); // the host's EXISTING binding
        return results;
    }
}

// The host installs the plugin's generated kernel once under its service contract.
await server.RegisterServerExtensionAsync<IMonsterKillerService, MonsterKillerKernel>();

List<KillResult> killed = server.ServerExtension<IMonsterKillerService>().KillMonsters(ids); // 1 round-trip, not N

The full version - the host-side [HostBinding] declaration, capability gating, registration, and how complex objects ride the IR Record type - is the Pushdown walkthrough and the Pushdown concept; the design record lives in docs/design/plugin-fluent-hooks-api/followups.md. The raw sandbox API underneath both modes (import → validate → execute under a fuel policy) is public too - see Kernels for the smallest end-to-end SandboxHost.

Security: what is and isn't a boundary

DotBoxD distinguishes three trust postures - read this before deploying:

  • Safe mode is the real boundary. A kernel is restricted IR that is validated, capability-gated, fuel/quota-metered, and (for compiled mode) verified before it runs. Users never supply C#, raw IL, CLR member names, assemblies, or arbitrary host calls.
  • Trusted-plugin mode is NOT a security boundary. It loads normal .NET assemblies via AssemblyLoadContext, and AssemblyLoadContext is not a sandbox - loaded code has full CLR capabilities. Only use it for code you already trust.
  • Untrusted arbitrary .NET code must be out-of-process / OS-isolated. In-process restrictions defend against accidental and many malicious-author attacks, but hard multi-tenant isolation requires a worker process, container, or OS-level boundary.

See SECURITY.md and Sandbox caveats for the threat model, the three trust postures, and the capabilities/bindings model.

Where to go next

Your journey Start here
Get a verified end-to-end win Getting started
Understand the why and pick a mode Why DotBoxD? · Choosing a mode
RPC & Unity: typed calls between processes Tutorial 1: your first Service
Plugin author: react to events, ship batches Event pipelines walkthrough · Pushdown walkthrough
Host integrator: expose bindings, set policy Host bindings · Kernel runtime
See everything working together GameServer walkthrough
Review the security model Sandbox caveats

Features that older, removed samples used to demonstrate are tracked in the examples coverage-gaps page.

Architecture

flowchart LR
    subgraph PluginProc["Plugin / client process (unprivileged)"]
        Plugin["Plugin code<br/>native C#"]
    end

    subgraph HostProc["Host process (privileged)"]
        Services["Services<br/>generated dispatch, trusted impl"]
        Sandbox["Kernel sandbox<br/>validated · capability-gated · fuel-metered IR"]
        HostState["Host bindings · events · state"]
        Services --- HostState
        Sandbox --- HostState
    end

    Plugin -->|"1 · call: typed RPC request/response"| Services
    Plugin -->|"2 · react: install Where/Select filter (IR)"| Sandbox
    Sandbox -->|"matching, projected events: one-way push"| Plugin
    Plugin -->|"3 · extend: submit batch (IR), one result back"| Sandbox

Every arrow crossing the process boundary rides the channel layer (DotBoxD.Transports.Tcp / DotBoxD.Transports.NamedPipes + DotBoxD.Codecs.MessagePack - all standalone packages), and the sandbox executes IR on an interpreted backend or a verified compiled backend. The generators (DotBoxD.Services.SourceGenerator, DotBoxD.Plugins.Analyzer) emit proxies, dispatchers, and plugin factories at compile time. Diagnostics are namespaced DBXS### (services) and DBXK### (kernels/plugins). See the docs overview for the full picture.

Installing from NuGet

DotBoxD ships as two stacks. Install a meta-package, or any individual package with dotnet add package <PackageId> --prerelease. Main-branch CI packages are published as 0.1.0-ci.* prereleases; omit --prerelease once you target a stable tag release.

For a focused host or plugin setup, install only the components you use:

dotnet add package DotBoxD.Hosting --prerelease
dotnet add package DotBoxD.Kernels.Serialization.Json --prerelease
dotnet add package DotBoxD.Hosting.Http --prerelease
dotnet add package DotBoxD.Plugins.Analyzer --prerelease
dotnet add package DotBoxD.Pushdown.Services --prerelease

Services & channels stack - netstandard2.1, stable API

Runs on .NET 8/9/10 and Unity. Unity/IL2CPP deployments must use generated/static MessagePack DTO formatters, root the generated registry, and validate their own IL2CPP build.

Package Purpose
DotBoxD.Services.All Meta-package: the service + channel bundle (AOT configuration required)
DotBoxD.Services Contract attributes, RpcPeer/RpcHost, dispatch, and the bundled source generator
DotBoxD.Codecs.MessagePack MessagePack serializer for the wire format (generated resolver required for AOT)
DotBoxD.Transports.Tcp TCP transport
DotBoxD.Transports.NamedPipes Named-pipe transport (local IPC)

DotBoxD.Services.SourceGenerator is bundled inside DotBoxD.Services as an analyzer asset, not published as a standalone package.

Kernels & plugins stack - net10.0, preview

Package Purpose
DotBoxD Meta-package: the full net10.0 stack (Services + Kernels + Pushdown)
DotBoxD.Abstractions Plugin authoring contracts ([Plugin], IEventKernel<TEvent>, HookContext)
DotBoxD.Kernels IR model, policy model, resource metering, canonical hashing
DotBoxD.Kernels.Validation Structural, type, effect, policy, binding validation
DotBoxD.Kernels.Runtime Safe host bindings (files, time, random, logging, strings, math)
DotBoxD.Kernels.Interpreter Direct IR execution backend
DotBoxD.Kernels.Compiler Generated-runtime backend + persistent artifact cache
DotBoxD.Kernels.Verifier Generated-assembly verifier
DotBoxD.Kernels.Serialization.Json JSON IR importer/exporter (JsonImporter/JsonExporter) + schema
DotBoxD.Hosting Host-facing orchestration API (SandboxHost: import, prepare, execute under policy)
DotBoxD.Hosting.Http HTTP GET binding, grant helpers, pinned-transport policy validation
DotBoxD.Plugins Host runtime that loads, validates, and dispatches plugins (PluginPackageJsonSerializer reads the plugin-package JSON envelope)
DotBoxD.Plugins.Analyzer Generator + analyzer that turns [Plugin] kernels into package-backed plugins (netstandard2.0)
DotBoxD.Pushdown.Services MessagePack IPC addon that composes kernels with services (prerelease)

DotBoxD.Pushdown.Services is published on a prerelease channel while its upstream net10.0 dependencies are prerelease; stable release gates fail if it is included in a stable package set.

Common namespaces & key types

After installing, these are the entry points you'll reach for:

  • DotBoxD.Services: [RpcService], RpcPeer / RpcHost, and the generated Provide{Service} / Get<TService>() wiring.
  • DotBoxD.Hosting: SandboxHost.
  • DotBoxD.Kernels.Serialization.Json: JsonImporter / JsonExporter.
  • DotBoxD.Pushdown.Services: the MessagePack IPC bridge that runs kernels next to host services.

Status & roadmap

DotBoxD merges the former standalone ShaRPC (RPC) and Safe-IR (kernel sandbox) repositories into one contract-first runtime. The netstandard2.1 Services/channels stack is the more mature surface; the net10.0 Kernels/Pushdown stack is preview. Deferred work and known gaps are tracked in docs/architecture/follow-up-issues.md.

Contributing

Build, test, and the CI gate list live in CONTRIBUTING.md. In short:

dotnet build DotBoxD.slnx -c Release
dotnet test  DotBoxD.slnx -c Release

Please read the Code of Conduct. For how to view pre-merge history of the two original repos, see Migration from standalone repos.

License

DotBoxD is MIT licensed. It preserves the attribution of both original projects: Copyright (c) 2026 Danial Jumagaliyev (ShaRPC, the Services/channels stack) and Copyright (c) 2026 Jonas Kamsker (Safe-IR / DotBoxD, the Kernels/Pushdown stack).

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on DotBoxD.Codecs.MessagePack:

Package Downloads
DotBoxD.Pushdown.Services

Preview DotBoxD MessagePack IPC addon that runs sandboxed kernels next to host RPC services, with named-pipe helpers.

DotBoxD.Services.All

DotBoxD service/channels bundle: the source-generated RPC core together with the MessagePack codec and TCP/named-pipe transports. Targets netstandard2.1; AOT deployments must supply generated MessagePack DTO formatters.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0-ci.3856 25 7/15/2026
0.1.0-ci.3828 33 7/15/2026
0.1.0-ci.3822 35 7/15/2026
0.1.0-ci.3815 35 7/15/2026
0.1.0-ci.3622 41 7/14/2026
0.1.0-ci.3617 42 7/14/2026
0.1.0-ci.3406 64 7/13/2026
0.1.0-ci.3371 56 7/13/2026
0.1.0-ci.3354 53 7/13/2026
0.1.0-ci.3342 56 7/12/2026
0.1.0-ci.3309 58 7/12/2026
0.1.0-ci.3206 62 7/12/2026
0.1.0-ci.2702 67 7/10/2026
0.1.0-ci.2630 75 7/9/2026
0.1.0-ci.2617 64 7/9/2026
0.1.0-ci.2515 65 7/9/2026
0.1.0-ci.2443 66 7/8/2026
0.1.0-ci.2369 75 7/8/2026
0.1.0-ci.2364 55 7/8/2026
0.1.0-ci.2361 65 7/8/2026
Loading failed