[package]
name = "skald-relay-server"
version = "0.1.0"
edition = "2024"
description = "Skald Remote Control relay: zero-trust store-and-forward + push bridge (see data/ios-app/relay.md)"
license = "MIT"

# Main binary (the relay). Deploy entrypoint is /skald-relay-server.
# Frame types + crypto live in the shared `skald-relay-common` crate; the
# `gen-vectors` reference generator (crypto interop test vectors,
# data/ios-app/test-vectors.md §3) moved there too (run with
# `cargo run -p skald-relay-common --bin gen-vectors`).

[dependencies]
# --- shared frame types + crypto (frames + verify/namespace subset) ---
skald-relay-common = { path = "../skald-relay-common" }

# --- async runtime + web/WS ---
axum         = { version = "0.8", features = ["ws"] }
tokio        = { version = "1", features = ["full"] }
tokio-util   = { version = "0.7", features = ["rt"] }
futures-util = "0.3"

# --- serde / frames ---
serde       = { version = "1", features = ["derive"] }
serde_json  = "1"
async-trait = "0.1"

# --- persistence ---
sqlx = { version = "0.9.0", features = ["runtime-tokio", "sqlite"] }

# --- encoding used directly in the WS handler ---
hex           = "0.4"
base64        = "0.22"
rand          = "0.8"        # CSPRNG for the 32-byte challenge nonce

# --- v2 wire format (data/ios-app/v2/relay-protocol.md) ---
# `prost`: matches the major used by `skald-relay-common` so the
#   generated `proto::v2::RelayFrame` types here are the same compile-time
#   ones the common crate re-exports. `bytes`: `prost` 0.13 generates
#   `bytes` fields as `prost::bytes::Bytes`; we use the crate directly in
#   the WS handler to build zero-copy frame payloads.
prost         = "0.13"
bytes         = "1"

# --- observability + misc ---
anyhow             = "1"
tracing            = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
tracing-appender   = "0.2"
chrono             = { version = "0.4", default-features = false, features = ["clock", "std"] }

# --- push-live senders (optional, off by default) ---
# reqwest: HTTP/2 client for APNs (`http2` enables ALPN h2, `rustls-no-provider`
#   uses rustls without pulling a crypto provider — the binary installs `ring`
#   as the process default, avoiding any OpenSSL/aws-lc C build; `json` matches
#   the body type).
# jsonwebtoken: ES256 JWT signing for APNs provider auth tokens.
#   `use_pem` lets us load the .p8 PEM directly; `p256` covers Apple's ES256
#   algorithm (the only curve APNs accepts) without pulling a separate crypto
#   crate.
# uuid: APNs requires a unique `apns-id` per message so retries are de-duped.
reqwest      = { version = "0.13", default-features = false, features = ["http2", "json", "rustls-no-provider"], optional = true }
jsonwebtoken = { version = "9", features = ["use_pem"], optional = true }
uuid         = { version = "1", features = ["v4"], optional = true }

[features]
default = []
# Live push senders (need real APNs/FCM credentials). Off by default so the
# relay builds & runs without external creds; the normative decision/payload
# logic is always compiled and unit-tested. See push.rs.
push-live = ["dep:reqwest", "dep:jsonwebtoken", "dep:uuid"]

[dev-dependencies]
# WebSocket client used by the protocol integration tests (tests/protocol.rs).
tokio-tungstenite = "0.29"
# Sign challenges / compute namespace_id from the test harness side.
ed25519-dalek = "2"
sha2          = "0.10"
# The integration test constructs the same protobuf `RelayFrame`s the relay
# sends on the wire (data/ios-app/v2/relay-protocol.md) — prost matches the
# generator used by `skald-relay-common`, bytes is the `Bytes` type prost 0.13
# generates for `bytes` fields.
prost         = "0.13"
bytes         = "1"
