chio-kernel 0.1.2

Chio runtime kernel: capability validation, guard evaluation, receipt signing
Documentation
#![allow(clippy::expect_used, clippy::unwrap_used)]

use std::collections::BTreeSet;

use chio_kernel::otel::{
    attribute_cardinality, build_gen_ai_tool_call_span, is_locked_attribute, AttributeCardinality,
    GenAiToolCallSpanInput, ATTRIBUTE_VALUE_MAX_CHARS, ATTR_CHIO_RECEIPT_ID,
    ATTR_GEN_AI_RESPONSE_FINISH_REASONS, ATTR_GEN_AI_SYSTEM, ATTR_GEN_AI_TOOL_CALL_ID,
    ATTR_GEN_AI_USAGE_INPUT_TOKENS, ATTR_GEN_AI_USAGE_OUTPUT_TOKENS, FINISH_REASONS_MAX_CHARS,
    GEN_AI_TOOL_CALL_LOCKED_ATTRIBUTES, GEN_AI_TOOL_CALL_OPERATION_NAME,
    GEN_AI_TOOL_CALL_SPAN_NAME, OTEL_SEMCONV_SCHEMA_URL,
};
use proptest::prelude::*;

#[test]
fn locked_span_shape_matches_m10_contract() {
    assert_eq!(
        OTEL_SEMCONV_SCHEMA_URL,
        "https://opentelemetry.io/schemas/1.31.0"
    );
    assert_eq!(GEN_AI_TOOL_CALL_SPAN_NAME, "gen_ai.tool.call");
    assert_eq!(GEN_AI_TOOL_CALL_OPERATION_NAME, "tool.call");

    let keys: BTreeSet<&str> = GEN_AI_TOOL_CALL_LOCKED_ATTRIBUTES.into_iter().collect();
    assert_eq!(keys.len(), GEN_AI_TOOL_CALL_LOCKED_ATTRIBUTES.len());
    for key in GEN_AI_TOOL_CALL_LOCKED_ATTRIBUTES {
        assert!(is_locked_attribute(key), "locked key rejected: {key}");
        assert!(
            attribute_cardinality(key).is_some(),
            "missing cardinality class for {key}"
        );
    }
}

#[test]
fn builder_emits_only_locked_attributes() {
    let span = build_gen_ai_tool_call_span(GenAiToolCallSpanInput {
        system: "openai",
        request_model: Some("gpt-5.4"),
        tool_call_id: "call-1",
        tool_name: "file_search",
        finish_reasons: &["tool_calls"],
        usage_input_tokens: Some(11),
        usage_output_tokens: Some(7),
        chio_receipt_id: Some("rcpt-1"),
        chio_kernel_id: Some("kernel-1"),
        chio_server_id: Some("server-1"),
        chio_agent_id: Some("agent-1"),
    });

    assert_eq!(span.name, GEN_AI_TOOL_CALL_SPAN_NAME);
    assert_eq!(span.schema_url, OTEL_SEMCONV_SCHEMA_URL);
    for key in span.attribute_keys() {
        assert!(is_locked_attribute(key), "unexpected attribute {key}");
    }
}

proptest! {
    #[test]
    fn dynamic_attribute_values_are_bounded(raw in "[A-Za-z0-9_./:-]{0,512}") {
        let finish_reason = raw.as_str();
        let span = build_gen_ai_tool_call_span(GenAiToolCallSpanInput {
            system: &raw,
            request_model: Some(&raw),
            tool_call_id: &raw,
            tool_name: &raw,
            finish_reasons: &[finish_reason],
            usage_input_tokens: Some(usize::MAX as u64),
            usage_output_tokens: Some(usize::MAX as u64),
            chio_receipt_id: Some(&raw),
            chio_kernel_id: Some(&raw),
            chio_server_id: Some(&raw),
            chio_agent_id: Some(&raw),
        });

        for attribute in span.attributes {
            prop_assert!(is_locked_attribute(attribute.key));
            match &attribute.value {
                serde_json::Value::String(value) => {
                    prop_assert!(
                        value.chars().count() <= ATTRIBUTE_VALUE_MAX_CHARS,
                        "{} exceeded limit {} with {} chars",
                        attribute.key,
                        ATTRIBUTE_VALUE_MAX_CHARS,
                        value.chars().count()
                    );
                }
                serde_json::Value::Array(values) => {
                    prop_assert_eq!(attribute.key, ATTR_GEN_AI_RESPONSE_FINISH_REASONS);
                    for value in values {
                        let value = value.as_str().unwrap_or_default();
                        prop_assert!(
                            value.chars().count() <= FINISH_REASONS_MAX_CHARS,
                            "{} exceeded limit {} with {} chars",
                            attribute.key,
                            FINISH_REASONS_MAX_CHARS,
                            value.chars().count()
                        );
                    }
                }
                serde_json::Value::Number(_) => {
                    prop_assert!(
                        attribute.key == ATTR_GEN_AI_USAGE_INPUT_TOKENS
                            || attribute.key == ATTR_GEN_AI_USAGE_OUTPUT_TOKENS
                    );
                }
                other => prop_assert!(false, "unexpected value type for {}: {other:?}", attribute.key),
            }
        }
    }
}

#[test]
fn high_cardinality_keys_are_restricted_to_ids() {
    let high: BTreeSet<&str> = GEN_AI_TOOL_CALL_LOCKED_ATTRIBUTES
        .into_iter()
        .filter(|key| attribute_cardinality(key) == Some(AttributeCardinality::High))
        .collect();
    assert_eq!(
        high,
        BTreeSet::from([ATTR_GEN_AI_TOOL_CALL_ID, ATTR_CHIO_RECEIPT_ID])
    );
    assert_eq!(
        attribute_cardinality(ATTR_GEN_AI_SYSTEM),
        Some(AttributeCardinality::Low)
    );
    assert_eq!(
        attribute_cardinality(ATTR_GEN_AI_USAGE_INPUT_TOKENS),
        Some(AttributeCardinality::Bounded)
    );
    assert_eq!(
        attribute_cardinality(ATTR_GEN_AI_USAGE_OUTPUT_TOKENS),
        Some(AttributeCardinality::Bounded)
    );
}