Skip to main content

lifeloop/router/
mod.rs

1//! Lifecycle router skeleton: pre-dispatch validation and adapter resolution.
2//!
3//! Lifeloop owns lifecycle event routing as a neutral mechanism. Clients
4//! own product behavior: a client receives the routed event via a
5//! callback and decides what (if anything) to deliver. The router is the
6//! seam that turns a `CallbackRequest` plus the adapter manifest registry
7//! into a typed [`RoutingPlan`] that downstream stages — capability
8//! negotiation, callback invocation, receipt emission, failure mapping —
9//! consume without re-validating wire-level invariants.
10//!
11//! # Boundary (issue #7, skeleton slice)
12//!
13//! This module owns:
14//! * pre-dispatch validation of [`crate::CallbackRequest`] envelopes
15//!   (schema version, non-empty identifiers, frame-context invariants,
16//!   payload-ref structure);
17//! * adapter manifest resolution by both `adapter_id` *and*
18//!   `adapter_version` (the two are distinguished failure classes —
19//!   wrong id is not the same as wrong version of a known id);
20//! * synthesis of a typed [`RoutingPlan`] that names the resolved
21//!   adapter and preserves opaque `PayloadRef`s for downstream stages;
22//! * the trait *seams* through which later issues plug in negotiation,
23//!   callback invocation, receipt emission, and failure mapping.
24//!
25//! This module does **not** own:
26//! * capability negotiation (future router issue) — see
27//!   [`NegotiationStrategy`];
28//! * callback invocation against renderers (issue #3 will wire a
29//!   protocol renderer into [`CallbackInvoker`]) — see
30//!   [`CallbackInvoker`];
31//! * receipt persistence/emission (future router issue) — see
32//!   [`ReceiptEmitter`];
33//! * failure-class mapping for receipt synthesis (future router
34//!   issue) — see [`FailureMapper`];
35//! * payload body inspection. The router treats
36//!   [`crate::PayloadRef`] and [`crate::PayloadEnvelope`] bodies as opaque: it does
37//!   not parse, transform, or pattern-match on payload contents.
38//!
39//! # Client compatibility
40//!
41//! This module has none. It is provider-neutral by construction. Any
42//! historic host-adapter flow that fused lifecycle routing with
43//! client product semantics is replaced by Lifeloop routing plus
44//! client callbacks — every client (including the first one) becomes
45//! a consumer of these seams, not a peer of the router.
46
47mod callbacks;
48mod failure_mapping;
49mod negotiation;
50mod plan;
51mod receipts;
52mod seams;
53mod subprocess;
54mod validation;
55
56pub use callbacks::{ClientCallback, DefaultCallbackInvoker, FnClientCallback, synthesize_request};
57pub use failure_mapping::{
58    LifeloopFailureMapper, TransportError, classes_for_negotiation_outcome,
59    failure_class_for_receipt_error, failure_class_for_route_error, failure_class_for_transport,
60    retry_class_for, validate_receipt_eligible,
61};
62pub use negotiation::{
63    CapabilityKind, CapabilityRequest, CapabilityRequirement, DefaultNegotiationStrategy,
64    NegotiatedPlan, PayloadPlacementDecision, PlacementRejection, negotiate,
65};
66pub use plan::{RoutingPlan, route};
67pub use receipts::{
68    IdempotencyKey, IdempotencyStore, InMemoryIdempotencyStore, LifeloopReceiptEmitter,
69    ReceiptContext, ReceiptError, SequenceGenerator, StoreOutcome,
70};
71pub use seams::{CallbackInvoker, FailureMapper, NegotiationStrategy, ReceiptEmitter};
72pub use subprocess::{
73    SubprocessCallbackInvoker, SubprocessInvokerConfig, SubprocessInvokerError,
74    failure_class_for_subprocess_error, transport_error_for,
75};
76pub use validation::{AdapterRegistry, AdapterResolution, BuiltinAdapterRegistry, RouteError};