Skip to main content

alien_commands/
lib.rs

1//! # alien-commands
2//!
3//! Commands protocol implementation for Alien.
4//!
5//! This crate provides a transport-agnostic protocol for sending commands
6//! to customer-side agents without requiring inbound connections.
7//!
8//! ## Features
9//!
10//! - **Core types**: Always available protocol types and serialization
11//! - **server**: Command server implementation for managers
12//! - **runtime**: Command envelope processing for alien-worker-runtime
13//! - **receiver**: App-owned pull command receiver for Containers/Daemons
14//! - **openapi**: OpenAPI schema generation support
15
16pub mod error;
17pub mod types;
18
19pub use error::{Error, ErrorData, Result};
20pub use types::*;
21
22#[cfg(any(feature = "server", feature = "dispatchers"))]
23pub mod dispatchers;
24
25#[cfg(feature = "server")]
26pub mod server;
27
28#[cfg(any(feature = "runtime", feature = "receiver"))]
29pub mod runtime;
30
31#[cfg(feature = "receiver")]
32pub mod receiver;
33
34#[cfg(feature = "test-utils")]
35pub mod test_utils;
36
37// Re-export commonly used types
38pub use types::{
39    BodySpec, CommandResponse, CommandState, CommandStatusResponse, CreateCommandRequest,
40    CreateCommandResponse, Envelope, LeaseInfo, LeaseRequest, LeaseResponse, ResponseHandling,
41    StorageUpload, SubmitResponseRequest, UploadCompleteRequest, UploadCompleteResponse,
42};
43
44#[cfg(feature = "server")]
45pub use server::{create_axum_router, CommandRegistry, CommandServer, InMemoryCommandRegistry};
46
47#[cfg(any(feature = "runtime", feature = "receiver"))]
48pub use runtime::{
49    command_budget, decode_params, parse_envelope, submit_response, LeaseClient,
50    LEASE_SAFETY_MARGIN,
51};
52
53// NB: `receiver::Context` is intentionally NOT re-exported at the crate root —
54// it would collide with `alien_error::Context` (the error-chaining trait).
55// Import it as `alien_commands::receiver::Context`.
56#[cfg(feature = "receiver")]
57pub use receiver::{Receiver, ShutdownHandle};
58
59/// Default inline size limit in bytes (150 KB)
60/// This is the most conservative platform limit (Azure Service Bus Standard at 256KB)
61/// with headroom for base64 encoding (~4/3 inflation) and envelope metadata.
62pub const INLINE_MAX_BYTES: usize = 150_000;
63
64/// Protocol version identifier
65pub const PROTOCOL_VERSION: &str = "arc.v1";
66
67/// Resolve manager-relative URLs in a leased command envelope against the
68/// trusted commands endpoint used to acquire that lease.
69///
70/// The manager cannot know which address is reachable from a deployment's
71/// network boundary or which path prefix its reverse proxy adds, so lease
72/// responses use path-relative references for manager endpoints.
73/// Cloud-presigned absolute URLs remain byte-for-byte unchanged.
74pub fn resolve_envelope_urls(envelope: &mut Envelope, base: &url::Url) {
75    let resolve = |target: &mut String| {
76        if url::Url::parse(target).is_ok() || target.starts_with("//") {
77            return;
78        }
79        if let Ok(resolved) = base.join(target) {
80            *target = resolved.to_string();
81        }
82    };
83
84    resolve(&mut envelope.response_handling.submit_response_url);
85    if let alien_core::presigned::PresignedRequestBackend::Http { url, .. } =
86        &mut envelope.response_handling.storage_upload_request.backend
87    {
88        resolve(url);
89    }
90    if let alien_core::commands_types::BodySpec::Storage {
91        storage_get_request: Some(request),
92        ..
93    } = &mut envelope.params
94    {
95        if let alien_core::presigned::PresignedRequestBackend::Http { url, .. } =
96            &mut request.backend
97        {
98            resolve(url);
99        }
100    }
101}