On this page
When the stable bind is gone
A release-controlled product declares one consumer-facing stable_bind and
two candidate_ports under
release_control.products.<product>.targets.<host>. Read those values from
the selected registry; do not copy a port from another deployment.
Consumers use the stable bind. The release agent brings up a candidate,
probes its readiness_path, and switches the stable proxy only after that
candidate qualifies.
The release agent is the only thing that publishes a stable bind. The
legacy launchd daemon named by legacy_launchd_label does not: in a settled
blue-green state that daemon is the live candidate, so restarting it moves
nothing and only interrupts the running service. stado repair stado --step host reports
candidate_live:<port> for exactly that case and touches nothing.
Why a namespace declared without its grant takes the stable binds down
The agent learns which ports to publish from release_control in the
canonical registry, which it reads through the object API. The object API
gates every non-release object read on its object authorization boundary, and
that boundary is open only while the host's object verifier holds a read on
the Skarbiec item of every namespace in object_api.namespaces. One
namespace declared without its item in the grant closes the whole boundary,
and the host's log says so:
object authorization boundary revalidation failed: Skarbiec deployment configuration:
object verifier grant item set mismatch (missing=[<namespace-credential-item>], unexpected=[])
The object and release verifiers keep no credential through a failed vault
read: the request is answered 503 object authorization unavailable. A
last-known-good registry may keep existing processes serving while fresh
authority reads fail; its health is not proof that authorization recovered.
The release agent reports when it uses its last-known-good registry and checks
the authoritative store again on each tick. Diagnose the verifier's actual
refusal rather than restarting a process that may currently preserve the
serving path.
The repair
Read the boundary's own reason first, because it names the item:
stado service unit logs com.wisent.stado --host <host> --lines 300 | grep 'object authorization boundary'
Then declare the missing namespace on the machine you are running from —
reconcile-object-verifier computes the item set from the local
configuration, so a namespace that exists only on the host can never be
satisfied from elsewhere — and reconcile the host's grant:
stado config set object_api.namespaces.<ns> '<the same JSON the host declares>'
stado repair stado --step object-verifier --target <host> --json
Read the exact grant report, then prove recovery through the real consumers.
An exact: true grant result alone is not evidence that the stable bind is
serving. Verify in this order:
stado storage stat stado://<queue-namespace>/registry.json # state present, no 503
stado host exec <host> -- lsof -nP -iTCP -sTCP:LISTEN # every stable bind held
stado service unit logs com.wisent.stado.release-agent --host <host> --lines 200 # no infra_down loop
stado service verify --host <host>
stado host config set warns when a declared namespace names an item not
covered by the local configuration. Reconcile the actual declarations rather
than adding an unrelated credential.
The fallback, and its reversal
The release agent first asks the authoritative registry. If that read fails, it reads this host's last-known-good registry and reports both the authority failure and the recovery source. An unreadable cache reports its own cause; a cached document identifying a different host is refused.
This fallback preserves the declared release-control inputs. It does not rewrite consumers to a candidate URL or select a port from an example. Each later tick tries the authority first, so recovery returns to the authoritative declaration without a manual configuration reversal. Read the actual stable-bind and consumer results before accepting recovery. Do not restart a serving candidate merely to recreate its separate proxy.
What now prevents the recurrence
- The release agent falls back to this host's last-known-good
release_controlwhen the authority cannot be read, the way the resolver already did forservice_directory, and saysrelease agent recovery: …when it does. A closed boundary no longer takes the stable binds with it. stado release version convergepolls every declared stable bind of the units it restarted, for up to 120 seconds, and reportsstable_bindswith a verdict per port. It refuses to reportokwhile one isabsent, so a roll can no longer succeed on paper through an outage.stado repair stado --step hostreports every declared stable bind asalready_bound,candidate_live:<port>orrefused:<reason>, and bootstraps only a declared bind that nothing at all is holding.
Source: this website