Skip to main content

trellis_rs/
lib.rs

1//! Curated public Rust facade for Trellis clients, services, contracts, auth, and jobs.
2//!
3//! This crate is the normal Rust authoring entrypoint. It re-exports stable,
4//! commonly used runtime types without exposing low-level service loops,
5//! bootstrap hosts, or generated artifact internals.
6//!
7//! Generated SDK crates and participant facades include a package-local
8//! `TRELLIS.md` for AI-agent use. Prefer descriptor and generated facade APIs:
9//! `TrellisClient::call::<RpcDescriptor>(...)`,
10//! `TrellisClient::publish::<EventDescriptor>(...)`,
11//! `TrellisClient::subscribe::<EventDescriptor>()`,
12//! `TrellisClient::feed::<FeedDescriptor>(input)`,
13//! `TrellisClient::operation::<Operation>().start(...)`, generated wrappers
14//! like `.rpc().group().method(...)`, and service registration through
15//! `handle().rpc().group().method(handler)` where generated.
16//!
17//! Prepared event and outbox/inbox support lives under [`client`]:
18//! `PreparedTrellisEvent`, `prepare_event::<Descriptor>(...)`,
19//! `publish_prepared`, `dispatch_outbox_once`, `OutboxStore`, `InboxStore`,
20//! `SqliteOutboxStore`, `SqliteInboxStore`, `PostgresOutboxStore`,
21//! `PostgresInboxStore`, `NatsKvOutboxStore`, and `NatsKvInboxStore`.
22
23/// Authenticated outbound client runtime types for generated SDKs and normal clients.
24pub mod client;
25
26/// High-level service runtime and service-authoring support types.
27pub mod service;
28
29/// Contract manifest, pagination, and schema helper types.
30pub mod contracts {
31    pub use trellis_contracts::{
32        canonicalize_json, contract_capability_namespace, digest_contract_json,
33        digest_contract_value, digest_json, event, feed, global_capability_name, job_queue, kv,
34        load_json_value, load_manifest, manifest_paths_in_dir, normalize_manifest_value, operation,
35        parse_manifest, project_contract_digest_manifest, rpc, schema_ref, sha256_base64url, state,
36        store, use_contract, validate_catalog, validate_manifest, Catalog, CatalogEntry,
37        CatalogPack, ContractCapabilities, ContractCapabilityMetadata, ContractErrorDecl,
38        ContractErrorRef, ContractEvent, ContractExports, ContractFeed, ContractJobQueueResource,
39        ContractKind, ContractKvResource, ContractManifest, ContractManifestBuilder,
40        ContractOperation, ContractOperationSignal, ContractOperationTransfer,
41        ContractOperationTransferDirection, ContractResources, ContractRpcMethod,
42        ContractRpcTransfer, ContractRpcTransferDirection, ContractSchemaRef, ContractStateKind,
43        ContractStateStore, ContractStoreResource, ContractUseFeed, ContractUseOperation,
44        ContractUsePubSub, ContractUseRef, ContractUseRpc, ContractUses, ContractsError,
45        FeedCapabilities, LoadedManifest, OperationCapabilities, PageRequest, PageResponse,
46        PubSubCapabilities, RpcCapabilities, CATALOG_FORMAT_V1, CONTRACT_FORMAT_V1,
47    };
48}
49
50/// Public authentication flows, session helpers, and auth protocol types.
51pub mod auth;
52
53/// Service-local jobs runtime types for service authors.
54pub mod jobs;
55
56/// Public facades for Trellis-owned generated contract SDKs.
57pub mod sdk {
58    /// Auth contract SDK surface.
59    pub mod auth;
60
61    /// Core contract SDK surface.
62    pub mod core;
63
64    /// Health contract SDK surface.
65    pub mod health;
66
67    /// Jobs contract SDK surface.
68    pub mod jobs;
69
70    /// State contract SDK surface.
71    pub mod state;
72}
73
74#[cfg(test)]
75mod tests {
76    use std::fs;
77
78    #[test]
79    fn exposes_core_facade_modules() {
80        let _request = crate::contracts::PageRequest {
81            offset: None,
82            limit: 25,
83        };
84        let _options =
85            crate::service::ServiceConnectOptions::new("http://localhost:8080", "svc", "seed");
86        let _state = crate::jobs::JobState::Pending;
87    }
88
89    #[test]
90    fn low_level_workspace_crates_are_not_publishable_packages() {
91        let crate_dir = std::path::Path::new(env!("CARGO_MANIFEST_DIR"));
92        let crates_dir = crate_dir
93            .parent()
94            .expect("trellis crate should live under rust/crates");
95        for manifest in [
96            "auth/Cargo.toml",
97            "auth-adapters/Cargo.toml",
98            "client/Cargo.toml",
99            "cli/Cargo.toml",
100            "codegen-rust/Cargo.toml",
101            "codegen-ts/Cargo.toml",
102            "core-bootstrap/Cargo.toml",
103            "generate-runner/Cargo.toml",
104            "integration-harness/Cargo.toml",
105            "jobs/Cargo.toml",
106            "local-bootstrap/Cargo.toml",
107            "service/Cargo.toml",
108            "service-jobs/Cargo.toml",
109            "service-runtime/Cargo.toml",
110        ] {
111            let contents = fs::read_to_string(crates_dir.join(manifest))
112                .expect("internal crate manifest should be readable");
113            assert!(
114                contents.contains("publish = false"),
115                "{manifest} must stay non-publishable"
116            );
117        }
118    }
119
120    #[test]
121    fn trellis_does_not_depend_on_generated_trellis_owned_sdk_packages() {
122        let manifest =
123            fs::read_to_string(std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("Cargo.toml"))
124                .expect("trellis manifest should be readable");
125        for package in [
126            "trellis-sdk-auth",
127            "trellis-sdk-core",
128            "trellis-sdk-health",
129            "trellis-sdk-jobs",
130            "trellis-sdk-state",
131        ] {
132            assert!(
133                !manifest.contains(package),
134                "{package} must be embedded as trellis_rs::sdk, not a trellis dependency"
135            );
136        }
137    }
138
139    #[test]
140    fn trellis_does_not_depend_on_old_internal_package_identities() {
141        let manifest =
142            fs::read_to_string(std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("Cargo.toml"))
143                .expect("trellis manifest should be readable");
144        for package in [
145            "trellis-auth",
146            "trellis-auth-adapters",
147            "trellis-client",
148            "trellis-core-bootstrap",
149            "trellis-jobs",
150            "trellis-service",
151            "trellis-service-runtime",
152        ] {
153            assert!(
154                !manifest.contains(package),
155                "{package} must be implemented as a trellis module, not a trellis dependency"
156            );
157        }
158    }
159
160    #[test]
161    fn trellis_owned_generated_sdk_packages_are_not_publishable_packages() {
162        let repo_root = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
163            .ancestors()
164            .nth(3)
165            .expect("trellis crate should live under rust/crates/trellis");
166        for manifest in [
167            "generated/packages/cargo/auth/Cargo.toml",
168            "generated/packages/cargo/trellis-core/Cargo.toml",
169            "generated/packages/cargo/health/Cargo.toml",
170            "generated/packages/cargo/jobs/Cargo.toml",
171            "generated/packages/cargo/state/Cargo.toml",
172        ] {
173            let contents = fs::read_to_string(repo_root.join(manifest))
174                .expect("generated Trellis-owned SDK manifest should be readable");
175            assert!(
176                contents.contains("publish = false"),
177                "{manifest} must stay non-publishable"
178            );
179        }
180    }
181}