[package]
name = "s4-server"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
authors.workspace = true
repository.workspace = true
homepage.workspace = true
documentation.workspace = true
keywords.workspace = true
categories.workspace = true
readme = "README.md"
description = "S4 — Squished S3 — GPU-accelerated transparent compression S3-compatible storage gateway (cargo install s4-server installs the `s4` binary)."
include = [
    "src/**/*.rs",
    "Cargo.toml",
    "LICENSE",
    "NOTICE",
    "README.md",
]

[lints]
workspace = true

[features]
default = []
# Enable GPU compression via nvCOMP. Requires CUDA + NVCOMP_HOME at build time
# and a CUDA-capable GPU at runtime. Propagates to s4-codec/nvcomp-gpu.
nvcomp-gpu = ["s4-codec/nvcomp-gpu"]
# v0.5 #28: SSE-KMS envelope encryption with AWS KMS as the KEK backend.
# Off by default to keep the default build from pulling the entire
# aws-sdk-kms tree. Enable with `--features aws-kms` when deploying with
# AWS KMS for KEK custody. The default-features `LocalKms` (file-backed
# KEKs) is always available for dev / on-prem.
aws-kms = ["dep:aws-sdk-kms"]
# v0.6 #35: SQS / SNS notification destinations. The `Webhook` variant of
# `notifications::Destination` is always available (no extra deps); SQS /
# SNS pull `aws-sdk-sqs` / `aws-sdk-sns` only when this feature is
# enabled, mirroring the `aws-kms` flag's shape.
aws-events = ["dep:aws-sdk-sns", "dep:aws-sdk-sqs"]

[[bin]]
name = "s4"
path = "src/main.rs"

[dependencies]
s3s.workspace = true
s3s-aws.workspace = true
aws-config.workspace = true
aws-sdk-s3.workspace = true
aws-credential-types.workspace = true
tokio.workspace = true
hyper.workspace = true
hyper-util.workspace = true
clap.workspace = true
tracing.workspace = true
tracing-subscriber.workspace = true
async-trait.workspace = true
anyhow.workspace = true
bytes.workspace = true
serde.workspace = true
futures.workspace = true
thiserror.workspace = true
http = "1"
async-compression.workspace = true
tokio-util.workspace = true
crc32c.workspace = true
pin-project-lite.workspace = true
http-body-util = "0.1"
metrics.workspace = true
metrics-exporter-prometheus.workspace = true
opentelemetry.workspace = true
opentelemetry_sdk.workspace = true
opentelemetry-otlp.workspace = true
tracing-opentelemetry.workspace = true
tokio-rustls = { version = "0.26", default-features = false, features = ["ring", "tls12"] }
rustls-pemfile = "2"
serde_json = "1"
arc-swap = "1"
rustls-acme = { version = "0.15", default-features = false, features = ["ring", "webpki-roots"] }
governor = "0.10"
dashmap = "6"
aes-gcm = "0.10"
rand = "0.8"
base64 = "0.22"
hmac = "0.12"
sha2 = "0.10"
# v0.5 #27: SSE-C key fingerprinting. AWS S3 SSE-C uses MD5 of the
# customer key (sent as `x-amz-server-side-encryption-customer-key-MD5`)
# as a non-secret tag the server stores to verify GETs supply the same
# key. MD5 is fine here — it's a fingerprint, not a security primitive.
md-5 = "0.10"
# v0.5 #33: SigV4a (asymmetric ECDSA-P256-SHA256) signature verification.
# Used only for verifying SigV4a-signed S3 requests; key issuance / signing
# is out of scope (operators load PEM-encoded P-256 public keys via
# `--sigv4a-credentials <DIR>`).
p256 = { version = "0.13", features = ["ecdsa", "std", "pem", "pkcs8"] }
ecdsa = "0.16"
# v0.5 #34: versioning state machine — UUIDv4 version-id 採番 (`uuid`) と、
# in-memory snapshot を `to_json` / `from_json` する serde 系 timestamp
# (`chrono` の `clock` + `serde` features 限定) のため。
chrono = { version = "0.4", default-features = false, features = ["clock", "serde"] }
uuid = { version = "1", features = ["v4"] }
# v0.5 #28: SSE-KMS envelope encryption — optional AWS KMS backend.
# `LocalKms` (file-backed KEKs) is always compiled in; the AWS backend
# is gated behind the `aws-kms` cargo feature so the default `cargo
# build` doesn't pull aws-sdk-kms.
aws-sdk-kms = { version = "1", optional = true }
# v0.6 #35: webhook destination for bucket notifications. Always pulled
# in (default-features off, rustls + json) because the `Webhook` variant
# of `notifications::Destination` is the always-available baseline.
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "json"] }
# v0.6 #35: SQS / SNS notification destinations — both gated behind the
# `aws-events` cargo feature so the default build doesn't pull the
# aws-sdk-sns / aws-sdk-sqs trees.
aws-sdk-sns = { version = "1", optional = true }
aws-sdk-sqs = { version = "1", optional = true }

s4-codec = { path = "../s4-codec", version = "0.9" }
s4-config = { path = "../s4-config", version = "0.9" }
# v0.6 #41: S3 Select — server-side SQL filter on object body.
sqlparser = "0.51"
csv = "1"
crc32fast = "1"
# v0.8.12 #128 (MED-C): SHA-1 verifier for `x-amz-checksum-sha1`.
# RustCrypto crate, same `Digest` trait as `sha2` / `md-5` so the
# helper shape stays consistent.
sha1 = "0.10"
# v0.6 #42: MFA Delete — RFC 6238 TOTP verification on DELETE / DELETE-version
# / delete-marker requests when a bucket has Versioning + MfaDelete Enabled.
# `default-features = false` keeps the dep tree minimal (no QR generation, no
# otpauth URL handling — we only need TOTP::check + base32 secret decoding).
totp-rs = { version = "5", default-features = false }
# Direct base32 dep for our own header-secret decoding helper. totp-rs pulls
# the same crate transitively, but listing it here keeps the import path
# stable if totp-rs ever drops its base32 re-export.
base32 = "0.5"
# v0.7 #49: percent-encode S3 object keys before splicing them into a
# synthetic `/{bucket}/{key}` request URI used by the sidecar / replication
# helpers. S3 keys can contain spaces, control bytes, and arbitrary
# Unicode that would make `format!(...).parse::<Uri>()` panic; we encode
# the byte-stream so the resulting URI is always parseable, and fall back
# to a typed `S3Error` if anything still fails.
percent-encoding = "2"
# v0.8.1 #58: zeroize SSE-KMS DEK plaintext on drop. Defense in depth —
# guards against process memory dumps / swap-out / core dumps leaking the
# 32-byte AES-256 DEK after it leaves scope. `Zeroizing<T>` is a thin
# wrapper that calls `T::zeroize()` in its `Drop`, so the existing call
# sites that go through `Deref<Target=T>` keep compiling untouched.
zeroize = { version = "1", features = ["zeroize_derive"] }

[dev-dependencies]
tempfile = "3"
http = "1"
testcontainers-modules = { version = "0.15", features = ["minio"] }
zstd = { workspace = true }
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "http2"] }
metrics-exporter-prometheus.workspace = true
proptest.workspace = true
rcgen = "0.13"
# v0.8.18 P4: server-side fuzz coverage. Same engine the codec
# fuzz farm uses (`crates/s4-codec/tests/fuzz_bolero.rs`), now
# applied to the SigV4a Authorization parser and the IAM
# policy parser — both ingest untrusted JSON / header strings.
bolero = "0.13"
