pub struct Surface {
pub schema: String,
pub origin: Origin,
pub capabilities: BTreeMap<String, PublicCapability>,
}Expand description
The public surface of one tree or one ref.
use majordomus_cli::release::surface::{public_capabilities, Origin, Surface, SURFACE_SCHEMA};
use serde_json::json;
let of = |caps| Surface {
schema: SURFACE_SCHEMA.to_string(),
origin: Origin::WorkingTree,
capabilities: public_capabilities(&json!({"capabilities": caps})),
};
// The same surface enumerated in a different order is the same surface.
let one = of(json!([{"id": "b", "kind": "query"}, {"id": "a", "kind": "query"}]));
let other = of(json!([{"id": "a", "kind": "query"}, {"id": "b", "kind": "query"}]));
assert_eq!(one.fingerprint(), other.fingerprint());Fields§
§schema: StringThe normalisation these capabilities were reduced by.
origin: OriginWhere it was read from.
capabilities: BTreeMap<String, PublicCapability>Every public capability, by id, in a deterministic order.
Implementations§
Source§impl Surface
impl Surface
Sourcepub fn of_registry(registry: &CapabilityRegistry) -> Surface
pub fn of_registry(registry: &CapabilityRegistry) -> Surface
The surface of the current tree, from the live registry.
Never reads the committed projection: a stale docs/generated/registry.json would
make this side of the comparison a description of an older tree, and every verdict
drawn from it wrong in a way nothing else would catch.
use majordomus_cli::capability::registry::CapabilityRegistry;
use majordomus_cli::release::surface::{Origin, Surface};
let registry = CapabilityRegistry::builder().build().expect("an empty registry composes");
let surface = Surface::of_registry(®istry);
assert_eq!(surface.origin, Origin::WorkingTree);Sourcepub fn read_ref(root: &Path, reference: &str) -> Result<Surface, SurfaceError>
pub fn read_ref(root: &Path, reference: &str) -> Result<Surface, SurfaceError>
The surface a ref published, from the registry projection committed at it.
use majordomus_cli::release::surface::{Surface, SurfaceError};
let dir = tempfile::tempdir().unwrap();
// Not a work tree, so there is no such ref — and it says so rather than
// comparing against an empty surface.
assert!(matches!(
Surface::read_ref(dir.path(), "v0.5.0"),
Err(SurfaceError::NoSuchRef { .. })
));Sourcepub fn atoms(&self) -> usize
pub fn atoms(&self) -> usize
How many public atoms this surface carries: the things a caller can hold, counted.
One per capability identity, plus one per binding it answers to. This is what the reports mean by “87 public atoms”; it is a size, never an input to a verdict.
use majordomus_cli::release::surface::{public_capabilities, Origin, Surface, SURFACE_SCHEMA};
use serde_json::json;
let surface = Surface {
schema: SURFACE_SCHEMA.to_string(),
origin: Origin::WorkingTree,
capabilities: public_capabilities(&json!({"capabilities": [{
"id": "a.one", "kind": "query", "visibility": "public",
"exposure": {"mcp": {"tool": "t"}, "http": {"method": "GET", "path": "/x"}}
}]})),
};
assert_eq!(surface.atoms(), 3, "the identity, the tool, the route");Sourcepub fn fingerprint(&self) -> String
pub fn fingerprint(&self) -> String
A stable identity for this surface.
Deterministic, ordering-independent and schema-versioned: the same logical surface hashes the same however the registry enumerated it, because the capabilities are a sorted map and every schema was normalised before it got here. Two trees with the same fingerprint have the same public contract, which is what makes it usable as release evidence rather than decoration.
use majordomus_cli::capability::registry::CapabilityRegistry;
use majordomus_cli::release::surface::Surface;
let registry = CapabilityRegistry::builder().build().expect("an empty registry composes");
let surface = Surface::of_registry(®istry);
assert_eq!(surface.fingerprint(), surface.fingerprint(), "deterministic");
assert!(surface.fingerprint().starts_with("sha256:"));Trait Implementations§
Source§impl<'de> Deserialize<'de> for Surface
impl<'de> Deserialize<'de> for Surface
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for Surface
Source§impl JsonSchema for Surface
impl JsonSchema for Surface
Source§fn schema_id() -> Cow<'static, str>
fn schema_id() -> Cow<'static, str>
Source§fn json_schema(generator: &mut SchemaGenerator) -> Schema
fn json_schema(generator: &mut SchemaGenerator) -> Schema
Source§fn inline_schema() -> bool
fn inline_schema() -> bool
$ref keyword. Read moreimpl StructuralPartialEq for Surface
Auto Trait Implementations§
impl Freeze for Surface
impl RefUnwindSafe for Surface
impl Send for Surface
impl Sync for Surface
impl Unpin for Surface
impl UnsafeUnpin for Surface
impl UnwindSafe for Surface
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.