On this page
Reading a public origin report
The report of a public origin, field by field.
stado web origin status [NAME] --json emits an array of
stado.public-origin-report.v1 rows — one per declaration, or one for the name
given — and exits non-zero when any row's verdict is not serving.
[
{
"schema": "stado.public-origin-report.v1",
"name": "release-object",
"hostname": "example-host.example-tailnet.ts.net",
"origin": "https://example-host.example-tailnet.ts.net",
"target": "example-host",
"publication": "tailscale-funnel",
"upstream": "http://upstream.example",
"paths": ["/api/release/object"],
"verdict": "origin-not-public",
"origin_error": "example-host.example-tailnet.ts.net has no public A or AAAA record, so nothing outside this deployment's own network can reach that origin, whatever it is serving",
"resolution": { "state": "dns_unresolved", "resolver": "…", "answers": [], "detail": "…" },
"publication_state": {
"state": "published",
"published_paths": ["/api/release/object"],
"missing_paths": [],
"funnel_enabled": true,
"detail": "…"
},
"edge_selection": {
"state": "agrees",
"origin": "https://example-host.example-tailnet.ts.net",
"endpoint": "https://stado.wisent.com/api/release/origin",
"detail": "…"
}
}
]
That row is a failure reported rather than guessed: the node publishes the
path, and the name is still not public. origin_error is the one sentence for
the verdict, or null when there is nothing wrong to say.
Each registry, public-edge, actual release-proxy, public-DNS and host-publication
read has a ten-second budget. Independent reads run together; a failed source
does not discard completed readings. registry_observation, observations,
edge_selection.observation and edge_selection.readback_observation retain the
operation, source, start and finish times, elapsed milliseconds, budget, state
and actual error. A report that cannot complete uses complete: false and
diagnostic-incomplete, not a conclusion that the origin is down. If the registry
cannot be read, the row still carries the public edge and release-proxy results,
but its declaration fields are absent.
Verdicts
verdict |
What it means |
|---|---|
serving |
Public resolution and publication agree with the selected origin, and a request through the actual public release proxy received an authoritative object response. This is channel evidence, not proof that a particular artifact exists. |
origin-undeclared |
The registry carries no public_origins entry of that name. Nothing was measured, because nothing was declared. When the public edge named no origin either, or named one that is not a URL with a host, hostname and origin are null, never empty text. |
origin-not-public |
The name has no public A or AAAA record. Nothing outside this deployment's network can reach it, whatever the node is serving. |
resolver-unavailable |
The public resolver could not be asked. That is not evidence the name is missing, and it is never reported as one. |
origin-unpublished |
The name resolves, but the target's publication does not carry every declared path. missing_paths names which. |
origin-unreachable |
The target, edge or origin read-back could not be obtained, failed, or supplied no usable read-back evidence. |
origin-mismatch |
The deployment's own selected origin is not the declared one, so the public edge is fetching something this document does not describe. |
diagnostic-incomplete |
At least one diagnostic source failed or exceeded its read budget. Completed measurements remain available; missing data is not proof that the origin or host is down. |
resolution.state
The registry-origin DNS reader reports the three states defined by
channels. The deployment's originDiagnosis additionally
uses dns_not_required for a literal IP address, with no invented DNS answer.
resolution.state |
What it means |
|---|---|
dns_unresolved |
The resolver answered, and the name has no public A or AAAA record. |
dns_resolved |
The resolver answered and the name has public records; answers carries them, and the detail names the resolver that said so. It states nothing about whether a client can read the origin: that is what a read reports, and the public edge's own diagnosis carries a second read with the status or the error it got. |
dns_unavailable |
The resolver itself could not be asked. A resolver that did not answer says nothing about the name. |
publication_state.state
For tailscale-funnel: published when the target's Funnel configuration
carries every declared path, unpublished when it carries some or none —
missing_paths names them — and unknown when the target could not be asked.
funnel_enabled is that node's own answer about Funnel, never an inference from
the DNS result. For web-edge: published with web_declaration and edge
when a web declaration owns the hostname, and unpublished with the refusal
that names the command creating one when none does.
edge_selection.state
Read from /api/release/origin on the public deployment: agrees when the
origin it selected is the declared one, differs when it selected another,
undeclared when it has no origin configured at all, and unreadable when
that route could not be read.
An origin release clients read directly — api.url (STADO_API_URL) is that
origin itself, as it is for every web-edge origin and for a funnel origin
the public deployment does not forward to —
has no second edge in front of it. Its state is agrees, /api/release/origin
is not asked, and the read-back below through that URL is what decides
serving.
edge_selection.readback records a request through the public /api/release/object route itself. Stado uses a fresh, valid release coordinate and accepts only that route's authoritative HTTP 404 document naming the same absent URI. The result retains the requested URI, HTTP status, response and actual failure cause. A missing or failed read cannot become serving merely because configuration matches.
edge_selection.diagnosis retains the deployment's complete DNS queries and socket-level origin probe. That probe may use a different HTTP client and must not replace the original proxy request's result. Its success is not sufficient for serving. Stado Desktop shows the actual public release request, every read's source and error, and the full DNS, TCP, TLS and HTTP evidence in Web → Public origins. To prove availability of specific software bytes, run stado storage get URI DESTINATION for that artifact.
Stado 0.18.0 replaces edge_selection.diagnostic_probe with the complete edge_selection.diagnosis object described above; clients that need the same probe read edge_selection.diagnosis.probe. This is a preview JSON contract change, not a registry or persisted-state migration. Rolling back to 0.17.2 restores the old field. The deployment's GET /api/release/origin returns the complete originDiagnosis independently of the installed CLI version.
Release downloads and authenticated object reads, writes and chunk composition resolve the selected origin through the same public DNS reader used by diagnostics. Every declared public resolver — https://cloudflare-dns.com/dns-query and https://dns.google/resolve — is asked for both A and AAAA at once, and their answers are unioned: one resolver's NXDOMAIN cannot take a download down, and an available address family can serve the request even if the other query fails. resolution.resolver and originDiagnosis.resolver name every resolver asked, and queries carries one entry per resolver and family with the URL that was asked. The diagnosis asks exactly what the read asks, so the two cannot contradict each other. The original URL, HTTP Host, TLS server name and certificate checks are unchanged, and literal IP origins do not require DNS. The independent socket probe still uses the deployment's system resolver: its ENOTFOUND can therefore coexist with a successful public release request, and neither observation replaces the other.
If no usable address is returned by any resolver, the actual request records ORIGIN_DNS_UNRESOLVED when DNS answered without addresses, or ORIGIN_DNS_UNAVAILABLE when every resolver request failed. Its cause includes the resolvers and hostname. The gateway returns HTTP 503; Stado preserves unavailable, exits 69 and does not save that error as a downloaded artifact.
Source: this website