web.surfaces
The web topology in route-precedence order, with each surface's mount, category, visibility, kind, producer, artifact, runtime feature and the provenance of every value a reader could be surprised by; and which ids are served, published and offered to a person. Answered from the resolution this process serves from, so it cannot disagree with what the router routes or what the home page lists.
The web topology in route-precedence order, with each surface's mount, category, visibility, kind, producer, artifact, runtime feature and the provenance of every value a reader could be surprised by; and which ids are served, published and offered to a person. Answered from the resolution this process serves from, so it cannot disagree with what the router routes or what the home page lists.
- query
- behaviorally_verified
- module web
- #web
- #introspection
Exposure
Where this one definition is reachable. Absence is explicit: a surface not listed does not carry it.
| surface | as |
|---|---|
| MCP | tool majordomus_web_surfaces resource majordomus://web |
| HTTP | GET /api/v1/web/surfaces operationId web.surfaces |
| command line | — |
Schemas
The canonical input and output, from the Rust types; the MCP tool schema and the OpenAPI parameters and responses are derived from these.
input · Empty
No input.
No properties: the capability takes no input.
JSON Schema
{
"additionalProperties": false,
"description": "No input.",
"title": "Empty",
"type": "object"
}output · SurfaceReport
The web surfaces of this repository, as the process that answers resolved them.
| property | type | required | description |
|---|---|---|---|
| findings | array | yes | What validation says about the topology as it stands. Empty is the healthy answer; a finding here is the same one `majordomus web validate` reports, with its remedy. |
| public | array | yes | The ids offered to a person, which is what the home page lists. |
| published | array | yes | The ids a publication holds, in the same order. |
| served | array | yes | The ids a process answers for, in the same order. A surface published and not served is absent here. |
| surfaces | array | yes | Every resolved surface, in route-precedence order: the order a router consults them in, so the first whose mount owns a path is the one that answers it. |
JSON Schema
{
"$defs": {
"Feature": {
"description": "A capability of the running process a surface needs in order to exist.\n\nThe registry describes the effective process, not the maximum one: a build or an\ninvocation that answers no MCP has no MCP surface, and the home page cannot link to\none. Stating the dependency as data is what keeps that automatic.",
"oneOf": [
{
"const": "mcp",
"description": "This process answers MCP over HTTP.",
"type": "string"
},
{
"const": "cockpit",
"description": "This process serves the Cockpit.",
"type": "string"
}
]
},
"Mount": {
"description": "An absolute mount path, without a trailing slash.",
"type": "string"
},
"Provenance": {
"description": "Where a resolved value came from.\n\nKept for every field a consumer can be surprised by, so that `web explain` can answer\n\"why is this mounted here?\" without anybody reading the discovery code.",
"oneOf": [
{
"description": "Read from the capability registry: the routes the executable already declares once.",
"properties": {
"source": {
"const": "registry",
"type": "string"
}
},
"required": [
"source"
],
"type": "object"
},
{
"description": "Read from a producer's own declaration beside its output (`surface.json`).",
"properties": {
"path": {
"description": "The declaration file, repository-relative.",
"type": "string"
},
"source": {
"const": "producer-declaration",
"type": "string"
}
},
"required": [
"source",
"path"
],
"type": "object"
},
{
"description": "Inferred from a file or directory being where the convention says it is.",
"properties": {
"path": {
"description": "What was found, repository-relative.",
"type": "string"
},
"source": {
"const": "filesystem",
"type": "string"
}
},
"required": [
"source",
"path"
],
"type": "object"
},
{
"description": "Inferred from the site generator's own configuration.",
"properties": {
"path": {
"description": "The configuration file, repository-relative.",
"type": "string"
},
"source": {
"const": "site-config",
"type": "string"
}
},
"required": [
"source",
"path"
],
"type": "object"
},
{
"description": "The model's documented default for a value nobody stated.",
"properties": {
"source": {
"const": "default",
"type": "string"
}
},
"required": [
"source"
],
"type": "object"
}
]
},
"Surface": {
"description": "One resolved surface: everything a consumer needs, with the provenance of what it could\nbe surprised by.",
"properties": {
"artifact": {
"description": "The generated directory, repository-relative, for a static surface.",
"type": [
"string",
"null"
]
},
"availability": {
"$ref": "#/$defs/SurfaceAvailability",
"description": "Where the surface's files go and who answers for it."
},
"built_from": {
"description": "The revision the artifact was built from, when its producer recorded one: what\nmakes a stale build a finding rather than a surprise.",
"type": [
"string",
"null"
]
},
"category": {
"$ref": "#/$defs/SurfaceCategory",
"description": "What it is for, which is how a listing groups it."
},
"feature": {
"anyOf": [
{
"$ref": "#/$defs/Feature"
},
{
"type": "null"
}
],
"description": "The runtime capability it needs; absent when the process always has it."
},
"id": {
"description": "Identity, unique across the topology; the selector `--only` and `--exclude` use it.",
"type": "string"
},
"index": {
"description": "The file served for the mount itself, when the surface has one.",
"type": [
"string",
"null"
]
},
"kind": {
"$ref": "#/$defs/SurfaceKind",
"description": "How it answers."
},
"mount": {
"$ref": "#/$defs/Mount",
"description": "Where it answers."
},
"producer": {
"description": "What produced it: a command, a module, or the generator that writes the directory.",
"type": "string"
},
"provenance": {
"additionalProperties": {
"$ref": "#/$defs/Provenance"
},
"description": "Where each interesting value came from, by field name.",
"type": "object"
},
"title": {
"description": "One line: what a reader sees in a listing.",
"type": "string"
},
"visibility": {
"$ref": "#/$defs/SurfaceVisibility",
"description": "Whether a person is shown it."
}
},
"required": [
"id",
"title",
"category",
"visibility",
"kind",
"mount",
"producer",
"availability",
"provenance"
],
"type": "object"
},
"SurfaceAvailability": {
"description": "Whether a surface is part of the static publication, served only while a process runs,\nor both.",
"oneOf": [
{
"const": "both",
"description": "Served by the running executable and published as files.",
"type": "string"
},
{
"const": "served-only",
"description": "Answered by the running executable and never published: a route the process\ncomputes, or a build made for this server's own mount rather than for deployment.",
"type": "string"
},
{
"const": "published-only",
"description": "Published as files; the running executable serves it from the same directory.",
"type": "string"
}
]
},
"SurfaceCategory": {
"description": "What a surface is for, which is how a reader is shown it.\n\nA category is the one piece of intent that a mount cannot carry: `/openapi.json` and\n`/swagger` sit beside each other and are a document and a viewer for it. Grouping is\nderived from this field and never from a list of paths kept somewhere else.",
"oneOf": [
{
"const": "interface",
"description": "Something a person opens and looks at: the home page, the Cockpit.",
"type": "string"
},
{
"const": "documentation",
"description": "Prose and reference written for a person: the site, the Swagger UI.",
"type": "string"
},
{
"const": "api",
"description": "A machine-readable surface of the capability registry.",
"type": "string"
},
{
"const": "protocol",
"description": "A wire protocol another program speaks.",
"type": "string"
},
{
"const": "report",
"description": "Generated evidence of a run: a test report, a benchmark report.",
"type": "string"
}
]
},
"SurfaceFinding": {
"description": "One thing wrong with a topology, said so a person can fix it without reading this file.",
"properties": {
"message": {
"description": "What is wrong.",
"type": "string"
},
"remedy": {
"description": "What to do about it.",
"type": "string"
},
"rule": {
"description": "The rule that produced it, stable enough to grep for.",
"type": "string"
},
"severity": {
"$ref": "#/$defs/SurfaceFindingSeverity",
"description": "How much it matters."
},
"surface": {
"description": "The surface it is about.",
"type": "string"
}
},
"required": [
"severity",
"rule",
"surface",
"message",
"remedy"
],
"type": "object"
},
"SurfaceFindingSeverity": {
"description": "How much a finding matters.",
"oneOf": [
{
"const": "warning",
"description": "Worth reading; serving is still coherent.",
"type": "string"
},
{
"const": "error",
"description": "The topology may not be served or published in this state.",
"type": "string"
}
]
},
"SurfaceKind": {
"description": "How a surface answers a request.\n\nOnly what this repository serves: a directory of generated files, a path the executable\nanswers itself, and a redirect. A new *kind* is a new behaviour, never a new name for\nthe same behaviour with different data.",
"oneOf": [
{
"const": "static-directory",
"description": "A generated directory, mounted under its prefix and served from disk.",
"type": "string"
},
{
"const": "native-route",
"description": "A path the executable answers itself, from its own registry or handlers.",
"type": "string"
},
{
"const": "redirect",
"description": "A path that answers with a redirect to another one.",
"type": "string"
}
]
},
"SurfaceVisibility": {
"description": "Who a surface is offered to.\n\nTwo values and no more: a surface is either offered for a person to discover, or it is\npart of the topology without being advertised. Both are always in the machine-readable\nanswer — hiding a served route from introspection would only hide it from the people\nmaintaining it.",
"oneOf": [
{
"const": "public",
"description": "Listed for a person: it appears on the home page.",
"type": "string"
},
{
"const": "internal",
"description": "Served and introspectable, not advertised: a machine speaks to it, or another\nsurface links to it.",
"type": "string"
}
]
}
},
"description": "The web surfaces of this repository, as the process that answers resolved them.",
"properties": {
"findings": {
"description": "What validation says about the topology as it stands. Empty is the healthy answer;\na finding here is the same one `majordomus web validate` reports, with its remedy.",
"items": {
"$ref": "#/$defs/SurfaceFinding"
},
"type": "array"
},
"public": {
"description": "The ids offered to a person, which is what the home page lists.",
"items": {
"type": "string"
},
"type": "array"
},
"published": {
"description": "The ids a publication holds, in the same order.",
"items": {
"type": "string"
},
"type": "array"
},
"served": {
"description": "The ids a process answers for, in the same order. A surface published and not\nserved is absent here.",
"items": {
"type": "string"
},
"type": "array"
},
"surfaces": {
"description": "Every resolved surface, in route-precedence order: the order a router consults\nthem in, so the first whose mount owns a path is the one that answers it.",
"items": {
"$ref": "#/$defs/Surface"
},
"type": "array"
}
},
"required": [
"surfaces",
"served",
"published",
"public",
"findings"
],
"title": "SurfaceReport",
"type": "object"
}Policies
- benchmark
- required — a target on every transport the exposure declares; the cases are the input type's
- cache
- process — up to 2 entries in the process, 5s each, scoped by the registry fingerprint
Benchmark targets
Derived from the registry for this repository: one requirement per transport, and the cases the input type provides. The whole matrix is on the benchmarks page.