Skip to content

HTTP API: served

Whether a deployment serves the commit it was meant to: the build identity a site serves, read from outside the way a visitor reads it, judged by commit containment and recorded so that a later reader can re-judge it. Only `served` passes; a site that could not be reached, an identity that could not be read, a build from an uncommitted tree and a served commit this clone does not hold are each an unanswered question, never a yes. Observing reaches the network and is a command of the trusted command line; reading the recorded standing is a read on every surface.

Rendered from docs/generated/openapi.json, which the executable generates from its capability registry and CI refuses stale. The raw document is at /openapi.json; a running server serves the same document at its own /openapi.json and Swagger UI at /swagger.

served

Whether a deployment serves the commit it was meant to: the build identity a site serves, read from outside the way a visitor reads it, judged by commit containment and recorded so that a later reader can re-judge it. Only `served` passes; a site that could not be reached, an identity that could not be read, a build from an uncommitted tree and a served commit this clone does not hold are each an unanswered question, never a yes. Observing reaches the network and is a command of the trusted command line; reading the recorded standing is a read on every surface.

GET /api/v1/served served.show

What each deployment was last seen serving

The newest recorded observation of each deployment, re-judged against a commit (HEAD unless named). A record keeps proving every commit its served build contains and stops proving the moment the commit asked about is not among them; a record that received nothing proves nothing. Asks no network and writes nothing.

  • query
  • behaviorally_verified
  • benchmark required
  • cache disabled
  • MCP tool majordomus_served
  • MCP resource {"name": "served", "uri": "majordomus://served"}
  • $ served show

Query parameters

nametyperequireddescriptionexamples
commit string no The commit each record is re-judged against, any revision git resolves; `HEAD` when absent. pages-against-head: "HEAD"
deployment string no Only this deployment. pages-against-head: "pages"

Try it

The port is whatever the server logged; 8741 is the one it asks for first. The values are the operation's first example.

curl -s "http://127.0.0.1:8741/api/v1/served?commit=HEAD&deployment=pages"

Tested by apps/majordomus-cli/tests/http_serve.rs, which replays the route with these values against a server on a real socket.

Responses

statusbodymeaning
200 ServedStanding What each deployment was last seen serving: the result.
400 ErrorBody invalid_input: The input does not fit the schema: a parameter of the wrong type, an unknown one, or a value the capability rejects.
404 ErrorBody not_found: The input names something the repository does not hold.
500 ErrorBody internal: The capability failed for a reason of its own; the message names it.
default ErrorBody Any other failure the transport reports: 405 method_not_allowed for another method on this path, 400 invalid_input for a body that is not a JSON object.

Schemas

The components only this tag's operations use. Each row is the type's own field, its doc comment the description; a type another page owns links there.

BuildIdentity

object
The build identity a deployment serves, as far as this module relies on it. Other fields of the served document are ignored rather than refused: the document is written by another program, and a field it adds is not a malformation.

use majordomus_cli::served::BuildIdentity;
let id = BuildIdentity {
    commit: "a".repeat(40),
    dirty: false,
    source_version: Some("0.7.0".into()),
    source_hash: None,
};
// what is judged is the commit and whether the tree it was built from was committed
assert_eq!(id.commit.len(), 40);
assert!(!id.dirty);
propertytyperequireddescription
commit string yes The full commit the served build was made from.
dirty boolean yes Whether the tree it was built from had uncommitted changes. A dirty build names a commit it does not equal, so it proves no commit.
source_version string | null no The version the build states, when it states one.
source_hash string | null no The fingerprint of the site's canonical inputs, when the build states one.

Used by Observation

DeploymentStanding

object
One deployment's newest record and what it proves about the commit asked. Both are carried: the recorded judgement is what was seen, now is what it still proves.

use majordomus_cli::capability::builtin::served::DeploymentStanding;
use majordomus_cli::served::ServedVerdict;
let json = r#"{"deployment":"pages","observation":{"schema":"majordomus.served-observation/v1",
  "deployment":"pages","url":"https://majordomus.dev/build.json",
  "expected":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","verdict":"served",
  "reason":"the deployment serves aaaaaaaaaaaa","at":"1970-01-01T00:00:00Z"},
  "now":{"verdict":"stale","reason":"it does not contain bbbbbbbbbbbb"}}"#;
let s: DeploymentStanding = serde_json::from_str(json).unwrap();
// seen as served, and no longer proving the commit asked about
assert_eq!(s.observation.judgement.verdict, ServedVerdict::Served);
assert_eq!(s.now.verdict, ServedVerdict::Stale);
propertytyperequireddescription
deployment string yes The deployment name.
observation Observation → Observation yes The newest record of it.
now Judgement → Judgement yes That record re-judged against the commit asked about. This, not the recorded judgement, is what a reader acts on.

Used by ServedStanding

Judgement

object
The judgement of one served identity against one expected commit, with its reason. The reason travels with the verdict so that every surface can say why without re-deriving it.

use majordomus_cli::served::{judge, Fetched, Judgement, ServedVerdict};
let j: Judgement = judge(&Err(Fetched::Unreachable("timeout".into())), &"a".repeat(40), &fake());
assert_eq!(j.verdict, ServedVerdict::Unreachable);
assert!(j.reason.contains("timeout"));
#### use majordomus_cli::served::Ancestry;
#### struct N; impl Ancestry for N {
####     fn has(&self, _: &str) -> Option<bool> { Some(true) }
####     fn contains(&self, _: &str, _: &str) -> Option<bool> { Some(true) }
#### }
#### fn fake() -> impl Ancestry { N }
propertytyperequireddescription
verdict ServedVerdict → ServedVerdict yes The verdict.
reason string yes Why, in one line a reader can act on.

Used by DeploymentStanding

Observation

object
One observation of one deployment, as recorded: what was asked, what was served, what was judged and when. Everything needed to judge it again later is in the record, which is what lets Observation::rejudge answer without probing.

use majordomus_cli::served::{observe, Fetch, Fetched, GitAncestry, Observation, OBSERVATION_SCHEMA};
use std::{path::Path, time::SystemTime};
struct None_;
impl Fetch for None_ {
    fn fetch(&self, _: &str) -> Fetched { Fetched::Unreachable("no route".into()) }
}
let git = GitAncestry { root: Path::new(env!("CARGO_MANIFEST_DIR")) };
let o: Observation = observe("pages", "https://s", "build.json", &"a".repeat(40), &None_,
                              &git, SystemTime::UNIX_EPOCH);
assert_eq!(o.schema, OBSERVATION_SCHEMA);
assert_eq!(o.url, "https://s/build.json");
assert_eq!(o.at, "1970-01-01T00:00:00Z");
propertytyperequireddescription
schema string yes Always OBSERVATION_SCHEMA.
deployment string yes Which deployment: the name the caller observed it under (pages, or a deployment object's id).
url string yes The identity URL probed.
expected string yes The commit that was expected, full.
served BuildIdentity | null → BuildIdentity no What was served, when a build identity was received.
verdict ServedVerdict → ServedVerdict yes The verdict.
reason string yes Why, in one line a reader can act on.
at string yes When, RFC 3339 UTC.

Used by DeploymentStanding

ServedStanding

object
Every deployment's standing against one commit: the answer served.show gives on the command line, over HTTP and to an MCP client, from one derivation.

use majordomus_cli::capability::builtin::served::{standing, ServedStanding};
use majordomus_cli::served::{Ancestry, OBSERVATIONS_PATH};
#### struct A; impl Ancestry for A {
####     fn has(&self, _: &str) -> Option<bool> { Some(true) }
####     fn contains(&self, _: &str, _: &str) -> Option<bool> { Some(true) } }
let dir = tempfile::tempdir().unwrap();
let s: ServedStanding = standing(dir.path(), &"a".repeat(40), None, &A);
assert_eq!(s.observations, OBSERVATIONS_PATH);
assert!(s.deployments.is_empty(), "nothing observed yet");
assert_eq!(s.unreadable, 0);
propertytyperequireddescription
expected string yes The full commit every record was re-judged against.
observations string yes The checkout-local file the records were read from.
unreadable integer (uint) yes Lines of that file that were not readable observations.
deployments array of DeploymentStanding → DeploymentStanding yes One entry per deployment observed, in name order.

Used by served.show

ServedVerdict

"served" | "stale" | "unreachable" | "malformed" | "dirty" | "undecided"
What an observation says about the expected commit. Only ServedVerdict::Served is a proof; the other five are each a different reason the question was not answered yes.

use majordomus_cli::served::ServedVerdict;
// a measured no and an unanswered question are never spelled the same
assert!(ServedVerdict::Served.passes());
assert_eq!(ServedVerdict::Stale.exit_code(), 10);
assert_eq!(ServedVerdict::Unreachable.exit_code(), 12);
  • servedThe served build is the expected commit or contains it. The only passing verdict.
  • staleThe served build does not contain the expected commit: the deployment is behind.
  • unreachableNothing was received. The deployment was not measured.
  • malformedSomething was received and it is not a build identity.
  • dirtyThe served build was made from an uncommitted tree, so it proves no commit.
  • undecidedThe served commit is not in this clone, or git could not be asked; containment is undecided. Fetching the remote usually turns this into an answer.

Used by Judgement Observation

Searches the titles and descriptions of every page this site publishes.