[package]
name = "aion-server"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
description = "Aion workflow server library: HTTP, gRPC, WebSocket, and worker endpoints. Run it with the `aion` binary from the aion-cli crate."
license.workspace = true
authors.workspace = true
repository.workspace = true
documentation = "https://docs.rs/aion-server"
readme = "README.md"
keywords = ["aion", "workflow", "durable-execution", "server", "grpc"]
categories = ["asynchronous", "development-tools"]

[lints]
workspace = true

[dependencies]
aion = { package = "aion-rs", version = "0.8.0", path = "../aion" }
aion-proto = { version = "0.8.0", path = "../aion-proto", features = ["generated"] }
aion-store-libsql = { version = "0.8.0", path = "../aion-store-libsql" }
aion-store = { version = "0.8.0", path = "../aion-store" }
# Single-node haematite event-store backend. OPTIONAL and OFF by default: a
# default aion-server build does not link aion-store-haematite (nor its
# transitive haematite engine), so the default dependency surface and backend
# selection are byte-identical to before. Enabled only by the
# `haematite-backend` feature, which lights up the `backend = haematite` arm.
aion-store-haematite = { version = "0.8.0", path = "../aion-store-haematite", optional = true }
aion-package = { version = "0.8.0", path = "../aion-package" }
# Server-side authoring toolchain. It embeds NO Gleam compiler — it only
# spawns the external `gleam` binary — so depending on it adds no compiler to
# aion-server (CN7/C15). The authoring endpoints stay dark unless
# `[authoring].gleam_path` is configured.
aion-toolchain = { version = "0.8.0", path = "../aion-toolchain" }
tokio = { workspace = true, features = ["full"] }
axum = { workspace = true, features = ["ws"] }
tonic = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
thiserror = { workspace = true }
aion-core = { version = "0.8.0", path = "../aion-core" }
dashmap = { workspace = true }
uuid.workspace = true
futures.workspace = true
chrono = { workspace = true, features = ["serde"] }
prost.workspace = true
tokio-stream = { workspace = true }
# Names the typed body length-limit error so the deploy archive upload can
# distinguish "over deploy.max_archive_bytes" (413) from transport read
# failures; same version axum already uses internally.
http-body-util = { workspace = true }
tower = { workspace = true, features = ["util"] }
# Provides the CorsLayer the public HTTP router applies so a browser dashboard
# served from a different origin (e.g. the Vite dev server) can call the API.
# CORS is config-driven and secure-by-default: with no configured origins the
# layer is not installed and no cross-origin request is allowed.
tower-http = { workspace = true }
# Embeds the built dashboard bundle into the binary. OPTIONAL and OFF by
# default: a default `cargo build -p aion-server` does NOT pull rust-embed and
# does NOT require the dashboard to be built (no bun needed). Enabled only by
# the `embed-dashboard` feature, which release builds turn on so the single
# binary ships the real web UI. With the feature off, `/` serves a branded
# placeholder page documenting how to build/run the dashboard.
rust-embed = { workspace = true, optional = true }
tracing.workspace = true
tracing-subscriber = { workspace = true, features = ["env-filter"] }
toml = { workspace = true }
prometheus = { workspace = true }
async-trait.workspace = true
base64 = { workspace = true }
# jsonwebtoken 10 panics at validation time unless exactly one crypto-provider
# feature is selected; rust_crypto is the pure-Rust provider.
jsonwebtoken = { workspace = true, optional = true }
reqwest = { workspace = true, optional = true }
# Cross-node outbox dispatch over the liminal bus (#13). OPTIONAL and OFF by
# default: a default aion build does not link liminal-sdk (nor its transitive
# beamr distribution). Enabled only by the `liminal-transport` feature. Resolved
# from crates.io (liminal-sdk); the default `std` feature carries the real TCP
# transport and the canonical wire codec.
liminal-sdk = { workspace = true, optional = true }
# Used only by the feature-gated #13-0 integration test to stand up a real
# liminal server over loopback TCP (the spike's worker-side endpoint). Optional
# and enabled only by `liminal-transport`, so a default build never pulls it.
liminal-server = { workspace = true, optional = true }
# Liminal core protocol types (LSUB-L2): the connection-keyed `ConnectionNotifier`
# receives a `liminal::protocol::WorkerRegistration` to build a registry entry from.
# Already in the dependency graph transitively (liminal-sdk/liminal-server depend
# on it); named directly only so the in-band registration notifier can reference
# the wire type. Optional, enabled only by `liminal-transport`.
liminal = { workspace = true, optional = true }

[dev-dependencies]
# The LSUB-1 cross-node dispatch e2e drives a REAL aion-worker over the liminal
# push transport, so the test build enables the worker's `liminal-transport`
# feature. A default (non-test) build never pulls this; the worker feature is OFF
# in the production dependency graph.
aion-worker = { path = "../aion-worker", features = ["liminal-transport"] }
aion-core = { version = "0.8.0", path = "../aion-core" }
# The SS-5b auto-failover test reuses the aion-rs SS-5 example-build helper,
# which rebuilds the `hello-world` archive from source and advisory-locks the
# build dir; these dev-deps back that helper for the haematite test build.
aion-package = { version = "0.8.0", path = "../aion-package", features = ["test-support"] }
fs4 = { workspace = true }
libsql = { workspace = true }
reqwest = { workspace = true }
tempfile = { workspace = true }
tokio-stream = { workspace = true, features = ["net"] }
tokio-tungstenite = { workspace = true }
# Used ONLY by the feature-gated SS-5b auto-failover integration test, which
# stands up a real 3-node loopback haematite cluster through the raw
# DistributionEndpoint/Database harness (mirroring the aion-rs SS-5 demo). The
# test file is `#![cfg(feature = "haematite-backend")]`, so without that feature
# it compiles to nothing; this dev-dep only links for the haematite test build.
haematite = { workspace = true }
# Deploy e2e builds hostile DEFLATE-bomb archives; PackageBuilder writes
# Stored entries only, so it cannot produce one.
zip = { workspace = true }

[features]
default = []
auth = ["dep:jsonwebtoken", "dep:reqwest"]
# Embeds the built dashboard bundle (rust_embed over `dashboard-embed/`) into the
# binary so the single `aion server` process serves the real web UI at `/`. OFF
# by default to keep `cargo build -p aion-server` bun-free for backend-only devs;
# with it off, `/` serves a branded placeholder page that documents the dev-server
# URL and the build command. Release builds enable it (via aion-cli's `release`
# feature). Build the bundle first with `cargo xtask build-dashboard`.
embed-dashboard = ["dep:rust-embed"]
# Cross-node outbox dispatch over liminal (#13-0 spike). OFF by default so a
# default build is byte-identical and never links liminal-sdk/beamr. When on,
# `outbox.transport = liminal` selects the liminal dispatch + completion path.
liminal-transport = ["dep:liminal-sdk", "dep:liminal-server", "dep:liminal"]
# Selectable haematite event-store backend. OFF by default so a default build is
# byte-identical and never links aion-store-haematite/haematite. When on,
# `store.backend = haematite` constructs a single-node HaematiteStore rooted at
# `store.data_dir` with `store.shard_count` shards.
haematite-backend = ["dep:aion-store-haematite"]

# The runnable multi-node failover demo: boots an in-process haematite cluster,
# kills the shard owner, and watches the SS-5b supervisor auto-recover the
# workflow. Requires the haematite backend (and `gleam` on PATH at runtime).
[[example]]
name = "failover_demo"
required-features = ["haematite-backend"]

# The runnable LSUB-5 capstone demo: boots an in-process haematite cluster + a
# real liminal worker, kills the fan-out shard owner MID-DISPATCH, and narrates
# the survivor adopting the shard and re-driving the fan-out to an exactly-once
# completion. Requires both the haematite backend and the liminal transport.
[[example]]
name = "lsub5_xnode_failover_demo"
required-features = ["haematite-backend", "liminal-transport"]
