pub mod query;
use anyhow::{bail, Result};
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, BTreeSet};
#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum Harness {
Claude,
Codex,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Pin {
pub skill: String,
pub share_id: String,
pub version: String,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct SkillProfile {
pub id: String,
pub public_only: bool,
pub harnesses: Vec<Harness>,
pub pins: Vec<Pin>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Release {
pub pin: Pin,
pub name: String,
pub render_spec: String,
pub public: bool,
pub harnesses: Vec<Harness>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct CatalogueSnapshot {
pub transaction: u64,
pub complete: bool,
pub releases: Vec<Release>,
}
#[derive(Clone, Debug, Serialize)]
pub struct Selection {
pub profile: String,
pub transaction: u64,
pub harnesses: Vec<Harness>,
pub releases: Vec<Release>,
}
fn text(value: &str) -> bool {
!value.is_empty()
&& value.len() <= 2_048
&& !value.chars().any(|c| c.is_control() || c.is_whitespace())
}
fn valid_pin(pin: &Pin) -> bool {
text(&pin.skill)
&& text(&pin.version)
&& pin.share_id.strip_prefix("sha256:").is_some_and(|digest| {
digest.len() == 64
&& digest
.bytes()
.all(|b| b.is_ascii_digit() || (b'a'..=b'f').contains(&b))
})
}
fn harnesses(input: &[Harness]) -> Result<BTreeSet<Harness>> {
let set: BTreeSet<_> = input.iter().copied().collect();
if set.is_empty() || set.len() != input.len() {
bail!("empty or duplicate harness selection");
}
Ok(set)
}
pub fn select(profile: &SkillProfile, snapshot: &CatalogueSnapshot) -> Result<Selection> {
if !text(&profile.id) || !snapshot.complete || snapshot.transaction == 0 {
bail!("profile or transaction-pinned catalogue is unavailable");
}
if profile.pins.is_empty() || profile.pins.len() > 128 || snapshot.releases.len() > 1_024 {
bail!("skill selection exceeds its bounded contract");
}
let requested = harnesses(&profile.harnesses)?;
let mut catalogue = BTreeMap::new();
for release in &snapshot.releases {
if !valid_pin(&release.pin)
|| !text(&release.render_spec)
|| release.name.is_empty()
|| release.name.len() > 64
|| !release
.name
.bytes()
.all(|b| b.is_ascii_lowercase() || b.is_ascii_digit() || b == b'-')
{
bail!("invalid skill release metadata");
}
harnesses(&release.harnesses)?;
let key = (&release.pin.skill, &release.pin.share_id);
if catalogue.insert(key, release).is_some() {
bail!("ambiguous skill release metadata");
}
}
let mut selected = BTreeMap::new();
let mut names = BTreeSet::new();
for pin in &profile.pins {
if !valid_pin(pin) {
bail!("invalid profile pin");
}
let release = catalogue
.get(&(&pin.skill, &pin.share_id))
.ok_or_else(|| anyhow::anyhow!("pinned skill release is unavailable"))?;
if pin.version != release.pin.version
|| (profile.public_only && !release.public)
|| !requested.is_subset(&harnesses(&release.harnesses)?)
{
bail!("pinned release does not satisfy the profile");
}
if selected
.insert(pin.skill.clone(), (**release).clone())
.is_some()
|| !names.insert(release.name.clone())
{
bail!("duplicate skill identity or destination name");
}
}
Ok(Selection {
profile: profile.id.clone(),
transaction: snapshot.transaction,
harnesses: requested.into_iter().collect(),
releases: selected.into_values().collect(),
})
}
#[cfg(test)]
mod tests;