# Project:   hyperi-rustlib
# File:      Cargo.toml
# Purpose:   Rust shared library for HyperI projects
# Language:  TOML
#
# License:   FSL-1.1-ALv2
# Copyright: (c) 2026 HYPERI PTY LIMITED

[package]
name = "hyperi-rustlib"
version = "2.4.5"
edition = "2024"
rust-version = "1.94"
description = "Opinionated Rust framework for high-throughput data pipelines at PB scale. Auto-wiring config, logging, metrics, tracing, health, and graceful shutdown — built from many years of production infrastructure experience."
license = "FSL-1.1-ALv2"
repository = "https://github.com/hyperi-io/hyperi-rustlib"
publish = true
keywords = ["config", "logging", "metrics", "prometheus", "opentelemetry"]
categories = ["development-tools"]
exclude = [".claude/", ".github/", "ci/", "ai/", "docs/", "examples/", "benches/", "scripts/"]

[features]
default = ["config", "logger", "metrics", "runtime", "shutdown", "health"]

# Core features
health = []
shutdown = ["tokio", "tokio-util"]
runtime = ["dirs"]
config = ["figment", "dotenvy", "serde_yaml_ng", "serde_json", "toml", "dirs", "tracing"]
logger = ["tracing", "tracing-subscriber", "owo-colors", "serde_json", "tracing-throttle"]
metrics = ["dep:metrics", "metrics-exporter-prometheus", "sysinfo", "tokio", "serde_json"]

# OpenTelemetry support (modern observability)
otel = ["opentelemetry", "opentelemetry_sdk", "opentelemetry-otlp", "tracing-opentelemetry", "tracing"]
otel-metrics = ["otel", "dep:metrics", "metrics-util", "metrics-exporter-opentelemetry", "sysinfo", "tokio", "tracing"]
otel-tracing = ["otel"]

# DFE-specific metric groups (opt-in, DFE pipeline apps only)
metrics-dfe = ["metrics"]

# Directory config store (YAML directory-backed)
directory-config = ["serde_yaml_ng", "tokio", "tracing", "fs4"]
directory-config-git = ["directory-config", "git2"]

# Extended features (P2)
http = ["reqwest", "reqwest-middleware", "reqwest-retry", "serde_json"]
http-server = ["axum", "tower", "tower-http", "tokio"]
spool = ["yaque", "zstd"]
tiered-sink = ["yaque", "zstd", "lz4_flex", "snap", "tokio", "tower-resilience", "libc"]
resilience = ["tower-resilience", "tower"]
database = ["serde_json"]
cache = ["moka", "serde_json"]

# Cgroup-aware memory backpressure (OOM prevention)
memory = ["sysinfo", "tracing"]

# Scaling pressure calculation (KEDA autoscaling)
scaling = ["parking_lot", "tracing"]

# Adaptive worker pool (hybrid rayon + tokio, pressure-based scaling)
worker = ["rayon", "config", "metrics", "tokio", "sysinfo", "parking_lot", "tracing", "sonic-rs", "dashmap", "bytes"]

# Worker pool with msgpack batch serialisation support
worker-msgpack = ["worker", "rmp-serde"]

# Standard CLI framework (clap-based)
cli = ["clap", "tracing"]
# TUI metrics dashboard (ratatui + crossterm via ratatui re-export)
top = ["cli", "ratatui"]

# Shared NDJSON file I/O (used by dlq + output-file)
io = ["file-rotate", "parking_lot", "chrono", "tracing"]

# Dead letter queue (file backend always available)
dlq = ["io", "base64", "serde_json", "tokio", "async-trait", "tracing"]
dlq-kafka = ["dlq", "transport-kafka"]
dlq-http = ["dlq", "reqwest"]
dlq-redis = ["dlq", "transport-redis"]

# File output sink (local NDJSON file output)
output-file = ["io", "serde_json", "tracing"]

# CEL expression evaluation (DFE expression profile)
expression = ["cel-interpreter", "serde_json"]

# Deployment contract validation (Helm chart + Dockerfile sync)
deployment = ["serde_yaml_ng", "serde_json"]

# Startup version check (calls HyperI version API)
version-check = ["reqwest", "tokio", "serde_json", "tracing", "uuid", "chrono"]

# Config hot-reload (SharedConfig<T> + ConfigReloader<T>)
config-reload = ["config", "parking_lot", "tokio", "tracing"]

# PostgreSQL config source (optional)
config-postgres = ["config", "sqlx", "tokio", "serde_json"]

# Transport features
transport = ["tokio", "serde_json", "rmp-serde", "chrono", "async-trait"]
transport-memory = ["transport"]
transport-kafka = ["transport", "rdkafka", "regex", "tokio-util"]
transport-grpc = ["transport", "dep:tonic", "dep:tonic-prost", "dep:prost", "dep:prost-types", "dep:tonic-prost-build", "dep:prost-build"]
transport-grpc-vector-compat = ["transport-grpc"]
transport-file = ["transport", "io"]
transport-pipe = ["transport"]
transport-http = ["transport", "http"]
transport-redis = ["transport", "redis"]
transport-all = ["transport-memory", "transport-kafka", "transport-grpc", "transport-file", "transport-pipe", "transport-http", "transport-redis"]

# Secrets management
secrets = ["tokio", "serde_json", "async-trait", "parking_lot", "base64", "dirs", "tracing"]
secrets-vault = ["secrets", "vaultrs"]
secrets-aws = ["secrets", "aws-config", "aws-sdk-secretsmanager"]
secrets-all = ["secrets-vault", "secrets-aws"]

# Full feature set
full = ["config", "config-reload", "logger", "metrics", "metrics-dfe", "otel", "otel-metrics", "runtime", "shutdown", "health", "http", "http-server", "spool", "tiered-sink", "resilience", "database", "cache", "transport-all", "transport-grpc-vector-compat", "secrets-all", "directory-config", "directory-config-git", "deployment", "version-check", "scaling", "memory", "worker", "cli", "io", "dlq", "dlq-kafka", "dlq-http", "dlq-redis", "output-file", "expression"]

[dependencies]
# Serialisation (always needed)
serde = { version = ">=1.0.228, <2", features = ["derive"] }

# Error handling
thiserror = ">=2.0.18, <3"

# Environment detection
dirs = { version = ">=6.0.0, <7", optional = true }

# Configuration
figment = { version = ">=0.10.19, <0.11", features = ["yaml", "toml", "json", "env"], optional = true }
dotenvy = { version = ">=0.15.7, <0.16", optional = true }

# Concurrent hash map (field interning)
dashmap = { version = ">=6.1, <7", optional = true }
serde_yaml_ng = { version = ">=0.10.0, <0.11", optional = true }
serde_json = { version = ">=1.0.149, <2", optional = true }
toml = { version = ">=0.8, <2", optional = true }

# UUID generation (for version-check instance ID)
uuid = { version = ">=1.10, <2", features = ["v4"], optional = true }

# Advisory file locking (for directory-config writes)
fs4 = { version = ">=0.12, <0.14", features = ["sync"], optional = true }

# Git operations (for directory-config-git)
git2 = { version = ">=0.20.0, <0.21", optional = true }

# CEL expression evaluation
cel-interpreter = { version = ">=0.10.0, <0.11", features = ["json"], optional = true }

# CLI framework
clap = { version = ">=4.5, <5", features = ["derive", "env"], optional = true }

# Logging
tracing = { version = ">=0.1.44, <0.2", optional = true }
tracing-subscriber = { version = ">=0.3.22, <0.4", features = ["json", "env-filter", "fmt", "time", "local-time"], optional = true }
time = { version = ">=0.3.45, <0.4", optional = true }
owo-colors = { version = ">=4.2.3, <5", optional = true }
tracing-throttle = { version = ">=0.4.2, <0.5", default-features = false, optional = true }

# OpenTelemetry (modern observability - OTLP native)
opentelemetry = { version = ">=0.31.0, <0.32", optional = true }
opentelemetry_sdk = { version = ">=0.31.0, <0.32", features = ["rt-tokio"], optional = true }
opentelemetry-otlp = { version = ">=0.31.0, <0.32", features = ["grpc-tonic", "http-proto", "metrics", "logs"], optional = true }
tracing-opentelemetry = { version = ">=0.32.1, <0.33", optional = true }

# Metrics (Prometheus-native)
metrics = { version = ">=0.24.3, <0.25", optional = true }
metrics-exporter-prometheus = { version = ">=0.16, <0.19", optional = true }
metrics-util = { version = ">=0.20.1, <0.21", optional = true }
metrics-exporter-opentelemetry = { version = ">=0.2.1, <0.3", optional = true }
sysinfo = { version = ">=0.38.0, <0.39", optional = true }

# Async runtime (for metrics server, http-server, shutdown)
tokio = { version = ">=1.50.0, <2", features = ["rt-multi-thread", "net", "sync", "time", "macros", "signal", "fs", "io-std", "io-util"], optional = true }
tokio-util = { version = ">=0.7.14, <0.8", optional = true }

# HTTP client — pinned to reqwest 0.12 until vaultrs and opentelemetry-otlp
# support 0.13. reqwest-middleware 0.4 and reqwest-retry 0.7 target 0.12.
reqwest = { version = ">=0.12, <0.13", features = ["json"], optional = true }
reqwest-middleware = { version = ">=0.4, <0.5", optional = true }
reqwest-retry = { version = ">=0.7, <0.8", optional = true }

# In-memory cache (TinyLFU, async, concurrent)
moka = { version = ">=0.12, <0.13", features = ["future"], optional = true }

# HTTP server (axum)
axum = { version = ">=0.8.8, <0.9", optional = true }
tower = { version = ">=0.5.3, <0.6", optional = true }
tower-http = { version = ">=0.6.8, <0.7", features = ["timeout", "trace"], optional = true }

# Resilience patterns (circuit breaker, retry, bulkhead)
tower-resilience = { version = ">=0.4.0, <0.10", optional = true }

# Async (for transport)
chrono = { version = ">=0.4.43, <0.5", optional = true }

# MessagePack (for transport)
rmp-serde = { version = ">=1.3.1, <2", optional = true }

# Kafka transport (dynamic-linking: use system librdkafka instead of compiling C++ from source)
rdkafka = { version = ">=0.39.0, <0.40", features = ["dynamic-linking"], optional = true }

# Redis/Valkey Streams transport
redis = { version = ">=1.0, <2", features = ["tokio-comp", "streams"], optional = true }

# gRPC transport (tonic + prost)
tonic = { version = ">=0.14, <0.15", features = ["gzip"], optional = true }
tonic-prost = { version = ">=0.14.5, <0.15", optional = true }
prost = { version = ">=0.14, <0.15", optional = true }
prost-types = { version = ">=0.14, <0.15", optional = true }

# TUI dashboard (ratatui re-exports crossterm)
ratatui = { version = ">=0.29, <0.32", optional = true }

# File rotation (for DLQ file backend)
file-rotate = { version = ">=0.7, <0.9", optional = true }

# Filesystem stats (disk-aware capacity management for tiered-sink)
libc = { version = ">=0.2, <0.3", optional = true }

# Spool (disk-backed async queue) - yaque is async-native and maintained
yaque = { version = ">=0.6.6, <0.7", optional = true }
zstd = { version = ">=0.13.3, <0.14", optional = true }

# TieredSink compression codecs
lz4_flex = { version = ">=0.11, <0.14", optional = true }
snap = { version = ">=1.1.1, <2", optional = true }

# SIMD JSON (BatchEngine — 2-4x faster than serde_json)
sonic-rs = { version = ">=0.5, <1", optional = true }

# Regex (topic resolver include/exclude filters)
regex = { version = ">=1.11, <2", optional = true }

# Async trait (for tiered-sink Sink trait)
async-trait = { version = ">=0.1.88, <0.2", optional = true }

# PostgreSQL (for config-postgres)
sqlx = { version = ">=0.8, <0.9", features = ["runtime-tokio", "tls-rustls-ring-webpki", "postgres", "json"], optional = true }

# Secrets management
parking_lot = { version = ">=0.12.3, <0.13", optional = true }

# Data parallelism (CPU-bound work distribution for worker pool)
rayon = { version = ">=1.10, <2", optional = true }
base64 = { version = ">=0.22, <0.23", optional = true }

# Zero-copy byte buffers (BatchEngine)
bytes = { version = ">=1.10, <2", optional = true }

# Vault/OpenBao (for secrets-vault)
vaultrs = { version = ">=0.7, <0.9", optional = true }

# AWS (for secrets-aws)
# NOTE: aws-config and aws-sdk-* transitively pull in aws-lc-sys, which compiles
# C/C++ and assembly. Amazon hardcode their own crypto lib into the SDK and offer
# no way to opt out at compile time. Every other C dependency in this crate is
# dynamically linked against system libs, but aws-lc-sys gets a free pass because
# apparently the AWS SDK team think we all enjoy watching cmake run. ~20-30s on
# first build, cached by sccache after that. Revisit when they offer a ring-only
# build — or when we find a reason to drop the AWS secrets backend entirely.
aws-config = { version = ">=1.8, <2", optional = true }
aws-sdk-secretsmanager = { version = ">=1.102, <2", optional = true }

[build-dependencies]
tonic-prost-build = { version = ">=0.14.5, <0.15", optional = true }
prost-build = { version = ">=0.14, <0.15", optional = true }

[dev-dependencies]
tokio = { version = ">=1.50.0, <2", features = ["full", "test-util"] }
tempfile = ">=3.24.0, <4"
criterion = { version = ">=0.5, <0.9", features = ["html_reports"] }
pretty_assertions = ">=1.4.1, <2"
temp-env = ">=0.3.6, <0.4"
async-trait = ">=0.1.88, <0.2"
git2 = ">=0.20.0, <0.21"

[lints.rust]
unsafe_code = "deny"

[lints.clippy]
pedantic = { level = "warn", priority = -1 }
# expect_used = "warn"  # Disabled for MVP, re-enable for stricter error handling

# Allows for test/bench/example code (these don't inherit lib.rs attributes)
doc_markdown = "allow"                    # Don't require backticks in doc comments
unnecessary_debug_formatting = "allow"    # Allow {:?} in examples
await_holding_lock = "allow"              # Common in test code with mocked locks
redundant_closure = "allow"               # Sometimes clearer in tests
redundant_closure_for_method_calls = "allow"  # Sometimes clearer in tests
needless_raw_string_hashes = "allow"      # Convenience in test strings
items_after_statements = "allow"          # Test helper structs defined where needed
inefficient_to_string = "allow"           # Clarity over micro-optimization in tests
unwrap_used = "allow"                     # Allowed in tests for cleaner assertions

[[bench]]
name = "config_benchmark"
harness = false

[[bench]]
name = "logger_benchmark"
harness = false

[[bench]]
name = "engine_benchmark"
harness = false
required-features = ["worker"]
