Learn Search docs

Stations & the Conductor

A Station is the hard control-plane isolation boundary a Conductor occupies. It is not Bindle ⊂ Camp ⊂ Yard ⊂ Junction containment. The Conductor (sometimes called the broker in lower-level surfaces) is a pure runtime that mounts a Station client + active Rail(s), runs resolve/scale/deliver, and emits receipts that pin stationId + railHash (+ catalog/policy hashes). It owns no durable Connections or policy packs — the Station does.

Station owns

AssetRole
ConnectionsAuthorized dial/control relationships
RailsContent-addressed profiles / pins
Bootstrap RailInitial trusted least-privilege profile
Local client stateUnder HOBO_HOME/stations/

Authoring and ops surfaces: station() helpers, Rails, local client, and Privileged Access Gateway hooks.

Station CLI (ops/setup)

hobo station init|up|down|status|rails *

These are ops, not app lifecycle verbs. Missing Station fails closed for control-plane work — run hobo station init.

Profile requirements

FieldRole
defaultStationWhich Station is active
activeRailWhich Rail pins policy/profile
defaultBrokerUriRemote Conductor HTTP endpoint only — not a setup path

Cross-Station Connection use fails closed without federation grant.

PAM

Privileged Access Gateway sessions can be Station-aware — break-glass paths still audit.


The Conductor

Somebody has to decide which provider hosts your bindle, whether a deploy is allowed, whether it fits the budget, whether it breaks a downstream contract, whether the app scales up or down to zero. That somebody is the Conductor — the one who decides which train you’re riding. In code: broker (Conductor). Same component.

The Conductor decides only from the policies it is configured to maintain, while occupying a Station.

What it does

It takes a brokering request — “place these resources for this bindle, in this scope” — and answers with exactly one of:

  • a Resolution Receipt: per-resource placements (provider, region, SKU, price), pinned to content hashes of the provider catalog and the policy set — optionally Ed25519-signed; or
  • a Resolution Rejection: machine-readable reasons from a closed rejection catalog, each naming the enforcement plane that refused (policy, contracts, billing, placement, connectors) with a remediation agents can act on.

Placement is brokered per resource, across providers. Spin-up/spin-down (up / down / zero) are Conductor commands; accepted receipts go to delivery (Argo CD Application rendering / live submission when wired).

The five planes it wraps

PlaneWhat it enforcesDefaultAlso shipped
Policyplacement, approvals, junction lockdownsTypeScript policy packsOPA/Rego fail-closed
Contractscan-deploy compatibilityGatekeeper / PACTexternal Pact broker feed
Billingbudget, spend caps, quotasin-proc billing policymetered plane over usage facts
Deliveryrolling out accepted receiptsrendered Argo Applicationslive Argo CD API, fail-closed
Connectorsexternal systems the Conductor may act throughconnector registryexternal catalog

Unreachable external policy engines fail closed — no engine, no placement.

Policies are layered — lockdowns win

Merge outside-in: junction → yard → camp → bindle. Choice-shaped fields can be overridden by narrower scopes; restrictions accumulate (denied providers stay denied). Junction broker-admin lockdowns cannot be relaxed by bindle policy.

Connector registry

Connectors (GitHub App, Pulumi, Azure, Vercel, Cloudflare, …) are registered with credentialRef pointers only — never secrets in the registry. The Conductor brokers short-lived access through identity/Station connections.

CLI

hobo broker config [--init]
hobo broker up

Requires Station context when available (HOBO_STATION / profile / --station). With no cloud config, the local machine can register as a zero-cost local provider host so the loop is testable offline.

Control plane · Security · Matching · CLI · Connectivity