arcly-http 0.2.2

Enterprise-grade NestJS-inspired web framework on axum: zero-lock DI, declarative controllers, multi-tenant data routing, transactional outbox, ABAC, and a self-documenting OpenAPI surface
Documentation
//! **arcly-http** — NestJS ergonomics meets Rust safety & speed.
//!
//! An enterprise-grade web framework on [axum]: declarative controllers,
//! zero-lock dependency injection, one shared request pipeline for every
//! entry point, and the operational machinery (multi-tenancy, transactional
//! outbox, ABAC, PII masking, field-level encryption, graceful shutdown
//! governance) that production systems otherwise hand-roll.
//!
//! ```ignore
//! use arcly_http::prelude::*;
//!
//! #[Injectable]
//! pub struct GreetService;
//! impl GreetService {
//!     fn greet(&self, name: &str) -> String { format!("hello, {name}") }
//! }
//!
//! #[Controller("/hello")]
//! impl HelloController {
//!     #[Get("/:name")]
//!     async fn hello(&self, #[Param] name: String, svc: Inject<GreetService>) -> String {
//!         svc.greet(&name)
//!     }
//! }
//!
//! #[Module(controllers(HelloController), providers(GreetService))]
//! pub struct AppModule;
//!
//! #[tokio::main]
//! async fn main() -> std::io::Result<()> {
//!     App::launch::<AppModule>("0.0.0.0:3000").await // Swagger UI at /docs
//! }
//! ```
//!
//! ## Design invariants
//!
//! - **One request pipeline** — HTTP routes, plugin routes, and WebSocket
//!   handshakes authenticate through the same boundary; a security fix lands
//!   everywhere at once.
//! - **No locks on the request path** — frozen `&'static` DI container,
//!   atomics, and `ArcSwap` snapshots only.
//! - **Handlers never see axum** — [`RequestContext`] is the only request
//!   surface, so the HTTP layer can evolve without breaking user code.
//!
//! ## Module layout
//!
//! | Module          | Responsibility                                              |
//! |-----------------|--------------------------------------------------------------|
//! | [`app`]         | Launch contract, [`LaunchConfig`] governance knobs           |
//! | [`auth`]        | Identity & access: JWT, cookies, sessions, OAuth2, ABAC, guards |
//! | [`core`]        | DI engine + plugin lifecycle (HTTP-agnostic)                 |
//! | [`web`]         | HTTP layer: boundary, context, errors, interceptors, CORS    |
//! | [`data`]        | DB facade (SQLx/SeaORM/Diesel), tenancy, migrations, outbox  |
//! | [`messaging`]   | Event consumer mesh, retries, dead-letter                    |
//! | [`compliance`]  | PII masking + field-level envelope encryption                |
//! | [`realtime`]    | WebSocket gateways + SSE                                      |
//! | [`observability`] | Structured logs, Prometheus, OTLP, health, trace propagation |
//! | [`resilience`]  | Circuit breaker, rate limiting, bulkhead, distributed locks  |
//! | [`security`]    | Security headers                                              |
//!
//! ## Cargo features
//!
//! | Feature | Effect |
//! |---|---|
//! | *(none)* | Full framework, no database driver |
//! | `db-sqlx` / `db-sqlx-postgres` / `db-sqlx-mysql` / `db-sqlx-sqlite` | SQLx-backed [`data`] layer |
//! | `db-seaorm` | SeaORM driver |
//! | `db-diesel` | Diesel (r2d2) driver |
//!
//! Most applications only need `use arcly_http::prelude::*;`.
//!
//! [axum]: https://docs.rs/axum

#![deny(unsafe_code)]
#![deny(rustdoc::broken_intra_doc_links)]

pub mod app;
pub mod auth;
pub mod compliance;
pub mod core;
pub mod data;
pub mod docs;
pub mod http;
pub mod messaging;
pub mod observability;
pub mod pipeline;
pub mod realtime;
pub mod resilience;
pub mod testing;
pub mod web;

// ─── Path-compat shims ─────────────────────────────────────────────────────────
// The auth subsystem was consolidated from five root files into `auth/`.
// These re-exports keep every pre-existing import path compiling unchanged:
// `arcly_http::cookie::CookieService`, `arcly_http::guards::Guard`, etc.
pub use auth::cookie;

// Path-compat shims for the module re-org (root files moved into their
// owning domains). Every pre-existing import path keeps compiling:
// `arcly_http::security::…`, `arcly_http::validation::…`,
// `arcly_http::openapi::…`, `arcly_http::event::…`.
pub use auth::guards;
pub use auth::oauth;
pub use auth::session;
pub use docs::openapi;
pub use messaging::event;
pub use web::security;
pub use web::validation;

// Convenience re-exports.
pub use core::plugins;
pub use web::cache;
pub use web::interceptors;

// Re-exports needed by macro expansions.
#[doc(hidden)]
pub use axum as __axum;
pub use futures;
pub use inventory;
pub use schemars;
pub use serde_json;
pub use validator;

pub use app::{App, LaunchConfig};
pub use web::{Error, RequestContext};

#[doc(hidden)]
#[inline]
pub fn __schema_for<T: schemars::JsonSchema>() -> serde_json::Value {
    serde_json::to_value(schemars::schema_for!(T)).unwrap_or(serde_json::Value::Null)
}

/// Single stable surface for `arcly-http-macros` codegen.
///
/// Every symbol the proc-macros emit is re-exported here, so internal files
/// can move freely without touching the macro crate — only this module's
/// `pub use` lines need to follow.
#[doc(hidden)]
pub mod __macro_support {
    pub use crate::auth::guards::Guard;
    pub use crate::auth::policy::check_policies;
    pub use crate::compliance::crypto::EncryptRecord;
    pub use crate::compliance::masking::mask_response;
    // Explicit list — ONLY what macro expansions actually reference.
    // A glob here silently turned every engine internal into a contract
    // with the macro crate; new drivers/transports must not widen this
    // surface by accident.
    pub use crate::core::engine::{
        FrozenDiContainer, HttpMethod, Module, ModuleDescriptor, ParamLoc, ParamSpec,
        ProviderDescriptor, Resolver, RouteDescriptor, RouteSpec,
    };
    pub use crate::data::tx::run_transactional;
    pub use crate::http::Json;
    pub use crate::messaging::{EventContext, EventError, EventHandlerDescriptor};
    pub use crate::observability::audit::emit_route_audit;
    pub use crate::realtime::gateway::{GatewayDescriptor, GatewayRuntime, MessageHandler};
    pub use crate::realtime::{ArclyGateway, WsClient};
    pub use crate::resilience::timeout::run_with_timeout;
    pub use crate::resilience::{BreakerOpen, CircuitBreaker};
    pub use crate::web::context::RequestContext;
    pub use crate::web::extract::{
        extract_body_validated, extract_header, extract_param, extract_query_validated, Inject,
    };
    pub use crate::web::idempotency::run_idempotent;
    pub use crate::web::interceptors::{Interceptor, NextHandler};
    pub use crate::web::Error;
}

/// `use arcly_http::prelude::*;` brings in everything a user needs.
pub mod prelude {
    pub use crate::app::{App, LaunchConfig};
    pub use crate::auth::cookie::{CookieConfig, CookieService, SameSite};
    pub use crate::auth::guards::{
        JwtAuthGuard, RoleGuard, SessionAuthGuard, JWT_AUTH, SESSION_AUTH,
    };
    pub use crate::auth::oauth::{OAuth2Provider, OAuth2Service, OAuth2UserInfo};
    pub use crate::auth::policy::{
        check_policies, Decision, EnvAttributes, PolicyEngine, PolicyInput, PolicySet, PolicySource,
    };
    pub use crate::auth::secrets::{spawn_secret_watcher, Rotating, SecretSource, SecretVersion};
    pub use crate::auth::session::{Session, SessionConfig, SessionManager, SessionStore};
    pub use crate::auth::{JwtConfig, JwtService};
    pub use crate::cache::{stats as cache_stats, CacheInterceptor, CacheStats};
    pub use crate::compliance::{
        CryptoError, CryptoVault, DataKey, EncryptRecord, EncryptedField, KekSource, KeyId,
        MaskRule, MaskStrategy, Masker, MaskingPolicy,
    };
    pub use crate::core::engine::FrozenDiContainer;
    pub use crate::core::plugins::{ArclyPlugin, ArclyPluginContext, PluginError, PluginStage};
    pub use crate::data::db::{ArclyDbPool, DbDriver, DbHealthCheck, OwnedDbConn};
    #[cfg(feature = "db-sqlx")]
    pub use crate::data::migrate::{Migration, MigrationReport, MigrationRunner};
    pub use crate::data::outbox::{
        with_transaction, OutboxEntry, OutboxPublisher, OutboxRelay, OutboxStore, OutboxTx,
        TransactionalDataSource,
    };
    pub use crate::data::tx::{in_transaction, with_current_tx, ArclyTransaction};
    pub use crate::data::{
        AccessIntent, DataError, DataErrorKind, DataSource, DataSourceRegistry, ReadAfterWritePin,
    };
    pub use crate::http::{IntoResponse, Json, Response};
    pub use crate::interceptors::{
        EnvelopeResponse, Interceptor, LatencyLog, NextHandler, TelemetryLog, TraceInterceptor,
    };
    pub use crate::messaging::{
        ConsumerRuntime, EventContext, EventHandlerDescriptor, InboundMessage, MessageTransport,
    };
    pub use crate::observability::audit::{AuditOutcome, AuditPipeline, AuditRecord, AuditSink};
    pub use crate::observability::health::{HealthCheck, HealthRegistry, HealthStatus};
    pub use crate::observability::plugin::ArclyObservabilityPlugin;
    pub use crate::openapi::{ApiKeyIn, OpenApiInfo, SecurityScheme};
    pub use crate::pipeline::Provenance;
    pub use crate::resilience::{
        Bulkhead, DLockBackend, DistributedLock, DistributedRateLimit, FailurePolicy, LockGuard,
        RateDecision, RateLimit, RateLimitBackend,
    };
    pub use crate::security::{configure as configure_security, FrameOptions, SecurityConfig};
    pub use crate::validation::Validated;
    pub use crate::web::boundary::BoundaryFilter;
    pub use crate::web::cors::CorsConfig;
    pub use crate::web::dynamic::{DynamicRouteTable, DYNAMIC_PREFIX};
    pub use crate::web::error::{
        BadRequest, Conflict, FieldError, Forbidden, GatewayTimeout, HttpError, HttpException,
        Internal, NotFound, ProblemDetails, ServiceUnavailable, TooManyRequests, Unauthorized,
        Validation,
    };
    pub use crate::web::idempotency::{IdempotencyDecision, IdempotencyStore};
    pub use crate::web::responses::{Accepted, Created, NoContent};
    pub use crate::web::tenant::{
        TenantConfig, TenantGuard, TenantId, TenantRegistry, TenantStrategy, TENANT,
    };
    pub use crate::web::{Error, Inject, RequestContext};
    pub use arcly_http_macros::{
        circuit_breaker, AuditLog, CacheKey, CacheTTL, Controller, Delete, Deprecated,
        EncryptFields, EventConsumer, EventPattern, Get, Idempotent, Injectable, MaskFields,
        Module, Patch, Post, Put, RequirePolicies, Timeout, Transactional, UseInterceptors,
        Version,
    };
    pub use schemars::JsonSchema;
    pub use validator::Validate;
}