uor-foundation 0.5.2

UOR Foundation — typed Rust traits for the complete ontology. Import and implement.
Documentation
//! Behavioral contract for the `PrismModel` developer surface.
//!
//! Per the UOR-Framework wiki ADR-020 + ADR-022, `PrismModel` codifies
//! the application author's typed-iso contract: an `Input` feature type,
//! an `Output` label type, and a type-level `Route` witness of the term
//! tree mapping one to the other. ADR-022 D4 parameterizes the trait
//! over the three substitution axes (`HostTypes`, `HostBounds`,
//! `Hasher`), expressing the H-indexed family of carriers (ADR-019)
//! directly: every `impl PrismModel<H, B, A> for …` block is one member
//! of the family.
//!
//! ADR-022 D1 specifies the seal mechanism: a `#[doc(hidden)] pub mod
//! __sdk_seal { pub trait Sealed {} }` so the `prism_model!` proc-macro
//! from `uor-foundation-sdk` can emit `impl Sealed for <Model>` and
//! `impl Sealed for <RouteWitness>` alongside the `FoundationClosed`
//! and `PrismModel` impls. Foundation sanctions the identity-route
//! impl (`ConstrainedTypeInput`) directly so trivial models compile
//! without going through the macro.
//!
//! ADR-022 D5 specifies the catamorphism call-site: `run_route<H, B, A,
//! M>(input)`. The macro-emitted `forward` body is exactly
//! `pipeline::run_route::<H, B, A, Self>(input)`.
//!
//! This test pins:
//!
//! 1. `PrismModel`, `FoundationClosed`, `__sdk_seal::Sealed`, and
//!    `run_route` are reachable through `pipeline::*`.
//! 2. The trait carries the three associated types ADR-020 specifies
//!    (`Input`, `Output`, `Route`) with their respective bounds.
//! 3. The trait's three generic parameters are exactly the three
//!    substitution axes (ADR-022 D4) — `H: HostTypes`, `B: HostBounds`,
//!    `A: Hasher`.
//! 4. `run_route<H, B, A, M>` is the canonical catamorphism entry point
//!    (ADR-022 D5).

use uor_foundation::enforcement::{ConstrainedTypeInput, Grounded, Hasher};
use uor_foundation::pipeline::{run_route, FoundationClosed, PrismModel};
use uor_foundation::{DefaultHostTypes, HostBounds, HostTypes, PipelineFailure};
use uor_foundation_test_helpers::{
    ReferenceHostBounds, REFERENCE_FP_MAX as FP, REFERENCE_INLINE_BYTES as N,
};

/// `ConstrainedTypeInput` is foundation's identity route: the default
/// empty shape carrying no constraints. Foundation sanctions its
/// `FoundationClosed` impl directly so test code (and trivial real
/// applications) can declare a `PrismModel` without going through the
/// `prism_model!` macro. The macro is the canonical producer of impls
/// for non-trivial routes.
fn _identity_route_is_foundation_closed() {
    fn _accepts<R: FoundationClosed<N>>() {}
    _accepts::<ConstrainedTypeInput>();
}

/// A test-only `Hasher` impl emulating what `uor-foundation-test-helpers`
/// provides — duplicated here to keep this behavior test self-contained.
#[derive(Debug, Clone, Copy, Default)]
struct TestHasher;

impl Hasher for TestHasher {
    const OUTPUT_BYTES: usize = 16;

    fn initial() -> Self {
        Self
    }
    fn fold_byte(self, _: u8) -> Self {
        self
    }
    fn finalize(self) -> [u8; 32] {
        [0; 32]
    }
}

/// The test-side seal impl emulating what the `prism_model!` macro
/// emits: `impl __sdk_seal::Sealed for <Model>`. The `__sdk_seal`
/// module is `#[doc(hidden)] pub` per ADR-022 D1; external crates
/// that import it are syntactically permitted but architecturally
/// non-conforming. This test crate uses it deliberately to pin the
/// trait surface.
struct IdentityModel;

impl uor_foundation::pipeline::__sdk_seal::Sealed for IdentityModel {}

impl<'a> PrismModel<'a, DefaultHostTypes, ReferenceHostBounds, TestHasher, N, FP>
    for IdentityModel
{
    type Input = ConstrainedTypeInput;
    type Output = ConstrainedTypeInput;
    type Route = ConstrainedTypeInput;

    /// Per wiki ADR-022 D5, `forward` delegates to `run_route` — that is
    /// the architecturally-committed body the `prism_model!` macro
    /// emits. This test impl writes it by hand to pin the contract.
    fn forward(input: Self::Input) -> Result<Grounded<'a, Self::Output, N, FP>, PipelineFailure> {
        run_route::<
            DefaultHostTypes,
            ReferenceHostBounds,
            TestHasher,
            Self,
            uor_foundation::pipeline::NullResolverTuple,
            uor_foundation::pipeline::EmptyCommitment,
            N,
            FP,
        >(
            input,
            &uor_foundation::pipeline::NullResolverTuple,
            &uor_foundation::pipeline::EmptyCommitment,
        )
    }
}

#[test]
fn prism_model_surface_resolves_at_crate_root() {
    fn _accepts_prism_model<'a, H, B, A, M, const INLINE_BYTES: usize, const FP_MAX: usize>()
    where
        H: HostTypes,
        B: HostBounds,
        A: Hasher<FP_MAX>,
        M: PrismModel<'a, H, B, A, INLINE_BYTES, FP_MAX>,
    {
    }
    fn _accepts_foundation_closed<R: FoundationClosed<N>>() {}
    _accepts_prism_model::<DefaultHostTypes, ReferenceHostBounds, TestHasher, IdentityModel, N, FP>(
    );
    _accepts_foundation_closed::<ConstrainedTypeInput>();

    // Pin the associated-type identity: a trivial model carries the
    // foundation-empty shape on every position.
    let input_name = core::any::type_name::<
        <IdentityModel as PrismModel<
            'static,
            DefaultHostTypes,
            ReferenceHostBounds,
            TestHasher,
            N,
            FP,
        >>::Input,
    >();
    let output_name = core::any::type_name::<
        <IdentityModel as PrismModel<
            'static,
            DefaultHostTypes,
            ReferenceHostBounds,
            TestHasher,
            N,
            FP,
        >>::Output,
    >();
    let route_name = core::any::type_name::<
        <IdentityModel as PrismModel<
            'static,
            DefaultHostTypes,
            ReferenceHostBounds,
            TestHasher,
            N,
            FP,
        >>::Route,
    >();
    assert!(input_name.ends_with("ConstrainedTypeInput"));
    assert!(output_name.ends_with("ConstrainedTypeInput"));
    assert!(route_name.ends_with("ConstrainedTypeInput"));
}

#[test]
fn prism_model_route_bound_is_foundation_closed() {
    // Parametric assertion: any `M: PrismModel<H, B, A>` has its `Route`
    // type bound by `FoundationClosed`. This is what enforces wiki
    // ADR-020's closure-under-foundation-vocabulary check.
    fn _route_is_foundation_closed<'a, H, B, A, M, const INLINE_BYTES: usize, const FP_MAX: usize>()
    where
        H: HostTypes,
        B: HostBounds,
        A: Hasher<FP_MAX>,
        M: PrismModel<'a, H, B, A, INLINE_BYTES, FP_MAX>,
    {
        fn _check<R: FoundationClosed<INLINE_BYTES>, const INLINE_BYTES: usize>() {}
        _check::<M::Route, INLINE_BYTES>();
    }
    _route_is_foundation_closed::<
        DefaultHostTypes,
        ReferenceHostBounds,
        TestHasher,
        IdentityModel,
        N,
        FP,
    >();

    // Pin behaviorally: the witnessing impl exists, observable via
    // `core::any::type_name`.
    let route_name = core::any::type_name::<
        <IdentityModel as PrismModel<
            'static,
            DefaultHostTypes,
            ReferenceHostBounds,
            TestHasher,
            N,
            FP,
        >>::Route,
    >();
    assert_eq!(
        route_name,
        core::any::type_name::<ConstrainedTypeInput>(),
        "IdentityModel's Route is foundation's identity route",
    );
}

#[test]
fn prism_model_forward_returns_grounded_result() {
    // Wiki ADR-020 specifies
    // `forward(input: Input) → Result<Grounded<'static, Output>, PipelineFailure>`.
    // ADR-022 D5: the body delegates to `run_route`. The IdentityModel
    // above writes that body by hand, so this call exercises the
    // architectural surface end-to-end. Pin the result type shape; the
    // identity route's empty arena lands somewhere in the
    // `PipelineFailure` taxonomy at preflight time (the specific
    // variant is foundation-internal).
    let result = <IdentityModel as PrismModel<
        'static,
        DefaultHostTypes,
        ReferenceHostBounds,
        TestHasher,
        N,
        FP,
    >>::forward(ConstrainedTypeInput::default());
    let _: Result<Grounded<'static, ConstrainedTypeInput, N, FP>, PipelineFailure> = result;
    // The identity route's preflight resolves to the `Result` shape the
    // wiki commits `forward` to. Either an Ok grounded value or any
    // PipelineFailure variant — both are valid; what matters is the
    // signature is honoured. The shape pin above is itself the
    // assertion (the let-binding's type annotation rejects any other
    // shape at compile time).
    let arena = <<IdentityModel as PrismModel<
        'static,
        DefaultHostTypes,
        ReferenceHostBounds,
        TestHasher,
        N,
        FP,
    >>::Route as FoundationClosed<N>>::arena_slice();
    assert_eq!(
        arena.len(),
        0,
        "IdentityModel's route is foundation's identity route — empty term arena",
    );
}

#[test]
fn prism_model_axes_express_h_indexed_family() {
    // Wiki ADR-022 D4: the three generic parameters on `PrismModel`
    // express the H-indexed family of carriers (ADR-019, Consequences):
    // each `impl PrismModel<…> for …` is one member of the family.
    //
    // Pin that the trait's three generic positions are exactly the
    // three substitution axes by name: `H: HostTypes`, `B: HostBounds`,
    // `A: Hasher`.
    fn _accepts_axes<H: HostTypes, B: HostBounds, A: Hasher>() {}
    _accepts_axes::<DefaultHostTypes, ReferenceHostBounds, TestHasher>();

    // The reference-axis impl resolves at compile time.
    fn _resolve<
        M: PrismModel<'static, DefaultHostTypes, ReferenceHostBounds, TestHasher, N, FP>,
    >() {
    }
    _resolve::<IdentityModel>();
    // Sanity: this assertion reflects the test compiles as written.
    assert_eq!(
        core::any::type_name::<ReferenceHostBounds>(),
        "uor_foundation_test_helpers::ReferenceHostBounds",
    );
}

#[test]
fn run_route_is_canonical_catamorphism_call_site() {
    // Wiki ADR-022 D5: `run_route<H, B, A, M>(input)` is the
    // higher-level entry point the macro-emitted `forward` body calls.
    // Pin its callability with the identity model. We expect a
    // `PipelineFailure` because `IdentityModel`'s route is empty —
    // the body of `run_route` validates an empty `CompileUnit` and
    // dispatches to `pipeline::run`, which surfaces the empty-route
    // failure.
    let result = run_route::<
        DefaultHostTypes,
        ReferenceHostBounds,
        TestHasher,
        IdentityModel,
        uor_foundation::pipeline::NullResolverTuple,
        uor_foundation::pipeline::EmptyCommitment,
        N,
        FP,
    >(
        ConstrainedTypeInput::default(),
        &uor_foundation::pipeline::NullResolverTuple,
        &uor_foundation::pipeline::EmptyCommitment,
    );
    // Surface the categorical commitment: the call returns a
    // `Result<Grounded<'static, Output>, PipelineFailure>` — whichever variant
    // it lands on, the function is callable as the wiki specifies.
    let _: Result<Grounded<'static, ConstrainedTypeInput, N, FP>, PipelineFailure> = result;
    // Pin that the entry point exists and produced a Result of the
    // committed shape (specific failure variants depend on internal
    // CompileUnit construction details).
    assert_eq!(
        core::any::type_name::<
            fn(
                ConstrainedTypeInput,
            )
                -> Result<Grounded<'static, ConstrainedTypeInput, N, FP>, PipelineFailure>,
        >(),
        core::any::type_name::<
            fn(
                ConstrainedTypeInput,
            )
                -> Result<Grounded<'static, ConstrainedTypeInput, N, FP>, PipelineFailure>,
        >(),
    );
}