bus-integration-node
Node Integration Contract
bus-integration-node defines generic Bus node event contracts. It covers
inside-the-machine work after a cloud provider has created or discovered a
host.
Run the discovery commands after installing the matching release binary. No SSH
credentials are required for these local contract checks. --events prints one
event name per line, --events --format json prints transport, event, and
direct-bootstrap capability metadata, and --self-test prints
OK bus-integration-node self-test.
bus-integration-node --events
bus-integration-node --events --format json
bus-integration-node --self-test
Node request and response events include:
-
bus.node.bootstrap.requestandbus.node.bootstrap.response: request fields include node id, transport target reference, packages, directories, credential references, and services; responses include applied actions, diagnostics, and error class. -
bus.node.harden.requestandbus.node.harden.response: request fields include node id, SSH policy, firewall policy, service account rules, and confirmation; responses include hardening actions and diagnostics. -
bus.node.status.requestandbus.node.status.response: request fields identify the node; responses include reachability, service state, and last diagnostic details. -
bus.node.verify.requestandbus.node.verify.response: request fields include node id and expected listeners/services; responses includeok, check results, and first failing check.
The integration uses bus-integration-ssh-runner for remote command execution
instead of embedding SSH transport details in operator or API-provider modules.
Operators normally send these requests through bus operator node or the
internal bus-api-provider-node route. Direct event publishers send the JSON
payload to the Bus Events API with the matching event type, for example
POST /api/v1/events on bus-api-provider-events with a bearer token that has
event publish scope. Set $BUS_EVENTS_API_BASE_URL to the Bus Events provider
base URL, for example https://example.test, and set $BUS_EVENTS_TOKEN to a
token with events:write for publish and events:read for streaming. Include
a correlation_id field in the event envelope. A bus-integration-node
worker or bus-api-provider-node route must already be running and subscribed;
otherwise the event can be stored but no node action or response event appears.
The node inventory must be configured where that worker or provider resolves
target_ref; exporting BUS_NODE_TARGETS_FILE in the publisher shell is only
valid when the same shell starts the local worker. For a service-managed worker,
install the inventory on the worker host and restart the worker with that
environment before publishing:
sudo install -m 700 -d /etc/bus
sudo tee /etc/bus/nodes.json >/dev/null <<'EOF'
{
"proxy": {
"host": "10.0.0.10",
"user": "bus",
"port": 22
}
}
EOF
sudo systemctl set-environment BUS_NODE_TARGETS_FILE=/etc/bus/nodes.json
sudo systemctl set-environment BUS_SSH_PRIVATE_KEY_SECRET=secret://deployment/proxy-ssh-key
sudo systemctl restart bus-integration-node
The secret://deployment/proxy-ssh-key secret must already resolve on the
bus-integration-ssh-runner host to a private key accepted by bus@10.0.0.10.
Then publish from the operator shell:
install -m 700 -d ./deploy
cat > ./deploy/node-bootstrap-event.json <<'EOF'
{
"name": "bus.node.bootstrap.request",
"correlation_id": "deploy-001-node-proxy",
"delivery": "broadcast",
"payload": {
"node_id": "proxy",
"transport": "ssh-runner",
"target_ref": "nodes.proxy",
"credentials": {
"ssh_private_key_secret": "secret://deployment/proxy-ssh-key"
},
"dry_run": true,
"confirm": false
}
}
EOF
curl -fsS -X POST "$BUS_EVENTS_API_BASE_URL/api/v1/events" \
-H "Authorization: Bearer $BUS_EVENTS_TOKEN" \
-H "Content-Type: application/json" \
--data @./deploy/node-bootstrap-event.json
Successful publish returns 202 Accepted or 200 OK with stored event
metadata. Consume the matching response event with the same correlation id
through the Events stream endpoint:
curl -fsS -N "$BUS_EVENTS_API_BASE_URL/api/v1/events/stream?name=bus.node.bootstrap.response&delivery=broadcast" \
-H "Authorization: Bearer $BUS_EVENTS_TOKEN" |
grep '"correlation_id":"deploy-001-node-proxy"'
target_ref is resolved by bus-integration-node from deployment inventory.
The nodes.<id> namespace maps to a node entry, for example
nodes.proxy={"host":"10.0.0.10","user":"bus","port":22} from
BUS_NODE_TARGETS_FILE or the running Bus node inventory service.
This is a minimal bus.node.bootstrap.request payload published through the
Bus Events API as the event payload for event type bus.node.bootstrap.request:
{
"node_id": "proxy",
"transport": "ssh-runner",
"target_ref": "nodes.proxy",
"dry_run": true,
"confirm": false,
"packages": ["nginx"],
"directories": ["/etc/bus"],
"credentials": {
"ssh_private_key_secret": "secret://deployment/proxy-ssh-key"
}
}
Minimal node response payloads use this shape:
{
"ok": true,
"node_id": "proxy",
"actions": ["check-ssh", "install-packages"],
"checks": [],
"diagnostics": []
}
Required fields per event are:
-
bus.node.bootstrap.request:node_idstring,transportstring,target_refstring, optionalpackagesstring array, optionaldirectoriesstring array, optionalcredentialsobject, optionaldry_runboolean defaulting totrue, andconfirmboolean. Bootstrap changes are applied only whendry_runisfalseandconfirmistrue. -
bus.node.harden.request:node_idstring,transportstring,target_refstring, optionalssh_policyobject, optionalfirewall_policyobject, optionaldry_runboolean defaulting totrue, andconfirmboolean. Hardening changes are applied only whendry_runisfalseandconfirmistrue. -
bus.node.status.request:node_idstring and optionalchecksstring array. -
bus.node.verify.request:node_idstring andchecksstring array, such as["ssh","systemd","listeners"].
Allowed credentials keys are ssh_private_key_secret,
ssh_private_key_file, sudo_password_secret, and known_hosts_file; inline
secret values are invalid. ssh_policy may contain disable_password_auth
boolean defaulting to true, allow_root_login boolean defaulting to false,
and authorized_key_secret string secret reference. firewall_policy may
contain allowed_ports integer array, default_deny_inbound boolean
defaulting to true, and allow_established boolean defaulting to true.
Every policy object is optional, but unknown keys should fail validation.
Response fields for every node response are ok boolean, node_id string,
actions string array, optional checks array of objects with name, ok,
and diagnostic fields for status/verify responses, diagnostics string
array, and optional error_class string when ok is false. Credential values must be file references or
secret references. ssh_private_key_file is resolved on the SSH runner host,
not on the event publisher’s workstation; when publishing through the Events
API, prefer ssh_private_key_secret such as
secret://deployment/proxy-ssh-key so the runner resolves the credential in
its own environment. Error responses include the first failing action or check.
For example, a failed verify response can include
"diagnostics":["listener 127.0.0.1:8080 is not reachable"] and
"error_class":"verify_failed".
Using from .bus files
Inside a .bus file, call the integration diagnostic command directly:
# same as: bus-integration-node --events
run command -- bus-integration-node --events