better/compute

Protocol

Every service, message and enum of the daemon protocol, from the .proto sources, with field numbers and types.

The wire contract between bcd, the gateway and drivers. It is frozen: changes are additive only (buf breaking), and messages and fields marked with a phase are part of the frozen shape before they are used. For the session flow, framing, renewal and the WebSocket fallback, see Protocol.

commands.proto

Package bettercompute.agent.v1, proto/bettercompute/agent/v1/commands.proto.

Payloads and results of the built-in v0.1 command kinds (PLAN.md §7.3). A Command carries the request in CommandBody.payload (google.protobuf.Any); the CommandUpdate carries the serialized result in result. The kind table (lane and flags) lives in @better-compute/protocol (commandKinds) and in the daemon's dispatcher; both must agree.

DiagNvmlRequest

FieldNumberTypeDescription
gpu_uuids1repeated stringGPUs to check; empty checks every GPU.
expected_gpu_count2uint32When non-zero, fewer visible GPUs fails the check "gpu.count".

DiagNvmlResult

FieldNumberTypeDescription
passed1boolEvery check on every GPU passed.
gpu_count2uint32GPUs visible to NVML.
driver_version3string
checks4repeated DiagnosticCheckNode-level checks, e.g. "nvml.init", "gpu.count".
gpus5repeated GpuDiagnosticSorted by uuid.

GpuDiagnostic

FieldNumberTypeDescription
uuid1string
passed2bool
checks3repeated DiagnosticChecke.g. "ecc.uncorrectable", "row-remap.pending", "row-remap.failure", "pcie.link", "xid.recent".

DiagnosticCheck

FieldNumberTypeDescription
name1string
passed2bool
message3string

InventoryRefreshRequest

FieldNumberTypeDescription
sections1repeated stringSection names to send; empty sends every section.
rescan2boolRe-collect from the hardware first instead of resending the last collection.

InventoryRefreshResult

FieldNumberTypeDescription
section_hashes1map of string to bytesSection name → SHA-256 of the section content as sent.

LogsCollectRequest

FieldNumberTypeDescription
upload_url1stringPresigned HTTPS PUT URL.
upload_headers2repeated HttpHeaderHeaders the presigned request requires.
units3repeated stringsystemd units; empty means bcd's own units.
lookback_seconds4uint32How far back to collect.
max_bytes5uint64Upload cap; the bundle is truncated (oldest first) beyond it.
support_bundle6boolInclude the support bundle (bcd status, doctor, journal metadata, inventory).

HttpHeader

FieldNumberTypeDescription
name1string
value2string

LogsCollectResult

FieldNumberTypeDescription
uploaded_bytes1uint64
sha2562bytesSHA-256 of the uploaded object.
truncated3bool
content_type4stringe.g. "application/zstd".

NodeRebootRequest

FieldNumberTypeDescription
reason1string
delay_ms2uint32Wait before rebooting (lets the CommandUpdate RUNNING reach the gateway).

NodeRebootResult

FieldNumberTypeDescription
previous_boot_id1stringThe boot that ran the command; CommandUpdate.boot_id is the new one.

GpuResetRequest

FieldNumberTypeDescription
gpu_uuids1repeated stringAt least one GPU; an empty list fails "invalid-payload".

GpuResetResult

FieldNumberTypeDescription
gpus1repeated GpuResetOutcomeSorted by uuid.

GpuResetOutcome

FieldNumberTypeDescription
uuid1string
reset2bool
healthy3boolECC and row-remap state read after the reset.
message4string

DiagDcgmRequest

diag.dcgm: lane provision, retry-safe, attested. Commissioning (level 2) and acceptance (level 1).

FieldNumberTypeDescription
level1uint32dcgmi diag -r level: 1 (seconds), 2 (~2 min), 3 (~15 min), 4 (long).
gpu_uuids2repeated stringGPUs to test; empty tests every GPU.

DiagDcgmResult

FieldNumberTypeDescription
passed1bool
level2uint32
tests3repeated DiagnosticCheckNode-level tests, e.g. "dcgm.deployment", "pcie.bandwidth".
gpus4repeated GpuDiagnosticPer-GPU tests, sorted by uuid.

WipeRequest

wipe: lane provision, NOT retry-safe, attested, destructive (signed from v0.2). The §11.1 invariant "ready only after a verified wipe" rests on this result's node signature.

FieldNumberTypeDescription
mode1WipeMode
disks2repeated stringDisks to wipe, by WWN or serial; empty wipes every non-removable disk.

WipeResult

FieldNumberTypeDescription
mode1WipeMode
disks2repeated DiskWipeSorted by id.

DiskWipe

FieldNumberTypeDescription
id1stringWWN, or the serial when the disk has no WWN.
method2stringHow the disk was wiped, e.g. "nvme-format", "ata-secure-erase", "blkdiscard", "crypto-erase".
verified3boolA read-back check confirmed the result.
message4string

DeployImageRequest

deploy.image: lane provision, NOT retry-safe, attested, destructive. Streams the image from the site cache (HTTP range reads) through decompression straight to the root disk, checking the SHA-256 inline (§3.5 step 4).

FieldNumberTypeDescription
url1stringHTTPS URL, normally the site agent's image cache.
sha2562bytesSHA-256 of the image as stored (before decompression).
format3ImageFormat
compression4ImageCompression
root_disk5RootDiskHint
user_data_ref6stringSecret ref of the rendered user data (it embeds a single-use provisioned join token); the agent fetches it with SecretRequest, never in the command.
user_data_kind7string"cloud-init", "ignition" or "talos".
uefi8boolWrite for UEFI boot (EFI system partition) rather than legacy BIOS.

RootDiskHint

The disk to install to; the first non-empty field wins, and a hint matching no disk fails the step.

FieldNumberTypeDescription
wwn1string
serial2string
device3stringe.g. "/dev/nvme0n1"; last resort, device names are not stable.
min_size_bytes4uint64Smallest disk at least this big.

DeployImageResult

FieldNumberTypeDescription
written_bytes1uint64
sha2562bytesSHA-256 verified while streaming (equals the request's).
root_disk3stringWWN or serial of the disk written.
duration_ms4uint32

KexecRequest

boot.kexec: lane control, retry-safe, self-terminating. Boots the installed OS from the ramdisk without firmware POST; completes when the agent rejoins with a new boot_id and role node.

FieldNumberTypeDescription
kernel_path1stringKernel and initrd paths on the installed root filesystem; empty means the distribution defaults.
initrd_path2string
kernel_cmdline3repeated stringAppended to the installed kernel command line.

KexecResult

FieldNumberTypeDescription
previous_boot_id1stringThe ramdisk boot that ran the command; the rejoining agent reports the new one.

DriverInvokeRequest

FieldNumberTypeDescription
workflow_id1string
step_id2string
attempt3uint32
target_node_id4stringSet when a site agent runs it for another node.
args5google.protobuf.StructThe expanded step: {concern, operation, args, driver?, config?}; config holds secret:// refs only, never secret values.

DriverInvokeResult

FieldNumberTypeDescription
result_json1stringThe operation's JSON result (bcx InvokeResponse.result_json).

InstanceSnapshotRequest

FieldNumberTypeDescription
instance_id1string
upload_url2stringPresigned HTTPS PUT URL.
upload_headers3repeated HttpHeader
image_id4stringThe snapshot image id the control plane registers the upload under.
include_memory5boolInclude the memory state (a restorable running snapshot); false: disk only.

InstanceSnapshotResult

FieldNumberTypeDescription
uploaded_bytes1uint64
sha2562bytesSHA-256 of the uploaded object; restoring verifies it (InstanceSpec.restore_from.sha256).
runtime3stringThe runtime that wrote it; a restore needs the same runtime.
cpu_model4stringThe host CPU model the memory state depends on (the inventory label cpu.model), empty for disk only.

WipeMode

ValueNumberDescription
WIPE_MODE_UNSPECIFIED0
WIPE_MODE_QUICK1Partition tables, signatures and the first/last MiB of every disk.
WIPE_MODE_SECURE_ERASE2ATA secure erase / NVMe format with user-data erase.
WIPE_MODE_CRYPTO_ERASE3Rotate the self-encrypting drive's media key.

ImageFormat

ValueNumberDescription
IMAGE_FORMAT_UNSPECIFIED0
IMAGE_FORMAT_RAW1
IMAGE_FORMAT_QCOW22

ImageCompression

ValueNumberDescription
IMAGE_COMPRESSION_UNSPECIFIED0
IMAGE_COMPRESSION_NONE1
IMAGE_COMPRESSION_ZSTD2
IMAGE_COMPRESSION_GZIP3

inventory.proto

Package bettercompute.agent.v1, proto/bettercompute/agent/v1/inventory.proto.

NodeInventory v1 (PLAN.md §10.1; docs/research/prior-art.md §4).

NodeInventory

An assembled snapshot: what the control plane stores (append-only) and what an inspect driver returns. Never hashed as a whole.

FieldNumberTypeDescription
schema_version1uint321 for this schema.
collected_at2google.protobuf.Timestamp
section_hashes3map of string to bytesSection name → SHA-256 of that section's canonical encoding.
system10SystemSection
cpu11CpuSection
memory12MemorySection
disks13DisksSection
nics14NicsSection
gpus15GpusSection
bmc16BmcSection
os17OsSection
images18ImagesSection(v0.3) Section "images".

ImagesSection

FieldNumberTypeDescription
images1repeated CachedImageSorted by sha256; at most 1,000 entries (the most recently used).
capacity_bytes2uint64Cache capacity and use in bytes, when the runtime knows them (0 = unknown).
used_bytes3uint64

CachedImage

FieldNumberTypeDescription
image_id1stringThe catalog image id (img_…) the node pulled it for, when it knows it; else empty.
ref2stringThe reference it was pulled by (https URL or OCI ref).
sha2563bytes
size_bytes4uint64
state5CachedImageState
last_used6google.protobuf.TimestampLast use, truncated to the hour so the section hash does not churn on every use.

SystemSection

FieldNumberTypeDescription
vendor1string
product2string
serial3string
product_uuid4stringLowercase.
board_vendor5string
board_product6string
board_serial7string
chassis_serial8string
bios_vendor9string
bios_version10string
boot_mode11BootMode
secure_boot12optional boolAbsent when unknown.
tpm13TpmAbsent when no TPM is present.

Tpm

FieldNumberTypeDescription
version1stringe.g. "2.0".
manufacturer2string
ek_cert_issuer3string

CpuSection

FieldNumberTypeDescription
vendor1string
model2string
architecture3string"x86_64", "aarch64".
sockets4uint32
cores5uint32
threads6uint32
flags7repeated stringSorted, e.g. "amx_tile", "avx512f".
numa_nodes8repeated NumaNodeSorted by id.
isolated_cpus9string(v1.1 §3.8) CPUs the kernel isolates from the scheduler (/sys/devices/system/cpu/isolated, cpulist form; empty when none): bcd pins VMs and holds there first, and never counts them for the host's own reserve.

NumaNode

FieldNumberTypeDescription
id1uint32
cpus2stringKernel cpulist form, e.g. "0-31,64-95".
memory_bytes3uint64
hugepages4repeated HugepagePool(v1.1 §3.8) The node's hugepage pools (/sys/devices/system/node/nodeN/hugepages), sorted by page size: NUMA-local hugepage backing books from these.

MemorySection

FieldNumberTypeDescription
total_bytes1uint64
hugepages2repeated HugepagePoolSorted by page size.
dimms3repeated DimmSorted by slot; empty when dmidecode is unavailable.
edac4EdacCountersAbsent when EDAC is unavailable.

HugepagePool

FieldNumberTypeDescription
page_size_bytes1uint642097152 (2Mi) or 1073741824 (1Gi).
total2uint64

Dimm

FieldNumberTypeDescription
slot1string
size_bytes2uint64
speed_mts3uint32
type4stringe.g. "DDR5".
ecc5bool
manufacturer6string
part_number7string
serial8string

EdacCounters

FieldNumberTypeDescription
correctable1uint64
uncorrectable2uint64

DisksSection

FieldNumberTypeDescription
disks1repeated DiskSorted by name.

Disk

FieldNumberTypeDescription
name1stringKernel name, e.g. "nvme0n1".
model2string
serial3string
wwn4stringStable device id when available.
size_bytes5uint64
rotational6bool
transport7DiskTransport
smart8SmartStatusAbsent when SMART is unavailable.
removable9bool

SmartStatus

FieldNumberTypeDescription
healthy1bool
wear_percent2optional uint32
media_errors3optional uint64

NicsSection

FieldNumberTypeDescription
nics1repeated NicPhysical NICs only, sorted by MAC.

Nic

FieldNumberTypeDescription
name1string
mac2stringPermanent MAC, lowercase colon form.
driver3string
firmware4string
speed_mbps5uint32
pci_address6stringe.g. "0000:17:00.0".
numa_node7optional uint32Absent when the device reports no NUMA affinity.
sriov_total_vfs8uint32
rdma9RdmaType
link10LinkState
mtu11uint32

GpusSection

FieldNumberTypeDescription
driver_version1stringKernel driver version, e.g. "580.65.06" (node-wide).
cuda_driver_version2stringe.g. "13.0".
nvml_version3string
gpus4repeated GpuSorted by index.

Gpu

FieldNumberTypeDescription
index1uint32
uuid2string"GPU-…".
pci_bus_id3stringe.g. "00000000:18:00.0".
name4stringRaw NVML name, e.g. "NVIDIA H100 80GB HBM3".
architecture5stringe.g. "hopper", "blackwell".
vram_bytes6uint64
serial7string
vbios_version8string
board_part_number9string
numa_node10optional uint32
power_limit_mw11uint32
persistence_mode12bool
compute_mode13stringe.g. "default", "exclusive-process".
cuda_compute_capability_major14uint32
cuda_compute_capability_minor15uint32
mig16GpuMig
nvlinks17repeated NvlinkLinkSorted by link.
topology18repeated GpuPeerLinkTopology matrix row for this GPU: one entry per other GPU, sorted by peer_uuid.
fabric19GpuFabricAbsent unless the GPU is part of a multi-node NVLink domain (e.g. GB200 NVL72).
ecc20GpuEcc
row_remap21GpuRowRemapAbsent on GPUs without row remapping.

GpuMig

FieldNumberTypeDescription
capable1bool
current2MigMode
pending3MigModeSet when a mode change waits for a GPU reset.
profiles4repeated MigProfileGPU instance profiles, sorted by id.
instances5repeated MigInstanceCurrent GPU/compute instances, sorted by (gi_id, ci_id).

MigProfile

FieldNumberTypeDescription
id1uint32NVML GPU instance profile id.
name2stringe.g. "1g.10gb".
max_instances3uint32
memory_bytes4uint64

MigInstance

FieldNumberTypeDescription
gi_id1uint32
ci_id2uint32
profile3string
uuid4string"MIG-…".
FieldNumberTypeDescription
link1uint32
state2LinkState
peer3stringA GPU UUID, or "nvswitch:<pci bus id>" behind NVSwitch.
version4uint32

One cell of the nvidia-smi topo -m matrix.

FieldNumberTypeDescription
peer_uuid1string
link2GpuLinkType
nvlinks3uint32Number of NVLinks for GPU_LINK_TYPE_NV (the "NV<n>" figure); 0 otherwise.

GpuFabric

MNNVL / IMEX domain membership.

FieldNumberTypeDescription
cluster_uuid1string
clique_id2uint32

GpuEcc

FieldNumberTypeDescription
enabled1bool
pending_enabled2optional boolSet when a mode change waits for a reboot.
volatile_counts3EccCountsSince the last driver load.
aggregate_counts4EccCountsLifetime.

EccCounts

FieldNumberTypeDescription
correctable1uint64Single-bit (SBE).
uncorrectable2uint64Double-bit (DBE).

GpuRowRemap

FieldNumberTypeDescription
correctable1uint32
uncorrectable2uint32
pending3boolA remap waits for a GPU reset (XID 63).
failure4boolRemapping failed (XID 64): RMA.

BmcSection

FieldNumberTypeDescription
ip1string
mac2string
vendor3string
firmware_version4string
redfish5bool
ipmi6bool

OsSection

FieldNumberTypeDescription
distro1stringos-release ID, e.g. "ubuntu".
distro_version2stringos-release VERSION_ID, e.g. "24.04".
kernel3stringuname -r.
cgroup4CgroupVersion
kvm5bool
iommu6bool
runtimes7repeated stringSorted, e.g. "containerd", "docker", "libvirt".
hostname8string

CachedImageState

ValueNumberDescription
CACHED_IMAGE_STATE_UNSPECIFIED0
CACHED_IMAGE_STATE_READY1
CACHED_IMAGE_STATE_PULLING2
CACHED_IMAGE_STATE_EVICTING3

BootMode

ValueNumberDescription
BOOT_MODE_UNSPECIFIED0
BOOT_MODE_UEFI1
BOOT_MODE_BIOS2

DiskTransport

ValueNumberDescription
DISK_TRANSPORT_UNSPECIFIED0
DISK_TRANSPORT_NVME1
DISK_TRANSPORT_SATA2
DISK_TRANSPORT_SAS3
DISK_TRANSPORT_VIRTIO4
DISK_TRANSPORT_USB5

RdmaType

ValueNumberDescription
RDMA_TYPE_UNSPECIFIED0
RDMA_TYPE_NONE1
RDMA_TYPE_INFINIBAND2
RDMA_TYPE_ROCE3

LinkState

ValueNumberDescription
LINK_STATE_UNSPECIFIED0
LINK_STATE_UP1
LINK_STATE_DOWN2

MigMode

ValueNumberDescription
MIG_MODE_UNSPECIFIED0
MIG_MODE_DISABLED1
MIG_MODE_ENABLED2

GpuLinkType

Best to worst: NV > PIX > PXB > PHB > NODE > SYS (PLAN.md §10.3 topology scorer).

ValueNumberDescription
GPU_LINK_TYPE_UNSPECIFIED0
GPU_LINK_TYPE_NV1Connected by NVLink (directly or through NVSwitch).
GPU_LINK_TYPE_PIX2At most one PCIe bridge.
GPU_LINK_TYPE_PXB3Multiple PCIe bridges, no host bridge.
GPU_LINK_TYPE_PHB4A PCIe host bridge.
GPU_LINK_TYPE_NODE5Across host bridges within one NUMA node.
GPU_LINK_TYPE_SYS6Across NUMA nodes (SMP interconnect).

CgroupVersion

ValueNumberDescription
CGROUP_VERSION_UNSPECIFIED0
CGROUP_VERSION_V11
CGROUP_VERSION_V22

session.proto

Package bettercompute.agent.v1, proto/bettercompute/agent/v1/session.proto.

The daemon ↔ control-plane protocol (PLAN.md §7): join, renew, the bidi Session stream and its frames, desired state (NodeSpec) and tunnels.

AgentGateway

The gateway-facing service every bcd mode (node, site, ramdisk) talks to.

RPCRequestResponseDescription
JoinJoinRequestJoinResponseServer-authenticated TLS (serving CA pinned). Forwarded to the api JoinService; the gateway cannot read the sealed token or forge the signed response.
RenewRenewRequestRenewResponsemTLS, at ~60% of the certificate lifetime. Verified by the api JoinService, not the gateway.
Sessionstream AgentFramestream ServerFramemTLS. One live session per node; a newer session supersedes an older one (ABORTED).
Tunnelstream TunnelFramestream TunnelFrame(v0.3) mTLS. Opened by the daemon after it verified an OpenTunnel ticket.

JoinRequest

FieldNumberTypeDescription
sealed_token1bytesUTF-8 compact JWE of the join token ("bcjt_<id>.<secret>") to the pinned JoinService encryption key. The token is read from BCD_JOIN_TOKEN or stdin only and never stored.
csr2bytesDER PKCS#10 CSR for a fresh P-256 key (TPM-resident when available).
claims3HardwareClaims
attestor4stringAttestor that verifies this join: "join-token" (v0.1); "x509pop", "provisioned", "discovery" (v0.2); "cloud-iid" (v0.3); "tpm" (v0.5). Empty means "join-token".
attestation5bytesAttestor-specific evidence (v0.2+), e.g. a site agent's SignedDiscoveryAssertion.
daemon_version6string
role7AgentRoleThe role the agent runs as. The token decides what is allowed; a mismatch is rejected.

HardwareClaims

What the daemon reports about its hardware at join. JoinService derives hardware_key = sha256(product_uuid ‖ product_serial ‖ sorted permanent MACs ‖ sorted GPU UUIDs) after dropping placeholder values, and enforces the token's expect binding and reclaim rules.

FieldNumberTypeDescription
product_uuid1string/sys/class/dmi/id/product_uuid, lowercase.
product_serial2string/sys/class/dmi/id/product_serial.
board_serial3string
chassis_serial4string
sys_vendor5string
product_name6string
permanent_macs7repeated stringPermanent MAC addresses of physical NICs, lowercase colon form.
gpu_uuids8repeated string
bmc_mac9stringBMC MAC when readable in-band.
hostname10string
boot_id11string

JoinResponse

FieldNumberTypeDescription
body1bytesSerialized JoinResponseBody.
sig2SignaturePinned JoinService signing key. Purpose "join-response", parts [body].

JoinResponseBody

FieldNumberTypeDescription
node_id1string
cert_chain2repeated bytesDER certificates, leaf first. The leaf has URI SAN spiffe://<td>/site/<site>/node/<node_id> and a role OID; no tenant.
trust3TrustBundleCommand/spec signing trust (empty roots in v0.1).
csr_sha2564bytesSHA-256 of JoinRequest.csr: the daemon rejects a response that is not for its own CSR.
trust_domain5string
site_id6string
role7AgentRole
issued_at8google.protobuf.TimestampServer time at issue, for a first clock-offset estimate.
deferral9JoinDeferral(v0.2) Set when the attestor could not decide yet: node_id and cert_chain are empty, nothing was issued and no token was spent. The daemon re-sends Join with the SAME csr (csr_sha256 still binds this response to it): after pending.retry_after_seconds, or with its answer to challenge in JoinRequest.attestation.

JoinDeferral

A two-round join (§3.3): an operator approval (discovery → joinRequests) or an attestor challenge (tpm credential activation).

FieldNumberTypeDescription
pending1JoinPending (oneof kind)
challenge2JoinChallenge (oneof kind)

JoinPending

FieldNumberTypeDescription
request_id1stringThe join request an operator approves or rejects (joinRequests.*).
retry_after_seconds2uint32

JoinChallenge

FieldNumberTypeDescription
attestor1stringThe attestor that answers it, as in JoinRequest.attestor.
payload2bytesAttestor-specific (tpm: credential blob, encrypted secret and opaque server state).
not_after3google.protobuf.TimestampAnswers after this are refused.

RenewRequest

FieldNumberTypeDescription
csr1bytesDER PKCS#10 CSR (a new key, or the current one).
chain2repeated bytesThe current certificate chain, leaf first.
client_time3google.protobuf.Timestamp
pop_sig4bytesProof of possession by the CURRENT node key. Purpose "renew-pop", parts [sha256(csr), node_id, client_time]. Accepted within ±60 s of server time; 120 s replay cache.
key_attestation5TpmKeyAttestationRequired when the current certificate names a TPM attestation key (URI SAN urn:bc:tpm-ak:<nameAlg>:<digest>): that AK certifies the CSR's key as one the TPM holds. The new certificate carries the statement forward from the old one; without this the renewal is refused.

TpmKeyAttestation

TPM2_Certify of a node key by the AK a certificate names, qualifying data sha256(csr).

FieldNumberTypeDescription
ak_public1bytesTPMT_PUBLIC of the AK: its TPM name must be the one in the certificate.
key_public2bytesTPMT_PUBLIC of the node key: the CSR's key, fixedTPM | fixedParent | sensitiveDataOrigin.
certify_info3bytesThe TPMS_ATTEST (TPM_ST_ATTEST_CERTIFY) and the AK's TPMT_SIGNATURE over it.
signature4bytes

RenewResponse

FieldNumberTypeDescription
cert_chain1repeated bytesDER certificates, leaf first.
not_after2google.protobuf.Timestamp

AgentFrame

FieldNumberTypeDescription
hello1Hello (oneof msg)
heartbeat2Heartbeat (oneof msg)
update3CommandUpdate (oneof msg)
events4EventBatch (oneof msg)
status5StatusReport (oneof msg)
inventory6InventorySection (oneof msg)
spec_request7SpecRequest (oneof msg)
secret_request8SecretRequest (oneof msg)
workload_token_request9WorkloadTokenRequest (oneof msg)(v0.5) A hosted instance's IMDS asks for its workload identity token (§12.2, §13).

ServerFrame

FieldNumberTypeDescription
welcome1Welcome (oneof msg)
command2Command (oneof msg)
cancel3Cancel (oneof msg)
desired4DesiredState (oneof msg)
ack5Ack (oneof msg)
open_tunnel6OpenTunnel (oneof msg)
drain7Drain (oneof msg)
revoked8RevocationNotice (oneof msg)
secret9SecretResponse (oneof msg)
workload_token10WorkloadTokenResponse (oneof msg)(v0.5) The answer to a WorkloadTokenRequest.

Hello

The first frame of every session. Kept small for reconnect storms: inventory travels as hashes.

FieldNumberTypeDescription
node_id1stringMust equal the node id in the certificate SAN.
boot_id2string
journal_id3stringThe journal's id. A change (journal lost: ramdisk reboot, reinstall, corruption) makes the control plane fail in-flight commands with retry_safe=false ("journal-lost") instead of replaying them.
role4AgentRole
daemon_version5string
proto_min6uint32Supported protocol range (PROTOCOL_VERSION in @better-compute/protocol). Below the server's minimum the session is restricted to daemon.upgrade (Welcome.upgrade_required).
proto_max7uint32
capabilities8repeated string
drivers9repeated DriverManifest
last_epoch10uint64The last session epoch this daemon saw (0 if none); diagnostics only.
applied_generation11uint64The newest NodeSpec generation the daemon holds (converged or not).
unacked_results12repeated CommandUpdateTerminal results not yet acked; the control plane dedupes by command_id.
running_command_ids13repeated stringCommands the journal holds as running; the control plane does not re-send them.
last_event_seq14uint64The highest event seq written in this journal.
inventory_hashes15map of string to bytesInventory section name → SHA-256 of its InventorySection.content. The control plane asks for sections whose hash differs (Welcome.request_sections).
applied_spec_hash16bytesDesiredStateBody.spec_hash of the applied generation, echoed so the control plane can detect a divergent spec and resend a full one.
trust_version17uint64TrustBundle.version the daemon holds and verifies with (0: none). The gateway records it (node_sessions.trust_version) so a command-root switch waits for every connected node (§13).
approver_set_epoch18uint64(v1.0 §13) The approver set the daemon HOLDS: a bundle's version can be taken while its quorum part is refused (unsigned change, stale epoch), so trust_version alone would read "up to date" for a node still enforcing the old approvers. approver_set_sha256 is SHA-256 of the held set's approverSetInput (empty: no approver keys held).
approver_set_sha25619bytes

Welcome

FieldNumberTypeDescription
epoch1uint64node_sessions.session_epoch after this Hello's bump.
session_id2string
gateway_id3string
protocol_version4uint32The negotiated version: the highest version inside both ranges.
heartbeat_interval_ms5uint32Heartbeat period (10 000 ms by default). Three missed heartbeats close the session.
lease_ttl_ms6uint32Liveness lease TTL (40 000 ms by default).
credits7repeated LaneCreditsPer-lane in-flight limits the gateway keeps outstanding (control 8, provision 4, bulk 2).
acked_event_seq8uint64Cumulative ack for Hello.journal_id; the daemon resends events with a higher seq.
request_sections9repeated stringInventory sections to send now (hash mismatch or never seen).
server_time10google.protobuf.TimestampServer time (compute_now()). The daemon keeps the offset to its own clock and evaluates not_after and not_before in server time.
trust11SignedTrustBundleNewer signing trust, if any. Only accepted when signed by the pinned JoinService key and newer than the bundle the daemon holds.
upgrade_required12boolThe daemon is below the server's proto_min: only daemon.upgrade is accepted (v0.4).
capabilities13repeated string

LaneCredits

FieldNumberTypeDescription
lane1Lane
credits2uint32

Heartbeat

FieldNumberTypeDescription
credits1repeated LaneCreditsFree credits per lane right now; the gateway resynchronises its counters from them.
load2NodeLoad
inventory_hashes3map of string to bytesEvery 10th heartbeat: the same map as Hello.inventory_hashes; empty otherwise.
applied_generation4uint64

NodeLoad

Coarse load for admission and dashboards. Telemetry proper never uses the session (P8).

FieldNumberTypeDescription
load_average_1m1double1-minute load average.
memory_available_bytes2uint64
running_commands3uint32Commands currently running across lanes.
pending_events4uint32Unacked events in the journal.

Command

A one-shot action. Delivery is at-least-once; the daemon's journal makes it at-most-once in effect. The control plane stores body and signature verbatim and resends the same bytes.

FieldNumberTypeDescription
body1bytesSerialized CommandBody.
signature2SignatureWorker signing key. Purpose "command", parts [body]. Optional in v0.1; required for destructive kinds from v0.2 and for all kinds from v0.4 (the daemon's own kind table decides, never a flag an unsigned body could carry).
attempt3uint32Delivery attempt (1-based). Outside the signature: informational only.
batch_approval4BatchApproval(v1.0, §13 quorum) For a body with batch_id: the operators' approval of the batch and this command's inclusion proof. Outside the worker signature: the approval carries its own.
batch_proof5BatchProof

BatchApproval

k-of-n operator approval of a batch of destructive commands (PLAN.md §13). The scope is a Merkle tree (RFC 6962 style, SHA-256) with one leaf per (subject, kind, payload), leaves ordered by their hash (bytewise ascending, duplicates removed): leaf = H(0x00 ‖ lp(batch_id) ‖ lp(subject) ‖ lp(kind) ‖ lp(payload_sha256)), node = H(0x01 ‖ left ‖ right), with lp(x) = uint32_be(len(x)) ‖ x, and an odd node promoted unchanged to the next level. The subject is what the command acts on, computed by the executing agent from the signed body:

  • kinds a node runs on itself (disk.wipe, deploy.image, node.reboot, gpu.reset, boot.kexec…): the command's node_id;
  • site-relayed BMC kinds (bmc.*): "bmc:" + <the executing site agent's node_id> + "/" + BmcOperationRequest.address, the BMC acted on. BMC addresses are site-local (10.0.0.5 exists at every site), so the site is part of the subject: an approval for site A never admits a command at site B;
  • site.httpProxy: "node:" + its target_node_id (global ids). payload_sha256 is SHA-256 of the command's payload (CommandBody.payload.value), binding the leaf to exactly that operation (image, firmware, power action), or EMPTY for "any payload of this kind" where the payload is built later (approvers see unbound leaves flagged). The executing agent accepts a proof that walks to the root from either the bound leaf (its payload's digest) or the unbound one. Daemons run each leaf at most once per batch. Signing purpose "batch-approval", parts [batch_id, scope_root, uint32_be(scope_size), int64_be(not_after.seconds) ‖ int32_be(not_after.nanos), trust_domain]. The trust domain (the deployment's, JoinResponseBody.trust_domain) is supplied by each verifier from its own config, so an approval for staging never admits a command in production, even with shared approver keys.
FieldNumberTypeDescription
batch_id1string
scope_root2bytes
scope_size3uint32Leaves in the tree: what the operators saw and approved ("reimage 412 nodes").
not_after4google.protobuf.TimestampServer time after which the approval no longer admits a command.
signatures5repeated SignatureApprover key signatures (Signature.kid names an approver key); duplicates count once.

BatchProof

The path from this command's leaf to BatchApproval.scope_root.

FieldNumberTypeDescription
index1uint32The leaf's index in the sorted leaves.
siblings2repeated bytesSibling hashes from the leaf level up; a promoted odd node has no sibling at that level.

CommandBody

FieldNumberTypeDescription
id1stringULID; the journal's dedupe key.
node_id2stringMust equal the session's node id; anything else is rejected UNSUPPORTED.
seq3uint64Per-node monotonic sequence (nodes.next_cmd_seq); resume replays in seq order.
kind4stringRegistered kind, e.g. "diag.nvml". Unknown or role-disallowed kinds → REJECTED/UNSUPPORTED.
payload5google.protobuf.AnyThe kind's request message (commands.proto), e.g. bettercompute.agent.v1.DiagNvmlRequest.
lane6Lane
not_after7google.protobuf.TimestampServer time after which the command must not start. Checked before accepting (REJECTED/ EXPIRED); the CommandSweeper expires undelivered commands at the same instant.
min_generation8uint64The NodeSpec generation the command presupposes. If the daemon's applied generation is lower it sends SpecRequest and defers; still lower at not_after → REJECTED/STALE_GENERATION. 0 = none.
retry_safe9boolSafe to execute again when the journal shows accepted but not running after a crash. Otherwise that case reports FAILED{"interrupted"} for the controller to decide.
idempotency_key10stringUNIQUE(node_id, idempotency_key); workflow steps use "wf:<id>:<stepId>".
traceparent11stringW3C trace context, propagated api → worker → gateway → daemon → driver.
self_terminating12boolThe side effect ends this daemon process (node.reboot, boot.kexec, daemon.upgrade). The journal fsyncs running{boot_id} right before it; after restart with another boot_id (or on rejoin with another role) it completes as SUCCEEDED{rebooted}. Never replayed.
attested13boolThe result is a "this node says" statement: CommandUpdate.node_sig is required (v0.2) and the worker verifies it against node_certs before any state transition.
workflow_id14string(v0.2) The workflow step this command executes; SecretRequest binds secrets to it.
step_id15string
batch_id16string(v1.0, §13 quorum) The batch this destructive command belongs to. Inside the signed body, so a compromised gateway can neither add nor strip it; the daemon then requires Command.batch_approval + batch_proof.

CommandUpdate

Progress and outcome of one command. Terminal updates are journaled until acked and replayed in Hello.unacked_results after a reconnect.

FieldNumberTypeDescription
command_id1string
state2CommandStateOne of ACKED, RUNNING, SUCCEEDED, FAILED, REJECTED, CANCELLED.
result3bytesThe kind's serialized result message (commands.proto), when there is one.
boot_id4stringThe boot the daemon was in when it produced this update.
node_sig5SignatureNode key, for attested kinds (v0.2). Purpose "command-update", parts [command_id, uint32_be(state), sha256(result)].
reject_reason6CommandRejectReasonSet when state is REJECTED.
error7CommandErrorSet when state is FAILED.
rebooted8boolA self-terminating command completed by the reboot/exec it caused.

CommandError

FieldNumberTypeDescription
code1stringStable lowercase code: "interrupted" (accepted, not retry-safe, daemon restarted), "invalid-payload", "internal", or a kind- or driver-specific code.
message2string

Cancel

Stop a command between actions. Never hides a completed side effect: the daemon reports the real outcome, or CANCELLED if nothing ran.

FieldNumberTypeDescription
command_id1string
reason2string

DesiredState

Generation-numbered desired state. Signed like commands; the daemon stores the last full spec, its hash and signature in the journal and enforces it while offline.

FieldNumberTypeDescription
body1bytesSerialized DesiredStateBody.
signature2SignatureWorker signing key. Purpose "desired-state", parts [body]. Optional in v0.1; required when the spec changes access (v0.2) and always from v0.4.

DesiredStateBody

FieldNumberTypeDescription
node_id1string
generation2uint64Monotonic. A generation not greater than the applied one is ignored.
base_generation3uint640 for a full spec. For a patch: the generation it applies to; a daemon at any other generation discards the patch and sends SpecRequest{PATCH_BASE_MISMATCH}.
spec_hash4bytesOpaque id of the full spec at generation (SHA-256 over the control plane's canonical encoding). The daemon never recomputes it; it echoes it as applied_spec_hash.
full5NodeSpec (oneof spec)
patch6NodeSpec (oneof spec)Section-level patch: every section that is SET replaces that section wholesale (an empty section message clears it); unset sections keep their current value.
traceparent7string

NodeSpec

What the node should look like. The converger runs one idempotent plan(desired, observed) + apply per section; observed_generation advances only when every section converged or failed terminally. A section a daemon does not know arrives as an unknown field: the daemon reports condition "SectionUnsupported" (reason = the field number) and converges the rest.

FieldNumberTypeDescription
host1HostSection
devices2DevicesSection
instances3InstancesSection(v0.3)
access4AccessSection(v0.3) Empty in v0.1.
telemetry5TelemetrySection
daemon6DaemonSection(v0.4)
site7SiteSpec(v0.2, site agents only) DRAFT: its content is defined in site/v1, which is not yet frozen.

HostSection

Host configuration units (profile hostConfig, v0.2): nvidia-driver, container-toolkit, mig-layout, fabric-manager, sysctl, … Converged continuously so drift is corrected.

FieldNumberTypeDescription
units1repeated ConfigUnit

ConfigUnit

FieldNumberTypeDescription
unit1stringThe config driver id, e.g. "nvidia-driver".
config_json2stringCanonical JSON (RFC 8785) validated against the unit's manifest by the control plane.

DevicesSection

Device assignments (§3.4 step 9). The daemon rejects overlapping assignments, writes the CDI spec /etc/cdi/bcd-<allocation_id>.json, an env file and device ownership, then reports a node-signed AllocationBound; removing an assignment releases it (AllocationReleased). The daemon never drops an assignment on its own, not even while disconnected (P6).

FieldNumberTypeDescription
assignments1repeated DeviceAssignment

DeviceAssignment

FieldNumberTypeDescription
allocation_id1string
reservation_id2string
binding3Binding
devices4repeated AssignedDevice
instance_id5string(v0.3) Set when binding is BINDING_INSTANCE.
env6repeated stringExtra "KEY=VALUE" lines for the allocation's env file.
limits7ResourceLimits(v1.1 §3.8) The CPU, memory and hugepages booked with the devices. For HOLD, bcd creates the cgroup-v2 slice bcd-alloc-<allocation_id>.slice with these limits and names it in the CDI spec; for KUBERNETES they are what the kubelet may give pods using these devices. Absent: devices only.

ResourceLimits

Host resources an allocation may use (cgroup v2 semantics). Zero or empty = not limited.

FieldNumberTypeDescription
cpus1stringCPUs the allocation may run on (cpuset.cpus, cpulist form, e.g. "8-15,72-79").
mems2stringNUMA nodes its memory comes from (cpuset.mems, e.g. "1").
cpu_millis3uint32CPU time, in thousandths of a CPU (cpu.max; 4000 = 4 CPUs).
memory_bytes4uint64memory.max; bcd sets memory.high at 90% of it.
hugepages_2mi5uint64hugetlb.2MB.max / hugetlb.1GB.max, in pages.
hugepages_1gi6uint64

AssignedDevice

FieldNumberTypeDescription
id1stringAtom id: GPU UUID, "<gpuUuid>/gi<g>/ci<c>" (v0.5), "<gpuUuid>/s<k>" (v0.5), disk WWN, …
device_class2stringDevice class: "gpu", "gpu.mig", "gpu.slot", "nic.vf", "disk".

InstancesSection

(v0.3) VPS instances on this host; the daemon converges each toward desired_state.

FieldNumberTypeDescription
instances1repeated InstanceSpec
volumes2repeated HostVolume(v1.1, agent memory) Persistent volumes kept on this host across instances. bcd creates each missing one (a sparse raw file under its data directory; growing is a truncate, seen by the guest at its next start; never shrunk) and destroys (hole-punches, then unlinks) one the section no longer lists once no instance attaches it: an absent volume is a deleted volume, so a spec is only ever missing one the control plane deleted. Only a bcd with the instance.volumes capability keeps them.

HostVolume

FieldNumberTypeDescription
volume_id1string[A-Za-z0-9_-]{1,80}.
size_bytes2uint64A positive multiple of 512.
serial3stringThe virtio-blk serial (at most 20 bytes, [a-z0-9-]); the guest finds the disk at /dev/disk/by-id/virtio-<serial> and mounts it from its user data.

InstanceVolume

(v1.1) A HostVolume attached to an instance as an extra virtio disk, in list order after the root disk. bcd refuses (InstanceStatus error) an instance naming a volume the section lacks.

FieldNumberTypeDescription
volume_id1string
read_only2bool

InstanceSpec

FieldNumberTypeDescription
instance_id1string
desired_state2InstanceDesiredState
runtime3stringRuntime driver id, e.g. "libvirt-kvm", "cloud-hypervisor".
allocation_id4string
vcpu5uint32
memory_bytes6uint64
disk_bytes7uint64
image8ImageRef
user_data_ref9stringSecret ref of the NoCloud user-data, fetched with SecretRequest{allocation_id}.
gpu_device_ids10repeated stringGPU atoms passed through with VFIO (never overcommitted).
nics11repeated InstanceNic
restore_from12ImageRef(v0.5, sandboxes) Boot from this snapshot (an instance.snapshot upload) instead of image: disk and, when captured, memory state. The daemon verifies sha256 before restoring and fails the instance on a runtime or CPU model mismatch.
network_policy13InstanceNetworkPolicy(v0.5, sandboxes) What the instance's NICs may reach, enforced by bcd as host nftables rules on its taps, whatever the runtime. bcd's own tunnel dial from the host always works.
identity_rebind_ref14string(v0.5, review 13 H2) After a restore, the guest's per-instance identity (SSH host keys, machine id, workload credentials) must not stay the snapshot's. A secret ref (fetched with SecretRequest) of the new identity material; bcd delivers it to the running guest (a hotplugged raw disk read by a vps-installed guest unit) and reports the ref back in InstanceStatus.identity_rebound_ref once the guest acked it. Changing it asks for a new rebind.
ssh_from_host_only15bool(review 13 L5) Port 22 of the guest is reachable only from the host (bcd's tunnel dial), never from other guests or the network, whatever network_policy allows.
placement16InstancePlacement(v1.1 §3.8) Where the guest's vCPUs and memory live on the host. Absent: the runtime's default (floating vCPUs, host memory).
volumes17repeated InstanceVolume(v1.1, agent memory) Persistent volumes to attach (InstancesSection.volumes).

InstancePlacement

FieldNumberTypeDescription
cpus1stringHost CPUs for the vCPUs (cpulist). With exactly vcpu CPUs, vCPU i is pinned to the i-th one; otherwise the vCPUs float within the set.
mems2stringNUMA nodes the guest memory is bound to (e.g. "1").
hugepage_size_bytes3uint64Back guest memory with hugepages of this size (2097152 or 1073741824); 0 = normal pages. The pages come from the host's pools on mems.
balloon4boolGive the guest a virtio balloon (libvirt memballoon, cloud-hypervisor balloon) so the host can reclaim free guest memory; never with hugepages.

ImageRef

A content-addressed image the daemon may fetch and cache.

FieldNumberTypeDescription
ref1stringCatalog reference, e.g. "ubuntu-24.04-cloud@2026.09".
url2string
sha2563bytes
format4string"raw" or "qcow2".
compression5string"" or "zstd".

InstanceNic

FieldNumberTypeDescription
network1stringBridge or network name on the host.
mac2string
addresses3repeated stringAddresses assigned by IPAM, CIDR form.
gateway4string(v1.1) The IPAM range's default gateway; empty: no default route through this NIC. bcd renders it, with addresses, into the guest's NoCloud network-config (the guest runs no DHCP client against the host).
nameservers5repeated string(v1.1) DNS servers for the guest; empty: the guest keeps its image's resolver configuration.

AccessSection

(v0.3) Interactive access material. Empty in v0.1.

FieldNumberTypeDescription
exec_ticket_jwks_json1stringJWKS (JSON) the daemon verifies exec tickets against (§7.6).
ssh_ca_public_keys2repeated stringOpenSSH-format public keys of the compute SSH CA trusted for break-glass certificates.
ssh_principals3repeated stringPrincipals such certificates may use.
ssh_revoked_serials4repeated uint64(v0.3) Serials of break-glass certificates revoked before they expired. The daemon writes them into an OpenSSH KRL (RevokedKeys), so a revoked certificate stops working at the next spec.

TelemetrySection

Where bcd sends its own telemetry (OTLP). Never the session or Postgres (P8).

FieldNumberTypeDescription
otlp_endpoint1stringEmpty disables export.
export_interval_ms2uint32
resource_attributes3repeated stringExtra "key=value" resource attributes.
headers_ref4stringSecret ref of the exporter's auth headers, fetched with SecretRequest.

DaemonSection

(v0.4) Self-update target; the Rollout controller sets it within the disruption budget.

FieldNumberTypeDescription
version1string
url2string
sha2563bytes
signature4bytesDetached release signature over the artifact.

SpecRequest

Ask for a full DesiredState.

FieldNumberTypeDescription
have_generation1uint64
reason2SpecRequestReason

StatusReport

Convergence state, coalesced latest-wins.

FieldNumberTypeDescription
observed_generation1uint64Every section converged or failed terminally at this generation. Never regresses on the control plane (GREATEST).
applied_generation2uint64The newest generation held (converging or converged).
applied_spec_hash3bytes
sections4repeated SectionStatus
conditions5repeated ConditionThe node's full current condition set as seen by the daemon (health, drift, section errors).
instances6repeated InstanceStatus(v0.3) What the host runtimes hold: every VM or container they know, managed or not, so the control plane can move instances by what actually runs and find leaks (an instance no live row places here). Latest-wins with the rest of the report.
instances_complete7bool(v0.3) instances is the runtimes' whole inventory: a placed instance missing from it is absent.
pressure8HostPressure(v0.3) Host resource pressure for the Disk/Memory/CpuPressure conditions (§10.1). Absent when the kernel exposes no PSI.
trust_version9uint64TrustBundle.version the daemon holds, as in Hello.trust_version, reported again once it applies a newer bundle mid-session (Welcome.trust), so the ack does not wait for a reconnect. 0: unchanged.
approver_set_epoch10uint64The approver set held after that bundle, as in Hello (set whenever trust_version is).
approver_set_sha25611bytes
discovered12repeated DiscoveredMachine(v1.1, site agents only) Machines seen PXE/HTTP-booting (DHCP PXEClient/HTTPClient) from a MAC with no live boot entry: never answered, never enrolled; a list for metal to match (by product_uuid, the SMBIOS UUID a BMC also reports) or an operator to act on. The whole list, capped at 256 (oldest last_seen evicted, forgotten 24 h after last seen).
volume_storage13VolumeStorage(v1.1, hosts with a runtime) The volume store's filesystem, so capacity books persistent volumes against what can really be written (volumes are sparse). bcd refuses a volume create or growth beyond available − reserved − outstanding; capacity applies the same rule.

VolumeStorage

FieldNumberTypeDescription
total_bytes1uint64The data directory's filesystem (statfs).
available_bytes2uint64statfs Bavail.
reserved_bytes3uint64Kept from volumes: overlays, journal, images (5% of total, at least 2 GiB).
committed_bytes4uint64The sum of every volume's size.
outstanding_bytes5uint64The sum of every volume's unwritten (sparse) space: promised but not yet taken.

DiscoveredMachine

FieldNumberTypeDescription
mac1stringLowercase colon form.
product_uuid2stringDHCP option 97 (the SMBIOS system UUID); empty when the client sent none.
arch3stringDHCP option 93, as the site agent names it: x86_64-efi, bios, arm64-efi, x86_64-efi-http, …
first_seen4google.protobuf.Timestamp
last_seen5google.protobuf.Timestamp
count6uint32
relay7stringgiaddr when the request was relayed (which L2 segment it came from); empty when direct.

HostPressure

Linux pressure stall information (/proc/pressure/*, "some" avg10, percent of wall time) and CPU steal (percent over the last report interval).

FieldNumberTypeDescription
cpu_some_avg101float
memory_some_avg102float
io_some_avg103float
steal_pct4float

InstanceStatus

(v0.3) One instance as a host runtime reports it.

FieldNumberTypeDescription
instance_id1stringThe InstanceSpec.instance_id, or the runtime's own name for an object bcd did not create.
state2InstanceObservedState
addresses3repeated stringAddresses the guest holds, CIDR form (guest agent or DHCP leases).
message4string
runtime5stringRuntime driver id, e.g. "libvirt-kvm".
identity_rebound_ref6string(review 13 H2) The InstanceSpec.identity_rebind_ref the guest acknowledged (its nonce written back); empty until then. Until it matches the spec's, the control plane refuses exec into a restored instance (it would still carry the snapshot's identity); readiness still means "runs", since guests restored from snapshots taken before the guest half existed never ack.

SectionStatus

FieldNumberTypeDescription
section1stringNodeSpec section name: "host", "devices", "instances", "access", "telemetry", "daemon", "site".
state2SectionState
generation3uint64The generation this status refers to.
reason4string
message5string

Condition

A Kubernetes-style condition (PLAN.md §10.1).

FieldNumberTypeDescription
type1stringe.g. "SectionUnsupported", "DriverMismatch", "Xid79" (v0.2).
status2ConditionStatus
reason3string
message4string
device_id5stringWhen set, the condition concerns one device (atom id).
age_ms6uint64How long ago the daemon saw the last transition, on its monotonic clock. The control plane derives since from compute_now() (P9: agents report ages, not timestamps).

InventorySection

One inventory section, sent when Welcome.request_sections asks for it, when inventory.refresh runs, or when a re-collection changes its hash.

FieldNumberTypeDescription
section1stringSection name (INVENTORY_SECTIONS): "system", "cpu", "memory", "disks", "nics", "gpus", "bmc", "os". It selects the message type of content.
sha2562bytesSHA-256 of content. The control plane verifies it and compares it with the hash stored with the last accepted section; it never re-encodes to compare.
content3bytesBinary encoding of the canonicalized section message from inventory.proto (e.g. GpusSection): arrays sorted by their stable key, no volatile values.
collected_at4google.protobuf.TimestampDaemon clock, corrected by the Welcome offset; advisory.
schema_version5uint32NodeInventory schema version of content (1).

EventBatch

Journaled events, sent in seq order. Results and transitions are never dropped; metric-like events are dropped oldest-first when the journal is full.

FieldNumberTypeDescription
journal_id1stringThe journal the seqs belong to (Hello.journal_id).
events2repeated Event

Event

FieldNumberTypeDescription
seq1uint64Per journal_id, strictly increasing from 1. Cumulatively acked (Ack.event_seq); deduplicated on (node_id, journal_id, seq).
observed_at2google.protobuf.TimestampDaemon clock, corrected by the Welcome offset; advisory.
attested10AttestedReport (oneof body)
allocation_failed11AllocationFailed (oneof body)

AttestedReport

A node-signed statement about allocations (§6 "Attested kinds").

FieldNumberTypeDescription
body1bytesSerialized AttestedReportBody.
node_sig2SignatureNode key. Purpose "attested-report", parts [body]. Optional in v0.1; required from v0.2, when workers verify it against node_certs before any state transition.

AttestedReportBody

FieldNumberTypeDescription
node_id1stringThe reporting node (must equal the session's node id).
boot_id2string
allocation_bound10AllocationBound (oneof report)
allocation_released11AllocationReleased (oneof report)

AllocationBound

The assignment is materialized: CDI spec, env file and device ownership are in place.

FieldNumberTypeDescription
allocation_id1string
generation2uint64The NodeSpec generation that carried the assignment.
device_ids3repeated string
cdi_devices4repeated stringFully qualified CDI device names, e.g. "bcd.dev/gpu=GPU-…".
cdi_spec_path5stringe.g. "/etc/cdi/bcd-<allocation_id>.json".
env_file6string
cgroup_parent7string(v1.1 §3.8) The cgroup-v2 slice a HOLD's workload must run in, e.g. "bcd-alloc-<allocation_id>.slice" (also in the CDI spec and env file); empty when the assignment carried no limits or its binding is KUBERNETES (the kubelet enforces those).

AllocationReleased

The assignment is gone: CDI spec and env file removed, ownership restored.

FieldNumberTypeDescription
allocation_id1string
generation2uint64
device_ids3repeated string

AllocationFailed

The daemon refused or failed to materialize an assignment (e.g. overlap with a live one).

FieldNumberTypeDescription
allocation_id1string
generation2uint64
reason3stringStable lowercase code, e.g. "overlap", "device-missing", "cdi-write-failed".
message4string

Ack

Cumulative acknowledgement of durably stored events and results.

FieldNumberTypeDescription
journal_id1string
event_seq2uint64Every event with seq <= event_seq in journal_id is stored.
command_ids3repeated stringTerminal CommandUpdates stored; the journal may stop replaying them.

SecretRequest

Fetch one secret for current work. Forwarded to the api secret broker, which checks node_sig and that the ref is bound to the agent's current step or allocation.

FieldNumberTypeDescription
ref1string"secret://…", "vault://…", "env://…".
workflow_id2string
step_id3string
allocation_id4string
epk5bytesFresh ephemeral P-256 public key, uncompressed SEC1 point (65 bytes). Used once.
node_sig6SignatureNode key. Purpose "secret-request", parts [request_id, ref, workflow_id, step_id, allocation_id, epk].
request_id7stringCorrelates the SecretResponse.

SecretResponse

FieldNumberTypeDescription
ref1string
jwe2stringCompact JWE (ECDH-ES+A256KW / A256GCM) to SecretRequest.epk. Gateways only see ciphertext.
request_id3string
error4stringSet instead of jwe on refusal: "not-found", "not-bound", "access-denied", "unavailable".

WorkloadTokenRequest

(v0.5) Workload identity (§12.2, §13): a VPS host's IMDS, bound to one instance, asks for that instance's token. The control plane mints it only for a live instance placed on this node, in a pool with workload identity on, for a configured audience.

FieldNumberTypeDescription
request_id1stringCorrelates the WorkloadTokenResponse.
instance_id2string
audience3string
epk4bytesFresh ephemeral P-256 public key, uncompressed SEC1 point (65 bytes). Used once: the token is sealed to it, so a gateway relaying it never holds a usable token.
node_sig5SignatureNode key. Purpose "workload-token", parts [request_id, instance_id, audience, epk].

WorkloadTokenResponse

FieldNumberTypeDescription
request_id1string
jwe2stringCompact JWE (ECDH-ES+A256KW / A256GCM) of the workload JWT to WorkloadTokenRequest.epk.
expires_at3google.protobuf.Timestamp
error4stringSet instead of jwe on refusal: "not-bound", "disabled", "audience", "rate-limited", "access-denied", "unavailable".

Drain

Reconnect elsewhere (rolling deploys, rebalancing). The daemon closes the session and redials after the delay, keeping its journal.

FieldNumberTypeDescription
reconnect_after_ms1uint32rand(0, 60 s) by default.
reason2string

RevocationNotice

This agent's certificate was revoked; the gateway closes the session right after sending it. The daemon stops using the certificate and does not redial with it.

FieldNumberTypeDescription
reason1string
serials2repeated bytesSerial numbers of the revoked certificates.

OpenTunnel

Ask the daemon to open a Tunnel stream. The daemon re-verifies the ticket against the AccessSection JWKS and its jti set before opening it.

FieldNumberTypeDescription
tunnel_id1string
ticket2stringExec ticket: ES256 JWT, 60 s, single-use jti, aud "node:<id>", sid, op.

TunnelFrame

FieldNumberTypeDescription
tunnel_id1string
channel2uint320 = stdin/stdout or the byte stream, 1 = stderr.
opened10TunnelOpened (oneof body)The daemon's first frame on the stream.
data11bytes (oneof body)
resize12TerminalSize (oneof body)
closed13TunnelClosed (oneof body)

TunnelOpened

No fields.

TerminalSize

FieldNumberTypeDescription
rows1uint32
cols2uint32

TunnelClosed

FieldNumberTypeDescription
exit_code1int32
reason2string

Binding

How an allocation is consumed (§10.5).

ValueNumberDescription
BINDING_UNSPECIFIED0
BINDING_HOLD1CDI hold, consumed by an operator-run workload manager on the node (v0.1).
BINDING_INSTANCE2Passed to a VPS instance (v0.3).
BINDING_NODE3The whole node, for a tenant deploy (v0.5).
BINDING_KUBERNETES4(v1.1 §3.8) Given to the node's kubelet (the node joined a Kubernetes cluster through its pool): bcd's device plugin advertises exactly the devices bound this way, and withdraws them on release.

InstanceNetworkPolicy

ValueNumberDescription
INSTANCE_NETWORK_POLICY_UNSPECIFIED0EGRESS: existing specs do not change.
INSTANCE_NETWORK_POLICY_EGRESS1Anything the pool's network allows (as before this field).
INSTANCE_NETWORK_POLICY_PRIVATE2Only the pool's IPAM subnet and the host.
INSTANCE_NETWORK_POLICY_NONE3Only the host: bcd's tunnel dial, DHCP and ARP; nothing else in or out.

InstanceDesiredState

ValueNumberDescription
INSTANCE_DESIRED_STATE_UNSPECIFIED0
INSTANCE_DESIRED_STATE_RUNNING1
INSTANCE_DESIRED_STATE_STOPPED2
INSTANCE_DESIRED_STATE_DELETED3
INSTANCE_DESIRED_STATE_PAUSED4(v0.5, sandboxes warm pools) Booted, then paused with its memory resident; resuming is desired RUNNING. A runtime that cannot pause keeps it STOPPED and reports STOPPED.

SpecRequestReason

ValueNumberDescription
SPEC_REQUEST_REASON_UNSPECIFIED0
SPEC_REQUEST_REASON_PATCH_BASE_MISMATCH1A patch's base_generation is not the applied generation.
SPEC_REQUEST_REASON_MIN_GENERATION2A command's min_generation is above the applied generation.
SPEC_REQUEST_REASON_NO_SPEC3The journal holds no usable spec (new journal, corruption, failed signature check).

InstanceObservedState

ValueNumberDescription
INSTANCE_OBSERVED_STATE_UNSPECIFIED0
INSTANCE_OBSERVED_STATE_RUNNING1
INSTANCE_OBSERVED_STATE_STOPPED2
INSTANCE_OBSERVED_STATE_ERROR3
INSTANCE_OBSERVED_STATE_PAUSED4(v0.5) Paused by the runtime (vCPUs stopped, memory resident).

SectionState

ValueNumberDescription
SECTION_STATE_UNSPECIFIED0
SECTION_STATE_CONVERGED1
SECTION_STATE_PROGRESSING2
SECTION_STATE_FAILED3Failed terminally at this generation (e.g. an overlapping assignment).
SECTION_STATE_UNSUPPORTED4

ConditionStatus

ValueNumberDescription
CONDITION_STATUS_UNSPECIFIED0
CONDITION_STATUS_TRUE1
CONDITION_STATUS_FALSE2
CONDITION_STATUS_UNKNOWN3

common.proto

Package bettercompute.common.v1, proto/bettercompute/common/v1/common.proto.

Shared types for every better-compute wire contract (PLAN.md §7).

Signature

An ES256 signature (ECDSA P-256 with SHA-256).

FieldNumberTypeDescription
kid1stringIdentifies the signing key. For node keys: base64url (no padding) of SHA-256 over the key's SubjectPublicKeyInfo DER. For control-plane keys: the key's certificate subject key id as published in the trust bundle.
sig2bytesThe raw 64-byte r ‖ s form (IEEE P1363 / JWS), not ASN.1 DER.
chain3repeated bytesOptional DER X.509 certificates, leaf first, chaining the key to a trust root the verifier already holds (worker signing keys chain to a TrustBundle root). Empty when the verifier knows the key by kid (node keys are looked up in node_certs).

TrustBundle

The command/spec signing trust the daemon accepts (PLAN.md §13). Delivered inside the signed JoinResponseBody, and refreshed through Welcome as a SignedTrustBundle. Rotation: new roots are added first; the old ones are dropped only after every daemon acknowledged the new version.

FieldNumberTypeDescription
version1uint64Monotonic. A daemon ignores a bundle whose version is not greater than the one it holds.
command_signing_roots2repeated bytesDER X.509 roots that certify the short-lived (24 h) worker keys signing Command and DesiredState bodies (v0.2). Empty in v0.1: signatures are optional there.
approver_keys3repeated ApproverKey(v1.0, §13 quorum) Operator approval keys (P-256), held off the control plane (laptops, HSMs). With any set, a destructive command carrying CommandBody.batch_id runs only with a BatchApproval signed by approver_threshold distinct keys of this set.
approver_threshold4uint32
unbatched_destructive_per_hour5uint32With approver keys set: destructive commands WITHOUT a batch_id this daemon runs per rolling hour (break-glass only; the default and recommended value is 0). A daemon cannot count fleet-wide, so any unbatched allowance lets a compromised worker touch every node once: fleet-wide limits come from the approvers (see quorum_tiers), never from this cap.
quorum_tiers6repeated QuorumTierThresholds by batch size, ascending max_scope_size with non-decreasing thresholds: a batch with scope_size ≤ max_scope_size needs threshold distinct approver signatures (the first tier that covers it); above every tier, approver_threshold. Small batches can then be approved by a rate-limited auto-approver (one approver key held by a service outside api/worker, which is the fleet-wide counter), while large ones need k people.
approver_set_signatures7repeated Signature(v1.0) The quorum fields (3-6) are signed by the approvers themselves, not only by the join key the control plane holds: k-of-the-CURRENT-set signatures, purpose "approver-set", parts [uint64_be(approver_set_epoch), sha256(approver set input), trust_domain] (see protocol's approverSetInput; the verifier's own trust domain). Published on every version while the set is current. One rule (review 10 M3): a daemon holding set H at epoch e adopts (set N, epoch e') only when e' > e AND k-of-H (H's threshold) signatures over (e', N, domain) verify; otherwise it keeps (H, e). That holds for N == H too: adopting a higher epoch for an unchanged set needs the set's own signatures. The list therefore carries both the previous set's signatures (which admit the change) and the new set's own signatures (which move daemons already holding it, or holding it again after a revert, to the new epoch, so a replay of an intermediate epoch fails). When the quorum part is refused, the rest of the bundle (roots, version) still applies. A daemon without keys takes the first set as-is unless pinned (approver_set_sha256 in its config). Residual risk: a daemon offline across two changes can be served an intermediate epoch by a compromised api; pin long-offline nodes again when they return.
approver_set_epoch8uint64(v1.0) The epoch of the quorum fields (3-6): monotonic, separate from version (roots rotate without touching it), raised with every change of the set.

QuorumTier

FieldNumberTypeDescription
max_scope_size1uint32
threshold2uint32

ApproverKey

One operator approval key.

FieldNumberTypeDescription
kid1stringbase64url (no padding) SHA-256 of spki_der, as Signature.kid names it.
spki_der2bytesSubjectPublicKeyInfo DER of the P-256 key.

SignedTrustBundle

A TrustBundle signed by the pinned JoinService signing key, so a gateway cannot inject roots. Signing purpose "trust-bundle", parts [body].

FieldNumberTypeDescription
body1bytesSerialized TrustBundle.
signature2Signature

DriverManifest

What a daemon-side driver (built into bcd or served over bcx) offers (PLAN.md §5.4, §5.5). Advertised in Hello.drivers and returned by bcx DriverPlugin.Describe; the control plane merges it into its registry as a remote driver scoped to the advertising agents.

FieldNumberTypeDescription
id1stringDriver id, e.g. "redfish", "ipmi", "libvirt-kvm", "nvidia".
version2stringSemantic version of the driver implementation.
kinds3repeated stringDriver kinds it implements, e.g. "power", "management", "runtime", "config".
runs_on4RunsOn
config_schema_json5stringJSON Schema 2020-12 of the driver's config (manifest().jsonSchema() on the TS side).
capabilities6repeated stringFree-form capability flags, e.g. "virtual-media", "uefi-http".
retry_safe_operations7repeated stringOperations that are safe to repeat after an interruption, as "<kind>.<operation>".

RunsOn

Where a step or driver runs (PLAN.md §5.1 RunsOn).

ValueNumberDescription
RUNS_ON_UNSPECIFIED0
RUNS_ON_CONTROL_PLANE1
RUNS_ON_SITE2
RUNS_ON_NODE3
RUNS_ON_RAMDISK4

AgentRole

The role carried by an agent's certificate (role OID) and declared in Hello (PLAN.md §6). Not the node's scheduling role (nodes.role: unassigned, host, dedicated, site).

ValueNumberDescription
AGENT_ROLE_UNSPECIFIED0
AGENT_ROLE_NODE1bcd node: every server; 24 h certificate.
AGENT_ROLE_SITE2bcd site: DHCP proxy, iPXE, image cache, BMC access (v0.2); 24 h certificate.
AGENT_ROLE_RAMDISK3bcd ramdisk: PXE commissioning (v0.2); restricted certificate, at most 2 h.

Lane

Command lanes (PLAN.md §6, §7.5). Each lane has its own daemon worker pool and credit budget.

ValueNumberDescription
LANE_UNSPECIFIED0
LANE_CONTROL1Short, latency-sensitive work: diagnostics, inventory, reboots, resets. Default credits 8.
LANE_PROVISION2Provisioning steps: wipe, deploy, kexec (v0.2). Default credits 4.
LANE_BULK3Large transfers and slow jobs: log collection, image pre-warm. Default credits 2.

CommandState

The command lifecycle (PLAN.md §7.4). The control plane stores every state; a daemon reports only ACKED, RUNNING, SUCCEEDED, FAILED, REJECTED and CANCELLED in CommandUpdate.

pending → dispatched(epoch) → acked → running → succeeded | failed | rejected pending → expired (CommandSweeper, past not_after); any non-terminal → cancelled

ValueNumberDescription
COMMAND_STATE_UNSPECIFIED0
COMMAND_STATE_PENDING1Stored, not yet sent. A BUSY rejection returns a command here with a backoff.
COMMAND_STATE_DISPATCHED2Sent on the session with the given epoch.
COMMAND_STATE_ACKED3The daemon journaled it as accepted (fsynced before any side effect).
COMMAND_STATE_RUNNING4The side effect has started.
COMMAND_STATE_SUCCEEDED5
COMMAND_STATE_FAILED6Terminal failure; CommandUpdate.error says why (e.g. "interrupted").
COMMAND_STATE_REJECTED7Refused before any side effect; CommandUpdate.reject_reason says why.
COMMAND_STATE_EXPIRED8Never delivered before not_after (control plane only).
COMMAND_STATE_CANCELLED9Stopped by Cancel between actions. A completed side effect is reported as its real outcome.

CommandRejectReason

Why a daemon refused a command before any side effect (PLAN.md §6 "Checks before accepting").

ValueNumberDescription
COMMAND_REJECT_REASON_UNSPECIFIED0
COMMAND_REJECT_REASON_UNSUPPORTED1Unknown kind, or a kind this agent role may not run.
COMMAND_REJECT_REASON_BAD_SIGNATURE2Missing, unknown-kid or invalid signature on a kind that requires one (destructive, v0.2).
COMMAND_REJECT_REASON_EXPIRED3Past not_after (server time, via the Welcome offset).
COMMAND_REJECT_REASON_STALE_GENERATION4min_generation still not applied at not_after.
COMMAND_REJECT_REASON_BUSY5No free credit on the command's lane. NOT terminal: the control plane puts the command back to pending with not_before = compute_now() + backoff (1 s → 30 s).
COMMAND_REJECT_REASON_BATCH_UNAPPROVED6(v1.0) A destructive command with a batch_id but no valid BatchApproval covering it (too few distinct approver signatures, expired, or an inclusion proof that does not reach scope_root).
COMMAND_REJECT_REASON_UNBATCHED_LIMIT7(v1.0) Over TrustBundle.unbatched_destructive_per_hour.

driver.proto

Package bettercompute.driver.v1, proto/bettercompute/driver/v1/driver.proto.

bcx: the out-of-process driver protocol (PLAN.md §5.5), served by plugins to both bcd and the control plane (externalDriver, remoteDriver).

DriverPlugin

RPCRequestResponseDescription
DescribeDescribeRequestDescribeResponseThe drivers this plugin serves.
ValidateValidateRequestValidateResponseValidate a driver config against the driver's manifest and live checks.
InvokeInvokeRequeststream InvokeResponseRun one operation; streams progress, then exactly one result or error.
Streamstream StreamRequeststream StreamResponseDuplex byte stream for consoles and similar (first request frame is open).
HealthHealthRequestHealthResponse

DescribeRequest

No fields.

DescribeResponse

FieldNumberTypeDescription
drivers1repeated DriverManifest
plugin_version2string
protocol_version3uint32bcx protocol version (1).

ValidateRequest

FieldNumberTypeDescription
driver_id1string
kind2string
config_json3stringDriver config, canonical JSON.
secrets4repeated SecretValueDeclared secret fields only.

ValidateResponse

FieldNumberTypeDescription
valid1bool
issues2repeated ValidationIssue

ValidationIssue

FieldNumberTypeDescription
path1stringJSON pointer into the config.
message2string

SecretValue

One secret field value, delivered only to the plugin that declared it.

FieldNumberTypeDescription
field1stringThe config field name declared with field.secret().
value2bytes

InvokeRequest

FieldNumberTypeDescription
driver_id1string
kind2string
operation3string
config_json4stringDriver config, canonical JSON.
args_json5stringOperation arguments, canonical JSON.
secrets6repeated SecretValue
idempotency_key7string
deadline8google.protobuf.Timestamp
traceparent9stringW3C trace context.

InvokeResponse

FieldNumberTypeDescription
progress1Progress (oneof msg)
result_json2string (oneof msg)The operation's result, canonical JSON. Terminal.
error3DriverError (oneof msg)

Progress

FieldNumberTypeDescription
percent1uint320-100, or 0 when unknown.
phase2string
message3string

DriverError

FieldNumberTypeDescription
code1stringStable lowercase code, e.g. "unsupported", "invalid-config", "timeout", "unreachable".
message2string
retryable3boolThe host may retry the operation (only for retry-safe operations).

StreamRequest

FieldNumberTypeDescription
open1InvokeRequest (oneof msg)First frame: what to open, with the same fields as an Invoke.
data2bytes (oneof msg)
close3StreamClose (oneof msg)

StreamResponse

FieldNumberTypeDescription
data1bytes (oneof msg)
error2DriverError (oneof msg)
close3StreamClose (oneof msg)

StreamClose

FieldNumberTypeDescription
reason1string

HealthRequest

No fields.

HealthResponse

FieldNumberTypeDescription
status1HealthStatus
message2string

HealthStatus

ValueNumberDescription
HEALTH_STATUS_UNSPECIFIED0
HEALTH_STATUS_SERVING1
HEALTH_STATUS_NOT_SERVING2

site.proto

Package bettercompute.site.v1, proto/bettercompute/site/v1/site.proto.

Site agent contracts (bcd site, PLAN.md §3.5, §8.5): boot lease state, proxy-DHCP entries, iPXE scripts, BMC operations and discovery assertions.

SiteSpec

The site section of a site agent's NodeSpec.

FieldNumberTypeDescription
boot1BootLeaseState
cache_images2repeated CacheImageImages the site cache pre-warms (§11.5), from its pools' policy. The agent pulls each one and re-verifies its digest before serving it.
proxy_targets3repeated ProxyTargetThe machines site.httpProxy may reach through this agent, each with its addresses: the source of "an address of target_node_id known to the site" (HttpProxyRequest). The agent refuses a request whose URL host is not one of target_node_id's addresses (IP literals compared as IPs, names compared by name and then by every resolved IP), so a request "about" one node can never reach another machine or a BMC. Contributed for nodes whose profile is agent-less (e.g. Talos).

ProxyTarget

FieldNumberTypeDescription
node_id1string
addresses2repeated stringIP literals or DNS names of the node's API endpoint(s), never a BMC address.

CacheImage

A verified catalog image the site cache holds.

FieldNumberTypeDescription
url1string
sha2562bytesSHA-256 of the image bytes.
format3string"qcow2", "raw", "iso", …

BootLeaseState

The site:<id>:boot lease as published by the SiteBoot controller. Only the active holder answers proxyDHCP, serves iPXE scripts and vouches for discovery. An agent that loses its session self-fences after ttl_ms: it stops all three.

FieldNumberTypeDescription
active1bool
epoch2uint64Lease epoch; every assertion the agent signs carries it, and the control plane rejects older epochs.
ttl_ms3uint32

ProxyDhcpEntry

One machine the active boot server answers for (boot.prepareRamdisk / boot.cleanUp).

FieldNumberTypeDescription
mac1stringPXE MAC, lowercase colon form.
product_uuid2string
arch3BootArch
boot_file4stringFirst-stage boot file served over TFTP or HTTP (e.g. an iPXE build).
ipxe_script_url5stringHTTPS URL of this machine's iPXE script, served by the site agent.
workflow_id6string
not_after7google.protobuf.TimestampServer time after which the entry is dropped.
discovery_token_ref8stringSecret ref of this machine's MAC-bound discovery join token. The site agent fetches it with SecretRequest{workflow_id} and puts it only into the ramdisk's boot parameters it serves, so the token never travels in plaintext in commands.body.
sanboot_sha2569bytes(v1.1) Boot this ISO instead of the ramdisk, for BMC drivers without virtual media (ipmi): the sha256 of a SiteSpec.cache_images entry with format "iso". The machine's iPXE script is then sanboot --no-describe <site agent>/cache/<hex>, the vendor or OS ISO as is (no discovery token, no bc.* parameters). A digest the cache does not hold verified is never answered (the site section fails) rather than falling back to the ramdisk. boot_file still chains iPXE; ipxe_script_url is ignored while this is set.

HttpProxyRequest

site.httpProxy: one HTTPS request made by the site agent on the control plane's behalf, for agent-less profiles (e.g. Talos, PLAN.md §5.6 walkthrough 3) whose API is reachable only inside the site. P5 holds: the control plane never dials into a site. The agent enforces, whatever the command says: the host resolves to an address of target_node_id known to the site (its inventory or BMC network), https only unless the address is on the provisioning VLAN, no redirects, a response cap (default 1 MiB) and the timeout. Anything else fails with "forbidden-target".

FieldNumberTypeDescription
target_node_id1stringThe node the request is about; the target host must be one of its addresses.
url2string
method3string"GET", "POST", "PUT", "DELETE".
headers4repeated HttpProxyHeader
body5bytes
tls_spki_sha2566bytesPinned SubjectPublicKeyInfo SHA-256 of the target's TLS certificate (Talos uses its own CA).
timeout_ms7uint32
secret_headers8repeated HttpProxyHeaderHeaders whose values are secret refs, fetched with SecretRequest and never logged.

HttpProxyHeader

FieldNumberTypeDescription
name1string
value2string

HttpProxyResponse

FieldNumberTypeDescription
status1uint32
headers2repeated HttpProxyHeader
body3bytes
truncated4boolThe body exceeded the cap and was cut.

BootCleanUpRequest

boot.cleanUp: drops the machine's proxy-DHCP entries and iPXE script (workflow cleanup).

FieldNumberTypeDescription
node_id1string
macs2repeated stringPXE MACs whose entries to drop; empty drops every entry of the node.
workflow_id3string

IpxeScriptRequest

The parameters iPXE sends when chainloading (${mac}, ${uuid}, ${buildarch}, ${platform}, …). The site agent matches them against its entries; an unknown machine becomes a discovery event.

FieldNumberTypeDescription
mac1string
uuid2string
ip3string
buildarch4stringiPXE ${buildarch}: "x86_64", "arm64", "i386".
platform5stringiPXE ${platform}: "efi", "pcbios".
serial6string
asset7string

IpxeScript

FieldNumberTypeDescription
script1stringThe rendered script, starting with "#!ipxe". Carries the single-use discovery credential.
not_after2google.protobuf.Timestamp

BmcOperationRequest

A BMC operation run by a site agent through bmclib (steps with runsOn: site).

FieldNumberTypeDescription
driver1string"redfish" or "ipmi" (or a vendor driver).
address2stringHost or URL of the BMC.
credentials_ref3stringSecret ref of the BMC credentials, fetched with SecretRequest; never a value.
operation4string"<kind>.<operation>", e.g. "power.setPower", "management.setBootDevice", "virtual-media.insert", "inspect.inspect".
args_json5stringOperation arguments, canonical JSON.
tls_spki_sha2566bytesSHA-256 of the BMC certificate's SubjectPublicKeyInfo, when pinned.
driver_options_json7stringPer-BMC driver options set at enrollment, canonical JSON (e.g. bcx-ipmi {"cipherSuite": 3} for old BMCs). The site agent hands them to the driver as they are; the driver validates them and refuses unknown keys. Never credentials: those travel only as credentials_ref.

BmcOperationResult

FieldNumberTypeDescription
ok1bool
result_json2stringOperation result, canonical JSON (e.g. {"power":"on"}).
error_code3string
message4string

SignedDiscoveryAssertion

A site agent's statement that a PXE-booted machine asked for a boot from this MAC/IP. It vouches for the ramdisk's discovery join (v0.2). Signing purpose "discovery-assertion", parts [body], by the site agent's node key.

FieldNumberTypeDescription
body1bytesSerialized DiscoveryAssertion.
sig2Signature

DiscoveryAssertion

FieldNumberTypeDescription
site_id1string
site_agent_node_id2stringThe vouching site agent.
boot_lease_epoch3uint64BootLeaseState.epoch held while vouching.
mac4string
ip5string
product_uuid6string
workflow_id7string
issued_at8google.protobuf.Timestamp
not_after9google.protobuf.Timestamp

BootArch

ValueNumberDescription
BOOT_ARCH_UNSPECIFIED0
BOOT_ARCH_BIOS1
BOOT_ARCH_X86_64_EFI2
BOOT_ARCH_ARM64_EFI3
BOOT_ARCH_X86_64_EFI_HTTP4

Was this page helpful?

Better Compute is created by Sean Filimon

Last updated

On this page

commands.protoDiagNvmlRequestDiagNvmlResultGpuDiagnosticDiagnosticCheckInventoryRefreshRequestInventoryRefreshResultLogsCollectRequestHttpHeaderLogsCollectResultNodeRebootRequestNodeRebootResultGpuResetRequestGpuResetResultGpuResetOutcomeDiagDcgmRequestDiagDcgmResultWipeRequestWipeResultDiskWipeDeployImageRequestRootDiskHintDeployImageResultKexecRequestKexecResultDriverInvokeRequestDriverInvokeResultInstanceSnapshotRequestInstanceSnapshotResultWipeModeImageFormatImageCompressioninventory.protoNodeInventoryImagesSectionCachedImageSystemSectionTpmCpuSectionNumaNodeMemorySectionHugepagePoolDimmEdacCountersDisksSectionDiskSmartStatusNicsSectionNicGpusSectionGpuGpuMigMigProfileMigInstanceNvlinkLinkGpuPeerLinkGpuFabricGpuEccEccCountsGpuRowRemapBmcSectionOsSectionCachedImageStateBootModeDiskTransportRdmaTypeLinkStateMigModeGpuLinkTypeCgroupVersionsession.protoAgentGatewayJoinRequestHardwareClaimsJoinResponseJoinResponseBodyJoinDeferralJoinPendingJoinChallengeRenewRequestTpmKeyAttestationRenewResponseAgentFrameServerFrameHelloWelcomeLaneCreditsHeartbeatNodeLoadCommandBatchApprovalBatchProofCommandBodyCommandUpdateCommandErrorCancelDesiredStateDesiredStateBodyNodeSpecHostSectionConfigUnitDevicesSectionDeviceAssignmentResourceLimitsAssignedDeviceInstancesSectionHostVolumeInstanceVolumeInstanceSpecInstancePlacementImageRefInstanceNicAccessSectionTelemetrySectionDaemonSectionSpecRequestStatusReportVolumeStorageDiscoveredMachineHostPressureInstanceStatusSectionStatusConditionInventorySectionEventBatchEventAttestedReportAttestedReportBodyAllocationBoundAllocationReleasedAllocationFailedAckSecretRequestSecretResponseWorkloadTokenRequestWorkloadTokenResponseDrainRevocationNoticeOpenTunnelTunnelFrameTunnelOpenedTerminalSizeTunnelClosedBindingInstanceNetworkPolicyInstanceDesiredStateSpecRequestReasonInstanceObservedStateSectionStateConditionStatuscommon.protoSignatureTrustBundleQuorumTierApproverKeySignedTrustBundleDriverManifestRunsOnAgentRoleLaneCommandStateCommandRejectReasondriver.protoDriverPluginDescribeRequestDescribeResponseValidateRequestValidateResponseValidationIssueSecretValueInvokeRequestInvokeResponseProgressDriverErrorStreamRequestStreamResponseStreamCloseHealthRequestHealthResponseHealthStatussite.protoSiteSpecProxyTargetCacheImageBootLeaseStateProxyDhcpEntryHttpProxyRequestHttpProxyHeaderHttpProxyResponseBootCleanUpRequestIpxeScriptRequestIpxeScriptBmcOperationRequestBmcOperationResultSignedDiscoveryAssertionDiscoveryAssertionBootArch