use std::sync::Arc;
use crate::application::registry::store::RegistryStore;
use crate::domain::FeatureProfile;
use crate::domain::registry::{AuthContext, PrimitiveKind, Registered, is_visible};
#[derive(Debug)]
pub struct Listing {
visible: Vec<Arc<Registered>>,
total: usize,
generation: u64,
}
impl Listing {
#[must_use]
pub fn visible(&self) -> &[Arc<Registered>] {
&self.visible
}
#[must_use]
pub const fn total(&self) -> usize {
self.total
}
#[must_use]
pub const fn hidden(&self) -> usize {
self.total.saturating_sub(self.visible.len())
}
#[must_use]
pub const fn generation(&self) -> u64 {
self.generation
}
}
impl RegistryStore {
#[must_use]
pub fn list_visible(
&self,
session: &AuthContext,
profile: &FeatureProfile,
kind: PrimitiveKind,
) -> Listing {
let snapshot = self.snapshot();
let all = snapshot.list(kind);
let total = all.len();
let visible = all
.iter()
.filter(|primitive| is_visible(session, profile, primitive.meta()))
.map(Arc::clone)
.collect();
Listing {
visible,
total,
generation: snapshot.generation(),
}
}
#[must_use]
pub fn get_visible(
&self,
session: &AuthContext,
profile: &FeatureProfile,
kind: PrimitiveKind,
id: &str,
) -> Option<Arc<Registered>> {
let snapshot = self.snapshot();
let registered = snapshot.get(kind, &id.into())?.clone();
is_visible(session, profile, registered.meta()).then_some(registered)
}
}
#[cfg(test)]
mod tests {
use super::RegistryStore;
use crate::domain::registry::TestError;
use crate::domain::registry::{AuthContext, Primitive, PrimitiveKind, Registered, Tool};
use crate::domain::{Feature, FeatureProfile};
fn tool(name: &str) -> Result<Registered, TestError> {
Ok(Registered::from(Primitive::from(Tool::new(
name,
r#"{"type":"object"}"#,
)?)))
}
fn everything() -> FeatureProfile {
FeatureProfile::empty()
.with(Feature::Tools)
.with(Feature::ToolStructuredOutput)
}
#[test]
fn a_listing_is_in_registration_order() -> Result<(), TestError> {
let store = RegistryStore::new();
for name in ["c", "a", "b"] {
store.register(tool(name)?);
}
let session = AuthContext::unrestricted("alice");
let listing = store.list_visible(&session, &everything(), PrimitiveKind::Tool);
let names: Vec<&str> = listing
.visible()
.iter()
.map(|held| held.id().as_str())
.collect();
assert_eq!(names, vec!["c", "a", "b"]);
Ok(())
}
#[test]
fn the_total_counts_what_the_filter_hid() -> Result<(), TestError> {
let store = RegistryStore::new();
let structured = Registered::from(Primitive::from(
Tool::new("structured", r#"{"type":"object"}"#)?
.with_output_schema(r#"{"type":"object"}"#)?,
));
store.register(structured);
store.register(tool("plain")?);
let session = AuthContext::unrestricted("alice");
let without = store.list_visible(
&session,
&FeatureProfile::empty().with(Feature::Tools),
PrimitiveKind::Tool,
);
assert_eq!(without.visible().len(), 1);
assert_eq!(without.total(), 2);
assert_eq!(without.hidden(), 1);
assert_eq!(
without.total(),
without.visible().len() + without.hidden(),
"visible plus hidden must account for every primitive"
);
Ok(())
}
#[test]
fn a_listing_reports_the_generation_it_came_from() -> Result<(), TestError> {
let store = RegistryStore::new();
store.register(tool("a")?);
let session = AuthContext::unrestricted("alice");
let listing = store.list_visible(&session, &everything(), PrimitiveKind::Tool);
assert_eq!(listing.generation(), 1);
Ok(())
}
#[test]
fn a_hidden_primitive_and_an_absent_one_both_read_as_none() -> Result<(), TestError> {
let store = RegistryStore::new();
let guarded = Registered::from(Primitive::from(Tool::new(
"guarded",
r#"{"type":"object"}"#,
)?))
.requiring_scope(crate::domain::registry::Scope::Admin);
store.register(guarded);
let nobody = AuthContext::new("mallory", crate::domain::registry::ScopeSet::empty());
let hidden = store.get_visible(&nobody, &everything(), PrimitiveKind::Tool, "guarded");
let absent = store.get_visible(&nobody, &everything(), PrimitiveKind::Tool, "nope");
assert!(hidden.is_none());
assert!(absent.is_none());
let root = AuthContext::unrestricted("root");
assert!(
store
.get_visible(&root, &everything(), PrimitiveKind::Tool, "guarded")
.is_some(),
"the same lookup must succeed for a principal that does hold the scope"
);
Ok(())
}
}