protocol-droid-schema 0.4.1

Per-revision Model Context Protocol wire types generated from the official schema.json for every published revision.
//! Per-revision Model Context Protocol wire types.
//!
//! Every published spec revision is vendored and generated from its official
//! `schema.json`, and the resulting types all coexist in this crate. They are
//! never mutually exclusive: which revision a process speaks is decided at
//! runtime, by negotiation, not by a feature flag chosen at compile time.
//!
//! This crate is data. It performs no I/O, holds no session state, and makes no
//! decisions. Lifting wire messages into the version-agnostic IR and lowering
//! them back is the job of the `protocol-droid` crate, which depends on this
//! one.
//!
//! The layer split below is the project's hexagonal layout, shared by every
//! crate in the workspace:
//!
//! - [`domain`] — pure value objects describing a spec revision.
//! - [`application`] — use cases that operate on those value objects.
//! - [`generator`] — the schema-to-Rust emitter that `build.rs` runs to produce
//!   the per-revision wire types. It is compiled into this crate so its output
//!   can be asserted on by the tests here, and into `build.rs` via `#[path]` so
//!   there is one definition of it rather than two that can drift.
//! - [`adapters::primary`] — driving adapters.
//! - [`adapters::secondary`] — driven adapters: the filesystem and the vendored
//!   specification sources they read from.
//!
//! There is deliberately no `ports` module. A port trait is owned by the
//! handler that needs it and lives beside that handler, so a shared port
//! module is never the place for one.

// `dead_code_pub_in_binary` is denied workspace-wide, and a `lib`/`lib test`
// build reports both the generated wire types (the codec layer that consumes
// them lands in T08) and the generator (consumed by `build.rs` via `#[path]`,
// which a library build cannot see) as unused. Both are the crate's surface,
// not leftovers, and both reach a real caller eventually — so the expectation
// is declared once at the crate root rather than scattered per module, where it
// would be true in one configuration and false in another.
#![cfg_attr(
    test,
    expect(
        dead_code_pub_in_binary,
        reason = "the wire types and the generator are public surface whose \
                  consumers are the codec layer (T08) and build.rs respectively"
    )
)]

pub mod adapters;
pub mod application;
pub mod domain;

/// The schema-to-Rust emitter, compiled for `build.rs` to run.
///
/// Feature-gated because in a normal build nothing in the library calls it:
/// `build.rs` does, through `#[path]`, and the tests that assert on its output
/// do. Exposing it unconditionally would make the whole module look unused to
/// the library's own build, and silencing that with a lint suppression would
/// hide a real signal — that a consumer of the wire types has not arrived yet.
#[cfg(feature = "codegen")]
pub mod generator;

/// The per-revision wire types, generated by `build.rs` from the vendored
/// `schema.json` files.
///
/// All six revisions are compiled unconditionally and coexist: which one a
/// process speaks is negotiated at runtime, not chosen at compile time.
///
/// # Why the modules are exempt from `dead_code` in a test build
///
/// The library's test target compiles all six revisions but references almost
/// none of them, so `dead_code` reports thousands of unused items. They are the
/// crate's public surface, not leftovers, and the only real consumer — the
/// codec layer in `protocol-droid` — has not been written yet (it is T08). The
/// expectation is scoped to the test build for that reason: in a normal library
/// build these are reachable from outside and no suppression applies.
pub mod wire {
    include!(concat!(env!("OUT_DIR"), "/wire.rs"));
}

pub use application::{VerifyError, verify_vendored_specs};
pub use domain::manifest::{Manifest, ManifestError, RevisionSpec};