Diataxis category: reference.
This document is the schema-style reference for the Unix-domain wire
protocol between the d2b CLI, d2bd, and the privileged
broker. The prose in this file is hand-maintained. The schema blocks
bounded by AUTO-GENERATED markers are regenerated by
cargo xtask gen-daemon-api from packages/d2b-contracts/src/ and are
therefore the implementation oracle for the IPC types.
The daemon uses non-abstract Unix-domain SOCK_SEQPACKET sockets for both
public and private traffic:
- public socket:
/run/d2b/public.sock - broker socket:
/run/d2b/priv.sock
Each application-level frame is:
- a 4-byte little-endian unsigned length prefix;
- followed immediately by one UTF-8 JSON document.
The maximum accepted frame size is 1 MiB. Oversized frames are rejected before JSON deserialization so callers get a typed failure instead of partial reads or truncated documents.
SOCK_SEQPACKET already preserves message boundaries, but the protocol keeps the
explicit length prefix so the wire format stays identical if a future
transport ever needs stream framing. There is never more than one
request or one response inside a frame.
Transport-neutral in v2. The local Unix socket at
/run/d2b/public.sockis one transport binding for the D2b daemon API. A relay-backed or remote daemon-access binding, when configured, carries daemon API requests only — it does not expose the broker socket (/run/d2b/priv.sock) and does not tunnel raw guest ttRPC traffic. Relay credentials used to authenticate a remote daemon-access session are node-management credentials, not realm or provider workload credentials. There is no implicit "remote caller is Admin" mapping: relay identity is never resolved tod2b-admin; theSO_PEERCRED-based admin/launcher gate remains the sole authn mechanism for the local Unix binding, and any non-local binding requires explicit principal mapping against a daemon-access trust anchor. Realm and provider workload credentials are held inside a gateway guest VM and never transit the daemon API or broker paths.
Every new connection begins with a Hello message. The client presents:
- a
SemverRangedescribing the versions it can speak; - a list of
FeatureFlagvalues it knows how to use.
The server replies with either:
HelloOk— version negotiation succeeded, and the server selected one concrete protocol version plus a capability set; orHelloRejected— the peer is local and authenticated, but version or capability negotiation failed before the first command payload.
Downgrades are allowed only when the selected version stays inside
the client's explicit SemverRange. There is no silent downgrade to a
server-chosen version outside that range.
Unknown feature flags are ignored for forward compatibility. Unknown
fields inside a known request or response type are rejected
(deny_unknown_fields) because the documented wire enums are a closed
compatibility surface.
| Type | Kind | Rust definition | Shape |
|---|---|---|---|
FeatureFlag |
struct | FeatureFlag |
empty struct |
GuestCapability |
enum | GuestCapability |
Health; Capabilities; ExecAttached; ExecDetached; ExecTty; ExecLogs; TtyResize; Signals; ReadGuestFile; UsbipImport; ShellAttached; ShellManagement; ShellForceAttach; UsbipStatus; SystemActivation; AudioStatus; AudioSet |
Hello |
struct | Hello |
struct { client_version: SemverRange; supported_features: Vec<FeatureFlag> } |
HelloOk |
struct | HelloOk |
struct { server_version: Version; selected_version: Version; capabilities: Vec<FeatureFlag> } |
HelloRejected |
struct | HelloRejected |
struct { reason: HelloRejectedReason } |
HelloRejectedReason |
enum | HelloRejectedReason |
VersionMismatch; CapabilityNegotiationFailed; InternalError |
HelloRequest |
struct | HelloRequest |
struct { client_version: String; supported_features: Vec<String> } |
HelloRequest |
struct | HelloRequest |
struct { metadata: GuestRequestMetadata; host_nonce: GuestNonce; transcript_version: u32 } |
HelloResponse |
struct | HelloResponse |
struct { server_version: String; selected_version: String; capabilities: Vec<String> } |
HelloResponse |
struct | HelloResponse |
struct { guest_nonce: GuestNonce; guest_boot_id: GuestBootId; protocol_version: u32 } |
KnownFeatureFlag |
enum | KnownFeatureFlag |
TypedErrors; ManifestV04; StatusCheckBridges; ExportBrokerAudit; ConfiguredLaunchV1; UnsafeLocalProviderV1; UnsafeLocalShellV1 |
/run/d2b/public.sock is the operator-facing socket.
The feature-negotiated workload frame carries a WorkloadOp body and returns
workloadResponse. List and Status expose provider-neutral, argv-free
metadata. LauncherExec accepts only canonical target, item id, and operation
id. The daemon reloads and hash-verifies the trusted bundle, cross-checks public
item metadata against its private configured item, and then routes to
guest-control or the exact requester-UID unsafe-local helper. Remote/relay
principals, UID fields, argv, environment, cwd, proxy paths, process ids, unit
names, and fallback transports are not accepted.
The existing protocol-v3 shell frame is provider-neutral without changing its
serde shape: the historical vm field carries either a local VM name or a
canonical target. d2bd resolves canonical and bare targets to local VM,
unsafe-local, or a typed capability refusal. Unsafe-local policy comes only from
the hash-verified private workload artifact. Attach dispatches a private helper
v2 request for the exact authenticated peer uid, validates one connected
terminal fd, generates a bounded opaque public session handle, and multiplexes
terminal-v1 operations over that fd. List/detach/kill use correlated helper
management responses. Public requests carry no policy, uid, argv, environment,
cwd, path, operation id, or provider override.
All shell operations require the local admin role before target resolution or
helper/guest contact. unsafe-local-shell-v1 is negotiated independently of
guest shell support; a client that does not negotiate it cannot reach the
unsafe-local route. Local VM shell behavior and protocol version 3 remain
unchanged.
Local-VM launcher execution uses a deterministic opaque guest exec id derived from the local peer uid and public operation identity. Guestd's durable detached record is the restart-stable idempotency authority; the same id and argv hash replay the existing exec, while a hash mismatch is rejected.
Daemon audit records the authenticated peer_uid and public operation_id on
each configured-launch outcome. Local-VM events also carry the opaque guest
exec_id and emit the standard detached-create event with that id, allowing
the launch request and guest execution to be correlated without recording argv,
environment, cwd, or output.
- transport: non-abstract Unix-domain
SOCK_SEQPACKET - path:
/run/d2b/public.sock - mode:
0660 - owner/group:
root:d2b
Authorization uses SO_PEERCRED.
The daemon reads the peer uid/gid from the socket, resolves the caller's
configured launcher/admin identity, and then performs a supplementary
group lookup through getgrouplist(3) as part of the user/group mapping
flow. Wheel membership alone never grants access. The public socket
is for configured launcher/admin identities only, and d2bd itself
is not treated as a valid public-socket client.
Unfiltered List and Status responses are served from a daemon-maintained
read model after the first successful build. The model is published as an
atomic frame snapshot and includes readModel metadata with:
schemaVersion;kind(listorstatus);generation;sourceFingerprint;updatedAtUnixMs;freshness;deepRefresh.
The source fingerprint covers the current system generation, public manifest, host/process/bundle artifacts, and the daemon pidfd-table generation. Mutating public operations and runner pidfd registration/deregistration invalidate the snapshot before later fast reads may reuse it. Filtered requests, explicit deep diagnostics, and bridge-check requests may bypass the read model so they can return request-specific data.
USB sysfs driver bind/unbind has no true async Rust wrapper in the current
implementation. The broker therefore uses a bounded isolated helper for both
USBIP bind and unbind rather than performing those writes on daemon status/read
paths or an async reactor thread. Status/read-model paths never trigger sysfs
driver mutation.
/run/d2b/priv.sock is the daemon-to-broker control path.
- transport: non-abstract Unix-domain
SOCK_SEQPACKET - path:
/run/d2b/priv.sock - mode:
0660 - owner/group:
root:d2bd
Authorization is stricter than the public socket: the peer uid obtained
through SO_PEERCRED must equal the d2bd uid. Root,
launchers, and admins are all rejected at the wire layer if they try to
speak directly to the broker.
Broker IPC is rate-limited before privileged dispatch. Direct broker
peers are bucketed by stable peer UID, while accepted daemon-forwarded
requests are bucketed by the daemon UID plus the forwarded caller role
class and closed operation name. Rate-limit failures return only the
generic Broker.IpcRateLimited envelope to the daemon, and direct
non-daemon peers still receive no privileged details. Broker audit
appends have a separate bounded write limiter so refused USB/module
requests cannot grow audit storage without bound.
The generated tables below list the concrete request and response shapes
captured in d2b-contracts. The table entries link back to the Rust
source files so a reviewer can diff the prose against the type
definitions directly.
Any field carrying a Linux interface, bridge, TAP, or bridge-port name
uses the IfName newtype rather than a raw String. Names at or
above IFNAMSIZ (16 bytes including the trailing NUL) and malformed
names are rejected during deserialization.
USBIP fields whose stable wire names include DurableClaim,
durableClaim, or preserve_durable_claim refer to the broker-owned
host-session claim under /run/d2b/locks/usbip. That claim survives
VM stop/restart and daemon restart during the current host boot, but not
host reboot.
| Type | Kind | Rust definition | Shape |
|---|---|---|---|
PublicRequest |
enum | PublicRequest |
Capabilities; AuthStatus; List — (ListRequest); Status — (StatusRequest); Audit — (AuditRequest); HostCheck — (HostCheckRequest); VmStart — (VmLifecycleRequest); VmStop — (VmLifecycleRequest); VmRestart — (VmLifecycleRequest); Switch — (ActivationRequest); Boot — (ActivationRequest); Test — (ActivationRequest); Rollback — (ActivationRequest); Gc — (GcRequest); KeysList; KeysShow — (KeysShowRequest); KeysRotate — (KeysRotateRequest); Trust — (TrustRequest); RotateKnownHost — (RotateKnownHostRequest); UsbipBind — (UsbipBindCliRequest); UsbipUnbind — (UsbipUnbindCliRequest); UsbipProbe; StoreVerify — (StoreVerifyRequest); Migrate — (MigrateRequest); HostPrepare — (HostPrepareRequest); HostDestroy — (HostDestroyRequest); HostInstall — (HostInstallRequest); HostReconcile — (HostReconcileRequest); ReadGuestConfig — (ReadGuestConfigRequest); Exec — (ExecOp); Shell — (ShellOp); Console — (ConsoleOp); Audio — (AudioOp); GatewayDisplay — (GatewayDisplayOp); Workload — (WorkloadOp); UsbSecurityKeyStatus; UsbSecurityKeySessions; UsbSecurityKeyCancel — (crate::security_key::SecurityKeyCancelRequest) |
ListRequest |
struct | ListRequest |
struct { env: Option<String>; vm: Option<String> } |
StatusRequest |
struct | StatusRequest |
struct { check_bridges: bool; vm: Option<String> } |
AuditRequest |
struct | AuditRequest |
struct { filter: Option<AuditSelector>; format: AuditFormat; since: Option<String> } |
HostCheckRequest |
struct | HostCheckRequest |
struct { read_only: bool; strict: bool } |
VmLifecycleRequest |
struct | VmLifecycleRequest |
struct { vm: String; flags: MutationFlags; force: bool; no_wait_api: bool } |
ActivationRequest |
struct | ActivationRequest |
struct { vm: String; flags: MutationFlags } |
GcRequest |
struct | GcRequest |
struct { flags: MutationFlags; keep_generations: Option<u32> } |
KeysShowRequest |
struct | KeysShowRequest |
struct { vm: String } |
KeysRotateRequest |
struct | KeysRotateRequest |
struct { vm: String; flags: MutationFlags } |
TrustRequest |
struct | TrustRequest |
struct { vm: String; flags: MutationFlags } |
RotateKnownHostRequest |
struct | RotateKnownHostRequest |
struct { vm: String; flags: MutationFlags } |
UsbipBindCliRequest |
struct | UsbipBindCliRequest |
struct { vm: String; bus_id: String; flags: MutationFlags } |
UsbipUnbindCliRequest |
struct | UsbipUnbindCliRequest |
struct { vm: String; bus_id: String; flags: MutationFlags } |
StoreVerifyRequest |
struct | StoreVerifyRequest |
struct { vm: String; repair: bool } |
ReadGuestConfigRequest |
struct | ReadGuestConfigRequest |
struct { vm: String } |
MigrateRequest |
struct | MigrateRequest |
struct { flags: MutationFlags } |
HostPrepareRequest |
struct | HostPrepareRequest |
struct { flags: MutationFlags } |
HostDestroyRequest |
struct | HostDestroyRequest |
struct { flags: MutationFlags } |
HostInstallRequest |
struct | HostInstallRequest |
struct { flags: MutationFlags; enable: bool; start: bool; no_start: bool } |
HostReconcileRequest |
struct | HostReconcileRequest |
struct { flags: MutationFlags; network: bool } |
UsbSecurityKeyStatusRequest |
struct | UsbSecurityKeyStatusRequest |
empty struct |
UsbSecurityKeySessionsRequest |
struct | UsbSecurityKeySessionsRequest |
empty struct |
UsbSecurityKeyCancelRequest |
struct | UsbSecurityKeyCancelRequest |
struct { session_id: Option<String>; current: bool } |
UsbSecurityKeyTestRequest |
struct | UsbSecurityKeyTestRequest |
struct { vm: String } |
| Type | Kind | Rust definition | Shape |
|---|---|---|---|
BrokerRequest |
enum | BrokerRequest |
ApplyNftables — (ApplyNftablesRequest); ApplyNmUnmanaged — (ApplyNmUnmanagedRequest); ApplyRoute — (ApplyRouteRequest); ApplySysctl — (ApplySysctlRequest); BindUnixSocket — (BindUnixSocketRequest); CreateOrReconcileUsersGroups — (CreateOrReconcileUsersGroupsRequest); CreatePersistentTap — (CreatePersistentTapRequest); CreateTapFd — (CreateTapFdRequest); DelegateCgroupV2 — (DelegateCgroupV2Request); ExportBrokerAudit — (ExportBrokerAuditRequest); Hello — (HelloRequest); GuestControlSign — (GuestControlSignRequest); InjectSecretById — (SecretByIdRequest); LaunchMinijailChild — (LaunchMinijailChildRequest); ModprobeIfAllowed — (ModprobeIfAllowedRequest); OpenCgroupDir — (OpenCgroupDirRequest); OpenDevice — (OpenDeviceRequest); OpenFuse — (OpenFuseRequest); OpenHidrawSecurityKey — (OpenHidrawSecurityKeyRequest); OpenKvm — (OpenKvmRequest); QemuMediaEnroll — (QemuMediaEnrollRequest); QemuMediaRefreshRegistry — (QemuMediaRefreshRegistryRequest); QemuMediaBoot — (QemuMediaBootRequest); QemuMediaSystemPowerdown — (QemuMediaLifecycleRequest); QemuMediaQueryStatus — (QemuMediaQueryStatusRequest); QemuMediaQuit — (QemuMediaLifecycleRequest); QemuMediaAttach — (QemuMediaHotplugRequest); QemuMediaDetach — (QemuMediaHotplugRequest); OpenPidfd — (OpenPidfdRequest); OpenVhostNet — (OpenVhostNetRequest); PauseBroker; PollChildReaped; PrepareRuntimeDir — (PrepareDirRequest); PrepareStateDir — (PrepareDirRequest); ReconcileStorageScope — (ReconcileStorageScopeRequest); ValidateLockSpec — (ValidateLockSpecRequest); PrepareStoreView — (PrepareStoreViewRequest); StoreSync — (StoreSyncRequest); StoreVerify — (StoreVerifyRequest); ReadSecretById — (SecretByIdRequest); ResumeBroker; RotateSecretById — (SecretByIdRequest); RunHostInstall — (RunHostInstallRequest); RunMigrate — (RunMigrateRequest); RunActivation — (RunActivationRequest); RunGc — (RunGcRequest); RunKeysRotate — (RunKeysRotateRequest); RunHostKeyTrust — (RunHostKeyTrustRequest); RunRotateKnownHost — (RunRotateKnownHostRequest); SetBridgePortFlags — (SetBridgePortFlagsRequest); SetSocketAcl — (SetSocketAclRequest); SetupMountNamespace — (SetupMountNamespaceRequest); SignalRunner — (SignalRunnerRequest); DeregisterRunnerPidfd — (DeregisterRunnerPidfdRequest); SpawnRunner — (SpawnRunnerRequest); UpdateHostsFile — (UpdateHostsFileRequest); UsbipBind — (UsbipBindRequest); UsbipBindFirewallRule — (UsbipBindFirewallRuleRequest); UsbipProxyReconcile — (UsbipProxyReconcileRequest); UsbipUnbind — (UsbipUnbindRequest); UsbipExplicitBind — (UsbipExplicitBindRequest); UsbipExplicitFirewallRule — (UsbipExplicitFirewallRuleRequest); ValidateBundle; SeedDnsmasqLease — (SeedDnsmasqLeaseRequest); BindMountFromHardlinkFarm — (BindMountFromHardlinkFarmRequest); OwnershipMatrixCheck — (OwnershipMatrixCheckRequest); SshHostKeyPreflight — (SshHostKeyPreflightRequest); DiskInit — (DiskInitRequest); SecurityKeyOpenDevice — (crate::security_key::SecurityKeyOpenDeviceRequest); SecurityKeyApplyUdevRules — (crate::security_key::SecurityKeyApplyUdevRulesRequest) |
RunHostInstallRequest |
struct | RunHostInstallRequest |
struct { bundle_installer_intent_ref: BundleOpId; enable: bool; start: bool; no_start: bool; tracing_span_id: Option<TracingSpanId> } |
RunMigrateRequest |
struct | RunMigrateRequest |
struct { bundle_migrate_intent_ref: BundleOpId; tracing_span_id: Option<TracingSpanId> } |
RunActivationRequest |
struct | RunActivationRequest |
struct { bundle_activation_intent_ref: BundleOpId; mode: ActivationMode; phase: ActivationPhase; vm: String; tracing_span_id: Option<TracingSpanId> } |
RunGcRequest |
struct | RunGcRequest |
struct { bundle_gc_intent_ref: BundleOpId; keep_generations: Option<u32>; tracing_span_id: Option<TracingSpanId> } |
RunKeysRotateRequest |
struct | RunKeysRotateRequest |
struct { bundle_keys_intent_ref: BundleOpId; vm: String; tracing_span_id: Option<TracingSpanId> } |
RunHostKeyTrustRequest |
struct | RunHostKeyTrustRequest |
struct { bundle_trust_intent_ref: BundleOpId; vm: String; tracing_span_id: Option<TracingSpanId> } |
RunRotateKnownHostRequest |
struct | RunRotateKnownHostRequest |
struct { bundle_rotate_known_host_intent_ref: BundleOpId; vm: String; tracing_span_id: Option<TracingSpanId> } |
HelloRequest |
struct | HelloRequest |
struct { client_version: String; supported_features: Vec<String> } |
ApplyNftablesRequest |
struct | ApplyNftablesRequest |
struct { bundle_nft_intent_ref: BundleOpId; scope_id: ScopeId; desired_hash: Option<String>; destroy: bool; tracing_span_id: Option<TracingSpanId> } |
ApplyNmUnmanagedRequest |
struct | ApplyNmUnmanagedRequest |
struct { bundle_nm_intent_ref: BundleOpId; scope_id: ScopeId; destroy: bool; tracing_span_id: Option<TracingSpanId> } |
ApplyRouteRequest |
struct | ApplyRouteRequest |
struct { bundle_route_intent_ref: BundleOpId; scope_id: ScopeId; destroy: bool; tracing_span_id: Option<TracingSpanId> } |
ApplySysctlRequest |
struct | ApplySysctlRequest |
struct { bundle_sysctl_intent_ref: BundleOpId; scope_id: ScopeId; destroy: bool; tracing_span_id: Option<TracingSpanId> } |
BindUnixSocketRequest |
struct | BindUnixSocketRequest |
struct { bundle_socket_intent_ref: BundleOpId; vm_id: VmId; role_id: RoleId; tracing_span_id: Option<TracingSpanId> } |
CreateOrReconcileUsersGroupsRequest |
struct | CreateOrReconcileUsersGroupsRequest |
struct { subject_ids: Vec<SubjectId>; tracing_span_id: Option<TracingSpanId> } |
CreatePersistentTapRequest |
struct | CreatePersistentTapRequest |
struct { role_id: RoleId; vm_id: VmId; tracing_span_id: Option<TracingSpanId> } |
CreateTapFdRequest |
struct | CreateTapFdRequest |
struct { role_id: RoleId; vm_id: VmId; tracing_span_id: Option<TracingSpanId> } |
DelegateCgroupV2Request |
struct | DelegateCgroupV2Request |
struct { scope_id: ScopeId; tracing_span_id: Option<TracingSpanId> } |
ExportBrokerAuditRequest |
struct | ExportBrokerAuditRequest |
struct { filter: Option<BrokerAuditFilter>; since: Option<String> } |
GuestControlSignRequest |
struct | GuestControlSignRequest |
struct { vm_id: VmId; role: GuestControlProofRole; protocol_version: u32; direction: GuestControlDirection; purpose: GuestControlAuthPurpose; guest_control_port: u32; peer_cid: Option<u32>; host_nonce: Vec<u8>; guest_nonce: Vec<u8>; guest_boot_id: GuestBootIdWire; capabilities_hash: Option<String>; tracing_span_id: Option<TracingSpanId> } |
SecretByIdRequest |
struct | SecretByIdRequest |
struct { opaque_id: String; tracing_span_id: Option<TracingSpanId> } |
LaunchMinijailChildRequest |
struct | LaunchMinijailChildRequest |
struct { vm_id: VmId; role_id: RoleId; tracing_span_id: Option<TracingSpanId> } |
ModprobeIfAllowedRequest |
struct | ModprobeIfAllowedRequest |
struct { module_name: String; tracing_span_id: Option<TracingSpanId> } |
OpenCgroupDirRequest |
struct | OpenCgroupDirRequest |
struct { scope_id: ScopeId; path_class: PathClass; tracing_span_id: Option<TracingSpanId> } |
OpenDeviceRequest |
struct | OpenDeviceRequest |
struct { role_id: RoleId; device_class: String; tracing_span_id: Option<TracingSpanId> } |
OpenKvmRequest |
struct | OpenKvmRequest |
struct { role_id: RoleId; tracing_span_id: Option<TracingSpanId> } |
QemuMediaEnrollRequest |
struct | QemuMediaEnrollRequest |
struct { vm_id: VmId; media_ref: MediaRef; bus_id: String; tracing_span_id: Option<TracingSpanId> } |
QemuMediaRefreshRegistryRequest |
struct | QemuMediaRefreshRegistryRequest |
struct { tracing_span_id: Option<TracingSpanId> } |
QemuMediaBootRequest |
struct | QemuMediaBootRequest |
struct { vm_id: VmId; tracing_span_id: Option<TracingSpanId> } |
QemuMediaLifecycleRequest |
struct | QemuMediaLifecycleRequest |
struct { vm_id: VmId; tracing_span_id: Option<TracingSpanId> } |
QemuMediaQueryStatusRequest |
struct | QemuMediaQueryStatusRequest |
struct { vm_id: VmId; shutdown_context: bool; tracing_span_id: Option<TracingSpanId> } |
QemuMediaHotplugRequest |
struct | QemuMediaHotplugRequest |
struct { vm_id: VmId; bus_id: String; tracing_span_id: Option<TracingSpanId> } |
OpenPidfdRequest |
struct | OpenPidfdRequest |
struct { vm_id: VmId; role_id: RoleId; pid: i32; expected_start_time_ticks: u64; tracing_span_id: Option<TracingSpanId> } |
OpenVhostNetRequest |
struct | OpenVhostNetRequest |
struct { role_id: RoleId; tracing_span_id: Option<TracingSpanId> } |
OpenFuseRequest |
struct | OpenFuseRequest |
struct { role_id: RoleId; tracing_span_id: Option<TracingSpanId> } |
OpenHidrawSecurityKeyRequest |
struct | OpenHidrawSecurityKeyRequest |
struct { vm_id: VmId; selector_id: String; tracing_span_id: Option<TracingSpanId> } |
PrepareDirRequest |
struct | PrepareDirRequest |
struct { vm_id: VmId; path_class: PathClass; tracing_span_id: Option<TracingSpanId> } |
PrepareStoreViewRequest |
struct | PrepareStoreViewRequest |
struct { vm_id: VmId; tracing_span_id: Option<TracingSpanId> } |
StoreSyncRequest |
struct | StoreSyncRequest |
struct { vm_id: VmId; bundle_closure_ref: BundleClosureRef; generation_token: u32; tracing_span_id: Option<TracingSpanId> } |
StoreVerifyRequest |
struct | StoreVerifyRequest |
struct { vm_id: VmId; repair: bool; tracing_span_id: Option<TracingSpanId> } |
SetBridgePortFlagsRequest |
struct | SetBridgePortFlagsRequest |
struct { vm_id: VmId; role_id: RoleId; tracing_span_id: Option<TracingSpanId> } |
SetSocketAclRequest |
struct | SetSocketAclRequest |
struct { bundle_socket_intent_ref: BundleOpId; vm_id: VmId; role_id: RoleId; tracing_span_id: Option<TracingSpanId> } |
SetupMountNamespaceRequest |
struct | SetupMountNamespaceRequest |
struct { vm_id: VmId; role_id: RoleId; tracing_span_id: Option<TracingSpanId> } |
UpdateHostsFileRequest |
struct | UpdateHostsFileRequest |
struct { bundle_hosts_intent_ref: BundleOpId; destroy: bool; tracing_span_id: Option<TracingSpanId> } |
UsbipBindRequest |
struct | UsbipBindRequest |
struct { bundle_usbip_bind_intent_ref: BundleOpId; tracing_span_id: Option<TracingSpanId> } |
UsbipBindFirewallRuleRequest |
struct | UsbipBindFirewallRuleRequest |
struct { bundle_usbip_firewall_intent_ref: BundleOpId; tracing_span_id: Option<TracingSpanId> } |
UsbipProxyReconcileRequest |
struct | UsbipProxyReconcileRequest |
struct { scope_id: ScopeId; tracing_span_id: Option<TracingSpanId> } |
UsbipUnbindRequest |
struct | UsbipUnbindRequest |
struct { bundle_usbip_bind_intent_ref: BundleOpId; preserve_durable_claim: bool; tracing_span_id: Option<TracingSpanId> } |
UsbipExplicitBindRequest |
struct | UsbipExplicitBindRequest |
struct { bus_id: String; vm: String; env: String; tracing_span_id: Option<TracingSpanId> } |
UsbipExplicitFirewallRuleRequest |
struct | UsbipExplicitFirewallRuleRequest |
struct { bus_id: String; env: String; host_uplink_ip: String; net_uplink_ip: String; tracing_span_id: Option<TracingSpanId> } |
SignalRunnerRequest |
struct | SignalRunnerRequest |
struct { vm_id: VmId; role_id: RoleId; signal: RunnerSignal; pid: Option<i32>; expected_start_time_ticks: Option<u64>; tracing_span_id: Option<TracingSpanId> } |
DeregisterRunnerPidfdRequest |
struct | DeregisterRunnerPidfdRequest |
struct { vm_id: VmId; role_id: RoleId; tracing_span_id: Option<TracingSpanId> } |
SpawnRunnerRequest |
struct | SpawnRunnerRequest |
struct { vm_id: VmId; role_id: RoleId; role: RunnerRole; bundle_runner_intent_ref: BundleOpId; runtime_allocations: Vec<RunnerAllocation>; tracing_span_id: Option<TracingSpanId>; workload_identity: Option<WorkloadIdentity> } |
SeedDnsmasqLeaseRequest |
struct | SeedDnsmasqLeaseRequest |
struct { vm_id: VmId; scope_id: ScopeId; tracing_span_id: Option<TracingSpanId> } |
BindMountFromHardlinkFarmRequest |
struct | BindMountFromHardlinkFarmRequest |
struct { vm_id: VmId; bundle_store_view_intent_ref: Option<BundleOpId>; tracing_span_id: Option<TracingSpanId> } |
OwnershipMatrixCheckRequest |
struct | OwnershipMatrixCheckRequest |
struct { vm_id: VmId; tracing_span_id: Option<TracingSpanId> } |
SshHostKeyPreflightRequest |
struct | SshHostKeyPreflightRequest |
struct { vm_id: VmId; tracing_span_id: Option<TracingSpanId> } |
ReconcileStorageScopeRequest |
struct | ReconcileStorageScopeRequest |
struct { storage_ref: BundleOpId; apply: bool; tracing_span_id: Option<TracingSpanId> } |
ValidateLockSpecRequest |
struct | ValidateLockSpecRequest |
struct { lock_ref: BundleOpId; tracing_span_id: Option<TracingSpanId> } |
DiskInitRequest |
struct | DiskInitRequest |
struct { vm_id: VmId; tracing_span_id: Option<TracingSpanId> } |
ConsoleOp and AudioOp are staged runtime public wire types committed to
d2b-contracts and included in the auto-generated tables above. d2bd
dispatches both op families; the design is governed by
ADR 0041.
See provider capability matrix for the
per-provider behavior each op implements.
The implemented surface contracts are:
ConsoleOp— Attach, Detach, ReadOutput.ReadOutputresponses include ring-buffer cursor metadata so clients can detect dropped output and fast-forward cleanly. Console bytes are never logged, audited, or used as metric labels.AudioOp— GetState, SetMic, SetSpeaker, SetOff, Status.Statusreturns per-targetAudioProviderResultstructs so one misconfigured provider does not fail the entire multi-target query. Volume and gain values are bounded0..=100domain integers validated at the wire boundary. Host PipeWire enforcement and guestdAudioSet/AudioStatusintegration reporthost-and-guestonly after both live enforcement paths complete; qemu-media reports the intentionalhost-onlyposture because guest enforcement is unsupported there.
Both ops follow the standard PublicRequest/PublicResponse framing;
see the auto-generated tables above for the committed Rust variants.
| Type | Kind | Rust definition | Shape |
|---|---|---|---|
PublicResponse |
enum | PublicResponse |
Capabilities — (CapabilitiesResponse); AuthStatus — (AuthStatusResponse); List — (ListResponse); Status — (StatusResponse); Audit — (AuditResponse); HostCheck — (HostCheckResponse); KeysList — (KeysListResponse); KeysShow — (KeysShowResponse); UsbipProbe — (UsbipProbeResponse); StoreVerify — (StoreVerifyResponse); MutatingVerb — (MutatingVerbResponse); ReadGuestConfig — (ReadGuestConfigResponse); Exec — (ExecOpResponse); Shell — (ShellOpResponse); Console — (ConsoleOpResponse); Audio — (AudioOpResponse); GatewayDisplay — (GatewayDisplayOpResponse); Workload — (WorkloadOpResponse); UsbSecurityKeyStatus — (crate::security_key::SecurityKeyStatusResponse); UsbSecurityKeySessions — (crate::security_key::SecurityKeySessionsResponse); UsbSecurityKeyCancel — (crate::security_key::SecurityKeyCancelResponse); Error — (Error) |
WorkloadOpResponse |
enum | WorkloadOpResponse |
List — (WorkloadListResult); Status — (Box); LauncherExec — (LauncherExecResult) |
GatewayDisplayOpResponse |
enum | GatewayDisplayOpResponse |
Start — (GatewayDisplayStartResult); Stop — (GatewayDisplayStopResult); Open — (GatewayDisplayOpenResult); Close — (GatewayDisplayCloseResult); List — (GatewayDisplayListResult); ListDetailed — (GatewayDisplayListDetailedResult) |
ReadGuestConfigResponse |
struct | ReadGuestConfigResponse |
struct { content_base64: String } |
ExecOpResponse |
enum | ExecOpResponse |
Start — (ExecStartResult); DetachedCreate — (ExecDetachedCreateResult); WriteStdin — (ExecWriteStdinResult); ReadOutput — (ExecReadOutputResult); Signal — (ExecControlResult); Resize — (ExecControlResult); Wait — (ExecWaitResult); Close — (ExecCloseResult); List — (ExecDetachedListResult); Logs — (ExecDetachedLogsResult); Status — (ExecDetachedStatusResult); Kill — (ExecDetachedKillResult) |
ShellOpResponse |
enum | ShellOpResponse |
Attach — (ShellAttachResult); WriteStdin — (crate::terminal_wire::TerminalWriteStdinResult); ReadOutput — (crate::terminal_wire::TerminalReadOutputChunk); Resize — (crate::terminal_wire::TerminalControlResult); Wait — (crate::terminal_wire::TerminalWaitResult); CloseStdin — (crate::terminal_wire::TerminalCloseResult); CloseAttach — (ShellDetachResult); List — (ShellListResult); Detach — (ShellDetachResult); Kill — (ShellKillResult) |
ConsoleOpResponse |
enum | ConsoleOpResponse |
Attach — (ConsoleAttachResult); WriteStdin — (ConsoleControlResult); ReadOutput — (ConsoleReadOutputResult); Resize — (ConsoleControlResult); Wait — (ConsoleWaitResult); Close — (ConsoleCloseResult) |
AudioOpResponse |
enum | AudioOpResponse |
Status — (AudioStatusResult); SetVolume — (AudioSetResult); Mute — (AudioSetResult) |
MutatingVerbResponse |
struct | MutatingVerbResponse |
struct { verb: String; outcome: MutatingVerbOutcome; target_wave: Option<String>; summary: Option<String>; remediation: Option<String>; api_ready: Option<String> } |
CapabilitiesResponse |
struct | CapabilitiesResponse |
struct { broker_socket: String; capabilities: Vec<FeatureFlag>; public_socket: String; server_version: Version; selected_version: Version } |
AuthStatusResponse |
struct | AuthStatusResponse |
struct { allowed_subcommands: Vec<String>; denied_subcommands: Vec<DeniedCommandHint>; role: AuthRole; sockets: Vec<SocketReachability> } |
ListResponse |
struct | ListResponse |
struct { vms: Vec<ListEntry>; read_model: Option<PublicReadModelMetadata> } |
StatusResponse |
struct | StatusResponse |
struct { entries: Vec<VmStatus>; read_model: Option<PublicReadModelMetadata> } |
AuditResponse |
struct | AuditResponse |
struct { entries: Vec<AuditEntry> } |
HostCheckResponse |
struct | HostCheckResponse |
struct { exit_code: u8; findings: Vec<HostFinding> } |
KeysListResponse |
struct | KeysListResponse |
struct { entries: Vec<KeyEntry> } |
KeysShowResponse |
struct | KeysShowResponse |
struct { vm: String; env: Option<String>; managed_key_path: String; public_key: String; fingerprint: String; known_hosts_entry: Option<String> } |
UsbipProbeResponse |
struct | UsbipProbeResponse |
struct { entries: Vec<UsbipProbeEntry> } |
UsbSecurityKeyStatusResponse |
struct | UsbSecurityKeyStatusResponse |
struct { host_proxy_enabled: bool; physical_keys: Vec<UsbSkPhysicalKeyStatus>; vm_devices: Vec<UsbSkVirtualDeviceStatus>; lease: UsbSkLeaseStatus } |
UsbSecurityKeySessionsResponse |
struct | UsbSecurityKeySessionsResponse |
struct { sessions: Vec<UsbSkSession> } |
UsbSecurityKeyCancelResponse |
struct | UsbSecurityKeyCancelResponse |
struct { cancelled_session_id: Option<String>; already_idle: bool } |
UsbSecurityKeyTestResponse |
struct | UsbSecurityKeyTestResponse |
struct { vm: String; ok: bool; checks: Vec<UsbSkTestCheck> } |
| Type | Kind | Rust definition | Shape |
|---|---|---|---|
RunHostInstallResponse |
struct | RunHostInstallResponse |
struct { installed: bool; enabled: bool; started: bool; artifacts_written: Vec<String> } |
RunMigrateResponse |
struct | RunMigrateResponse |
struct { migrated_vm_count: u32; notes: Vec<String> } |
RunActivationResponse |
struct | RunActivationResponse |
struct { mode: ActivationMode; vm: String; generation_number: Option<u64>; guest_switch_script_path: Option<String>; summary: String } |
RunGcResponse |
struct | RunGcResponse |
struct { keep_generations: Option<u32>; retained_store_path_count: u32; summary: String } |
RunKeysRotateResponse |
struct | RunKeysRotateResponse |
struct { vm: String; key_path: String; public_key_fingerprint: String } |
RunHostKeyTrustResponse |
struct | RunHostKeyTrustResponse |
struct { vm: String; static_ip: String; known_hosts_path: String; updated: bool } |
RunRotateKnownHostResponse |
struct | RunRotateKnownHostResponse |
struct { vm: String; static_ip: String; known_hosts_path: String; removed: bool } |
BrokerResponse |
enum | BrokerResponse |
Ack — (AckResponse); CreatePersistentTap — (TapReadyResponse); CreateTapFd — (TapReadyResponse); Error — (BrokerErrorResponse); ExportBrokerAudit — (ExportBrokerAuditResponse); RunHostInstall — (RunHostInstallResponse); RunMigrate — (RunMigrateResponse); RunActivation — (RunActivationResponse); RunGc — (RunGcResponse); RunKeysRotate — (RunKeysRotateResponse); RunHostKeyTrust — (RunHostKeyTrustResponse); RunRotateKnownHost — (RunRotateKnownHostResponse); Hello — (HelloResponse); GuestControlSign — (GuestControlSignResponse); QemuMediaEnroll — (QemuMediaEnrollResponse); QemuMediaRefreshRegistry — (QemuMediaRefreshRegistryResponse); QemuMediaBoot — (QemuMediaHotplugResponse); QemuMediaSystemPowerdown — (QemuMediaLifecycleResponse); QemuMediaQueryStatus — (QemuMediaQueryStatusResponse); QemuMediaQuit — (QemuMediaLifecycleResponse); QemuMediaAttach — (QemuMediaHotplugResponse); QemuMediaDetach — (QemuMediaHotplugResponse); OpenHidrawSecurityKey — (OpenHidrawSecurityKeyResponse); OpenPidfd — (OpenPidfdResponse); PollChildReaped — (PollChildReapedResponse); ReconcileStorageScope — (ReconcileStorageScopeResponse); SetBridgePortFlags — (BridgePortFlagsResponse); SignalRunner — (SignalRunnerResponse); DeregisterRunnerPidfd — (DeregisterRunnerPidfdResponse); SpawnRunner — (SpawnRunnerResponse); StoreSync — (StoreSyncResponse); StoreVerify — (StoreVerifyResponse); ValidateLockSpec — (ValidateLockSpecResponse); ValidateBundle — (ValidateBundleResponse) |
BrokerErrorResponse |
struct | BrokerErrorResponse |
struct { kind: String; operation: String; target_wave: Option<String>; message: String; action: String } |
HelloResponse |
struct | HelloResponse |
struct { server_version: String; selected_version: String; capabilities: Vec<String> } |
GuestControlSignResponse |
struct | GuestControlSignResponse |
struct { tag: Vec<u8> } |
QemuMediaEnrollResponse |
struct | QemuMediaEnrollResponse |
struct { vm_id: VmId; media_ref: MediaRef; read_only: bool; enrolled: bool; udev_rule_written: bool; udev_reloaded: bool } |
QemuMediaRefreshRegistryResponse |
struct | QemuMediaRefreshRegistryResponse |
struct { record_count: u32; redacted_index_written: bool; udev_rule_written: bool; udev_reloaded: bool } |
QemuMediaLifecycleResponse |
struct | QemuMediaLifecycleResponse |
struct { vm_id: VmId; command: QemuMediaLifecycleAction } |
QemuMediaQueryStatusResponse |
struct | QemuMediaQueryStatusResponse |
struct { vm_id: VmId; status: QemuMediaVmStatus } |
QemuMediaHotplugResponse |
struct | QemuMediaHotplugResponse |
struct { vm_id: VmId; media_ref: MediaRef; slot: String; read_only: bool; qmp_commands: Vec<String>; events: Vec<QemuMediaHotplugEvent> } |
OpenPidfdResponse |
struct | OpenPidfdResponse |
struct { vm_id: VmId; role_id: RoleId; pid: i32; verified_start_time_ticks: u64; pidfd_index: u32 } |
OpenHidrawSecurityKeyResponse |
struct | OpenHidrawSecurityKeyResponse |
struct { selector_resolved: String; device_class: String } |
StoreSyncResponse |
struct | StoreSyncResponse |
struct { vm: String; generation_id: String; generation_token: u32; hardlink_farm_path: String; closure_count: u32; retained_generations: Vec<u32>; swept_count: u32; cleanup_deferred: bool } |
StoreVerifyResponse |
struct | StoreVerifyResponse |
struct { vm: String; status: StoreVerifyStatus; checked: u32; drifted: u32; repaired: u32; unknown_reason: Option<StoreVerifyUnknownReason>; audit_ref: Option<String>; remediation: Option<String> } |
AckResponse |
struct | AckResponse |
struct { accepted: bool; operation: String } |
TapReadyResponse |
struct | TapReadyResponse |
struct { bridge: Option<IfName>; tap: IfName } |
ExportBrokerAuditResponse |
struct | ExportBrokerAuditResponse |
struct { lines: Vec<String> } |
BridgePortFlagsResponse |
struct | BridgePortFlagsResponse |
struct { bridge: IfName; isolated: bool; neigh_suppress: bool; port: IfName } |
ValidateBundleResponse |
struct | ValidateBundleResponse |
struct { valid: bool } |
SignalRunnerResponse |
struct | SignalRunnerResponse |
struct { signaled: bool; vm_id: VmId; role_id: RoleId } |
DeregisterRunnerPidfdResponse |
struct | DeregisterRunnerPidfdResponse |
struct { vm_id: VmId; role_id: RoleId; removed: bool } |
SpawnRunnerResponse |
struct | SpawnRunnerResponse |
struct { vm_id: VmId; role_id: RoleId; role: RunnerRole; pid: i32; start_time_ticks: u64; pidfd_index: u32; console_fd_index: Option<u32> } |
ReconcileStorageScopeResponse |
struct | ReconcileStorageScopeResponse |
struct { storage_ref: BundleOpId; scope: String; kind: String; status: StorageReconcileStatus; applied: bool; path_hash: String } |
ValidateLockSpecResponse |
struct | ValidateLockSpecResponse |
struct { lock_ref: BundleOpId; scope: String; kind: String; cloexec_required: bool; fd_passing_mechanism: String; order_key: String } |
PollChildReapedResponse |
struct | PollChildReapedResponse |
struct { notifications: Vec<ChildReapedNotification> } |
The VM lifecycle enum is frozen so supervisor work can reuse it without a wire break. The public state surface distinguishes:
StoppedStartingBootedRunningStoppingRestartingFailedUnknown
pendingRestart is a derived boolean carried forward from the
v0.4.0 bash CLI: it means the VM is running, booted exists,
current exists, and the two store paths differ. It is not a separate
state-machine node.
lifecycle.degraded and lifecycle.degradedReasons[] surface bounded
daemon-degraded conditions that require operator attention without
inventing a new lifecycle state. VM activation uses reason
activation-pending while a crash-consistent host marker says an
activation was in progress, and activation-indeterminate when guest
activation may have completed but host metadata commit has not been
proven. Remediation text is bounded and never includes guest output,
store paths, or activation command arguments.
Stop and restart requests accept a serde-defaulted force flag. When
force = false, d2bd applies the VM's manifest
lifecycle.gracefulShutdown policy: supported local providers receive a
bounded graceful guest-shutdown request before VMM pidfd cleanup. When
force = true, d2bd records explicit operator intent and skips only the
provider graceful wait; it still uses the standard SIGTERM/SIGKILL cleanup
policy rather than jumping directly to SIGKILL. Restart applies force to the
stop phase only.
The public activation requests (Switch, Test, Rollback, and
Boot) are daemon-owned operations. The generated request/response
tables below describe the currently committed wire shapes; when the
activation wire types change, regenerate the AUTO-GENERATED sections
with cargo xtask gen-daemon-api rather than editing those blocks by
hand.
Live activation (Switch, Test, and live Rollback) is not a broker
script-execution surface. d2bd prepares the VM toplevel, asks the
broker/store-view path to publish the closure into the per-VM live store
pool, opens authenticated guest-control to guestd, starts activation of
the prepared toplevel inside the running guest, polls guest activation
status, and only then asks the broker to commit host-owned generation
metadata. If the VM is stopped/offline or guestd does not advertise the
activation capability, the operation fails closed before host-side
generation commit.
Boot is the explicit offline staging mode. It publishes and commits
the declared toplevel for the next VM start without contacting guestd or
running live guest activation.
| Type | Kind | Rust definition | Shape |
|---|---|---|---|
VmLifecycleState |
enum | VmLifecycleState |
Stopped; Starting; Booted; Running; Stopping; Restarting; Failed; Unknown |
| Type | Kind | Rust definition | Shape |
|---|---|---|---|
ActivationMode |
enum | ActivationMode |
Switch; Boot; Test; Rollback |
ActivationPhase |
enum | ActivationPhase |
Prepare; Commit; MetadataOnly |
GuestControlProofRole |
enum | GuestControlProofRole |
HostProof; GuestProof |
GuestControlDirection |
enum | GuestControlDirection |
HostToGuest |
GuestControlAuthPurpose |
enum | GuestControlAuthPurpose |
GuestControlAuthV1 |
QemuMediaLifecycleAction |
enum | QemuMediaLifecycleAction |
SystemPowerdown; Quit |
QemuMediaVmStatus |
enum | QemuMediaVmStatus |
Running; Paused; Shutdown; Suspended; Watchdog; Debug; Inmigrate; InternalError; IoError; Postmigrate; Prelaunch; FinishMigrate; RestoreVm; SaveVm; GuestPanicked; Colo; Preconfig; Unknown; ConnectionLostDuringShutdown |
QemuMediaHotplugStatus |
enum | QemuMediaHotplugStatus |
IdentityResolved; QmpConnected; QmpCapabilities; FdAdded; BlockdevAdded; DeviceAdded; DeviceDeleted; BlockdevDeleted; FdRemoved; VmContinued |
StoreVerifyStatus |
enum | StoreVerifyStatus |
Ok; Drift; Unknown; Repaired; Failed; NotFound |
StoreVerifyUnknownReason |
enum | StoreVerifyUnknownReason |
MarkerOrManifestMissing; MarkerOrManifestUnreadable; OlderHostGeneration; GenerationIdentityUnavailable |
RunnerSignal |
enum | RunnerSignal |
Term; Kill; Quit |
RunnerRole |
enum | RunnerRole |
CloudHypervisor; QemuMedia; Virtiofsd; Swtpm; SwtpmFlush; Gpu; Audio; Video; VsockRelay; Usbip; OtelHostBridge; WaylandProxy |
RunnerAllocationKind |
enum | RunnerAllocationKind |
VsockCid; TapFdSlot; ApiSocketPath |
BrokerCallerRole |
enum | BrokerCallerRole |
AdminUid — struct { uid: u32 }; LauncherUid — struct { uid: u32 }; RootUid — struct { uid: u32 }; NotAuthorized |
StorageReconcileStatus |
enum | StorageReconcileStatus |
Clean; Created; Reused; CheckedOnly; TemplateUnexpanded; Refused |
ChildExitKind |
enum | ChildExitKind |
Exited; Signaled; Killed |
BrokerNotification |
enum | BrokerNotification |
ChildReaped — (ChildReapedNotification); Unknown |
AuthDirection |
enum | AuthDirection |
HostToGuest |
AuthPurpose |
enum | AuthPurpose |
GuestControlAuthV1 |
ProofRole |
enum | ProofRole |
Host; Guest |
GuestCapability |
enum | GuestCapability |
Health; Capabilities; ExecAttached; ExecDetached; ExecTty; ExecLogs; TtyResize; Signals; ReadGuestFile; UsbipImport; ShellAttached; ShellManagement; ShellForceAttach; UsbipStatus; SystemActivation; AudioStatus; AudioSet |
GuestFileId |
enum | GuestFileId |
GuestConfig |
GuestSubsystem |
enum | GuestSubsystem |
Guestd; Userd; Exec; LogStorage; Token; Vsock; Usbip; Shell; Shpool; SystemActivation; Audio |
TerminalKind |
enum | TerminalKind |
Exec; Shell |
ShellState |
enum | ShellState |
Attached; Detached; Killed; PoolUnavailable; FeatureDisabled; OutputGap |
ShellCloseCause |
enum | ShellCloseCause |
ClientDetach; EvictedByForce; EvictedByAdminDetach; KilledByAdmin; PoolUnavailable; OutputGap |
HealthOrigin |
enum | HealthOrigin |
GuestReported; HostSynthesized |
GuestVsockDirection |
enum | GuestVsockDirection |
HostToGuest |
GuestIdentityBinding |
enum | GuestIdentityBinding |
VmIdCidPortAndTokenTranscript |
GuestTransportKind |
enum | GuestTransportKind |
VirtioVsockTtrpc |
GuestConnectAckValue |
enum | GuestConnectAckValue |
OpaqueLocalPort |
HealthState |
enum | HealthState |
Healthy; Degraded; UnavailableOldGeneration; ListenerAbsent; TransportUnreachable; AuthFailed; ProtocolMismatch; StaleSession |
HealthReason |
enum | HealthReason |
None; OldGeneration; ListenerAbsent; ConnectRefused; ConnectTimeout; EofBeforeAck; MalformedAck; AckTooLong; TransportIo; AuthTokenRejected; ProtocolVersionUnsupported; SessionGenerationMismatch; ExecSubsystemUnavailable; LogStorageUnavailable; QuotaExceeded; RateLimited; InternalHealthCheckFailed |
HealthRemediation |
enum | HealthRemediation |
None; Retry; RestartVm; UpgradeGuest; CheckAuthToken; CheckGuestdService; ReduceLoad; InspectGuestLogs |
GuestActivationMode |
enum | GuestActivationMode |
Switch; Boot; Test; DryActivate |
GuestActivationState |
enum | GuestActivationState |
Running; Succeeded; Failed; TimedOut; Lost |
UsbipImportAction |
enum | UsbipImportAction |
Attach; Detach |
AudioSetKind |
enum | AudioSetKind |
Grant; Level |
AudioChannel |
enum | AudioChannel |
Microphone; Speaker |
OutputStream |
enum | OutputStream |
Stdout; Stderr |
WriteDisposition |
enum | WriteDisposition |
Accepted; Duplicate; Rejected |
ExecState |
enum | ExecState |
Created; Running; Exited; Signaled; Cancelled; SlowConsumerCancelled; ProtocolError; LostGuestd; Reaped |
StdinState |
enum | StdinState |
Open; Closing; Closed; ClosedByProcess; RejectedNotInteractive |
TerminalStatus |
enum | TerminalStatus |
ExitCode — struct { exit_code: i32 }; Signal — struct { signal: u32 }; StatusCode — struct { status_code: i32 }; Error — struct { error: GuestControlErrorKind } |
SignalTarget |
enum | SignalTarget |
ForegroundProcessGroup; ProcessTree |
ExecCancelReason |
enum | ExecCancelReason |
ClientDisconnect; UserRequested; SlowConsumer; ProtocolError |
KnownFeatureFlag |
enum | KnownFeatureFlag |
TypedErrors; ManifestV04; StatusCheckBridges; ExportBrokerAudit; ConfiguredLaunchV1; UnsafeLocalProviderV1; UnsafeLocalShellV1 |
WorkloadOp |
enum | WorkloadOp |
List — (WorkloadListArgs); Status — (WorkloadStatusArgs); LauncherExec — (LauncherExecArgs) |
WorkloadAvailability |
enum | WorkloadAvailability |
Ready; HelperUnavailable; HelperStale; UserManagerUnavailable; GraphicalSessionInactive; WaylandUnavailable; ProxyUnavailable; Degraded |
GraphicalLaunchPosture |
enum | GraphicalLaunchPosture |
Proxied; NotApplicable; GraphicalSessionInactive; WaylandUnavailable; ProxyUnavailable |
LauncherExecDisposition |
enum | LauncherExecDisposition |
Committed; AlreadyCommitted |
GatewayDisplayOp |
enum | GatewayDisplayOp |
Start — (GatewayDisplayStartArgs); Stop — (GatewayDisplayStopArgs); Open — (GatewayDisplayOpenArgs); Close — (GatewayDisplayCloseArgs); List — (GatewayDisplayListArgs); ListDetailed — (GatewayDisplayListArgs) |
ExecStream |
enum | ExecStream |
Stdout; Stderr |
ExecOp |
enum | ExecOp |
Start — (ExecStartArgs); WriteStdin — (ExecWriteStdinArgs); ReadOutput — (ExecReadOutputArgs); Signal — (ExecSignalArgs); Resize — (ExecResizeArgs); Wait — (ExecWaitArgs); Close — (ExecCloseArgs); List — (ExecDetachedListArgs); Logs — (ExecDetachedLogsArgs); Status — (ExecDetachedStatusArgs); Kill — (ExecDetachedKillArgs) |
ExecTerminalStatus |
enum | ExecTerminalStatus |
Exited — struct { code: i32 }; Signaled — struct { signal: u32 }; Error — struct { slug: String } |
ExecDetachedKillOutcome |
enum | ExecDetachedKillOutcome |
Cancelling; AlreadyTerminal |
ShellOp |
enum | ShellOp |
Attach — (ShellAttachArgs); WriteStdin — (crate::terminal_wire::TerminalWriteStdin); ReadOutput — (crate::terminal_wire::TerminalReadOutput); Resize — (crate::terminal_wire::TerminalResize); Wait — (crate::terminal_wire::TerminalWait); CloseStdin — (crate::terminal_wire::TerminalClose); CloseAttach — (ShellCloseAttachArgs); List — (ShellListArgs); Detach — (ShellDetachArgs); Kill — (ShellKillArgs) |
ShellSessionState |
enum | ShellSessionState |
Attached; Detached; Killed; PoolUnavailable; FeatureDisabled; OutputGap |
ShellCloseCause |
enum | ShellCloseCause |
ClientDetach; EvictedByForce; EvictedByAdminDetach; KilledByAdmin; PoolUnavailable; OutputGap |
ConsoleProviderKind |
enum | ConsoleProviderKind |
LocalHypervisor; QemuMedia; AcaSandbox |
ConsoleOp |
enum | ConsoleOp |
Attach — (ConsoleAttachArgs); WriteStdin — (ConsoleWriteStdinArgs); ReadOutput — (ConsoleReadOutputArgs); Resize — (ConsoleResizeArgs); Wait — (ConsoleWaitArgs); Close — (ConsoleCloseArgs) |
AudioChannel |
enum | AudioChannel |
Speaker; Microphone |
AudioEnforcementPosture |
enum | AudioEnforcementPosture |
HostAndGuest; HostOnly; GuestOnly; Unsupported |
AudioProviderKind |
enum | AudioProviderKind |
LocalHypervisor; QemuMedia; AcaSandbox |
AudioOp |
enum | AudioOp |
Status — (AudioStatusArgs); SetVolume — (AudioSetVolumeArgs); Mute — (AudioMuteArgs) |
AudioSetApplied |
enum | AudioSetApplied |
HostAndGuest; HostOnly; GuestOnly; Unsupported |
MutatingVerbOutcome |
enum | MutatingVerbOutcome |
DryRunPlanned; Applied; ApiReadyTimeout; NotYetImplemented; BrokerError; InvalidRequest |
UsbipProbeStatus |
enum | UsbipProbeStatus |
Bound; Unbound; Degraded; Enrollable; Enrolled; Stale; DirectConfig; Unknown |
UsbipDurableClaimState |
enum | UsbipDurableClaimState |
Missing; HeldByDesiredOwner; HeldByOtherOwner; StaleOwner; Corrupt; NotApplicable; Unknown |
UsbipHostBindState |
enum | UsbipHostBindState |
Unbound; BoundToUsbipHost; BoundToUnexpectedDriver; DeviceMissing; NotApplicable; Unknown |
UsbipHostCarrierState |
enum | UsbipHostCarrierState |
Absent; Unavailable; WithheldForOwner; Ready; DepartedDuringProbe; NotApplicable; Unknown |
UsbipProxyState |
enum | UsbipProxyState |
NotDeclared; Stopped; Starting; Listening; Stale; Failed; NotApplicable; Unknown |
UsbipGuestImportState |
enum | UsbipGuestImportState |
Detached; Imported; Unavailable; NotApplicable; Unknown |
UsbipTopologyState |
enum | UsbipTopologyState |
Match; Mismatch; Incomplete; NotObserved; NotApplicable; Unknown |
UsbipPolicyState |
enum | UsbipPolicyState |
Allowed; Denied; Missing; NotApplicable; Unknown |
UsbipProbeDegradedReasonCode |
enum | UsbipProbeDegradedReasonCode |
PolicyFailed; DeviceDepartedBeforeClaim; DeviceDepartedAfterLock; DeviceDepartedDuringMutation; DeviceReappearedWithDifferentTopology; LockHeldByOtherOwner; InvalidPersistedLockClaim; CarrierUnavailable; HostBindUnavailable; ProxyUnavailable; GuestImportUnavailable; StaleHostState; StaleGuestState; ProbeIncomplete; Unknown |
UsbProbeEntryKind |
enum | UsbProbeEntryKind |
Usbip; QemuMediaSlot |
AuditFormat |
enum | AuditFormat |
Human; Json |
AuthRole |
enum | AuthRole |
None; Launcher; Admin |
HostFindingSeverity |
enum | HostFindingSeverity |
Pass; Warn; Fail |
UsbSkLeaseState |
enum | UsbSkLeaseState |
Idle; Active; Queued; Unknown |
UsbSkSessionOutcome |
enum | UsbSkSessionOutcome |
Success; Timeout; Cancelled; DeviceUnavailable; Active; Unknown |
SecurityKeyVmSessionState |
enum | SecurityKeyVmSessionState |
Idle; AwaitingLease; Active; Completed; Cancelled |
SecurityKeySessionResult |
enum | SecurityKeySessionResult |
InProgress; Success; CtapError; Timeout; Cancelled; InternalError |
SecurityKeyEvent |
enum | SecurityKeyEvent |
SessionStarted — struct { session_id: SecurityKeySessionId; vm: String; device_label: SecurityKeyDeviceLabel; started_at: String }; SessionSucceeded — struct { session_id: SecurityKeySessionId; vm: String; device_label: SecurityKeyDeviceLabel; ended_at: String }; SessionFailed — struct { session_id: SecurityKeySessionId; vm: String; device_label: SecurityKeyDeviceLabel; result: SecurityKeySessionResult; ended_at: String }; SessionCancelled — struct { session_id: SecurityKeySessionId; vm: String; device_label: SecurityKeyDeviceLabel; ended_at: String }; DeviceRemoved — struct { device_label: SecurityKeyDeviceLabel; interrupted_session_id: Option<SecurityKeySessionId> }; DeviceReinserted — struct { device_label: SecurityKeyDeviceLabel }; SessionQueued — struct { session_id: SecurityKeySessionId; vm: String; device_label: SecurityKeyDeviceLabel; queued_at: String; blocking_vm: String } |
TerminalStream |
enum | TerminalStream |
Stdout; Stderr |
TerminalStatus |
enum | TerminalStatus |
Exited — struct { code: i32 }; Signaled — struct { signal: u32 }; Error — struct { slug: String } |
PathClass |
enum | PathClass |
Vm; Runtime |
HelperScopeKind |
enum | HelperScopeKind |
LauncherApp; WaylandProxy; PersistentShell |
HelperScopeState |
enum | HelperScopeState |
Starting; Active; Stopping; Exited; Degraded |
HelperFailureCode |
enum | HelperFailureCode |
InvalidRequest; OperationIdConflict; QueueFull; Timeout; UserManagerUnavailable; EnvironmentInvalid; ExecutableUnavailable; ScopeCreateFailed; ScopeIdentityMismatch; GraphicalSessionInactive; WaylandUnavailable; ProxyUnavailable; FirstClientTimeout; ShellUnavailable; ShellNotFound; ShellAlreadyAttached; TerminalOutputGap; TerminalOffsetMismatch; TerminalClosed; InvalidTerminalSize; Internal |
HelperOperationDisposition |
enum | HelperOperationDisposition |
Committed; AlreadyCommitted; Completed |
HelperTerminalTransport |
enum | HelperTerminalTransport |
ConnectedUnixStream |
DaemonToUnsafeLocalHelper |
enum | DaemonToUnsafeLocalHelper |
HelloAccepted — (HelperHelloAccepted); Heartbeat — (HelperHeartbeat); Launch — (HelperLaunchRequest); Shell — (HelperShellRequest) |
UnsafeLocalHelperToDaemon |
enum | UnsafeLocalHelperToDaemon |
Hello — (HelperHello); Snapshot — (HelperSnapshot); Heartbeat — (HelperHeartbeat); Operation — (HelperOperationResult); TerminalReady — (HelperTerminalReady); Shell — (HelperShellResponse); Rejected — (HelperOperationRejected) |
UsbipClaimSource |
enum | UsbipClaimSource |
Declared — struct { firewall_ref: String; bind_ref: String }; Explicit |
Every public daemon-API failure (Hello, host check, audit, status, broker dispatch, etc.) uses the same redacted typed envelope:
{
"kind": "...",
"code": 42,
"message": "...",
"remediation": "...",
"docsAnchor": "...",
"owningCommand": "..."
}This is the shape emitted by d2bd, the broker, and the wire
layer; CLI surfaces that proxy daemon-API responses deserialize and
re-render it.
The CLI host-verb skeletons (d2b host prepare, host destroy,
host doctor, host install) use a separate 7-field operator-UX
envelope documented in
error-codes.md.
That envelope is emitted by the CLI itself when it intercepts a
request before reaching the daemon (Tier-0 legacy refusals,
missing-flag usage errors, typed daemon-down /
not-yet-implemented envelopes per ADR 0015 v1.0 daemon-only).
Its anchors live in the same
error-codes.md catalog so both shapes resolve to a single source
of truth for docs_anchor/docsAnchor resolution; the two shapes
are tracked for future unification.
The redaction policy is strict:
- no host paths unless the path itself is already part of the stable public contract;
- no secrets, stack traces, credential material, or raw command output;
- no terminal payloads, argv/env/cwd, helper stderr/stdout, raw shell session handles, raw shell names, supervisor ids, unit names, or helper diagnostics in daemon metrics or broad debug/audit fields;
- one human-readable remediation hint per failure;
- one docs anchor into
error-codes.md.
owningCommand names the primary CLI subcommand or API surface that owns
the failure class, for example host check, audit, status, or
daemon-api/Hello.
| Type | Kind | Rust definition | Shape |
|---|---|---|---|
BrokerErrorResponse |
struct | BrokerErrorResponse |
struct { kind: String; operation: String; target_wave: Option<String>; message: String; action: String } |
GuestControlError |
struct | GuestControlError |
struct { kind: GuestControlErrorKind; remediation: HealthRemediation; retry_after_ms: Option<u64> } |
GuestControlErrorKind |
enum | GuestControlErrorKind |
ProtocolError; MaxChunkExceeded; StdinBackpressure; StdinClosed; StdinNotOpen; StdinClosedByProcess; StdinOffsetMismatch; StdinByteBudgetExhausted; OffsetExpired; OffsetInFuture; OffsetExhausted; OutputLost; TtyStderrUnavailable; TtyRequired; ExecCapacityExceeded; ExecAttachCapacityExceeded; ExecNotFound; ExecAlreadyExited; GuestExecDisabled; GuestExecRootDenied; GuestExecUserDenied; CwdInvalid; CwdDenied; RetainedLogPathUnsafe; RetainedLogQuotaExceeded; ReadWaitCapacityExceeded; WaitCapacityExceeded; SupersededReadWait; RateLimited; RequestIdConflict; ControlSeqMismatch; SlowConsumerCancelled; StaleSession; GuestControlUnavailableOldGeneration; AuthFailed; TransportUnreachable; ExecExpired; FileNotFound; FileTooLarge; PathUnsafe; ReadDenied; InvalidProgram; UsbipUnavailable; UsbipCommandFailed; UsbipInvalidBusId; UsbipInvalidHost; GuestShellDisabled; ShellInvalidName; ShellCapacityExceeded; ShellAttachCapacityExceeded; ShellNotFound; ShellAlreadyAttached; ShellPoolUnavailable; ShellDaemonEpochMismatch; ShellOutputGap; UsbipCommandTimeout; UsbipInvalidOutput; ActivationInvalidId; ActivationInvalidPath; ActivationInvalidMode; ActivationNotFound; ActivationStatusUnavailable; ActivationTimedOut; ActivationSpawnFailed; AudioPipeWireUnavailable; AudioChannelUnknown; AudioLevelOutOfRange; AudioEnforcementFailed |
ShellNameError |
struct | ShellNameError |
empty struct |
AudioErrorKind |
enum | AudioErrorKind |
ProviderMisconfigured; VmNotFound; EnforcementUnavailable; AudioNotEnabled; InternalError |
AudioVmError |
struct | AudioVmError |
struct { vm: String; kind: AudioErrorKind; remediation: Option<String> } |
BusIdError |
enum | BusIdError |
Empty; Invalid; TooLong — struct { max: usize } |
The broker is the only writer for the append-only audit log. Daily
rotation is in effect, and there is no legacy single-file path:
every record now lands in exactly one
per-date file under /var/lib/d2b/audit/:
- daily path:
/var/lib/d2b/audit/broker-<utc-date>.jsonl(e.g.broker-2026-05-28.jsonl) - mode:
0640 - owner/group:
root:d2bd - append-only via a pre-opened
O_APPENDfd held by the broker - retention: 14 days of daily files by default; override via
d2b.site.audit.retentionDays(set to0to disable pruning entirely). Reserved: the broker prune-on-rotate loop is shipping, but the NixOS module does not yet thread the option value through to the broker invocation (daemon-config.json→d2bd→ broker spawn args). Until then, the broker uses its 14-day default regardless of NixOS overrides.
Broker caller-role values such as peer_role = "d2b-launcher" are
stable audit/authz class labels, not Unix group names. See
naming-conventions.md § "Broker caller-role audit labels".
The audit CLI command does not read those files directly. Instead it
sends ExportBrokerAudit { since, filter } to d2bd over the
public socket. The daemon authorizes the caller against
d2b.site.adminUsers; if the caller is allowed, the daemon forwards
that request to the broker over /run/d2b/priv.sock and streams
back redacted log entries. The broker enumerates every
broker-YYYY-MM-DD.jsonl file in the audit directory in chronological
order, applies the since and filter substrings, and returns the
concatenated lines.
This keeps the read path narrow:
- non-root launchers never get direct file access;
- the daemon can read through the file's group permission as
d2bd; - the broker remains the only writer because it owns the append-only write fd and enforces write serialization internally.
Host shutdown stop requests are distinguishable from ordinary admin stops at
the daemon authorization layer. The systemd ExecStop hook connects as uid 0
and receives the narrow HostShutdown role; the daemon permits only vmStop
for that role and forwards the request to the broker with the normal lifecycle
audit path. Other admin-only daemon verbs remain denied for HostShutdown.
USBIP bind audit records may include deviceIdentity for privileged
forensics. That projection keeps raw serial descriptors out of the log:
VID/PID are normalized four-hex strings, serialObserved is boolean, and
serial correlation uses HMAC-SHA256 with broker-owned root-only key files under
${d2b.site.stateDir}/secrets/usb-audit-serial-hmac/. When previous.key
is present during the 30-day key-rotation grace window, the broker keeps both
key slots active and emits both correlations. The companion
UsbSerialCorrelationKeyRotate
audit/log shape carries only previousKeyId, currentKeyId,
activeKeyCount, graceWindowSeconds, and correlationVersion; it never
contains raw serials, key material, bus IDs, sysfs paths, or dynamic metric
labels. Key reload is per broker request, so non-root observability components
do not need systemd credentials or a key-read IPC path.
Retention. The broker now prunes
daily-rotated files older than d2b.site.audit.retentionDays
(default 14) on every day-boundary rotation in append_to_daily and
again on AuditLog::open so a long-stopped daemon catches up. Pruning
is best-effort — failures are logged but do not break the audit-write
path. Filename is the source of truth (broker-YYYY-MM-DD.jsonl); we
never parse JSON to inspect record timestamps. Non-matching artifacts
under audit/ (operator notes, export tarballs, etc.) are left alone.
Legacy retirement. The broker kept the historical
/var/lib/d2b/broker-audit.log single-file path as a read+write
compatibility shim while ExportBrokerAudit consumers and the
broker-export-audit.sh / broker-socket-acl.sh Layer-1 gates
migrated. The shim is dropped: both write paths (AuditEntry via
write_entry and OpAuditRecord via write_op_record) and the read
path (export_lines) operate solely against the daily files. The
broker serve CLI takes --audit-dir <path> instead of the prior
--audit-log-path flag.
Audit boundary. The broker audit log above is the local root-owned record for broker operations on this host. Any future gateway or realm aggregate audit (realm access events, provider operation records) is a separate record that lives inside the per-realm gateway guest VM, not in
/var/lib/d2b/audit/; a remote full-host node keeps its own broker/audit records on that node's local audit path (broker-mediated and node-owned), not in the gateway guest. Relay or realm identity never enters this local broker audit or auth path: the record's identity fields (e.g.peer_uid,authz_result) carry only the localSO_PEERCRED-derived classification, anddecisionis the local broker operation outcome.
d2bd also writes daemon-owned JSONL events for transitions that are
not broker operations, such as guest-control exec session establishment
and runner readiness failures. Those records live under the daemon state
directory as daemon-events-<utc-date>.jsonl. Each daemon record carries
bounded event metadata plus prev_hash and record_hash fields so a
verifier can detect missing, reordered, or modified lines. The hash-chain
helper reports tampering explicitly; the write path remains best-effort so
an audit sink outage does not abort an already-authorized local operation.
Persistent shell daemon events are in this daemon-owned stream, not the broker
audit log. The provider-neutral ShellLifecycle variant is the sole runtime
shell audit event for both guest-control and unsafe-local. It records only a
configured canonical target or local VM id, admin peer uid, closed
provider/action/result enums, optional force-takeover intent, and optional fixed
operation/session correlation digests. It covers create, attach, list, detach,
kill, close, and failure boundaries. Raw shell names, public handles,
supervisor ids, terminal bytes, helper diagnostics, argv, env,
cwd, PIDs, unit names, and paths are never written. Abrupt owner disconnects,
close timeouts, stale helper generations, and malformed terminal frames are
represented by closed results or typed-error buckets rather than free-form
text.
Graceful-shutdown daemon events also use this daemon-owned stream. Before a
normal stop sends CH vm.shutdown or broker-mediated QMP system_powerdown,
d2bd records bounded intent fields (vm, peer uid/authz class, provider,
timeout seconds, trigger). It records a final bounded outcome such as
clean_guest_shutdown, clean_vmm_cleanup, api_unavailable,
timeout_exceeded, or force_requested; raw provider HTTP/QMP payloads,
socket paths, command output, argv, and guest-controlled strings stay out of
audit records.
Daemon audit sink health is exposed as an explicit report rather than a
silent fallback. The report distinguishes writable, degraded, and
unavailable states, including retention-floor degradation. It intentionally
records only closed reason codes such as write-probe-failed or
retention-below-floor; it does not include filesystem paths, raw IO
errors, argv/env content, output bytes, provider credentials, or relay
tokens.
The protocol deliberately mixes strict shape checking with bounded feature negotiation:
- unknown feature flags are ignored during handshake negotiation;
- unknown fields in known message types are rejected;
- closed enums remain closed until a new negotiated version or explicit feature flag says otherwise;
- additive message types belong in a new negotiated protocol revision, not as undocumented fields on an old one.
The result is intentionally conservative: callers may discover new capabilities, but they do not get silent success from partially understood payloads.
v2 constellation protocol schemas. The v2 constellation peer-session, operation-routing, and stream protocol shapes are not yet published as reference
.mdor.jsoncontract files in this repository. Do not treat any draft field shape as a stable contract until the corresponding reference document is published.
On d2bd.service startup — after the pidfd-table is restored
from disk and orphan adoption has reconciled any leftover runners
from a previous instance — the daemon runs a single autostart pass
to bring per-env net VMs and workload VMs up in a controlled order.
See docs/reference/daemon-autostart.md for
the full contract (net VMs first, configurable concurrency cap,
degraded-mode tolerance, idempotent re-entry). The cap is
controlled by d2b.daemon.autostart.parallelism (default 3).
/etc/d2b/daemon-config.json carries both
autostartParallelism and gracefulShutdownTimeoutSeconds. The latter is the
daemon-wide default used when a v7 manifest entry has
lifecycle.gracefulShutdown.timeoutSeconds = null.